C51 单片机开发串口初始化实现

共 3126字,需浏览 7分钟

 ·

2024-07-05 07:30






公众号文章同步阅读网址:www.netor0x86.com


闲话:多快好省如果存在的话,就没有时间换空间,空间换时间一说了吧?鱼和熊掌就兼得了。


本篇文章回顾一下串口初始化的文档,然后再用代码实现一下。实现代码后会惊奇的发现,这么多文档性的东西,然后对应这么少的代码。





上篇文章整理了关于串口配置的寄存器,都是手册上比较概念的内容,本篇通过手册自己来写一下串口寄存器的配置。


0x01:回顾串口配置所需寄存器


通过上篇文章了解到,串口寄存器的使用包含 PCON、SCON 和 定时器相关的寄存器,一共三个部分。


简单的再次回顾一下,PCON 是电源控制寄存器,SCON 是串行控制寄存器。


PCON 的第七位控制串口的波特率是否加倍。PCON 的第六位决定了 SCON 的第七位和第六位的作用。


SCON 用来设定串口的工作方式。


0x02:PCON 寄存器配置


PCON 寄存器实际上可以不用进行配置。在文档 P232 中可以看到 PCON 寄存器的复位值,如下图:



从图中可以看出,它的复位值 00x1 0000。


最高位是 0,表示波特率不加倍;第六位也是 0,表示 SCON 的最高两位用来配置工作方式。因此,我们为了省事可以不对 PCON 进行配置。


0x03:SCON 寄存器配置




SCON 寄存器用来配置工作方式。


在上篇文章中已经知道 SCON 有四种工作方式,这里选择工作方式1。四种工作方式的区别,我认为首先它们的长度不一样,其次是帧格式不同。具体可以找相关的设计原理来看。


这里我们选择工作方式1,如下图,文档 P233。



工作方式1给出了 SM0 和 SM1 的值,并给出了波特率。


其中工作方式0和工作方式2和晶振不挂钩,方式1和方式3波特率可变。所以我们选择工作方式1,需要配置定时器。在上图中有一个溢出率,它和晶振有关,和定时器 TH1 的初值有关系。如下图,文档 P244





在 SCON 中有一个 TI 位,它是中断相关的,TI 是发送中断,配置为 0 即可。


根据上面的描述,SCON 每位的配置为 0100 0000 = 40H 即可。






0x04:定时器的配置


波特率由内部定时器/计数器产生,运行的速度靠晶振,晶振跟时钟周期和机器周期相关。如下图,文档 P232。



在 C51 单片机中由定时器0和定时器1,在前面也提到了,具体和定时器1相关。那么我们需要回顾一下定时器1的相关寄存器。如下图,文档 P187。





上图是 TMOD 寄存器,我们使用定时器1,那么就是使用 TMOD 的高4位。我们需要设置 M1 和 M0,这两位表示定时器1的模式。这里,我们选择8位自动重装载定时器,即 M1 为 1,M0 为 0。


那么它们的配置方式如下:


TMOD &= 0x0F;
TMOD |= 0x20;

上面的方式是在不影响定时器0的情况下去设置定时器1。





0x05:配置波特率


在 SCON 中选择了工作方式1,而工作方式1中给出了波特率的计算的公式。公式如下图,文档 P233。






通过这个公式,我们需要计算 TL1 和 TH1 的初值(是否还记得定时器就是数数,数的过程让它溢出,通过溢出次数来计算时间的流逝,从而完成过定时)。


把上面的公式展开来计算一下,计算的过程如下:


2 ^ 0 / 32 * 定时器1的溢出率
定时器1的溢出率 = SYSclk/12/(256-TH1) = 11059200 / 12 / (256 - t)
(2 ^ 0 / 32) * (11059200 / 12 / (256 -t) ) = 9600
(1 / 32) * (1105900 / 12 / (256 -t) ) = 9600
11059200 / 32 / 12 = 28800
28800 / (256 -t) = 9600
28800 / 9600 = 3
256 -3 = 253 = 0xFD





最后得出,TH1 和 TL1 的初值为 0xFD。


0x06:初始化串口代码


根据上面的详细整理,最后得出如下代码:


sfr AUXR = 0x8e;    /* 声明AUXR寄存器的地址 */

void UartInit(void)
{
    AUXR = 0x01;
    
    // 配置串口工作方式1,REN不使能接收
    SCON = 0x40;
    
    TMOD &= 0x0F;
    TMOD |= 0x20;   // 定时器1工作方式为8位自动重载
    
    TH1 = 0xFD;
    TL1 = 0xFD;
    TR1 = 1// 启动定时器
    
}

我们可以用这段代码替换前面文章中的初始化串口的代码来进行测试。






我是一个程序员,了解 C、PHP、Java、ASM、Python,有 信安、CISP 证书,写小白也能看得懂的文章,感谢关注!!!


我的网站:https://www.netor0x86.com


我录制的视频课程:



1. 入门级栈溢出分析


2. WEB端获取MAC地址真实项目案例


3. PHP扩展模块开发之DLL编写与调用


4. C语言零基础入门教程


5. PE 文件结构初识与二进制手写可执行程序






浏览 48
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报