摘要:目前各类串口的输入输出都是可以的。串行全双工通信没有时钟脉冲,只能依靠晶振脉冲定时器的溢出脉冲。读入中断,清除标志,然后返回给计算机,等待反重叠定时器的最小时间完成。实现烧录程序的目的。
小农户不敢收妖妇(想多活几年)。但是串口还是一种可以传输数据的并行通信。串行通信= =同步= = =异步:= =串行通信:发送和接收一个字节(只有时间可以用于同步)串行通信的相关术语STC串口1通信寄存器1。模式设置和中断标志寄存器2。波特率加倍功能寄存器3。数据接收和发送缓冲寄存器SBUF4。辅助寄存器AUXR控制定时器。分频,独立波特率发生器3和串口2的相关控制。5.独立波特率发生器寄存器BRT,用于存储定时器的初始值。6.与串行通信相关的中断寄存器IE,中断优先级IPH,IP串口1工作模式1: 8位UART,波特率变量= =收发波特率需要一致= = =收发波特率需要不一致,导致RX端无法正常接收:= =串口11。配置SCON。SM0 = 0;SM1 = 1;任= 1;PCON & = 0x3f;2.将定时器2配置为:16位自动重载模式,不申请中断AUXR | = 0x01AUXR | = 0x14其实也可以写成AUXR | = 0x153.计算定时器2: 4的溢出率。配置定时器2的初始值。5.启动定时器2,关闭串口1的中断开关,关闭主中断开关。ES = 16。在中断期间读取SBUF,清除RI标志,然后将其返回给计算机。等到传输完成,防止重叠的最短时间=4次/*10位/*定时器时间。然后清除TI串口1中断函数串口1中断号串口中断使微控制器软复位,从而实现自动烧录IAP_CONTR |= 0xe0。它上面是发送一个字节。现在,我们首先发送一个字符串来了解SBUF延迟,然后我们将在调整最后一个字节的发送后立即发送下一个字节。如果微控制器不接收数据,串行端口标志将不会被设置为1。电压发不出来= = =如果微控制器接收数据,串口标志置1,电压发出= =汉字发送缓冲区有/n/r换行,汉字发送缓冲区有/n换行,汉字发送缓冲区有/r换行,汉字发送缓冲区有/r换行和主代码uart1 _ drive.cuart _ drive.h。
小农不敢收妖妇(想多活几年),但串口还是可以并行通信传输数据的。
多位数据的同时传输
通信介质通常是TTL,差分(低压差分芯片)。
例如:LCO1602、ADC0804、LVDS(液晶显示器)等。
串行通信
多位数据排队传输,任何IO口都可以收发数据。
通信介质通常是TTL、差分(485)和无线电。
同步:74HC595(单工)、IIC(半双工)、SPI。
异步:单线归零,1-线,CAN总线,电台,UART(包括DMX512和modbus)。
UART是单片机的一个独立模块。我们设置好模块的参数,需要发送什么就扔给串行模块。CPU不需要逐位读写。该模块是指定的引脚输入和输出。目前所有STC型号的串口1输入为RxD1=P3.0,输出为TxD1=P3.1,STC15开发板使用STC15W4K16S4芯片,有四个串口,其中串口3的输入为RxD3= P0.0,输出为TxD3= P0.1,与矩阵键盘共用两个IO。
串行通信:发送和接收一个字节(只有时间可以用来同步)。CPU将一个字节写入SBUF,CPU可以运行执行其他功能。如果传输完成,串行模块向CPU申请中断(T1);
串口收发一位数据,要靠严格的时间来保证同步。
如果串行模块接收到一个字节,它也会向CPU施加一个中断(RI ), CPU可以从SBUF读取数据。
串行通信相关术语**1。位采样脉冲:* *接收器对每一位的时间进行平均,并在对下一位数据进行采样之前对线路电平进行采样,以确定接收电平是高还是低。STC89是16个相等的判决7、8、9(三选二)。STC15W和STC8系列是4等份(四分之三,官方数据错写成16)。
2.波特率::指的是串行通信线上一秒钟发送的数据位数,简单理解为一秒钟内电平跳变多少次。常用的波特率是9600,在STC下载软件中有很多波特率可以选择。我们后面要学的DMX512是250000bps。
* *波特率的本质是设置信号时间点。* *当它到达时,准时发送或接收一个。串行全双工通信没有时钟脉冲,只能依靠晶振脉冲和定时器的溢出脉冲。
==3.波特率从何而来?= =波特率来自定时器的溢出,独立的波特率发生器和系统时钟的分频。
STC串行端口1通信寄存器1。模式设置和中断标志寄存器。
2.功率控制寄存器中的波特率加倍功能寄存器
3.数据收发器缓冲寄存器SBUF
4.辅助寄存器AUXR控制定时器分频、独立波特率发生器和串口2。
5.独立波特率发生器寄存器BRT,用于存储定时器的初始值。
6.与串行通信相关的中断寄存器IE,中断优先级IPH,IP。
串口1工作模式1: 8位UART,波特率可变。
发送和接收的波特率需要一致。
发送和接收波特率不一致导致接收端接收异常:
串行端口1 1。配置SCON,选择模式1,8位可变波特率,并允许接收。SM0 = 0;SM1 = 1;任= 1;
PCON & = 0x3f;
2.将定时器2配置为:16位自动重载模式,不申请中断AUXR | = 0x01AUXR | = 0x14其实也可以写成AUXR | = 0x15
3.计算定时器2的溢出率:波特率为9600,每位采样4次。定时器2每秒需要溢出9600*4次=38400。
4.为定时器2溢出配置定时器2初始值所需的脉冲数为:24,000,000 ÷ 38,400 = 625。那么,Timer2的预装初始值为:655,36-625 = 64911 = 0 xfd8f。
5.启动定时器2,关闭串口1中断开关,关闭主中断开关。ES = 1
6.在中断期间读取SBUF,清除RI标志,然后将其返回给计算机,并等待传输完成。防重叠的最小时间=4倍*10位*定时器时间。然后清除TI void UART 1 _ Init(){ SM0 = 0;SM1 = 1;任= 1;//以上三条语句等价于运算SCON | = 0x 50;PCON & = 0x3f;AUXR | = 0x01AUXR | = 0x14T2H = 0xfdT2L = 0x8f;ES = 1;}串口1中断功能串口1中断号
在中断中我们做什么?中断中首先要做的是清除接收标志并将标志发送给软件,然后做一系列操作。
void Uart1_Routine()中断4 { if(RI){ RI = 0;//首先清除接收标志。Uart1 _ Data = SBUF} if(TI){ TI = 0;//首先清除发送标志}}
串口中断使微控制器软复位,实现IAP_CONTR |= 0xe0监控串行通信内容的自动烧录。如果波特率为9600时连续接收的10个字节为0x7f,则让微控制器软复位以支持ISP监控区域代码。实现烧录程序的目的。单片机可以不间断下载程序,方便工程调试。
上面我们故意用的最低波特率和最高波特率都是1200,不到9600,我就点了下载。(板卡上电)不是板卡的开关复位,而是纯软件复位。等了几秒,没有反应,说明我们用9600下载方式不支持1200下载。
9600下载很慢(哈哈)
我们发现只要最低波特率达到9600就可以软复位,越高下载越快。
void UART 1 _ routine()interrupt 4 {//记录收到的命令流变量static char UART 1 _ ser _ n = 0;if(RI){ RI = 0;//首先清除接收标志。Uart1 _ Data = SBUFIf (SBUF == 0x7f) //9600波特率{/+UART 1 _ ser _ n++接收命令为0x7f时;If(Uart1_ser_n > 10)//大于10基本是下载命令{ UART 1 _ ser _ n = 0;//然后进行软复位IAP _ CONTR | = 0xe0} } } if(TI){ TI = 0;//先清除发送标志}}以上是发送一个字节。现在先发一串理解SBUF。
为什么总是0xFF,而且一看就不是1,是吗?我们用逻辑分析仪抓取一下看看。
延迟后
完美,为了让你直观的看到美,我收集一下给你看看。
我们调整最后一个字节,并在发送后立即发送下一个字节。我们给他一个标志位。发送完前一个字节后,修改标志位,然后发送第二个字节,依此类推。
//串口驱动的函数Void UART 1 _ up _ data _ drive()只能在串口1的标志为1时发送字节。//如果(Uart1_Flag){Uart1_Flag = 0,可以使数据有效发送;SBUF = 1;} }//串口1中断void UART 1 _ routine()interrupt 4 {//记录收到的命令流变量static char UART 1 _ ser _ n = 0;if(RI){ RI = 0;//先清除接收标志if (SBUF == 0x7f) //9600波特率{//当接收命令为0x7f时,将为++ UART 1 _ ser _ n++;If(Uart1_ser_n > 10)//大于10基本是下载命令{ UART 1 _ ser _ n = 0;//然后进行软复位IAP _ CONTR | = 0xe0} } } if(TI){ TI = 0;//先清除发送标志//所有数据发送完毕后,标志位为1//置1后,下一个字节Uart1_Flag = 1准备发送;//调用串口发送函数UART 1 _ Up _ Data _ Drive();}}发送字符串
没有数据接收,串口标志不会设置为1,电压也不会发出。
我们可以看到,接收缓冲区什么都没有,就是因为发送缓冲区没有发送数据,单片机没有接收到数据,也没有设置标志,然后就没有触发单片机发送数据。
当微控制器接收到数据时,串行端口标志将被设置为1,电压将被发送出去。
我们可以发送任何数据,只要微控制器接收到数据,然后串口标志就会置1,这样串口发送功能就有用了,我们可以看到显示的电压。不过细心的同学会发现,我的发送汉字缓冲区明明是换行符和回车符,你也没看出来。这是SPI软件的一个小问题。我们换个软件吧。
用/n/r换行符和回车发送汉字缓冲区。
发送带/n换行符且无回车的汉字缓冲区。
发送不带换行符的汉字缓冲区,带回车/r
发送汉字缓冲区,不换行,不回车。
所以你知道我为什么在发送汉字缓冲区写换行符回车吗?
主代码Uart1 _ Drive.c #包含需要显示串口的“all . h”//临时变量位Uart1 _ Flag = 1//汉字是固定的。直接编码//串口发送汉字数组缓存。换行优先/n回车/ru8 code UART 1 _ up _ symbol _ buffer[30]= { "/N/R电压:" };//串口发送20个数字数组到缓存足够以后使用,u8 xdata UART 1 _ Up _ Num _ Buffer[20];//串口1初始化void UART 1 _ Init(){ SM0 = 0;SM1 = 1;任= 1;//以上三条语句等价于运算SCON | = 0x 50;PCON & = 0x3f;AUXR | = 0x01AUXR | = 0x14T2H = 0xfdT2L = 0x8f;ES = 1;}//串口发送函数void ua t1 _ up _ data _ drive(){ static xdata u8 count = 0;//只有串口1的标志为1时才能发送字节。//如果(Uart1_Flag){Uart1_Flag = 0,数据可以有效发送;count++;switch(count){ case 1:SBUF = UART 1 _ Up _ Symbol _ Buffer[0];打破;情况二:SBUF = UART 1 _ Up _ Symbol _ Buffer[1];打破;情况三:SBUF = UART 1 _ Up _ Symbol _ Buffer[2];打破;情况4:SBUF = UART 1 _ Up _ Symbol _ Buffer[3];打破;情况5:SBUF = UART 1 _ Up _ Symbol _ Buffer[4];打破;情况6:SBUF = UART 1 _ Up _ Symbol _ Buffer[5];打破;情况7:SBUF = UART 1 _ Up _ Symbol _ Buffer[6];打破;情况8:SBUF = UART 1 _ Up _ Symbol _ Buffer[7];打破;情况9:SBUF = UART 1 _ Up _ Symbol _ Buffer[8];打破;情况10:SBUF = UART 1 _ Up _ Symbol _ Buffer[9];打破;情况12:SBUF = UART 1 _ Up _ Num _ Buffer[0];打破;情况14:SBUF = UART 1 _ Up _ Num _ Buffer[1];打破;案例16:SBUF = UART 1 _ Up _ Num _ Buffer[2];打破;情况18:SBUF = UART 1 _ Up _ Num _ Buffer[3];打破;情况20:SBUF = UART 1 _ Up _ Num _ Buffer[4];打破;情况22:SBUF = UART 1 _ Up _ Num _ Buffer[5];打破;情况24:count = 0;打破;} } }//串口1中断void UART 1 _ routine()interrupt 4 {//记录收到的命令流变量static char UART 1 _ ser _ n = 0;if(RI){ RI = 0;//先清除接收标志//当接收到一个字节时,将串口标志置1Uart1 _ Flag = 1If (SBUF == 0x7f) //9600波特率{/+UART 1 _ ser _ n++接收命令为0x7f时;If(Uart1_ser_n > 10)//大于10基本是下载命令{ UART 1 _ ser _ n = 0;//然后进行软复位IAP _ CONTR | = 0xe0} } } if(TI){ TI = 0;//先清除发送标志//所有数据发送完毕后,标志位为1//置1后,下一个字节Uart1_Flag = 1准备发送;//调用串口发送函数UART 1 _ Up _ Data _ Drive();} } UART _ drive . h # ifndef UART 1 _ drive # define UART 1 _ drive//外部声明extern void UART 1 _ Init();外部位Uart1 _ Flagextern void UART 1 _ Up _ Data _ Drive();extern u8 xdata UART 1 _ Up _ Num _ Buffer[20];#endif
评论前必须登录!
注册