【蓝桥杯】串口通信详解附双串口代码
作者:互联网
目录
IAP15F2K61S2单片机拥有两个全双工串口通信接口(串口1和串口2)
1、串口相关寄存器
每个串口都有2个数据缓冲器、一个移位寄存器、一个串行控制器和一个波特率发生器
1.1数据缓冲器SBUF
这是两个物理上独立的接收、发送缓冲器,可同时发送、接收数据。
发送缓冲器只写不能读,接收缓冲器只读不能写。因此两个缓冲器共用一个地址码
从STC15F2K60S2这个头文件的190行和192行可以看出串行口1SBUF
地址是99H,串行口2S2UBF
地址是9BH。
1.2串行口(工作方式)控制寄存器SCON
IAP15F2K61S2 单片机的串行口有 4 种工作方式。
(1)SM0、SM1控制工作方式
方式0:同步串行通信
方式1:异步串行通信8位,串行口1波特率取决于定时器T1,串行口1波特率取决于定时器T2,波特率都可变
方式2:异步串行通信9位(多一个奇偶检验位、或地址帧/数据帧标识位),波特率取决于内部晶振,波特率不可变
方式3:异步串行通信9位(多一个奇偶检验位、或地址帧/数据帧标识位),串行口1波特率取决于定时器T1,串行口1波特率取决于定时器T2,波特率可变
(2)SM2多机通信控制位,用来控制是否激活RI
①当串口以方式2或方式3接收时:
如果SM2 = 1,则只有当接收到的第9位数据(RB8)为“1”时,才使RI置“1”,产生中断请求,并将接收到的前8位数据送入SBUF。当接收到的第9位数据(RB8)为“0”时,不使RI置“1”,并将接收到的前8位数据丢弃。
当SM2 = 0时,则不论第9位数据是“1”还是“0”,都将前8位数据送入SBUF中,并使RI置“1”,产生中断请求。
②方式0、方式1时,SM2 = 0。
(3)TB8—发送的第9位数据
在多机通信中用来表示主机发送的是地址帧还是数据帧,TB8=1为地址帧,TB8=0为数据帧。
双机串行通信时,为奇偶校验位。
(4)RB8—接收的第9位数据
方式0,不使用RB8。
方式1中,RB8是接收到的停止位。
方式2和方式3,RB8存放接收到的第9位数据。作为地址帧/数据帧标识位、或奇偶校验位。
(5)REN—允许串行接收位。
由软件置“1”或清“0”。
REN=1,允许串行口接收数据。
REN=0,禁止串行口接收数据。
(6)TI—发送中断标志位
TI =1,表示一帧数据发送结束。TI状态可供软件查询,也可申请中断。CPU响应中断后,在中断服务程序中向SBUF写入要发送的下一帧数据。
方式0,串行发送的第8位数据结束时TI由硬件置“1”,
在其他方式中,串行口发送停止位的开始时置TI 为“1”。
TI必须由软件清“0”
(7)RI—接收中断标志位
RI=1,表示一帧数据接收完毕,并申请中断,要求CPU从接收SBUF取走数据。该位的状态也可供软件查询。
方式0时,接收完第8位数据时,RI由硬件置“1”。
在其他工作方式中,串行接收到停止位时,该位置“1”。
RI必须由软件清“0”。
1.3特殊功能寄存器PCON
PCON中仅最高位SMOD与串口有关:SMOD:波特率倍增位。
方式0时(同步),此位未采用,即波特率的速度不受SMOD影响。
方式1、2、3时,SMOD=1时的波特率比SMOD=0时的波特率速度提高一倍。所以称SMOD位为波特率倍增位。
2、波特率
异步通信没有时钟线的约束,通信双方都有自己的通信频率(波特率),且双方的波特率要相同。
波特率的设置 (fosc:frequency oscillate晶振频率)
方式0的波特率 = fosc/12
方式2的波特率 =(2SMOD/64*fosc
方式1的波特率 =(2SMOD/32)*(T溢出率)
方式3的波特率 =(2SMOD/32)*(T溢出率)
一般我们使用定时器作为波特率的发生器,进行串口通信,如果两个串口同时使用,那么我们需要准备两个波特率发生器
串行口1使用定时器1作为波特率发生器
串行口2使用定时器2作为波特率发生器
下面进行串口通信波特率可变的函数编写(两个串口全部使用)
串口2的S2CON 的8个位没有在头文件定义,要自己定义
#include <STC15F2K60S2.H>
#include <stdio.h>
#define S2RI 0x01
#define S2TI 0x02
#define S2RB8 0x04
#define S2TB8 0x08
#define S2_S0 0x01
//定义接收数组
unsigned char Buffer1[5]={0};//串口1接收数组
unsigned char Buffer2[5]={0};//串口2接收数组
unsigned char buf[12]={0}; //发送数组
unsigned char i=0,j=0;
void Uart1Init(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xC7; //设定定时初值
TH1 = 0xFE; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA=1;
ES=1;
}
void Uart2Init(void) //9600bps@12.000MHz
{
S2CON = 0x50; //8位数据,可变波特率
AUXR |= 0x04; //定时器2时钟为Fosc,即1T
T2L = 0xC7; //设定定时初值
T2H = 0xFE; //设定定时初值
AUXR |= 0x10; //启动定时器2
}
//串口1字符串发送
void Uart_Sendstring(unsigned char *pucStr)
{
while(*pucStr != '\0')
{
SBUF = *pucStr;
while(TI == 0);
TI = 0;
pucStr++;
}
}
//主函数
void main()
{
Uart1Init();
Uart2Init();
sprintf (buf,"%u","lianglujun");
while(1)
{
}
}
//中断接收函数
void UART1receive() interrupt 4
{
if(RI)
{
Buffer1[i]=SBUF;
RI=0;
}
SBUF=Buffer1[i]; //TI =1,表示一帧数据发送结束。TI状态可供软件查询,也可申请中断
while(!TI) ;
TI=0;
i++;
if(i>=5){
i=0;
}
}
//中断函数
void UART2receive() interrupt 8 using 2
{
//接收标记,S2RI=1,表示一帧数据接收完毕,并申请中断
//因为头文件对串口2缺少定义,这里采用一些位操作
if(S2CON &S2RI)
{
Buffer2[j]=S2BUF;
S2CON &= ~S2RI;
}
S2BUF=Buffer2[j];//发送数据
while(!S2CON & S2TI);
S2CON &= ~S2TI;
j++;
if(j>=5){
j=0;
}
}
标签:附双,定时器,TI,串行口,蓝桥,串口,波特率,接收 来源: https://blog.csdn.net/C_white_llj/article/details/122765426