这是本人一个作业,却整整花了两天时间才搞完,因为网上关于stm32的仿真很少,所以应该是网上第一份protues两块单片机实现串口交互的程序,实在是值得纪念一下。
前文提要,由于protues仿真库函数bug太多,所以采用寄存器的初始化版本原作者
后面会发原程序下载地址
首先我们知道串口交互程序需要uasrt初始化,这边采用的是原子哥的例程实验四的初始化,这个可以自行参考资料,这边就不放代码图了。
led和key配置,这边放两个的.h代码就好
//led.h
#define LED5 PBout(4)// PB4
#define LED4 PBout(5)// PB5
#define LED3 PBout(6)// PB6
void LED_Init(void);//初始化
//key.h
#define KEY0 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)//读取按键0
#define KEY1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)//读取按键1
#define KEY2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)//读取按键2
#define KEY3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)//读取按键3
#define KEY4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)//读取按键4
#define KEY0_PRES 1 //KEY0按下
#define KEY1_PRES 2 //KEY1按下
#define KEY2_PRES 3 //KEY2按下
#define KEY3_PRES 4 //KEY3按下
#define KEY4_PRES 5 //KEY4按下
这两个初始化程序也是原子哥的,可以自行找代码参考如何实现。
这个是作业内容,但是问题是如何实现
按键控制实现比较简单,如何实现发送信号和接收信号是一个问题
首先必须知道usar的函数是如何实现,这边就介绍我们需要的发送和接收就好。
//USART_SenData
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
{
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_DATA(Data));
USARTx->DR = (Data & (uint16_t)0x01FF);
}
//例子
//USART_SendData(USART1, 0x00);
//发送0x02
0x02就是十六进制,0x02=00000010,这里我也不多赘述了。
这边还有一个关键点,很多人可能发送数据只会发一个数据,例如:
USART_SendData(USART1,0x00) ;
USART_SendData(USART1,0x01) ;
USART_SendData(USART1,0x02) ; 这样通过上位机收到的只是02并不是00 01 02
因为数据还来不及发送,数据就被后面来的数据覆盖了,所以收到的数据是02,不是00 01 02
USART_SendData(USART1,0x00) ;
delay_ms(1);
USART_SendData(USART1,0x01) ;
delay_ms(1);
USART_SendData(USART1,0x02) ;
delay_ms(1); 这样收到的才是00 01 02
这个是个蠢办法,但是由于本人也还没理解那么多,就先用着,后面链接就是参考来源,里面有一个更好的设置办法。
参考
然后是接收函数
USART_RX_BUF[0]==0x02;
//当第一个字符为0x02时
这个函数我也放个链接个需要的同学参考
STM32通过串口控制LED闪烁或者呼吸效果
这边也有一个问题,由于protues仿真只能读取第一一个字符,所以后面调试过程我基本都是使用串口模拟器,让计算机来调试。
然后是主函数的东西,由于我写的比较乱就放出一个给别人参考后面放源程序链接给同学。
int main(void)
{
vu8 key=0;
u8 t;
u8 len;
u16 times=0;
Stm32_Clock_Init(9); //系统时钟设置
// delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
uart_init(9600); //串口初始化为9600
LED_Init(); //初始化与LED连接的硬件接口
KEY_Init();
for(t=0;t<10;t++)
{
Array[t]=t;
}
while(1)
{
if(USART_RX_BUF[0]==0x01)
{
hxf_delay_s(10);
LED4=!LED4;
hxf_delay_s(10);
USART_SendData(USART1, 0x01);
hxf_delay_s(10);
USART_SendData(USART1, 0x01);
hxf_delay_s(10);
USART_SendData(USART1, 0x02);
hxf_delay_s(10);
USART_SendData(USART1, 0x03);
hxf_delay_s(10);
USART_SendData(USART1, 0xaa);
}
//输如代码和USART_RX_BUF
key=KEY_Scan(0); //得到键值
if(key)
{
switch(key)
{
case KEY2_PRES: //控制LED4点亮
delay_ms(1000);
LED4=!LED4;
hxf_delay_s(10);
USART_SendData(USART1, 0x01);
hxf_delay_s(10);
USART_SendData(USART1, 0x01);
hxf_delay_s(10);
USART_SendData(USART1, 0x02);
hxf_delay_s(10);
USART_SendData(USART1, 0x03);
hxf_delay_s(10);
USART_SendData(USART1, 0xaa);
}
break;
}
}
//key2 、led1和USART_SendData
这里面由于原本的时钟不知道为什么定时不精确,也没去深究,就自己按原本那个写了一个新的放进main.c函数里面了。
这样程序部分就完成了。
然后是仿真部分,先上一份仿真图
这里面的stm32需要设置72MHZ,然后由于virtual teminal会吞掉信号,所以我们不使用他,后面看波形,我们在用示波器看。
用串口模拟器和xcom调试看看运行如何。
发现符合要求,这边仿真图看看就行,因为protues的局限性太大了,这是我目前能做出来最完美的一份,然后两块单片机交互时候,大家可以自行用protues去尝试,也是能成功的,希望对大家有用。
资源下载
QQ3209448656