1.串口通信

来源:互联网 发布:室内设计学习软件 编辑:程序博客网 时间:2024/06/07 04:08

实验是在原子的STM32F429阿波罗板子实现

STM32F429IGT6多达8路串口,有分数波特率发生器、支持同步单线通信和半双工单线通讯、支持 LIN、 支持调制解调器操作、 智能卡协议和 IrDA SIR ENDEC 规范、具有 DMA 等。

波特率计算公式:

智能卡、LIN和lrDA模式下的波特率

                 fPclkxTx/Rx波特率=  ----------------               (16*USARTDIV)

适用于标准USART(包括SPI模式)的波特率

               fPclkxTx/Rx波特率=-------------------         8*(2-OVER8)*USARTDIV
在F429上PCLK1用于UART2-5,UART7-8.       PCLK2用于USART1和USART6

板载引出的串口:

          TX          RX    USART1: PA9        PA10  UART2: PA2        PA3  UART3: PB10       PB11

实际有的串口和引脚:
这里写图片描述


需要注意的是:

串口1和6时钟使能实在APB2ENR寄存器

其他串口在APB1ENR寄存器

合适的过采样方法:(两种)

  • 8倍过采样(OVER8=1)以获得更高的速度(高达fPclk/8)。缺点:接收器对时钟偏差的最大容差将会降低
  • 16倍过采样(OVER8=0)以增加接收器对时钟偏差的差容。 速度降低到fPclk/16。

串口控制寄存器描述:
这里写图片描述
常用寄存器:

  • OVER8:过采样模式设置位
  • UE:串口使能位
  • M:字长选择位
  • PCE:检验使能位
  • PS:脚要选择位
  • TXIE:发送缓冲区中断使能位
  • TCIE:发送完成中断使能位
  • RXNEIE:接收缓冲区非空中断使能
  • TE:发送使能位(发送期间不能复位该位,若复位将会冻结波特率计数器,从而将损坏TX引脚上的数据,当前传输数据将会丢失。 而后再使能TE位,将会发送空闲帧)
  • RE:接收使能位

串口状态寄存器描述:
这里写图片描述

常用寄存器:

  • RXNE:(读数据寄存器非空),当该位被置1的时候,就是提示已经有数据被接收到了,并且可以读出来了。这时就需要尽快去读取USART_DR,通过读取USART_DR可以将该位清零,也可以向该位写0,直接清除。
  • TC:(发送完成),当该位被置位时,表示USART_DR内的数据已经被发送完成了。如果设置了这个位的中断,则会产生中断。清零方式也有两种:1)读USART_SR,写USART_DR。 2)直接向该位写0。

更详细的内容就没有记录,满足基本通信

hal库函数初始化代码如下:
(引用原子代码)

//初始化IO 串口1 //bound:波特率void uart_init(u32 bound){       //UART 初始化设置    UART1_Handler.Instance=USART1;                      //USART1    UART1_Handler.Init.BaudRate=bound;                  //波特率    UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式    UART1_Handler.Init.StopBits=UART_STOPBITS_1;        //一个停止位    UART1_Handler.Init.Parity=UART_PARITY_NONE;         //无奇偶校验位    UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控    UART1_Handler.Init.Mode=UART_MODE_TX_RX;            //收发模式    HAL_UART_Init(&UART1_Handler);                      //HAL_UART_Init()会使能UART1    HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量}//UART底层初始化,时钟使能,引脚配置,中断配置//此函数会被HAL_UART_Init()调用//huart:串口句柄void HAL_UART_MspInit(UART_HandleTypeDef *huart){    //GPIO端口设置    GPIO_InitTypeDef GPIO_Initure;    if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化    {        __HAL_RCC_GPIOA_CLK_ENABLE();           //使能GPIOA时钟        __HAL_RCC_USART1_CLK_ENABLE();          //使能USART1时钟        GPIO_Initure.Pin=GPIO_PIN_9;            //PA9        GPIO_Initure.Mode=GPIO_MODE_AF_PP;      //复用推挽输出        GPIO_Initure.Pull=GPIO_PULLUP;          //上拉        GPIO_Initure.Speed=GPIO_SPEED_FAST;     //高速        GPIO_Initure.Alternate=GPIO_AF7_USART1; //复用为USART1        HAL_GPIO_Init(GPIOA,&GPIO_Initure);     //初始化PA9        GPIO_Initure.Pin=GPIO_PIN_10;           //PA10        HAL_GPIO_Init(GPIOA,&GPIO_Initure);     //初始化PA10#if EN_USART1_RX        HAL_NVIC_EnableIRQ(USART1_IRQn);        //使能USART1中断通道        HAL_NVIC_SetPriority(USART1_IRQn,3,3);  //抢占优先级3,子优先级3#endif      }}

寄存器版本:(我更喜欢这种简介的版本)

//初始化IO 串口1//pclk2:PCLK2时钟频率(Mhz)//bound:波特率 void uart_init(u32 pclk2,u32 bound){        float temp;    u16 mantissa;    u16 fraction;          temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV@OVER8=0    mantissa=temp;               //得到整数部分    fraction=(temp-mantissa)*16; //得到小数部分@OVER8=0     mantissa<<=4;    mantissa+=fraction;     RCC->AHB1ENR|=1<<0;     //使能PORTA口时钟      RCC->APB2ENR|=1<<4;     //使能串口1时钟     GPIO_Set(GPIOA,PIN9|PIN10,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU);//PA9,PA10,复用功能,上拉输出    GPIO_AF_Set(GPIOA,9,7); //PA9,AF7    GPIO_AF_Set(GPIOA,10,7);//PA10,AF7             //波特率设置    //USART1->BRR 为波特率寄存器    USART1->BRR=mantissa;   //波特率设置      USART1->CR1&=~(1<<15);     //设置OVER8=0 增加接收器对时钟偏差的差容,速度(fPclk/16)                              //设置OVER8=1 获取更高的速度高达(fPclk/8),时钟偏差差容降低    USART1->CR1|=1<<3;      //串口发送使能 #if EN_USART1_RX            //如果使能了接收    //使能接收中断     USART1->CR1|=1<<2;      //串口接收使能    USART1->CR1|=1<<5;      //接收缓冲区非空中断使能               MY_NVIC_Init(3,3,USART1_IRQn,2);//组2,最低优先级 #endif    USART1->CR1|=1<<13;     //串口使能}
原创粉丝点击