西门子杯工业嵌入式系列:串口数据收发实战详解

西门子杯工业嵌入式-5-串口实现数据收发

  • 一、通信基础
  • 1.1 什么是通信
  • 1.2 嵌入式系统中的通信
  • 二、串行通信原理
  • 2.1 串行通信简介
  • 2.2 通信参数约定
  • 三、GD32F470 串口资源与性能
  • 3.1 串口硬件资源
  • 四、串口通信的实现
  • 4.1 串口初始化流程
  • 4.2 串口发送函数编写
  • 4.3 使用 printf 实现串口输出
  • 五、串口接收中断机制
  • 5.1 接收中断原理
  • 5.2 接收中断配置
  • 六、总结与注意事项
  • 6.1 串口通信优势
  • 6.2 编程注意事项
  • 接线图
  • 链接:
    B站视频

    一、通信基础

    1.1 什么是通信

    信息从一个设备传输到另一个设备的过程

    生活中的通信例子(通话、短信、上网)

    1.2 嵌入式系统中的通信

    微控制器与外设信息交互的关键方式

    分类方式:

    按传输介质:有线通信 vs 无线通信

    按传输方式:串行通信 vs 并行通信

    按同步方式:同步通信 vs 异步通信

    二、串行通信原理

    2.1 串行通信简介

    基本方式

    特点:一条数据线、按位传输、硬件简单

    2.2 通信参数约定

    关键参数:波特率、数据位、停止位、奇偶校验

    参数不一致导致通信失败的例子(摩斯电码类比)

    三、GD32F470 串口资源与性能

    3.1 串口硬件资源

    支持8个 USART/UART 接口

    支持全双工通信

    可配置波特率,最高10.5Mbps

    内置16位波特率发生器

    支持DMA和多种中断

    四、串口通信的实现

    4.1 串口初始化流程

    启用 GPIO 和 USART 时钟

    配置 GPIO 引脚复用功能(AF7, PA9, PA10)

    设置 GPIO 模式为复用输出

    串口复位并配置通信参数(波特率、校验、字长、停止位)

    启用串口发送与接收功能

    关闭流控 RTS/CTS

    配置并启用 USART 中断

    void USART0_Config(void)
    {
        rcu_periph_clock_enable(RCU_GPIOA);    // 使能GPIO时钟
        rcu_periph_clock_enable(RCU_USART0);   // 使能串口时钟
    	
    	gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9 | GPIO_PIN_10);				//配置端口复用
    	
    	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);  		//端口类型配置为复用
        gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);  
    
    	gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_10);  	//端口类型配置为复用	
    	gpio_output_options_set(GPIOA, GPIO_MODE_ANALOG, GPIO_OSPEED_50MHZ, GPIO_PIN_10);  
    
    
        usart_deinit(USART0);    						// 串口复位
        usart_word_length_set(USART0, USART_WL_8BIT);   // 字长为8位
        usart_stop_bit_set(USART0, USART_STB_1BIT);     // 停止位1位
        usart_parity_config(USART0, USART_PM_NONE);		// 无校验
        usart_baudrate_set(USART0, 115200U);     		// 波特率115200
        usart_receive_config(USART0, USART_RECEIVE_ENABLE);     // 接收使能
    	usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);   // 发送使能
    	usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);
        usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);
        usart_enable(USART0);          							// 串口使能
    }
    
    

    4.2 串口发送函数编写

    定义发送函数:传入数据指针和长度

    轮询发送:等待发送完成标志

    使用 usart_data_transmit() 实现字符逐个发送

    
    ```css
    void USART0_SendData(uint16_t *buf,uint16_t len)
     {
         uint16_t t;
         for(t=0;t<len;t++)      
         {           
             while(usart_flag_get(USART0, USART_FLAG_TC) == RESET);  
             usart_data_transmit(USART0,buf[t]);
         }     
         while(usart_flag_get(USART0, USART_FLAG_TC) == RESET);          
    }
    

    4.3 使用 printf 实现串口输出

    重定向 fputc()

    使能 MicroLib,配置标准输出到串口

    printf 实质上也是通过 usart_data_transmit() 实现的

    int fputc(int ch, FILE *f)
    {
        usart_data_transmit(USART0, (uint8_t)ch);
        while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
        return ch;
    }
    

    五、串口接收中断机制

    5.1 接收中断原理

    接收缓冲区非空时触发中断

    避免轮询方式,提高实时性

    应用场景:传感器数据采集、远程控制、通信协议实现等

    5.2 接收中断配置

    启用 USART 接收功能

    启用接收缓冲区非空中断

    编写中断服务函数

    判断中断类型

    读取数据并存储

    清除中断标志,避免死循环

    void USART0_Config(void)
    {
        rcu_periph_clock_enable(RCU_GPIOA);    // 使能GPIO时钟
        rcu_periph_clock_enable(RCU_USART0);   // 使能串口时钟
    	
    		gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9 | GPIO_PIN_10);				//配置端口复用
    	
    		gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);  		//端口类型配置为复用
    		gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);  
    
    		gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_10);  	//端口类型配置为复用	
    		gpio_output_options_set(GPIOA, GPIO_MODE_ANALOG, GPIO_OSPEED_50MHZ, GPIO_PIN_10);  
    	
    
        usart_deinit(USART0);    						// 串口复位
        usart_word_length_set(USART0, USART_WL_8BIT);   // 字长为8位
        usart_stop_bit_set(USART0, USART_STB_1BIT);     // 停止位1位
        usart_parity_config(USART0, USART_PM_NONE);		// 无校验
        usart_baudrate_set(USART0, 115200U);     		// 波特率115200
        usart_receive_config(USART0, USART_RECEIVE_ENABLE);     // 接收使能
    		usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);   // 发送使能
    		usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);
        usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);
    		
    		
    		nvic_irq_enable(USART0_IRQn, 0, 0);
    		usart_interrupt_enable(USART0, USART_INT_RBNE);
    		
    		
        usart_enable(USART0);          							// 串口使能
    		
    }
    
    /************************************************************ 
     * Function :       USART0_IRQHandler
     * Comment  :       串口中断服务函数,用来接收串口数据
     * Parameter:       null
     * Return   :       null
     * Author   :       Lingyu Meng
     * Date     :       2025-03-14 V0.2 original
    ************************************************************/
    void USART0_IRQHandler(void)
    {
        if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE))
    	{			
    		data_recv = usart_data_receive(USART0);    //  接收串口数据
    		usart_interrupt_flag_clear(USART0, USART_INT_FLAG_RBNE); 	//清除接收中断标志位
            process_data(data_recv); 		//处理数据
    				
        }    
    }
    
    /************************************************************ 
     * Function :       process_data
     * Comment  :       数据为 ‘a’的时候点亮LED2
    					数据为'b'的时候关断LED2
    					其他数据则直接串口打印出来
     * Parameter:       char型的数据,只支持单字符
     * Return   :       null
     * Author   :       Lingyu Meng
     * Date     :       2025-03-14 V0.2 original
    ************************************************************/
    void process_data(uint8_t data)
    {
    	if (data == 'a')
    	{
    		LED2_ON();
    	}
    	else if(data == 'b')
    	{
    		LED2_OFF();
    	}
    	else
    	{
    		usart_data_transmit(USART0, data_recv);    //  发送数据 
    	}
    
    }
    

    六、总结与注意事项

    6.1 串口通信优势

    实现简单

    应用广泛

    配合中断机制高效可靠

    6.2 编程注意事项

    初始化要完整、参数一致

    中断处理后必须清除中断标志

    使用串口调试助手验证数据发送

    接线图

    注意TX与RX相接,原图好像有点不对,反正试出来是横着接的。

    作者:三万棵雪松

    物联沃分享整理
    物联沃-IOTWORD物联网 » 西门子杯工业嵌入式系列:串口数据收发实战详解

    发表回复