0

0

0

修罗

站点介绍

只有了解事实才能获得真正的自由

UART(二)使用说明

修罗 2025-08-02 48 0条评论 51单片机

首页 / 正文

UART(二)使用说明

STC89C52系列单片机内部集成了一个功能强大的全双工串行通信口,以下是相关引脚。

image-20250802094712554.png

该通信口具有四种工作模式,如下。

image-20250802094722702.png

  • 其中模式0为同步通讯,该模式下,TxD引脚会作为时钟信号线,RxD作为数据信号线,该模式下只能实现半双工通讯。
  • 模式1、2、3为经典的UART通讯,三者的区别在与是否有校验位,以及波特率是否可变。

    模式1的一个数据帧包含1个起始位,8个数据位和1个停止位。

    模式2和模式3的一个数据帧包含1个起始位,8个数据位,1个校验位和1个停止位。

    另外模式1和模式3的波特率可由定时器1进行配置,因而可以自由设置,而方式2的波特率直接由系统时钟决定,因而不可自由配置。

1.1 设置工作模式

​ 工作模式需要通过SCON(Serial Control,串行口控制)寄存器中的M0SM1两个控制位进行设置,如下图所示。

image-20250802095148878.png

​ 如果使用方式1,则应将SM0置为0,SM1置为1。

1.2 设置波特率

1.2.1 设置原理

方式1为例:

方式1的波特率会受到两个因素的影响,分别是SMOD控制位和定时器1的溢出频率,具体作用如下图所示。

  1. 以中间水平线大致分割,上面为发送模块,下面为接收模块:

image-20250802095407738.png

  1. 时钟脉冲决定了发送一帧数据的频率:

image-20250802095736529.png

  1. 最初时钟来源为定时器1溢出频率,每溢出一次向外输出一次时钟信号,经过SMOD根据配置是否分频,再往后分频16次即为波特率:

image-20250802095805080.png

  1. 溢出频率由定时器初始值决定,SMOD由配置决定

image-20250802095834522.png

​ 根据结构图可以得出公式,模式一的波特率为:

image-20250802095933893.png

1.2.2 设置步骤

​ UART常用的波特率有4800、9600、19200、38400、57600、115200等,此处以9600为例。

1.2.2.1 设置SMOD控制位

SMOD控制位位于PCON(Power Control,电源控制)寄存器,如下图所示。

image-20250802140910059.png

此处选择0,所以此时的波特率应为(定时器1的溢出率)/ 32

1.2.2.2 设置定时器1

​ 由于定时器1当前的作用仅仅是为串口提供时钟信号,因此可不开启定时器中断,只需完成以下配置即可。

(1)选择定时器工作模式

​ 定时器1的工作模式需要通过TMOD寄存器中的C/T控制位,以及M1M0两个控制位进行设置,如下图所示。

image-20250802141048935.png

C/T用于设置计数/定时的工作方式,此处应选择定时模式,因此需将C/T设置为0。

M1M0,用于配置具体的工作模式,相关配置如下。

image-20250802141139926.png

由于没有启用定时器中断,因此无法在中断中重新设置定时器脉冲计数器的初始值,所以此处选择模式2(8位自动重装载)最为合理。

(2)设置脉冲计数器初始值

  • 模式2的最大计数为2⁸=256,因此定时器1的溢出频率等于SYSclk / 12 /(256 - TH1)或者是SYSclk / 6 /(256 - TH1),假如当前MCU工作在12T模式,所以溢出频率就等于SYSclk / 12 /(256 - TH1)
  • SYSclk为系统时钟频率,工作模式为12t,则时钟频率分频12,即系统时钟频率除以12定时器计数+1
  • 寄存器为8位,可以存256个数,当TH1为255时,此时寄存器再来一次脉冲就溢出了;
  • 每秒定时器溢出几次 = 定时器每秒加了多少次(SYSclk / 12),再除以它每次溢出需要多少次(256 - TH1)

image-20250802142822114.png

​ 因此最终的波特率就应该等于SYSclk / 12 /(256-TH1)/32,假如当前的系统时钟频率为11059200Hz,目标的波特率为9600,那么就能得到以下方程

image-20250802142846653.png

​ 所以可计算出TH1的值应为253

(3)启动定时器

​ 定时器1的启动也无需外部引脚控制,因此应将GATE控制位设置为0,并将TR1控制位设置为1。

1.3 发送数据

STC89C52的串口的发送模块示意图如下。

image-20250802143049989.png

​ 数据发送的大致流程如下:

​ 开发者将待发送的8位数据写入发送缓冲器(SBUF),此时发送控制器(Tx Control)就会开始工作,它会自动为数据添加起始位和结束位,从而构成一个完整的UART数据帧,然后逐位通过TxD引脚输出出去。当完成一个数据帧的输出之后,发送控制器会将发送中断控制位TI置1,向CPU请求中断,CPU检测到中断请求后就执行相应的中断服务程序。

总结:发送数据只需要将待发送的数据写入SBUF即可。

1.4 接收数据

STC89C52的串口的接收模块示意图如下。

image-20250802143327462.png

​ 默认情况下,串口并不会接收数据。如需接收数据,需要先将REN(Receive Enable)控制位置为1,REN控制位位于SCON寄存器,如下图所示。

image-20250802143403228.png

​ 当REN置为1后,上图中的1到0跳变检测器(1-To-0 Transition Detector)就会开始工作,具体来讲就是不断检测RxD引脚的起始位。当检测到1到0的跳变后,就会启动接收控制器(Rx Control),接收控制器会将接收到数据逐位移入到输入移位寄存器(Input Shift REG),直到接收到停止位,就算完成了一帧数据的接收。

​ 正常情况下,接下来,接收控制器会将输入移位寄存器(Input Shift REG)中的数据加载到读取缓冲器(SBUF)中,并将读取中断控制位RI置1,向CPU请求中断,CPU检测到中断请求后就执行相应的中断服务程序,开发者就能在中断服务程序中读取SBUF获取当前帧的数据了。

​ 但是上述操作(加载数据到SBUFRI置位)的执行是有条件的,满足条件才会执行,不满足,那么当前数据帧就会被丢弃,具体条件如下:

1)结束位正常

​ 开发者可以配置是否检测停止位的有效性(高电平有效)。是否检测是由SCON寄存器中的SM2控制位来决定的。SM2=1时,接收控制器就会检测控制停止位,当SM2=0时,则不会检测停止位,建议将SM2设置为0

image-20250802143638497.png

1)读取中断标志位为复位状态

​ 读取中断标志位RI必须等于0,也就说要保证上一帧数据已经被读取或处理完毕,才能处理当前帧。

总结:接收数据需要先使能接收,也就是将REN控制位置1,然后开启串口中断,并在中断服务程序中读取SBUF

1.5 串口中断注意事项

​ 根据前文的描述,当使用串口发送完一帧数据后,会将发送中断标志位TI置1;当串口接收到一帧数据后,会将接收中断标志位RI置1。需要注意的是两个控制位请求的是同一个中断——串口中断(中断号为4)。

image-20250802143816453.png

​ 也就是说发送完一帧数据和接收完一帧数据之后,执行的都是串口中断的中断服务程序,因此,再编写该中段服务程序时,需要注意判断当前中断到底是由发送操作触发的,还是由接收操作触发的,代码示例如下。

/*
 * 串口中断的中断号为4
 */
void Dri_UART_Handler() interrupt 4
{
    /* 检查接收中断标志位RI,如果为1,表示有一帧数据接收完成 */
    if (RI == 1) {
    }

    /* 检查发送中断标志位TI,如果为1,表示有一帧数据发送完成 */
    if (TI == 1) {
    }
}

​ 另外RI和TI标志位,只能由软件复位,也就是需要在中断服务程序中将其设置为0,如下。

/*
 * 串口中断的中断号为4
 */
void Dri_UART_Hander() interrupt 4
{
    /* 检查接收中断标志位RI,如果为1,表示有一帧数据接收完成 */
if (RI == 1) {
        RI = 0;
    }

    /* 检查发送中断标志位TI,如果为1,表示有一帧数据发送完成 */
    if (TI == 1) {
        TI = 0;
    }
} 

评论(0)


最新评论

  • 1

    1

  • 1

    1

  • -1' OR 2+158-158-1=0+0+0+1 or 'TKCTZnRa'='

    1

  • 1

    1

  • 1

    1

  • 1

    1

  • 1

    1

  • @@5Qa2D

    1

  • 1

    1

  • 1

    1

日历

2025年09月

 123456
78910111213
14151617181920
21222324252627
282930    

文章目录

推荐关键字: Linux webpack js 算法 MongoDB laravel JAVA jquery javase redis