【蓝桥杯】串口通信详解附双串口代码

备赛目录

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作为波特率发生器

3、串口收发

回头看了看这个博客,觉得写的海慧寺太水了,现在推倒重来嗷

3.1串口初始化函数

咳咳,有两种方案嗷,
第一种建议完全理解了这个串口的人使用,就是自己算

配置步骤:
①配置SCON工作方式。
②配置AUXR这个寄存器,选择时钟,
③配置定时器用作波特率发生器比如定时器1 定时器1的16位工作方式,TH1、TL0初始计算,禁止定时器1中断
④允许总中断
⑤允许串口中断

说实话这一套下来,除非你基本功很扎实,不然都会出现或多或少的问题,建议刚开始多来几次自己配置,然后第二套方案

第二种办法

啊这,咱就用个波特率计算器不香么。一键配置完成。

这种软件很多,咱就说说ISP这个软件吧,毕竟蓝桥杯考试也能用的
在这里插入图片描述
打开这个软件,找到波特率计算器,你想要什么频率,哪个串口啥波特率哪个定时器,都妥妥了。

void Uart1Init(void)		//串口1,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
	TI = 1;//未发送完成
	ES=1;	//这里是自己加的
	EA=1;	//这里是自己加的
}

记得这里开启中断允许啊,一定要啊,不然白费

3.2串口发送函数

串口当然离不开数据的收发了,这里呢,咱最重要的就是对SCON寄存器的理解了,不太熟悉的看上面介绍

1、怎么存放数据?

SBUF这个寄存器,其实有俩,因为公用的同一地址,所以只有一个名字,具体的看上面介绍哈,咱把数据直接放里就好了,一个简单的赋值操作就行

2、怎么判断数据送完了,然后停下来?

方便大家and我查看,我复制下来了
TI—发送中断标志位 TI =1,表示一帧数据发送结束。TI状态可供软件查询,也可申请中断。CPU响应中断后,在中断服务程序中向SBUF写要发送的下一帧数据。所以说每次发送的时候,咱就让代码停在这里,守着TI直到他等于1,结束这次发送方式0,串行发送的第8位数据结束时TI由硬件置“1”,在其他方式中,串行口发送停止位的开始时置TI为“1”。

**TI必须由软件清“0”**这句话超重要,你每次发完了数据,TI必然要变成1,也就是一直停在发送结束这个状态。咱下次还要发,肯定要置0啊,它自己不能置零,需要我们给它赋值为0,
这里有两种写法,第一种是软件查询,第二种是串口中断
这里不建议使用第二种,为什么呢?TI=0就可以申请中断,这太麻烦了,而且串口会干扰咱,你根本不知道此时的TI=0是空闲状态还是发送状态?所以我们使用软件查询法,在查询时,关闭它的中断请求。

//串口发送字符 
void uart_send(unsigned char ch)
{
  ES=0;   //关串口中断,
  SBUF=ch;
  while(TI==0);  //等待发送完成
  TI=0;  //清除中断标记
  ES=1;   //开中断
}
//串口1字符串发送
void Uart1_Sendstring(unsigned char *Str) 
{ 
 ES=0;   //关串口中断
 while(*Str != '\0') 
 { 
	 SBUF = *Str; 
	 while(TI == 0); 
	 TI = 0; 
	 Str++; 
 } 
  ES=1;   //开串口中断
}

串口的写法,后面会有,也可以看看,不是不能用,

3.3串口接收函数

RI—接收中断标志位

RI=1,表示一帧数据接收完毕,并申请中断,要求CPU从接收SBUF取走数据。该位的状态也可供软件查询。
和发送的道理相似,我们也有RI作为接收的标志,同样也有两种方式,一种是软件查询,一种是中断
方式0时,接收完第8位数据时,RI由硬件置“1”。 在其他工作方式中,串行接收到停止位时,该位置“1”。 RI必须由软件清“0”。

软件查询法

//串口1字符串发送
unsigned char  Uart1_receive() 
{ 
 unsigned char dat;
 while(RI==0);   //等待接收完毕
 RI=0;  	//将接收中断标志RI清0,为接收下一帧数据做准备
 dat=SBUF; 	//将接收缓冲器中的数据存入dat 
  return dat;	//将接收到的数据返回
}

中断查询法

//串口接收 ( 通过中断 )
void uart1receive() interrupt 4
{
   if (RI==1) 
  { RI=0;
     buf=SBUF;
   }
}

4、串口1收发实验

各个模块都讲完了,下面咱得把它组合起来实战
简简单单写一个收发实验吧,我们给单片机发送消息,然后单片机将消息反馈给串口调试助手,这个是最简单的操作
(主函数什么都没写,我们可以在里面写点控制,比如串口发送了什么,单片机怎么样之类的,就实现了PC机控制单片机了,更有甚者,给它安一个WIFI、蓝牙什么的,直接无线控制,哈哈。WiFi的方式用过一次,挺有意思的)
如果发现发送的数据和接收的数据不一致,一定检查IRC频率是否是12mhz,
在这里插入图片描述

#include <STC15F2K60S2.H>
#include <stdio.h>
//定义接收数组
unsigned char Buffer1[12]={0};//串口1接收数组
unsigned char i;
void Uart1Init(void)		//串口1,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
	ES=1;	//这里是自己加的
	EA=1;	//这里是自己加的
}

//串口1字符串发送
void Uart1_Sendstring(unsigned char *pucStr) 
{ 
 while(*pucStr != '\0') 
 { 
	 SBUF = *pucStr; 
	 while(TI == 0); 
	 TI = 0; 
	 pucStr++; 
 } 
}
//主函数
void  main()
{
	Uart1Init();
	EA =1;
	while(1)
	{
	  	
	}
}

//中断接收函数
void UART1receive() interrupt 4
{
	 if(RI)
	 { 
		  Buffer1[i]=SBUF;
		  RI=0;
	 }
	
	 Uart1_Sendstring(Buffer1);
}
		 

在这里插入图片描述
点击发送后可以看到接收区消息
在这里插入图片描述
至此串口1收发实验完成,注意发送数据长度不能大于设定数组的长度。


咳咳我来更新了,今天玩一下串行口2,

手上没有串口通信的传感器,今天先这样吧,后面会更新串口2的传感器使用
有用的话,点个赞呗
备赛目录

版权声明:本文为CSDN博主「学到地中海」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/C_white_llj/article/details/122765426

生成海报
点赞 0

学到地中海

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

【蓝桥杯】我的单片机备赛准备目录

知其然,更需知其所以然 1、客观题准备 蓝桥杯历届客观题及答案解析 2、模块化准备 2.1、LED灯及蜂鸣器 1、关闭蜂鸣器 2、LED灯的操作 2.2、数码管 万能数码管编写 2.3、按键 1、独立按键 2、矩阵

【蓝桥杯】PCF8591AD转换模块

备赛目录】 1、PCF8591模块简介 PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出和1个串行I²C总线接口。 在PCF8591器件上输入输出的地址、控制和数据

蓝桥杯实用小技巧

前言 本文主要给大家介绍蓝桥杯的两个小技巧 一、定时器代码生成 把TF00改成EA0和ET00即可。 二、数码管断码获取 这里的数码管断码是共阴的断码,而我们使用的单片机采用的是共阳的断码,所以想使用这个断码的