stm32f407探索者开发板(十八)——串口通信实验讲解(USART_RX_STA流程图详解)

简介: stm32f407探索者开发板(十八)——串口通信实验讲解(USART_RX_STA流程图详解)

一、uart_init(串口初始化)

就是根据上一篇的一样的步骤,可以进行参考核对,尝试进行理解

串口时钟使能: RCC_APBxPeriphClockCmd);

GPIO时钟使能: RCC_ AHB1PeriphClockCmd();

引脚复用映射:GPIO_PinAFConfig();

GPIO端口模式设置:GPIO _Init(); 模式设置为GPIO_Mode_ AF

串口参数初始化: USART_ Init();

开启中断并且初始化NVIC ( 如果需要开启中断才需要这个步骤)

NVIC_ Init();

USART_ITConfig();

使能串口:USART_Cmd();

编写中断处理函数: USARTX_ IRQHandler();

串口数据收发:

void USART_SendData();//发送数据到串口,DR

uint16_ t USART_ReceiveData();//接受数据,从DR读取接受到的数据

串口传输状态获取:

FlagStatus USART_GetFlagStatus();

void USART_ClearlTPendingBit();

   //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
 
  //串口1对应引脚复用映射
  GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
  GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1
  
  //USART1端口配置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
  GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10

   //USART1 初始化设置
  USART_InitStructure.USART_BaudRate = bound;//波特率设置
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
    USART_Init(USART1, &USART_InitStructure); //初始化串口1
  
    USART_Cmd(USART1, ENABLE);  //使能串口1 

二、USART1_IRQHandler(串口1中断服务程序)

#define USART_REC_LEN 200 //定义最大接收字节数200
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_ REC LEN个字节.末字节为换行符
u16 USART_RX_STA; //接收状态标记

定义USART_REC_LEN是为了进行限定最大接收数

定义USART_RX_BUF就是为了进行设置了接收字符的缓冲区

定义USART_RX_STA是为了对缓冲区状态的事实监控

代码的整体逻辑

0-13位是为了记录接收数据的有效个数,不能大于200

14位是接受到0X0D的标志位,对于检测到其的出现则进行置1

15位是当前面14位为1又紧接着接收到0X0A的时候置1,表示数据接收完成

void USART1_IRQHandler(void)                  //串口1中断服务程序
{
  u8 Res;
#if SYSTEM_SUPPORT_OS     //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
  OSIntEnter();    
#endif
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
  {
    Res =USART_ReceiveData(USART1);//(USART1->DR);  //读取接收到的数据
    
    if((USART_RX_STA&0x8000)==0)//接收未完成
    {
      if(USART_RX_STA&0x4000)//接收到了0x0d
      {
        if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
        else USART_RX_STA|=0x8000;  //接收完成了 
      }
      else //还没收到0X0D
      { 
        if(Res==0x0d)USART_RX_STA|=0x4000;
        else
        {
          USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
          USART_RX_STA++;
          if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收    
        }    
      }
    }        
  } 

流程图详解

三、main.c(主函数)

主函数就比较简单了,先配置好相关变量和函数,直接死循环判断USART_RX_STA是否15位为1即可

int main(void)
{ 
 
  u8 t;
  u8 len; 
  u16 times=0;  
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
  delay_init(168);    //延时初始化 
  uart_init(115200);  //串口初始化波特率为115200
  LED_Init();         //初始化与LED连接的硬件接口  
  while(1)
  {
    if(USART_RX_STA&0x8000)
    {            
      len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
      printf("\r\n您发送的消息为:\r\n");
      for(t=0;t<len;t++)
      {
        USART_SendData(USART1, USART_RX_BUF[t]);         //向串口1发送数据
        while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
      }
      printf("\r\n\r\n");//插入换行
      USART_RX_STA=0;
    }else
    {
      times++;
      if(times%5000==0)
      {
        printf("\r\nALIENTEK 探索者STM32F407开发板 串口实验\r\n");
        printf("正点原子@ALIENTEK\r\n\r\n\r\n");
      }
      if(times%200==0)printf("请输入数据,以回车键结束\r\n");  
      if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
      delay_ms(10);   
    }
  }
}

成功

四、关于printf的支持

关于怎么配置printf,加入下面这串代码就行,关键就是fputc,如果是其他串口就对USART1->SR&0X40USART1->DR进行相应修改即可

#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
  int handle; 
}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
  x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{   
  while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
  USART1->DR = (u8) ch;      
  return ch;
}

相关文章
|
4月前
|
传感器
stm32f407探索者开发板(二十二)——通用定时器基本原理讲解
stm32f407探索者开发板(二十二)——通用定时器基本原理讲解
325 0
|
4月前
stm32f407探索者开发板(十九)——外部中断实验-EXIT
stm32f407探索者开发板(十九)——外部中断实验-EXIT
281 0
|
4月前
STM32CubeMX 串口收发一帧数据
STM32CubeMX 串口收发一帧数据
54 9
|
4月前
|
芯片
STM32CubeMX 串口数据收发
STM32CubeMX 串口数据收发
134 2
|
4月前
stm32f407探索者开发板(二十三)——定时器中断实验
stm32f407探索者开发板(二十三)——定时器中断实验
340 0
|
4月前
|
程序员
stm32f407探索者开发板(二十一)——窗口看门狗
stm32f407探索者开发板(二十一)——窗口看门狗
137 0
|
4月前
|
芯片
stm32f407探索者开发板(二十)——独立看门狗实验
stm32f407探索者开发板(二十)——独立看门狗实验
293 0
|
5月前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
416 2
|
4月前
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
675 0
|
5月前
|
IDE 开发工具
使用STM32F103标准库实现自定义键盘
通过本文,我们学习了如何使用STM32F103标准库实现一个简单的自定义键盘。我们首先初始化了GPIO引脚,然后实现了一个扫描函数来检测按键状态。这个项目不仅能够帮助我们理解STM32的GPIO配置和按键扫描原理,还可以作为进一步学习中断处理和低功耗设计的基础。希望本文对你有所帮助,祝你在嵌入式开发的道路上不断进步!
498 4