[应用相关]

STM32 串口传输--Alientek源码

[复制链接]
614|1
手机看帖
扫描二维码
随时随地手机跟帖
dsdfdcdx|  楼主 | 2019-3-28 15:08 | 显示全部楼层 |阅读模式
原贴链接:http://www.openedv.com/forum.php?mod=viewthread&tid=95
usart文件夹内包含了usart.c和usart.h两个文件。这两个文件用于串口的初始化和中断接收。这里只是针对串口1,比如你要用串口2或者其他的串口,只要对代码稍作修改就可以了。usart.c里面包含了2个函数一个是void USART1_IRQHandler(void);另外一个是void uart_init(u32 pclk2,u32 bound);里面还有一段对串口printf的支持代码,如果去掉,则会导致printf无法使用,虽然软件编译不会报错,但是硬件上STM32是无法启动的。这段代码不要去修该。
void USART1_IRQHandler(void)函数是一个串口1中断响应函数,当串口1发生了相应的中断后,就会跳到该函数执行。这里我们设计了一个小小的接收协议:通过这个函数,配合一个数组USART_RX_BUF[64],一个接收状态寄存器USART_RX_STA实现对串口数据的接收管理。USART_RX_BUF的最大值为64,也就是一次接收的数据最大不能超过64个字节。USART_RX_STA是一个接收状态寄存器其各的定义如下表:
USART_RX_STA
bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
接收完成标志
接收到0X0D标志
接收到的有效数据个数
                                        表2.7.2.2接收状态寄存器位定义表
设计思路如下:
当接收到从电脑发过来的数据,把接收到的数据保存在USART_RX_BUF中,同时在接收状态寄存器(USART_RX_STA)中计数接收到的有效数据个数,当收到回车(0X0D,0X0A)的第一个字节0X0D时,计数器将不再增加,等待0X0A的到来,而如果0X0A没有来到,则认为这次接收失败,重新开始下一次接收。如果顺利接收到0X0A,则标记USART_RX_STA的第七位,这样完成一次接收,并等待该位被其他程序清除,从而开始下一次的接收,而如果迟迟没有收到0X0D,那么在接收数据超过64个了,则会丢弃前面的数据,重新接收。函数代码如下:
/ #ifdef EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误            
u8 USART_RX_BUF[64];     //接收缓冲,最大64个字节.
//接收状态
//bit7,接收完成标志
//bit6,接收到0x0d
//bit5~0,接收到的有效字节数目
u8 USART_RX_STA=0;       //接收状态标记            
void USART1_IRQHandler(void)
{
     u8 res;      
     if(USART1->SR&(1<<5))//接收到数据
     {         
                 res=USART1->DR;
                 if((USART_RX_STA&0x80)==0)//接收未完成
                 {
                             if(USART_RX_STA&0x40)//接收到了0x0d
                             {
                                         if(res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
                                         else USART_RX_STA|=0x80;      //接收完成了
                             }else //还没收到0X0D
                             {         
                                         if(res==0x0d)USART_RX_STA|=0x40;
                                         else
                                         {
                                                     USART_RX_BUF[USART_RX_STA&0X3F]=res;
                                                     USART_RX_STA++;
                                                     if(USART_RX_STA>63)USART_RX_STA=0;//接收数据错误,重新开始接收        
                                         }                     
                             }
                 }                                                                                                                                       
     }                                                                                                                                   
}
#endif                              
从上面的代码我们可以看使用了宏定义#ifdef,当需要使用串口接收的时候,我们只要在usart.h里面定义EN_USART1_RX就可以了。不使用的时候,注释掉就可,这样可以省出部分sram和flash。
void uart_init(u32 pclk2,u32 bound)函数是串口1初始化函数。该函数有2个参数,第一个为pclk2,是系统的时钟频率。第二个参数为需要设置的波特率,例如9600,115200等。而这个函数的重点在与设置波特率。在《STM32参考手册》的第480页,24.4.4一节有详细介绍波特率的计算方式。这里我们不再详细介绍。uart_init在不同pclk2频率下初始化的不同波特率有些会存在误差,具体可以参考《STM32参考手册》的第481页的表154。需要注意的是这里初始化的串口都是按8位数据格式,1位停止位,无奇偶校验位的。具体代码如下:
//初始化IO 串口1
//pclk2CLK2时钟频率(Mhz)
//bound:波特率
void uart_init(u32 pclk2,u32 bound)
{   
     float temp;
     u16 mantissa;
     u16 fraction;        
     temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
     mantissa=temp;                                      //得到整数部分
     fraction=(temp-mantissa)*16; //得到小数部分     
   mantissa<<=4;
     mantissa+=fraction;
     RCC->APB2ENR|=1<<2;   //使能PORTA口时钟
     RCC->APB2ENR|=1<<14;  //使能串口时钟
     GPIOA->CRH=0X444444B4;//IO状态设置
                  
     RCC->APB2RSTR|=1<<14;   //复位串口1
     RCC->APB2RSTR&=~(1<<14);//停止复位                        
     //波特率设置
     USART1->BRR=mantissa; // 波特率设置
     USART1->CR1|=0X200C; //1位停止,无校验位.
#ifdef EN_USART1_RX                    //如果使能了接收
     //使能接收中断
     USART1->CR1|=1<<8;    //PE中断使能
     USART1->CR1|=1<<5;    //接收缓冲区非空中断使能                 
     MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级
#endif
}

使用特权

评论回复
dsdfdcdx|  楼主 | 2019-3-28 15:09 | 显示全部楼层
附件:
usart.rar (2.01 KB)

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

49

主题

80

帖子

0

粉丝