首页 > 其他分享 >11-串口通信的基本原理与应用

11-串口通信的基本原理与应用

时间:2023-10-08 23:25:30浏览次数:43  
标签:11 定时器 基本原理 串口 SBUF 寄存器 波特率 接收

串行通信概述

  • 微控制器与外部设备的数据通信,根据连线结构和传送方式的不同,可以分为两种:并行通信和串行通信。

​ 并行通信:指数据的各位同时发生或接收,每个数据位使用一条导线。

​ 串行通信:指数据一位接一位地顺序发送或接收

  • 串行通信有SPI、IIC、UART等多种,最常见最通用的就是指UART,大多数情况下,串口通信指的就是UART

  • 串口通信的制式有:单工、半双工、全双工三种。

​ RS385总线式半双工的通信制式

串口通信的主要方式有两种:同步异步

同步串口通信:需要使用同一个时钟,以数据块为单元传送数据。

异步串口通信:每个设备都有自己的时钟信号,通信中双方的波特率要保持一致,以字符为单元进行数据帧传送,依次传送一个帧。

关于波特率计算

  • 波特率:串口每秒钟传输的位数
  • 在波特率的介绍之前需要先提到一个寄存器

SCON : 串行控制寄存器 (可位寻址)

SFR name Address bit B7 B6 B5 B4 B3 B2 B1 B0
SCON 98H name SM0/FE SM1 SM2 REN TB8 RB8 TI RI

SM0/FE:当PCON寄存器中的SMOD0/PCON.6位为1时,该位用于帧错误检测。当检测到一个无效停止位时,通过UART接收器设置该位。它必须由软件清零.当PCON寄存器中的SMOD0/PCON.6位为0时,该位和SM1一起指定串行通信的工作

方式,如下表所示。

其中SM0、SM1按下列组合确定串行口1的工作方式:

SM0 SM1 工作方式 功能说明 波特率
0 0 方式0 同步移位串行方式:移位寄存器 当UART_M0x6 = 0时,波特率是SYSclk/12,
当UART_M0x6 = 1时,波特率是SYSclk / 2
0 1 方式1 8位UART,波特率可变 串行口1用定时器1作为其波特率发生器且定时器1工作于模式0(16位自动重装载模式)或串行口用定时器2作为其波特率发生器时,
波特率=(定时器T1的溢出率和定时器T2的溢出率 )/4
注意:此时波特率与SMOD无关。
当串行口1用定时器1作为其波特率发生器且定时器1工作于模式2(8位自动重装模式)时,
波特率=( 2SMOD/32 )×(定时器1的溢出率)
1 0 方式2 9位UART ( 2SMOD / 64) x SYSclk系统工作时钟频率
1 1 方式3 9位UART,波特率可变 当串行口1用定时器1作为其波特率发生器且定时器1工作于模式0(16位自动重装载模式)或串行口用定时器2作为其波特率发生器时,
波特率=(定时器1的溢出率或定时器2的溢出率)/4
注意:此时波特率与SMOD无关 当串行口1用定时器1作为其波特率发生器且定时器1工作于模式2(8位自动重装模式)时 波特率=( 2SMOD/32 )×(定时器1的溢出率)
当定时器1工作于模式0(16位自动重装载模式)且AUXR.6/T1x12 = 0时,
		定时器1的溢出率 = SYSclk/12/( 65536 - [RL_TH1,RL_TL1]) ;
当定时器1工作于模式0(16位自动重装载模式)且AUXR.6/T1x12 = 1时,
		 定时器1的溢出率 = SYSclk / (65536 - [RL_TH1,RL_TL1]) 
当定时器1工作于模式2(8位自动重装模式)且T1x12 = 0时,
		定时器1的溢出率 = SYSclk/12/( 256 - TH1);
当定时器1工作于模式2(8位自动重装模式)且T1x12 = 1时,
		 定时器1的溢出率 = SYSclk / ( 256 - TH1) 
当AUXR.2/T2x12 = 0时, 定时器T2的溢出率 = SYSclk / 12/ ( 65536 - [RL_TH2,RL_TL2] );
当AUXR.2/T2x12 = 1时, 定时器T2的溢出率 = SYSclk / ( 65536 - [RL_TH2,RL_TL2] );

SM2:允许方式2或方式3多机通信控制位。

​ 在方式2或方式3时,如果SM2位为1且REN位为1,则接收机处于地址帧筛选状态。此时

​ 可以利用接收到的第9位(即RB8)来筛选地址帧:若RB8=1,说明该帧是地址帧,地址信

​ 息可以进入SBUF,并使RI为1,进而在中断服务程序中再进行地址号比较;若RB8=0,

​ 说明该帧不是地址帧,应丢掉且保持RI=0。在方式2或方式3中,如果SM2位为0且REN位

​ 为1,接收收机处于地址帧筛选被禁止状态。不论收到的RB8为0或1,均可使接收到的

​ 信息进入SBUF,并使RI=1,此时RB8通常为校验位.

​ 方式1和方式0是非多机通信方式,在这两种方式时,要设置SM2 应为0。

REN:允许/禁止串行接收控制位。由软件置位REN,即REN=1为允许串行接收状态,可启动

​ 串行接收器RxD,开始接收信息。软件复位REN,即REN=0,则禁止接收。

TB8: 在方式2或方式3,它为要发送的第9位数据,按需要由软件置位或清0。例如,可用作数

​ 据的校验位或多机通信中表示地址帧/数据帧的标志位。在方式0和方式1中,该位不用.

RB8: 在方式2或方式3,是接收到的第9位数据,作为奇偶校验位或地址帧/数据帧的标志位。

​ 方式0中不用RB8(置SM2=0). 方式1中也不用RB8(置SM2=0, RB8是接收到的停止位)。

TI: 发送中断请求标志位。在方式0,当串行发送数据第8位结束时,由内部硬件自动置位,

​ 即TI=1,向主机请求中断,响应中断后TI必须用软件清零,即TI=0。在其他方式中,

​ 则在停止位开始发送时由内部硬件置位,即TI=1,响应中断后TI必须用软件清零。

RI: 接收中断请求标志位。在方式0,当串行接收到第8位结束时由内部硬件自动置位RI=1,

​ 向主机请求中断,响应中断后RI必须用软件清零,即RI=0。在其他方式中,串行接收

​ 到停止位的中间时刻由内部硬件置位,即RI=1,向CPU发中断申请,响应中断后RI必须

​ 由软件清零。

但是我们通常使用定时器1的工作模式2 (8位自动重装)来产生波特率,TL1作为脉冲计数寄存器,TH1作为自动重装寄存器,当计数到最大值溢出时,TH1会自动重装到TL1中

UART口的数据发送与接收

2. 串行口数据缓冲寄存器SBUF

STC15系列单片机的串行口1缓冲寄存器(SBUF)的地址是99H,实际是2个缓冲器,写SBUF

的操作完成待发送数据的加载,读SBUF的操作可获得已接收到的数据。两个操作分别对应两个

不同的寄存器,1个是只写寄存器,1个是只读寄存器。

串行通道内设有数据寄存器。在所有的串行通信方式中,在写入SBUF信号(MOV SBUF,A)

的控制下,把数据装入相同的9位移位寄存器,前面8位为数据字节,其最低位为移位寄存器的

输出位。根据不同的工作方式会自动将“1”或TB8的值装入移位寄存器的第9位,并进行发送.

串行通道的接收寄存器是一个输入移位寄存器。在方式0时它的字长为8位,其他方式时为

9位。当一帧接收完毕,移位寄存器中的数据字节装入串行数据缓冲器SBUF中,其第9位则装入

SCON寄存器中的RB8位。

如果由于SM2使得已接收到的数据无效时,RB8和SBUF中内容不变.由于接收通道内设有输入移位寄存器和SBUF缓冲器,从而能使一帧接收完将数据由移位

寄存器装入SBUF后,可立即开始接收下一帧信息,主机应在该帧接收结束前从SBUF缓冲器中

将数据取走,否则前一帧数据将丢失。SBUF以并行方式送往内部数据总线

也就是说串行口有两个缓冲寄存器都叫SBUF,一个是发送寄存器,一个是接收寄存器,这两个寄存器在物理结构上是独立的,但是他们的地址都是相同的
当是9位UART的时候,前八位是数据字节,后一位是移位寄存器的输出位,
在方式2或方式3时,如果SM2位为1且REN位为1,则接收机处于地址帧筛选状态。此时可以利用接收到的第9位(即RB8)来筛选地址帧
  • 这个重叠的地址靠读/写指令区分:

​ 串行发送时,CPU向SBUF写入数据,此时99H表示发送缓存SBUF

​ 串口接收时,CPU向SBUF读出数据,此时99H表示接收缓冲SBUF

  • 数据发送,把数据丢进SBUF后,内核会自动将数据发送出去,内容发生完成后,会将TI标志位置1

发送数据程序:SBUF= 数据/变量 如:SBUF= 0X58;

  • 数据接收:内核从串口接收到一个完整的数据后,会将RI标志位置1,用户用SBUF直接读取即可

接收数据程序:变量 = SBUF; 如:dat = SBUF

对于异步8位UART并且允许接收:SCON = 0X50;

对于IAP15F2K61S2单片机,你还要对辅助寄存器AUXR(0x8e) 进行设置

这边先了解下辅助寄存器AUXR:

3. 辅助寄存器AUXR

辅助寄存器AUXR的格式及各位含义如下:

AUXR : 辅助寄存器 (不可位寻址)

SFR name Address B7 B6 B5 B4 B3 B2 B1 B0
AUXR 8EH T0x12 T1x12 UART_M0x6 T2R T2_C/\(\overline{T}\) T2x12 EXTRAM S1ST2

T0x12: 定时器0速度控制位

​ 0, 定时器0是传统8051速度,12分频;

​ 1, 定时器0的速度是传统8051的12倍,不分频

T1x12: 定时器1速度控制位

​ 0, 定时器1是传统8051速度,12分频;

​ 1, 定时器1的速度是传统8051的12倍,不分频

如果UART1/串口1用T1作为波特率发生器,则由T1x12决定UART1/串口是12T还是1T

UART_M0x6: 串口模式0的通信速度设置位。

​ 0, 串口1模式0的速度是传统8051单片机串口的速度,12分频;

​ 1, 串口1模式0的速度是传统8051单片机串口速度的6倍,2分频

T2R: 定时器2允许控制位

​ 0, 不允许定时器2运行;

​ 1, 允许定时器2运行

T2_C/T: 控制定时器2用作定时器或计数器。

​ 0, 用作定时器(对内部系统时钟进行计数);

​ 1, 用作计数器(对引脚T2/P3.1的外部脉冲进行计数)

T2x12: 定时器2速度控制位

​ 0, 定时器2是传统8051速度,12分频;

​ 1, 定时器2的速度是传统8051的12倍,不分频

如果串口1或串口2用T2作为波特率发生器,则由T2x12决定串口1或串口2是12T还是1T.

EXTRAM: 内部/外部RAM存取控制位

​ 0, 允许使用逻辑上在片外、物理上在片内的扩展RAM;

​ 1, 禁止使用逻辑上在片外、物理上在片内的扩展RAM

S1ST2: 串口1(UART1)选择定时器2作波特率发生器的控制位

​ 0, 选择定时器1作为串口1(UART1)的波特率发生器;

​ 1, 选择定时器2作为串口1(UART1)的波特率发生器,此时定时器1得到释放,可以作为

独立定时器使用

串口1可以选择定时器1做波特率发生器,也可以选择定时器2作为波特率发生器。当设置AUXR寄存器中的S1ST2位(串行口波特率选择位)为1时,串行口1选择定时器2作为波特率发生器,此时定时器1可以释放出来作为定时器/计数器/时钟输出使用.对于STC15系列单片机,串口2只能使用定时器2作为波特率发生器,不能够选择其他定时器作为其波特率发生器;而串口1默认选择定时器2作为其波特率发生器,也可以选择定时器1作为其波特率发生器;串口3默认选择定时器2作为其波特率发生器,也可以选择定时器3作为其波特率发生器;串口4默认选择定时器2作为其波特率发生器,也可以选择定时器4作为其波特率发生器。

20231008160625

#include <REGX52.H>
sfr AUXR = 0x8E;

unsigned char urdat;

void _74HC138(unsigned char n) {
	switch(n) {
		case 4: P2=(P2&0x1f) | 0x80;
		break;
		case 5: P2=(P2&0x1f) | 0xa0;
		break;
		case 6: P2=(P2&0x1f) | 0xc0;
		break;
		case 7: P2=(P2&0x1f) | 0xe0;
		break;
	}
}

void SytemInit(void) {
	_74HC138(5);
	P0 = 0X00;
	_74HC138(4);
	P0 = 0xFF;

}

void UART_Init(void) {
	// 设置定时器1
	TMOD = 0x20;
	AUXR = 0x00;
	// 串口方式1,允许串行口接收控制位
	SCON = 0x50;
	// 9600  
	// 波特率=( 2^SMOD/32 )×(定时器1的溢出率)
	// 由于此时产生的是方式1的波特率,所以溢出率为
	// 溢出率: fosc/12 * (1/(2^8)-TH1);
	TH1 = 0xf9;
	TL1 = 0xf9;
	
	// 打开定时器1
	TR1 = 1;
	// 开启中断
	ES = 1;
	EA = 1;

}


void SendByte(unsigned char dat) {
	SBUF = dat;    // 将数据放到自动重装寄存器中
	while(TI == 0); //当TI 不等于1 的时候,就给TI清零 
		TI = 0;
}

void SendString(unsigned char *str) {
	while(*str != '\0') 
		SendByte(*str++); 
	

}



void main(void) {
	SytemInit();
	UART_Init();
	
	
	
	
	while(1);
	
}



void UART_Rountine (void) interrupt 4 {
	
	
	if(RI == 1) {
		// 接收内容
		urdat = SBUF;
		RI = 0;
		_74HC138(4);
		P0 = urdat;
		// 发送内容
		SendByte(urdat+1);
		
		
		
		
		
		
		
	}
	

}




标签:11,定时器,基本原理,串口,SBUF,寄存器,波特率,接收
From: https://www.cnblogs.com/bky111/p/17750450.html

相关文章

  • 解题报告P2486 [SDOI2011] 染色
    P2486[SDOI2011]染色题目链接分两段,最后靠同一条重链合树剖加线段树,典中典。这题的线段树维护比较新颖。线段树中维护这个区间左右端点的颜色和颜色段数量。建树和查询和修改时要判断左区间的右端点和右区间的左端点是否颜色相同。如果不相同,直接将段数相加,否则减一。然......
  • 用程序小小11孩岁女A片㓜或操作系统使用的逻辑地址式与具体的内存管理单元(MMU)的实现有
    在ARM架构中,块地址是物理地址的一部分,用于标识cache中存储数据的物理位置。索引(index)是用于确定cache行对应的物理地址的部分,而标记(tag)则用于标识cache行中所存储数据的虚拟地址。当CPU访问虚拟地址时,硬件会根据虚拟地址与索引掩码进行按位与(AND)操作,得到索引,然后使用索引和标记在c......
  • # 2023-2024-1 20231311《计算机基础与程序设计》第2周学习总结
    作业信息这个作业属于哪个课程https://edu.cnblogs.com/campus/besti/2023-2024-1-CFAP这个作业要求在哪里https://edu.cnblogs.com/campus/besti/2023-2024-1-CFAP/homework/12998这个作业的目标自学教材,计算机科学概论第1章并完成云班课测试,《C语言程序设计》第1......
  • Python-串口通信2
    安装pipinsatllpyserial 初始化简单初始化示例importserialser=serial.Serial('com1',9600,timeout=1) 所有参数 ser=serial.Serial(port=None,#numberofdevice,numberingstartsat#zero.ifeverythingfails,theuser#can......
  • ROG安装双系统win11和ubuntu
    问题:安装完成后需要在bios里设置VMDcontroller为Disabled,才能进入ubuntu。但是win11就进不去了。解决步骤:1,保持VMDcontroller为Enabled2、进入Win11界面,按Win+R,输入MSCONFIG,回车运行并在【引导】页面勾选“安全引导”后确定。3、重启时长按F2进入BIOS修改VMDcontroller为......
  • JN_0056:win11操作快捷方式,技巧汇总
    1,1,快捷键:win:打开win面板win+e:打开资源管理器win+s:打开搜索面板win+s:打开文件管理器win+a:打开常用设置面板ctrl+shift+esc:打开任务管理器win+alt+k:麦克风静音开关win+h:打开语音输入win+ctrl+l:打开字幕win+w:打开小组件面板win+shift+s或PrintScreen键:捕获屏幕图像win+v:剪贴板历史......
  • 11_流程控制
    一、条件语句select1.1select介绍select{casecommunicationclause:statement(s);casecommunicationclause:statement(s);/*你可以定义任意数量的case*/default:/*可选*/statement(s);}select{//不......
  • Python入门示例系列11 数据类型
    Python入门示例系列11数据类型标准数据类型Python3中有六个标准的数据类型:   Number(数字)   String(字符串)   List(列表)   Tuple(元组)   Set(集合)   Dictionary(字典)Python3的六个标准数据类型中:   不可变数据immutable(3个):Number(数字)、String(字符串)、......
  • 题解:洛谷P1119 灾后重建
    题解:洛谷P1119灾后重建题目传送门前言:没有掌握floyed求最短路的精髓是每次增加选一个中转点,导致写了2h才勉强卡过法1:最暴力的想法就是开个三维数组把前i个点的dis状态全部存下来,跑N次floyed,当然由于每次点数时递增的,所以实际复杂度远远小于O(N^4),算了下大概200个点跑了4e8多一......
  • 【Mysql】不要用int类型存储11位手机号
    一、遇到问题今天在做添加数据的时候,发现手机号存储错误,报错信息是:Cause:com.mysql.cj.jdbc.exceptions.MysqlDataTruncation:Datatruncation:Outofrangevalueforcolumn'f_phone'atrow1;Datatruncation:Outofrangevalueforcolumn'f_phone'atrow1;ne......