你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

单片机串口

[复制链接]
gaosmile 发布时间:2020-7-1 13:04

[导读] 单片机开发串口是应用最为广泛的通信接口,也是最为简单的通信接口之一,但是其中的一些要点你是否明了呢?来看看本人对串口的一些总结,当然这个总结并不能面面俱到,只是将个人认为具有共性以及相对比较重要的点做了些梳理。

啥是串口?

首先这玩意儿分两种:

  • 通用异步收发器(UART)是用于异步串行通信的一种物理层标准,其中数据格式和传输速度是可配置的。
  • 通用同步收发器(USART)是一种串行接口设备,可以对其进行编程以进行异步同步通信。
数据格式
微信图片_20200701130335.png

线上空闲、无数据状态为常高电平,故逻辑低定义为起始位。

  • 起始位:总是 1 位

  • 数据位:常见的有 8 位或 9 位。

  • 校验位


    • 奇校验
    • 偶校验
    • 无校验
  • 停止位:


    • 1 位
    • 2 位
  • 波特率:bit rate 就是位/秒的概念,就是 1 秒传送多少位的概念。常见的波特率有哪些呢?

    微信图片_20200701130339.png

这里须注意的要点:

  • 一个有效字节的传输时间怎么算?

    比如 9600 下,1 位起始位,8 位数据位,奇校验,1 位停止位,则

    为什么要理解清楚这个概念呢,因为在应用中需要计算数据吞吐率问题,就比如一个应用是数据采集串口传输问题,需要计算采集的位速率需要小于或等于传输波特率,否则数据就来不及传。当然如果说你有足够大的缓冲区可以临时存储,但是如果进来太快,而传出速度跟不上,多大的缓冲都会满!

  • 校验位有用吗?当你的传输介质处于一个有干扰的场景下,校验位就可以从物理层检测出错误。

  • 理解数据编码方式有啥意义呢?比如在调试中你可以利用逻辑分析直接去解析收发线上的数据报文。

  • 应用电路设计的时候 RX-TX 相连,很多初学者容易在这里踩坑!

  • 常见的传输位序为低有效位在前。

  • 对于波特率而言需要注意波特率发生器有可能带来误码问题


啥是 UART?
微信图片_20200701130316.jpg

两边分别代表两个通信的设备,单从 UART 编程的角度讲收发不需要物理同步握手,想发就发。图中箭头代表数据信息流向。RX 表示接收数据,TX 表示发送数据。数据总是从发送端传递到接收端,这就是为啥 RX 连接 TX,TX 连 RX 的原因。

啥是 USART?
微信图片_20200701130319.jpg

同步简单说,收发不可自如,不可以想发就发,收发需要利用硬件 IO 口进行握手,RTS/CTS 就是用于同步的握手信号:

  • RTS:Ready to send,请求发送,用于在当前传输结束时阻止数据发送。
  • CTS:clear to send,清除发送,用于指示 USART 已准备好接收数据。

这个对于普通应用而言并不常见,这里不做详细展开,需要用到的时候只需要对应收发时控制握手信号即可。

编程策略

对于不同的单片机,其硬件体系各异,寄存器也差异很大,但是从收发编程策略角度而言,常见有下面三种方式:

  • 查询发送/中断接收模式
  • 收发中断模式
  • DMA 模式
查询发送/中断接收模式

这里以伪代码方式描述一下:

/*查询发送字节*/
void uart_send_byte( uint8 ch )
{
    /*如果当前串口状态寄存器非空闲,则一直等待*/
    /*注意while循环后的分号,表示循环体为空操作*/
    while( !UART_IS_IDLE() );

    /*此时将发送字节写入发送寄存器*/
    UART_TX_REG = ch;
}

/*发送一个缓冲区*/
void uart_send_buffer( uint8 *pBuf,uint8 size )
{
    uint8 i = 0;
    /* 异常参数处理*/
    if( pBuf == NULL )
        return;

    for( i=0; i<size;i++ )
    {
        send_byte( pBuf );
    }
}

对于接收而言,如采用查询模式则几乎是没有任何应用价值,因为外部数据不知道什么时候会到来,所以查询接受就不描述了,这里描述一下中断接收。

static uint8 rx_index = 0;
void uart_rx_isr( void )
{
    /* 接收报文处理 */
    rx_buffer[rx_index++] = UART_RX_REG;
}

中断接收需要考虑的几个要点:

  • 断帧:这就取决于协议怎么制定了,比如应用协议定义的是 ASCII 码方式,就可以定义同步头、同步尾,比如 AT 指令的解析,做逻辑判断帧头、帧尾即可。但是如果传输的是 16 进制数据,比如 MODBUS-RTU 其断帧采用的是 3.5 个字节时间没有新的字节接收到,则认为收到完整的帧了。
  • 如何保证帧的完整性,一般会在报文尾部加校验,比较常用的校验模式有 CRC 校验算法。
  • 不同的单片机开发环境对于中断向量的处理方式略有不同,需要根据各自芯片的特点进行处理。比如 51 单片机,其发送/接收都共享一个中断向量号。
收发中断模式#define FRAME_SIZE  (128u)
static uint8 tx_buffer[FRAME_SIZE];
static uint8 tx_index  = 0;
static uint8 tx_length = 0;

static uint8 rx_buffer[FRAME_SIZE];
static uint8 rx_index = 0;
static bool  rx_frame_done = false;
void prepare_frame( uint8 * pBuf, uint8 size )
{
     /*将待传的报文按照协议封装*/
     /*可能需要处理的事情,比如帧头、帧尾、校验等*/
}

bool uart_start_sending( uint8 * pBuf, uint8 size )
{
    if( pBuf == NULL )
        return false;

     memcpy( tx_buffer,pBuf,size );
     tx_index  = 0;
     tx_length = size;

     /*使能发送中断,向发送寄存器写入一个字节,进入连续发送模式*/
     ENABLE_TX_INT = 1;
     UART_TX_REG   = tx_buffer[tx_index++];
}

void uart_tx_isr( void )
{
    if( tx_index<tx_length )
    {
        UART_TX_REG   = tx_buffer[tx_index++];
    }
    else
    {
        /*发送完毕,关闭发送中断*/
        DISABLE_TX_INT = 1;
    }
}

void uart_rx_isr( void )
{
    /*处理接收,待接收到完整的帧就设置帧完成标记*/
    /*由于应用各有不同,这里就无法描述实现了*/
}

还需要考虑的是,对于 UART 硬件层面的出错处置,以 STM32 为例,就可能有下面的错误可能发生:

  • 溢出错误
  • 噪声检测
  • 帧错误
  • 奇偶校验错误

另外不同的单片机其底层硬件实现差异也不较大,比如有的硬件发送缓冲是单字节的缓冲,有的则具有 FIFO,这些在选型编程时都需要综合考虑。

DMA 模式

DMA 发送模式而言,大致分这样几步:

  • 初始化 UART 为 DMA 发送模式,开启 DMA 结束中断,并写好 DMA 传输结束中断处理函数
  • 准备待发送报文,帧头、帧尾、校验处理
  • 将待发送报文缓冲区首地址赋值给 DMA 源地址,DMA 目标地址设置为 UART 发送寄存器,设置好发送长度。
  • 启动 DMA 传输,剩下传输完成就会进入传输结束中断处理函数。

DMA 接收模式而言,大致分这样几步:

  • 初始化 UART 为 DMA 接收模式,开启 DMA 结束中断,并写好 DMA 传输结束中断处理函数
  • 中断处理函数中标记接收到帧,对于使用 RTOS 而言,还可以使用的机制是利用 RTOS 的事件机制、消息机制进行通知有新的帧接收到了。
  • 对于 DMA 接收模式而言,对于变长帧的处理较为不利,所以如果想使用 DMA 接收,制定协议时尽量考虑将帧长度固定,这样处理会方便些。
总结一下

单片机串口是一个需要好好掌握的内容,这里总结了一些个人经验,尽量将一些个人共性的东西总结出来。至于实际实现而言,由于芯片体系差异较多,具体代码各异。但个人认为处置的思路方法却是基本一致。所以本文除了描述串口本身的细节而言,想表达的一个额外的观点是:

  • 对于一些技术点尽量学会将其共性的东西剥离总结出来。
  • 总结、概括、剥离抽象是一个比较好的学习思路,不用对具体的硬件死记,万变不离其宗。
  • 如果本文有喜欢的朋友,后面陆续可以总结一下I2C/SPI等常用接口。

收藏 评论0 发布时间:2020-7-1 13:04

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版