0

0

0

修罗

站点介绍

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

UART(二)使用说明

修罗 2025-08-02 273 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)


最新评论

  • https://www.studyglobus.com/author/carroll34a5552/

    Ценники на вывоз мусора сейчас космос, любые лайфхаки по экономии в тему.

  • Richardgrold

    1xbet onlayn kazino platforması ilə vaxtınızı daha səmərəli və maraqlı keçirin. Saytın canlı kazino bölməsi istifadəçilərə fərqli bir dünya təklif edir. Burada canlı dilerli kazino oyunlarının hər bir növünü sınaqdan keçirə bilərsiniz. Krupyelərin peşəkarlığı oyunun dinamikasını və marağını artırır. Müntəzəm olaraq yenilənən oyun siyahısı cansıxıcılığa yol vermir. Hesabınızı artırmaq üçün onlarla fərqli və etibarlı üsul mövcuddur. Qazanılan pullar cəmi bir neçə dəqiqə ərzində şəxsi hesabınıza köçürülür. Aktiv fəaliyyətinizə görə fərdi bonuslar və hədiyyələr qazana bilərsiniz. Dəstək xidməti həm çat, həm də e-poçt vasitəsilə kömək göstərir. 1xbet ailəsinə qoşulun və böyük uduşlar üçün ilk addımı atın. onlayn kazino

  • 砂岩白丘

    我一直梦想, 看到你们相册那样的地方。真棒。

  • 城市地標

    我喜欢, 这里分享真实经验。你的项目 就是 属于这里的。请继续。

  • 宗教地標

    我热爱这样的想法, 去那么多国家。真的很鼓舞。

  • 觀景高地

    能感受到热爱。继续保持 感受。

  • 最佳季節

    我关注这样的资源, 写得很实在。你的网站 就是 属于这里的。加油。

  • 1

    1

  • 1

    1

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

    1

日历

2026年07月

   1234
567891011
12131415161718
19202122232425
262728293031 

文章目录

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