STM32
直播中

张莉

7年用户 1276经验值
私信 关注
[问答]

STM32串口怎么使用

STM32串口怎么使用

回帖(1)

h1654155275.6260

2021-12-7 14:08:34

1,初始化IO 串口1,pclk2:PCLK2时钟频率(Mhz),波特率9600, 中断向量一般配置用中断方式接收数据


    I/O口配置:TXD配置为复用推挽输出(GPIO_Mode_AF_PP),RXD配置为浮空输入(GPIO_Mode_IN_FLOATING);


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&=0XFFFFF00F;
        GPIOA->CRH|=0X000008B0;//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
}
首先通过时钟频率和波特率计算出“mantisa”这个参数是一会儿赋值给USARTx->BRR 寄存器的,来设置串口的波特率
使能IO口时钟和所用串口的时钟
设置IO口(TX、RX),设置为复用功能,复用为USART
设置波特率,是否过采样(16倍过采样来保证较好的容错性),数据长度和有无校验位
使能发送和接收
使能中断,并且设置中断的优先级以及优先级分组
使能串口


NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先


void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)         
{
        u32 temp;       
        u8 IPRADDR=NVIC_Channel/4;  //每组只能存4个,得到组地址
        u8 IPROFFSET=NVIC_Channel%4;//在组内的偏移
        IPROFFSET=IPROFFSET*8+4;    //得到偏移的确切位置
        MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组
        temp=NVIC_PreemptionPriority<<(4-NVIC_Group);          
        temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
        temp&=0xf;//取低四位

        if(NVIC_Channel<32)NVIC->ISER[0]|=1<         else NVIC->ISER[1]|=1<<(NVIC_Channel-32);   
        NVIC->IPR[IPRADDR]|=temp< }
2,STM32串口接收数据







#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                                                       
是定义了一个接收缓冲数组,来存放接收到的数据,每个元素可以存放一个字节的数据,数组的长度为USART_REC_LEN。操作系统的部分暂时忽略,接下来定义了一个16位的接收状态标记USART_RX_STA
它的第15位是接收完成标志,第14位是接收到0x0d的标志,而0-13位表示接收到的有效字节的数目。当接收到一个数据后,把接收到的数据(DR寄存器中的值)暂存在中间变量中,先检验接收是否完成,若未完成,检验是否接收到0x0d,如果接收到,修改状态标记,然后把中间变量的值赋给缓冲数组,将状态标记的值自增,完成对一个字节的接收。
3,STM32串口发送数据:将要发送的数据(8位)赋给数据寄存器(DR)然后等待发送完成。
len=USART_RX_STA&0x3f;//得到此次接收到的数据长度

for(t=0;t {
        USART1->DR=USART_RX_BUF[t];
        while((USART1->SR&0X40)==0);//等待发送结束
}
        printf("nn");//插入换行
        USART_RX_STA=0;







举报

更多回帖

发帖
×
20
完善资料,
赚取积分