精华内容
下载资源
问答
  • UART串口嵌入式产品开发调试过程中会经常用到,下面将板卡与计算机串口通信调试过程总结如下,一来便于以后查看,二来尽量少走弯路。 二、串口定义 UART串口定义 UART串口嵌入式板卡中经常使用,一般有VCC, GND,...

    板卡与计算机UART串口调试总结

    一、概述

    UART串口在嵌入式产品开发调试过程中会经常用到,下面将板卡与计算机串口通信调试过程总结如下,一来便于以后查看,二来尽量少走弯路。

    二、串口定义

    UART串口定义
    UART串口在嵌入式板卡中经常使用,一般有VCC, GND, RX, TX这4个引脚, 我们只用到其中的GND、RX、TX这三个引脚。UART串口电平标准为TTL电平, 低电平为0(0V),高电平为1(3.3V或以上)。
    COM串口定义
    COM串口是计算机经常用到的,采用了9针定义(如下图所示),我们在制作COM串口线时,一般只用到2(接收)、3(发送)、5(地)引脚。COM串口电平标准为RS232电平, 采用负逻辑电平,5V到12V为低电平,而-12到-5V为高电平。
    在这里插入图片描述
    这里需要注意:由于电平标准不同,板卡上的UART串口与计算机上的COM串口是不能通信的,需要有TTL到RS232电平转换接口。

    三、硬件连接总结

    查看板卡硬件原理图,如果没有TTL到RS232电平转换电路,如上板卡上的UART串口与计算机上的COM串口是不能通信,需要TTL到RS232电平转换接口。
    目前计算机或者笔记本电脑用一般用USB转串口接口板,用于与板卡的串口通信,因此我们采用了FT232接口板(如下图)用于板卡与计算机之间实现USB转串口交互。
    在这里插入图片描述
    连接方式上,板卡与FT232接口板通过杜邦线连接TX、RX和GND,注意TX要与RX连接。FT232上通过条线可以选择3.3V电平或5V电平,均可以正常通信。

    四、软件调试总结

    1、软件调试前提

    软件调试前提是必须设置相同的串口参数,例如波特率、起始位、截止位、是否带校验位、是否带流空等,一般仅设置波特率即可,需要重点注意:波特率一定要保持一致,否则会有乱码或者无法收发通信。

    2、计算机侧串口配置

    计算机侧需要安装好FT232接口板USB转串口驱动,一般会插入接口板后会自动安装,然后采用SSCOM作为串口调试工具,选择好需要用到的USB转串口,设置好串口波特率。

    3、板卡侧串口调试

    板卡侧登录到shell,通过命令行方式发送和接受串口数据。
    (1)板卡向计算机SSCOM串口调试工具发送数据指令如下:
    echo “AAAA” > /dev/ttyS1
    调试发现:
    1)、发送的数据AAAA带双引号、单引号、或者不加引号均可正常接收;
    2)、发送要敲回车。
    (2)板卡从计算机SSCOM串口调试工具接收数据指令如下:
    cat /dev/ttyS1
    调试发现:SSCOM中输入的发送数据需要加回车,板卡shell才能收到串口数据。

    五、后记

    以上仅从操作层面,将UART串口调试过程记录如下,实际UART串口涉及tty驱动框架的内容,应用阻塞等模式配置,还有很多内部细节需要研究,相对比较复杂,后续将进一步补充总结相关内容。

    展开全文
  • 嵌入式UART的研究

    千次阅读 2018-07-16 13:11:31
    嵌入式串口通信研究 一、 通信过程:通信方将信息编码 → 传输信息 → 接收方接收信号并解码串口使用的图二、 串口通信基本概念:1) 同步通信和异步通信的区别同步(USART):发送方和接收方按照统一的时序传输...

    嵌入式串口通信研究

     

    一、       通信过程:

    通信方将信息编码 → 传输信息 → 接收方接收信号并解码

    串口使用的图

    二、       串口通信基本概念:

    1)    同步通信和异步通信的区别

    同步(USART):发送方和接收方按照统一的时序传输,适合通信时间不固定

    USART是全双工。

    异步(UART):发送方和接收房按照各自的时序工作,适合通信频率固定

    UART是半双工。

    2)    电平信号和差分信号

    电平信号:有参考电平(GND)

    差分信号:没有参考电平,两根电线的电压差,差分信号传输质量好。

    3)    并行接口和串行接口

    4)    波特率、数据格式

    波特率:双方协商好的每秒传输的二进制位,常用9600、115200

    波特率的设置:


    FCLK:外设输入时钟

    OSRVAL:过采样率,决定了一个采样一个数据需要几个时钟

    BRGVVAL:波特率发生器值,决定外设时钟分频多少后用于串口外设

    数据格式:起始位+数据位+奇偶校验位+停止位

    5)    串口通信的基本框图

    异步通信UART 


    同步通信USART



    三、       协议介绍

    概述:传输过程中,传输双方需要协商好,这个协商出的方案就是协议

    目前使用较多的是UART,下面我们先介绍UART

     

    1.     UART传输时序:

    UART是一种通用串行数据总线,数据传输过程是在数据线上一位一位的传输的。数据格式如下

    2.     USART时钟极性

    时钟极性控制位---CPOL

    决定了总线空闲时,SCK时钟线的电平状态

    CPOL = 0 当数据总线空闲时,SCK时钟线为低电平

    CPOL = 1 当数据总线空闲时,SCK时钟线为高电平

    时钟相位控制位---CPHA

    决定了总线上数据采样位置

    CPHA = 0 总线在时钟线第一个跳变沿采样数据。

    CPHA = 1 总线在时钟线第二个跳变沿采样数据。

    3.     USART传输时序

    USART通过一根时钟线进行同步

    4.     硬件流控

    流控的目的就是可以保证数据发送和接受正好配合(因为如果发送方比接收方速度快,可能会导致数据丢失)。

    目前流控使用很少,因为现在硬件水平很高,接受方速度很快。目前串口更多是用来测试调试信息。

    5.     软件流控

    6.     传输协议

    传输协议在应用所处的位置如下图所示:

    串口通讯中经常使用的几种文件传输协议:

    l  Xmodem

    l  1KXmodem

    l  Ymodem

    l  Zmodem

    l  KERMIT

    串口通讯中经常使用的总线协议:

    Modbus协议

    RS232

    RS484

    这里不详细论述

    四、       芯片中的UART外设

    1.     UART外设

    UART外设串口控制器,串口控制器分为transmitter和receiver两部分,两部分彼此独立,且这两部分都由缓冲区和移位器组成(缓冲区是关键,移位器是硬件控制的)。

    1)    FIFO模式

    典型的串口设计,每次发送/接收只能处理一字节,这样效率低下,CPU要不断切换上下文,于是比较高级的CPU扩展了发送缓冲器(Transmit FIFO Register,FIFO是一种数据结构,队列:先进先出),FIFO模式始终轻量级的解决方案

    2)    DMA模式

    直接内存访问。DMA本身是DSP中的一种技术,DMA技术的核心就是在交换数据时不需要CPU参与,模块自己完成。DMA模式适合大量数据迸发式的发送/接收时。

    3)    IrDA模式及其用法

    IrDA就是红外通信,某些芯片支持红外模式,我盟只需向串口写数据,这些数据就会以红外光的方式向外发射出去,后接收方接收这些红外数据即可解码得到我们的发送信息。

    2.     串口通信与中断的关系

    一般使用中断来接收数据

    五、       配置举例    

        如果使用固件库变成或者原厂提供的工具生成的库例如ST的STM32Cube、NXP的MCUconfigtool等等,你只需知道一些重要的参数及其意义即可,很多都已经写好了,如果为了提高效率使用寄存器直接开发的话,需要对照参考手册(也叫用户手册)去逐一配置了

    1)    使用流程概述

    2)    STM32的使用举例(HAL库)

    串口初始化

    void MX_USART2_UART_Init(void)
    {
    
      huart2.Instance = USART2;
      huart2.Init.BaudRate = 115200;
      huart2.Init.WordLength = UART_WORDLENGTH_8B;
      huart2.Init.StopBits = UART_STOPBITS_1;
      huart2.Init.Parity = UART_PARITY_NONE;
      huart2.Init.Mode = UART_MODE_TX_RX;
      huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
      huart2.Init.OverSampling = UART_OVERSAMPLING_16;
      if (HAL_UART_Init(&huart2) != HAL_OK)
      {
        _Error_Handler(__FILE__, __LINE__);
      }
    
    }
    引脚模式配置
    void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct;
      if(uartHandle->Instance==USART2)
      {
      /* USER CODE BEGIN USART2_MspInit 0 */
    
      /* USER CODE END USART2_MspInit 0 */
        /* USART2 clock enable */
        __HAL_RCC_USART2_CLK_ENABLE();
      
        /**USART2 GPIO Configuration    
        PA2     ------> USART2_TX
        PD6     ------> USART2_RX 
        */
        GPIO_InitStruct.Pin = GPIO_PIN_2;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
        GPIO_InitStruct.Pin = GPIO_PIN_6;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
        HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
      /* USER CODE BEGIN USART2_MspInit 1 */
    
      /* USER CODE END USART2_MspInit 1 */
      }
    }
    void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
    {
    
    
      if(uartHandle->Instance==USART2)
      {
      /* USER CODE BEGIN USART2_MspDeInit 0 */
    
    
      /* USER CODE END USART2_MspDeInit 0 */
        /* Peripheral clock disable */
        __HAL_RCC_USART2_CLK_DISABLE();
      
        /**USART2 GPIO Configuration    
        PA2     ------> USART2_TX
        PD6     ------> USART2_RX 
        */
        HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2);
    
    
        HAL_GPIO_DeInit(GPIOD, GPIO_PIN_6);
    
    
      /* USER CODE BEGIN USART2_MspDeInit 1 */
    
    
      /* USER CODE END USART2_MspDeInit 1 */
      }
    } 

    将debug信息通过串口输出

    /* Includes ------------------------------------------------------------------*/
    #include "usart.h"
    #include <stdio.h>
    #include "gpio.h"
    
    ///* USER CODE BEGIN 0 */
    //  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    ///* USER CODE END 0 */
    
    	#ifdef __GNUC__  
      /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf 
         set to 'Yes') calls __io_putchar() */  
      #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)  
    #else  
      #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)  
    #endif /* __GNUC__ */ 
    	
    	
    UART_HandleTypeDef huart2;
    
    /* USART2 init function */
    
    /* USER CODE BEGIN 1 */
    /**
      * @brief  Retargets the C library printf function to the USART.
      * @param  None
      * @retval None
      */
    PUTCHAR_PROTOTYPE
    {
    
        huart2.Instance->DR = (uint8_t) ch;  
      
      /* Loop until the end of transmission */  
        while(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TC) == RESET){}  
      
      return ch;  
    	
    }

    六、       注意事项

    l  使用USART时需要区分主从模式;

    l  使用硬件流控制时需要根据实际芯片介绍连接RTS与CTS

    l  使用软件流控制时,若传输的是二进制数据,标志字符也有可能在数据流中出现;

    l  引脚配置时注意,所使用的引脚是不是开漏引脚;

    l  普通电线和RS232的布线距离不易过长,如果使用长距离通讯建议选择RS485或RS422;

    l  过采样率设置的越小,抑制噪声能力越差

     

     

    展开全文
  • 嵌入式Linux下串口调试

    千次阅读 2017-04-06 15:42:43
    UART串口嵌入式设备最为常用的调试和通讯接口之一,无论是RS232还是RS422/485都有着非常广泛的应用,因此本文就基于嵌入式Linux演示在User Space进行串口调试。   本文所演示的平台来自于Toradex Colibri iMX6...

    By Toradex秦海

    1). 简介

    UART串口是嵌入式设备最为常用的调试和通讯接口之一,无论是RS232还是RS422/485都有着非常广泛的应用,因此本文就基于嵌入式Linux演示在User Space进行串口调试。

     

    本文所演示的平台来自于Toradex Colibri iMX6DL ARM嵌入式平台,这是一个基于NXP iMX6DL ARM处理器,支持双核Cortex-A9。

     

    2. 准备

    a).Colibri iMX6DL ARM核心版配合Colibri Eva Board载板,连接调试串口UART1到开发主机方便调试,同时配置好Ubuntu开发主机开发环境,具体操作方法可以参考这里

    b).Colibri iMX6DL系统使用Toradex Linux Release V2.6.1,下载和更新方法请参考这里

     

    3). RS232串口通讯测试

    a). Colibri iMX6S核心版默认定义提供了三个串口,如下所示,其中UART1为默认的调试串口,当然可以通过uboot设置关闭调试串口或者指定另外一个串口作为调试串口。


     

    b). Colibri Eva Board X25 Top DB9连接器默认为UART2接口,连接到Ubuntu开发主机进行UART2串口测试。另外,通过载板跳线测试也可以将UART3串口路由到X25 bottom DB9连接器上面,具体说明可以参考这里

     

    c). User Space下直接操作UART2串口设备进行测试

    ---------------------------------

    //设置串口bandrate

    root@colibri-imx6# stty -F /dev/ttymxc1 115200

    //发送数据

    root@colibri-imx6# echo Test > /dev/ttymxc1

    //接收数据

    root@colibri-imx6# cat /dev/ttymxc1

    --------------------------------

     

    d). User Space下通过C程序测试UART2串口

    ./ uart相关基本操作头文件和子程序

    //打开和关闭uart设备

    uart_open

    uart_close

    //配置uart baudrate以及其他参数并生效

    uart_config

    //利用write函数发送数据

    uart_send

    //利用select函数侦测事件发生,然后用read函数读取数据

    uart_read

     

    具体代码请见这里:

    uartconfig.h - https://github.com/simonqin09/uarttest/blob/master/uartconfig.h

    uartconfig.c - https://github.com/simonqin09/uarttest/blob/master/uartconfig.c

     

    ./ main主程序,打开并配置串口baud rate 115200,发送数据然后接收数据来测试串口。

    具体代码如下:

    https://github.com/simonqin09/uarttest/blob/master/uarttest.c

     

    ./执行情况,可见收发都正常

    --------------------------------

    //Colibri iMX6调试串口输出

    root@colibri-imx6:~# ./uarttest /dev/ttymxc1                                   

    send successflly                                                                

    send sucessfully                                                               

    test!

    //PC主机RS-232接口测试端口输出,收到message后,键盘键入”test!”后回车。

    Welcome to minicom 2.7

    ……

     

    this is a test program

    --------------------------------

     

    4). RS485串口通讯测试

    a). Colibri iMX6 UART除了RS232模式,也支持RS422/485模式,这里还是利用UART2来测试RS485半双工模式通讯,基于Colibri Eva Board的硬件连接如下:

    ./ 将Colibri Eva Board连接器X2 bottom DB9 管脚4(RXD+),管脚5(RXD-)以及管脚1(GND)和PC主机485接口设备对接

    ./ 将Colibri Eva Board下面几个跳线做如下设置:

       JP11 短接 – 让485接口可以发送以及接收收据,如果断开,则只能发送数据

       JP12,JP14断开 – 用于插入120ohm终端电阻,针对RS-422模式

       JP13,JP15短接 – 设置为半双工模式,如果断开,则为全双工模式

       JP16短接 – UART2到RS232的功能关闭,切换到RS485功能;断开则反之。

     

    b). 然后需要使能UART2 RS485功能,有两种方式,一种是在device tree中使能,另外一种是利用ioctrl TIOCSRS485在User Space中使能。

    ./ 在device tree中使能

    //参考这里下载Toradex Linux kernel V2.6版本源代码,根据如下patch文件修改arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts文件,并参考这里编译新的dtb文件后部署到Colibri iMX6模块上。

    https://github.com/simonqin09/uarttest/blob/master/485.patch

    然后可以和上面第三章节完全一样的两种方式操作UART2设备进行测试通信,无需任何改动。

     

    ./ 利用ioctrl TIOCSRS485 在C程序中使能并通信

    //在上面uartconfig.h和uartconfig.c文件中添加485使能函数,同时可以配置RTS在发送中和发送后的电平以及时间延迟设置。

    uart_485

    //在uarttest.c中添加下面485使能,其他和上面RS232都一致。

    --------------------------------

    if(uart_485(fd) < 0)

    {

             printf("failed enable RS485 mode\n");

             return -1;

    }

    else

             printf("RS485 mode enabled\n");

    --------------------------------

    完整代码同样可以参考上面第3章节里面的这三个文件链接

     

    //程序部署后执行情况,可见收发都正常

    --------------------------------

    //Colibri iMX6调试串口输出

    root@colibri-imx6:~# ./uarttest /dev/ttymxc1                                   

    RS485 mode enabled                                                             

    send successflly                                                               

    send sucessfully                                                                

    test!

    //PC主机RS485接口测试端口输出,收到message后,键盘键入”test!”后回车。

    Welcome to minicom 2.7

    ……

     

    this is a test program

    --------------------------------

     

    5). 总结

    本文基于NXP iMX6嵌入式平台在嵌入式linux系统下测试了UART相关通信,希望给大家有所帮助。

    展开全文
  • 在现场应用中,可以达到仅修改 Lua 脚本文件就能完成IED 装置与不同的串口通信外围设备之间的数据交互功能,从而实现对装置串口通信规约的现场可配置化
  •  串口(UART)是嵌入式里最基础最常用也最简单的一种通讯(数据传输)方式,可以说是工程师入门通讯领域的启蒙老师,同时串口打印也是嵌入式项目里非常经典的调试与交互方式。  最精简的串口仅使用两根单向信号线:TXD...

      大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是嵌入式里串口(UART)自动波特率识别程序设计与实现

      串口(UART)是嵌入式里最基础最常用也最简单的一种通讯(数据传输)方式,可以说是工程师入门通讯领域的启蒙老师,同时串口打印也是嵌入式项目里非常经典的调试与交互方式。

      最精简的串口仅使用两根单向信号线:TXD、RXD,这两根信号线是独立工作的,因此数据收发既可分开也可同时进行,这就是所谓的全双工。串口没有主从机概念,并且没有专门的时钟信号 SCK,所以串口通信也属于异步传输。

      说到异步传输,这就不得不提波特率(每秒钟传输bit数)的问题了,通信双方必须使用一致的波特率才能完成正确的数据传输。正常情况下,我们都是为两个串口设备事先约定好波特率,比如 MCU 与上位机通信,在 MCU 程序里按 115200 的波特率去初始化 UART 外设,然后上位机串口调试助手也设置 115200 波特率,双方再联合工作。

      有时候,我们也希望能有一种灵活的波特率约定方式,比如建立通信前,在上位机串口调试助手里随意设置一种波特率,然后按这个波特率发送数据,MCU 端能自动识别出这个波特率,并用识别出来的波特率去初始化 UART 外设,然后再进行后续数据传输,这种方式就叫自动波特率识别。痞子衡今天要分享的就是在 MCU 里实现自动波特率识别的程序设计:

    一、串口(UART)自动波特率识别程序设计

    1.1 函数接口定义

      首先是设计自动波特率识别程序头文件:autobaud.h ,这个头文件里直接定义如下 3 个接口函数原型。涵盖必备的初始化流程 init()、deinit(),以及最核心的波特率识别功能 get_rate()。

    //! @brief 初始化波特率识别
    void autobaud_init(void);
    
    //! @brief 检测波特率识别是否已完成,并获取波特率值
    bool autobaud_get_rate(uint32_t *rate);
    
    //! @brief 关闭波特率识别
    void autobaud_deinit(void);

    1.2 识别设计思想

      关于识别,因为上位机数据是从 RXD 引脚过来的,所以在 MCU 里需要先将 RXD 引脚配置成普通数字输入 GPIO(这个引脚需要上拉,默认保持高电平),然后检测这个 GPIO 的电平跳变(一般用下降沿)并计时。

      下图是典型的 UART 单字节传输时序,I/O 空闲状态是高电平,传输时总是由 1bit 低电平起始位开启,然后是从 LSB 到 MSB 的 8bit 数据位,校验位是可选项(我们暂不开启),最后由 1bit 高电平停止位结束,I/O 回归高电平空闲状态。

    • Note 1:检测下降沿跳变,是因为 I/O 空闲为高,起始位的存在保证了每 Byte 传输周期总是从下降沿开始。
    • Note 2:起始位和停止位两个 bit 的存在还兼有波特率容错的功能,通信双方波特率在 3% 的误差内数据传输均可以正常进行。

      虽然我们不需要约定上位机波特率,但是要想实现波特率自动识别,上位机初始传输的数据却必须要事先约定好(可理解为接头暗号),这涉及到 MCU 里检测电平跳变次数与相应计时计算。这个接头暗号是双向的,MCU 端根据接头暗号识别出波特率后,再将同样的接头暗号通过 UART_TXD 发送给上位机以确认(这部分逻辑不在自动波特率识别程序设计范畴里,应放在项目整体设计里)。

      痞子衡设计的接头暗号是 0x5A, 0xA6 两个字节,两字节暗号相比单字节暗号容错性更好一些(以防 I/O 上有干扰,导致误识别),根据指定的暗号和 UART 传输时序图,我们很容易得到如下常量定义:

    enum _autobaud_counts
    {
        //! 0x5A 字节对应的下降沿个数
        kFirstByteRequiredFallingEdges = 4,
        //! 0xA6 字节对应的下降沿个数
        kSecondByteRequiredFallingEdges = 3,
        //! 0x5A 字节(从起始位到停止位)第一个下降沿到最后一个下降沿之间的实际bit数
        kNumberOfBitsForFirstByteMeasured = 8,
        //! 0xA6 字节(从起始位到停止位)第一个下降沿到最后一个下降沿之间的实际bit数
        kNumberOfBitsForSecondByteMeasured = 7,
        //! 两个下降沿之间允许的最大超时(us)
        kMaximumTimeBetweenFallingEdges = 80000,
        //! 对实际检测出的波特率值做对齐处理,以便于更好地配置UART模块
        kAutobaudStepSize = 1200
    };

      上述常量定义里,kMaximumTimeBetweenFallingEdges 指定了两个下降沿之间允许的最大时间间隔,超过这个时间,自动波特率程序将丢掉前面统计的下降沿个数,重头开始识别,这个设计也是为了防止 I/O 上有电平干扰,导致误识别。

      kAutobaudStepSize 常量是为了对检测出的波特率值做对齐处理,公式是 rounded = stepSize * (value/stepSize + 0.5),其中 value 是实际检测出的波特率值,rounded 是对齐后的波特率值,用对齐后的波特率值能更好地配置UART外设(这跟UART模块里波特率发生器SBR设计有关)。

      最后就是 I/O 电平下降沿检测方法设计,这里既可以用软件查询(就是循环读取 I/O 输入电平,比较当前值与上一次值的差异),也可以使用GPIO模块自带的边沿中断功能。推荐使用后者,一方面计时更精确,另外也不用阻塞系统。检测到下降沿发生就调用一次如下 pin_transition_callback() 函数,在这个函数里统计跳变次数以及计时。

    //! @brief 管脚下降沿跳变回调函数
    static void pin_transition_callback(void);

    1.3 主代码实现

      根据上一小节描述的设计思想,我们很容易写出下面的主代码(autobaud_irq.c),代码里痞子衡都做了详细注释。有一点要提的是关于其中系统计时,可参考痞子衡旧文 《嵌入式里通用微秒(microseconds)计时函数框架设计与实现》

    //! @brief 使能GPIO管脚中断
    extern void enable_autobaud_pin_irq(pin_irq_callback_t func);
    //! @brief 关闭GPIO管脚中断
    extern void disable_autobaud_pin_irq(void);
    
    //!< 已检测到的下降沿个数
    static uint32_t s_transitionCount;
    //!< 0x5A 字节检测期间内对应计数值
    static uint64_t s_firstByteTotalTicks;
    //!< 0xA6 字节检测期间内对应计数值
    static uint64_t s_secondByteTotalTicks;
    //!< 上一次下降沿发生时系统计数值
    static uint64_t s_lastToggleTicks;
    //!< 下降沿之间最大超时对应计数值
    static uint64_t s_ticksBetweenFailure;
    
    void autobaud_init(void)
    {
        s_transitionCount = 0;
        s_firstByteTotalTicks = 0;
        s_secondByteTotalTicks = 0;
        s_lastToggleTicks = 0;
        // 计算出下降沿之间最大超时对应计数值
        s_ticksBetweenFailure = microseconds_convert_to_ticks(kMaximumTimeBetweenFallingEdges);
        // 使能GPIO管脚中断,并注册中断处理回调函数
        enable_autobaud_pin_irq(pin_transition_callback);
    }
    
    void autobaud_deinit(void)
    {
        // 关闭GPIO管脚中断
        disable_autobaud_pin_irq();
    }
    
    bool autobaud_get_rate(uint32_t *rate)
    {
        if (s_transitionCount == (kFirstByteRequiredFallingEdges + kSecondByteRequiredFallingEdges))
        {
            // 计算出实际检测到的波特率值
            uint32_t calculatedBaud =
                (microseconds_get_clock() * (kNumberOfBitsForFirstByteMeasured + kNumberOfBitsForSecondByteMeasured)) /
                (uint32_t)(s_firstByteTotalTicks + s_secondByteTotalTicks);
    
            // 对实际检测出的波特率值做对齐处理
            // 公式:rounded = stepSize * (value/stepSize + .5)
            *rate = ((((calculatedBaud * 10) / kAutobaudStepSize) + 5) / 10) * kAutobaudStepSize;
    
            return true;
        }
        else
        {
            return false;
        }
    }
    
    void pin_transition_callback(void)
    {
        // 获取当前系统计数值
        uint64_t ticks = microseconds_get_ticks();
        // 计数这次检测到的下降沿
        s_transitionCount++;
    
        // 如果本次下降沿与上次下降沿之间间隔过长,则从头开始检测
        uint64_t delta = ticks - s_lastToggleTicks;
        if (delta > s_ticksBetweenFailure)
        {
            s_transitionCount = 1;
        }
    
        switch (s_transitionCount)
        {
            case 1:
                // 0x5A 字节检测时间起点
                s_firstByteTotalTicks = ticks;
                break;
    
            case kFirstByteRequiredFallingEdges:
                // 得到 0x5A 字节检测期间内对应计数值
                s_firstByteTotalTicks = ticks - s_firstByteTotalTicks;
                break;
    
            case (kFirstByteRequiredFallingEdges + 1):
                // 0xA6 字节检测时间起点
                s_secondByteTotalTicks = ticks;
                break;
    
            case (kFirstByteRequiredFallingEdges + kSecondByteRequiredFallingEdges):
                // 得到 0xA6 字节检测期间内对应计数值
                s_secondByteTotalTicks = ticks - s_secondByteTotalTicks;
                // 关闭GPIO管脚中断
                disable_autobaud_pin_irq();
                break;
        }
    
        // 记录本次下降沿发生时系统计数值
        s_lastToggleTicks = ticks;
    }

    二、串口(UART)自动波特率识别程序实现

      前面讲的都是硬件无关设计,但最终还是要落实到具体 MCU 平台上的,其中 GPIO 中断部分是跟 MCU 紧相关的。我们以恩智浦 i.MXRT1011 为例来介绍硬件实现。

    2.1 管脚中断方式实现(基于i.MXRT1011)

      恩智浦 MIMXRT1010-EVK 有板载调试器 DAPLink,这个 DAPLink 中也集成了 USB 转串口的功能,对应的 UART 引脚是 IOMUXC_GPIO_09_LPUART1_RXD 和 IOMUXC_GPIO_10_LPUART1_TXD,我们就选用这个管脚 GPIO1[9] 做自动波特率检测,实现代码如下:

    typedef void (*pin_irq_callback_t)(void);
    static pin_irq_callback_t s_pin_irq_func;
    
    //! @brief UART引脚功能切换函数
    void uart_pinmux_config(bool setGpio)
    {
        if (setGpio)
        {
            IOMUXC_SetUartAutoBaudPinMode(IOMUXC_GPIO_09_GPIOMUX_IO09, GPIO1, 9);
        }
        else
        {
            IOMUXC_SetUartPinMode(IOMUXC_GPIO_09_LPUART1_RXD);
            IOMUXC_SetUartPinMode(IOMUXC_GPIO_10_LPUART1_TXD);
        }
    }
    
    //! @brief 使能GPIO管脚中断
    void enable_autobaud_pin_irq(pin_irq_callback_t func)
    {
        s_pin_irq_func = func;
        // 开启GPIO1_9下降沿中断
        GPIO_SetPinInterruptConfig(GPIO1, 9, kGPIO_IntFallingEdge);
        GPIO1->IMR |= (1U << 9);
        NVIC_SetPriority(GPIO1_Combined_0_15_IRQn, 1);
        NVIC_EnableIRQ(GPIO1_Combined_0_15_IRQn);
    }
    
    //! @brief GPIO中断处理函数
    void GPIO1_Combined_0_15_IRQHandler(void)
    {
        uint32_t interrupt_flag = (1U << 9);
        // 仅当GPIO1_9中断发生时
        if ((GPIO_GetPinsInterruptFlags(GPIO1) & interrupt_flag) && s_pin_irq_func)
        {
            //执行一次回调函数
            s_pin_irq_func();
            GPIO_ClearPinsInterruptFlags(GPIO1, interrupt_flag);
        }
    }

    2.2 在MIMXRT1010-EVK上实测

      一切就绪,我们现在来实测一下,主函数流程很简单,测试结果也表明达到了预期效果,每次将 MCU 程序复位运行后,串口调试助手里可任意设置波特率。

    int main(void)
    {
        // 略去系统时钟配置...
        // 初始化定时器
        microseconds_init();
        // 将GPIO1_9先配成输入GPIO
        bool setGpio = true;
        uart_pinmux_config(setGpio);
        // 初始化波特率识别
        autobaud_init();
        // 检测波特率识别是否已完成,并获取波特率值
        uint32_t baudrate;
        while (!autobaud_get_rate(&baudrate));
        // 关闭波特率识别
        autobaud_deinit();
        // 配置UART1引脚
        setGpio = false;
        uart_pinmux_config(setGpio);
        // 初始化UART1外设
        uint32_t uartClkSrcFreq = BOARD_DebugConsoleSrcFreq();
        DbgConsole_Init(1, baudrate, kSerialPort_Uart, uartClkSrcFreq);
    
        PRINTF("Autobaud test success\r\n");
        PRINTF("Detected baudrate is %d\r\n", baudrate);
    
        while (1);
    }

      至此,嵌入式里串口(UART)自动波特率识别程序设计与实现痞子衡便介绍完毕了,掌声在哪里~~~

    欢迎订阅

    文章会同时发布到我的 博客园主页CSDN主页知乎主页微信公众号 平台上。

    微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

    展开全文
  • 今天痞子衡给大家分享的是嵌入式串口(UART)自动波特率识别程序设计与实现。  本篇是 《串口(UART)自动波特率识别程序设计与实现(中断)》 的续集,上一篇我们利用 GPIO 模块自带的下降沿中断功能实现了 RXD 电平跳...
  •   串口全称叫做串行接口,通常也叫做 COM 接口,串行接口指的是数据一个一个的顺序传输,通信线路简单。使用两条线即可实现双向通信,一条用于发送,一条用于接收。UART为异步串行收发器。   数据位:数据位就是...
  • 嵌入式Linux UART

    2020-03-17 20:08:17
    文章目录前言串口连接串口测试C代码微信公众号 前言 这是前篇: 嵌入式Linux i.MX开发板 嵌入式Linux NFS 嵌入式Linux 交叉编译工具链 嵌入式Linux LED GPIO 嵌入式Linux input 本篇介绍下uart的使用, 采用米尔MYS-...
  • 问: 为什么需要串口调试?答: 因为显示器直连Respberry Pi的HDMI的启动信息无法向上滚动, 无法查看完整的启动信息, 非常不方便硬件调试. 如何使用串口连接到目标板 默认 iex 控制台显示在连接到HDMI端口的显示器上. ...
  • 一、UART初始化1. kernel-3.18/drivers/misc/mediatek/uart/uart.cstatic int __init mtk_uart_init(void){int ret = ;tx_history.buffer = kzalloc(UART_HISTORY_DATA_SIZE, GFP_KERNEL);rx_history.buffer = ...
  • 单片机UART串口通信 单片机的串口通信,一般指的就是UART串口通信(TXD,RXD)。本文实现的是单片机和电脑之间的串口通信,需要用到51单片机开发板,电脑,STC-ISP软件,代码已调试成功,切实可用。 文章目录单片机...
  •   在嵌入式的开发中,经常要用到通过串口打印调试信息。有时为了节省成本,而没有多余的串口可用。因此打印调试信息可以采用: 方式1:工程中添加SEGGER_RTT调试打印 方式2:模拟串口 UART工作原理   UART即通用...
  • 一般一个linux开发板的串口0默认作为调试串口使用,也就是linux的shell调试终端,如果要作为普通串口使用需要相应的设置,这里以应用层修改的方法介绍怎么使用 二、使用方法 1、切换调试终端到其他串口 //将shell...
  • 我们使用串口2也就是UART2来做调试口,将USB转串口线的RX,TX,GND连接到板子上UART2的TX,RX,GND。 2 波特率配置 如果CONFIG_BAUDRATE不是115200,修改为115200,因为不是所有芯片都可以支持高波特率的(15000
  • Linux UART接口调试技巧

    万次阅读 2017-03-03 10:27:14
    本文将梳理UART接口调试流程,为调试工作提供参考,解决调试过程中可能遇到的问题,快速完成UART接口调试,实现模块功能。配置驱动选项首先查看原理图确认串口号,比如UART1,同时查看该串口引脚是否有复用功能,...
  • uart这里的调试要注意的是管脚的功能配置,需要更改设备树文件; 更改设备树文件:https://blog.csdn.net/cao849861802/article/details/111604277 其他问题:这里是操作的232的配置,如果想做485的最好用硬件来...
  • 嵌入式开发输出调试信息的几种方法 嵌入式开发输出调试信息的几种方法 1、输出log信息到SRAM 2、通过SWO输出log 2.1 通过IDE输出 2.2 通过STM32 ST-LINK Utility输出 3、通过串口输出log 4、使用IO模拟串口...
  • UART串口嵌入式设备最为常用的调试和通讯接口之一,无论是RS232还是RS422/485都有着非常广泛的应用,因此本文就基于嵌入式Linux演示在Linux环境下使用minicom进行串口调试 准备 可以正常运行Bootloader的开发板 ...
  • UART串口

    千次阅读 2011-07-11 17:13:18
    通用异步接收器和发送器(Universal Asynchronous Receiver and Transmitter) 简称UART。...这是因为,很多嵌入式设备没有显示屏,无法获得嵌入式设备实时数据信息,通过UART串口和超级终端相连,打
  • 一、设备树下开启串口 路径:kernel\arch\arm\boot\dts下的对应dts文件 ...二、查看嵌入式设备是否成功挂载串口 /dev/ 路径下有:ttyS* 三、交叉编译 测试程序 uart_comm.c 执行 arm-linux-gnueabihf-gcc uart_comm.c
  • 关注+星标公众号,不错过精彩内容作者 | strongerHuang微信公众号|嵌入式专栏基于MCU的嵌入式软件开发,可能在某些情况下没有多余存储空间,从而没有在本地有效保存调试和日志...
  • UART串口通信软件推荐

    千次阅读 2021-02-09 13:41:49
    在我们调试单片机的时候,经常用到UART串口通信(没有足够的资金购入LCD屏、OLED屏等显示器件)。市面上这么多的串口调试软件实在是让人无从下手,下面安利3款串口调试软件,提供大家参考选择吧。 number one:VOFA+...
  • 嵌入式系统编程和调试技巧

    千次阅读 2014-09-17 21:47:54
    本文描述了嵌入式系统开发中编程调试的一些技巧,如何预防BUG出现,如何设置BUG陷阱,及时发现问题和定位问题,提高开发效率。
  • 区分:串口,COM口,UART,USART https://blog.csdn.net/qq_26904271/article/details/79829363 JTAG,串口和USB这三者的区别 http://bbs.eeworld.com.cn/thread-453119-1-1.html 1.串口 COM UART JTAG (它们是...
  • 参考资料:       蓝桥杯嵌入式备赛手册       蓝桥杯嵌入式开发经验分享(5.串口的配置) 总目录:目录 文章目录
  • 简介UART串口嵌入式设备最为常用的调试和通讯接口之一,无论是RS232还是RS422/485都有着非常广泛的应用,因此本文就基于嵌入式Linux演示在Linux环境下使用minicom进行串口调试准备可以正常运行Bootloader的开发板...
  • 代码比较简单,不需要硬件调试,直接就一次成功了。可是,有的时候你的代码工程比较大,难免存在 一些 bug,这时,就有必要通过在线调试来解决... 潘多拉开发板上已经ST LINK V2.1,并且没有预留 其他仿真器接口,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,073
精华内容 2,429
关键字:

嵌入式uart串口调试