串口相关知识点

串口通信

串口接线方式

RXD:数据输入引脚,数据接受,STC89系列对应P3.0口
TXD:数据发送引脚,数据发送,STC89系列对应P3.1口
两块芯片的RX TX要交叉接线

串口编程要素

输入/输出数据缓冲
器都叫做SBUF,都用99H地址码,但是是两个独立的8位寄存器
接受数据时char data = SBUF; 发送数据时SBUF = data;
UART是异步串行接口,通信双方使用的时钟不同,因为双方硬件配置不同,因此需要约定好通信速度,即波特率。

利用串口进行编程初体验

写一个函数,要求实现每隔一秒向串口SBUF写入一个数据a
在这里插入图片描述
首先利用软件生成波特率初始化代码,再生成软件延时1s的代码,向SBUF发送数据即SBUF = data;代码如下:

#include "reg52.h"
#include <intrins.h>

sfr AUXR = 0x8E;

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void UartInit(void)		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	AUXR &= 0xBF;		//定时器1时钟为Fosc/12,即12T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xFD;		//设定定时初值
	TH1 = 0xFD;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}


void main()
{
	char data_msg = 'a';
	
	//配置C51串口的通信方式
	UartInit();
	while(1){
		Delay1000ms();
		//往发送缓冲区写入数据,就完成数据的发送
		SBUF = data_msg;
	}
}
 


即可实现要求.
接下去对串口的初始化的代码进行解读。
在这里插入图片描述

SBUF 串行口数据缓冲寄存器

实际是2个缓冲器,写SBUF:SBUF = data;读SBUF:data = SBUF;两个操作分别对应两个不同的寄存器,1个是只写寄存器,1个是只读寄存器。

PCON 电源控制寄存器

在这里插入图片描述
当SMOD=0,串口方式1,2,3时波特率正常
当SMOD=1,串口方式1,2,3时波特率加倍
上述代码初始化中PCON &= 0x7F; //波特率不倍速
将7F展开为二进制0111 1111,PCON与上7F即第一位清零其他位不变,即SMOD置0,波特率不加倍
不配置时默认值为00x1 0000 满足我们的要求SMOD=0;因此无需配置

SCON 串行控制寄存器

在这里插入图片描述
我们使用方式1,SM0=0,SM1=1因此SCON配置为0x40;

SMO和SM1

通过配置SM0和SM1口来调整工作方式
在这里插入图片描述
方式1和3都涉及定时器的溢出率因此波特率可变,方式0和2波特率不可变

SM2

涉及多机通信控制位

REN

允许/禁止串行接收控制位,由软件置位REN,当REN=1允许串行接收状态,可启动串行接收器RxD,开始接收信息。软件复位REN即REN=0时,禁止接收

代码中SCON = 0x50; //8位数据,可变波特率
展开为2进制为0101 0000对应上表,SM0=0 SM1=1表示为工作方式1(8位UART,波特率可变)REN=1允许串口接收状态

TI,RI

TI是发送中断标志位,RI是接收中断标志位

配置定时器 TMOD

另外代码中也对定时器进行了初始化 TMOD &= 0x0F;与0F相与,清空前4位保留后4位;
TMOD |= 0x20;与20(0010 0000)相或,配置定时器1的M1 M2为10,8位自动重装载定时器
在这里插入图片描述
可以观察到RX CONTROL和TX CONTROL是由定时器1控制的,因此需要配置定时器1
之后我们针对9600波特率计算出TH1的值
在这里插入图片描述
在这里插入图片描述

SMOD定义为0,因此得出公式
在这里插入图片描述
之后计算出TH1=253转换为二进制为0xFD,因为采取8位自动重载定时器,TL1=TH1=0xFD
最终设置TR1=1打开中断即可完成配置。

此时就可以通过串口传送字符,可以封装一个sendByte函数

void sendByte(char data_msg){
	SBUF = data_msg;
}

如果想传送字符串,可以再写一个sendString函数结合指针的操作进行传输

void sendString(char* str){
	while(*str != '\0'){
		sendByte(*str);//传送指针指向的数据
		str++;//将指针后移
	}
}

如果就这样传送字符串会发生重复传送的错误,这是因为移位操作的运行也是需要时间的,因此我们可以在sendByte函数中,通过TI发送中断的方法进行延时,代码如下:

void sendByte(char data_msg){
	SBUF = data_msg;
	//当第8位数据发送完毕后,硬件会将TI置1,需要手动复位
	while(!TI);//当TI==0时卡在循环中,说明8位数据还没有传送完毕
	TI=0;//软件复位
}

相关推荐

  1. Mybatis相关知识

    2024-05-03 05:54:04       56 阅读
  2. 单片机相关知识

    2024-05-03 05:54:04       64 阅读
  3. mysql相关知识

    2024-05-03 05:54:04       25 阅读
  4. jvm的相关知识

    2024-05-03 05:54:04       70 阅读
  5. HTML 相关知识记录

    2024-05-03 05:54:04       60 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-03 05:54:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-03 05:54:04       100 阅读
  3. 在Django里面运行非项目文件

    2024-05-03 05:54:04       82 阅读
  4. Python语言-面向对象

    2024-05-03 05:54:04       91 阅读

热门阅读

  1. Android 当存在双卡时,移动网络默认为SIM卡1

    2024-05-03 05:54:04       38 阅读
  2. 用智慧树理解spring原理

    2024-05-03 05:54:04       30 阅读
  3. 深入浅出:ChatGPT的训练与优化之道

    2024-05-03 05:54:04       31 阅读
  4. 大数据组件之Storm简介

    2024-05-03 05:54:04       37 阅读
  5. python关键字(pass)

    2024-05-03 05:54:04       25 阅读
  6. 010_redhat安装zookeeper

    2024-05-03 05:54:04       31 阅读
  7. Go图片列表

    2024-05-03 05:54:04       32 阅读
  8. Spring 之 MatchingStrategy

    2024-05-03 05:54:04       37 阅读