STM32
直播中

刘桂兰

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

分享一个不错的STM32串口通信实验

分享一个不错的STM32串口通信实验

回帖(1)

何元

2021-12-7 14:07:11
使用蓝桥杯CT117E板子





DB9接口指9针的接口(串口连接器)


USART_InitTypeDef.USART_BaudRate        //波特率
USART_InitTypeDef.USART_WordLength        //字长
USART_InitTypeDef.USART_StopBits    //停止位
USART_InitTypeDef.USART_Parity        //奇偶校验位
USART_InitTypeDef.USART_Mode        //发送接收使能
USART_InitTypeDef.USART_HardwareFlowControl        //硬件流控制(很少用到,可不必深究)


串口配置一般步骤


GPIO_InitTypeDef usart_gpio;
USART_InitTypeDef usart;
NVIC_InitTypeDef nvic_n;


1:串口时钟使能,GPIO时钟使能


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);   
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);


2:串口复位(非必须)


USART_DeInit(USART2);


3:GPIO端口模式设置


usart_gpio.GPIO_Mode = GPIO_Mode_AF_PP;     //复用推挽输出(全双工)(查GPIO配置表决定输出模式)
usart_gpio.GPIO_Pin = GPIO_Pin_2;     //输出引脚
usart_gpio.GPIO_Speed = GPIO_Speed_50MHz;  
GPIO_Init(GPIOA,&usart_gpio);
   
usart_gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;     //浮空输入
usart_gpio.GPIO_Pin = GPIO_Pin_3;     //输入引脚
GPIO_Init(GPIOA,&usart_gpio);


4:串口参数初始化


usart.USART_BaudRate = 115200;   //设置波特率
usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;      //无硬件数据流控制
usart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;      //收发模式
usart.USART_Parity = USART_Parity_No;      //无奇偶校验位
usart.USART_StopBits = USART_StopBits_1;     //一个停止位
usart.USART_WordLength = USART_WordLength_8b;      //字长为8位(无奇偶校验位为8,有奇偶校验位为9)
USART_Init(USART2,&usart);


5:若要使用中断则开启中断并初始化NVIC


nvic_n.NVIC_IRQChannel = USART2_IRQn;  //串口2中断通道
nvic_n.NVIC_IRQChannelPreemptionPriority = 2;  //抢占优先级
nvic_n.NVIC_IRQChannelSubPriority = 2;  //响应优先级
nvic_n.NVIC_IRQChannelCmd = ENABLE;  //IRQ通道使能
NVIC_Init(&nvic_n);
//开启中断
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);    //设置开启哪个中断
//打开接收中断,接收到数据则执行中断服务函数















由中断映像图和库函数判断,上图TXNE和TXNEIE应为RXNE和RXNEIE
6:串口使能


USART_Cmd(USART2,ENABLE);
1
7:编写中断服务函数


#define USART_REC_LEN 200


u8 USART_RX_BUF[USART_REC_LEN];        //接收缓冲,最大USART_REC_LEN个字节
u16 USART_RX_STA = 0;        //接收状态标记
//接收状态
//bit16,接收完成标志位
//bit15,接收到0x0d(h回车)标志位
//bit14~0,接收到的有效字节数


void USART2_IRQHandler(void)
{   
    u8 res;
    if(USART_GetITStatus(USART2,USART_IT_RXNE))        //接收中断(接收到的数据必须是0x0d,0x0a结尾)
    {   
        res = USART_ReceiveData(USART2);        //读取接收到的数据
        if((USART_RX_STA & 0x8000) == 0)    //接收未完成
            //若上次接收未完成则第16位为0,与0x8000&运算后为0
        {
            if(USART_RX_STA & 0x4000)        //接收到了0x0d
            //若第15位为1,则接收到了0x0d
            {
                if(res!=0x0a)USART_RX_STA=0;        //接收错误重新开始
                //上一次若接收到了0x0d,后面没有接收到0x0a,则接收错误
                else USART_RX_STA|=0x8000;        //接收完成
                //若接收到了0x0a(连续接收到了0x0d,0x0a),则将USART_RX_STA第16位置为1
            }
            else    //还没接收到0x0d
            {
                if(res == 0x0d)USART_RX_STA|=0x4000;
                //上一次还没接收到0x0d,这一次若接收到0x0d,则将USART_RX_STA第15位置为1
                else        //还没接收到0x0d说明数据还在传输
                {
                    USART_RX_BUF[USART_RX_STA & 0x3fff] = res;
                    //将res的值循环赋值给USART_RX_BUF,只用到USART_RX_STA的0~14位,15,16位为状态标志位
                    USART_RX_STA++;        //在此循环
                    if(USART_RX_STA > (USART_REC_LEN-1))USART_RX_STA=0;    //接收数据错误,重新开始接收
                    //USART_RX_STA的个数若超过最大个数则接收错误,将USART_RX_STA清0
                }
            }
        }
        USART_SendData(USART2,res);  //发送数据
        //接收到数据后发生中断,将接收到的数据在发送回去(发送到电脑,在电脑显示,确认接收到数据)
    }
}


串口数据收发


USART_SendData();    //发送数据到串口
USART_ReceiveData();    //接受数据,从DR读取接受到的数据


串口传输状态获取


USART_GetFlagStatus();        //获取状态标志位
USART_ClearFlag();        //清除状态标志位
USART_GetITStatus();        //获取中断状态标志位
USART_ClearITPengingBit();        //清除中断状态标志位


举报

更多回帖

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