STM32F407探索者开发板:USART_RX_STA流程图分析与串口通信实验

文章目录

  • 一、uart_init(串口初始化)
  • 二、USART1_IRQHandler(串口1中断服务程序)
  • 三、main.c(主函数)
  • 四、关于printf的支持
  • 一、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;
    }
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32F407探索者开发板:USART_RX_STA流程图分析与串口通信实验

    发表评论