串口通信分为:并行和串行
并行通信传送速度快,但是所需线路复杂,串行通信传送速度慢,线路简单;
通信又分为:单工(单方向),半双工(不能同时发送和接收),全双工(可以同时进行半双工和全双工);
同步通信:收发双方采用的形同频率的时钟; 异步通信:收发双方采用不同时钟频率;

SCON 寄存器(可以位寻址)
SCON 寄存器是特殊功能寄存器之一,用来设定串口的工作方式、收发控制及设置状态标志;

PCON寄存器(可以位寻址)

SMOD(PCON.7)波特率倍增位。在串行口方式1、方式2、方式3时,波特率与SMOD有关,当SMOD=1时,波特率提高一倍。复位时,SMOD=0。
方式1的输入输出
方式1是10 位数据的异步通信口,TXD为数据发送引脚,RXD为数据接收引脚,传送一帧数据的格式如图所示。其中1位起始位,8位数据位,1位停止位。



(不太理解) 用软件置REN为1时,接收器以所选择波特率的16倍速率采样RXD引脚电平,检测到RXD引脚输入电平发生负跳变时,则说明起始位有效,将其移入输入移位寄存器,并开始接收这一帧信息的其余位。接收过程中,数据从输入移位寄存器右边移入,起始位移至输入移位寄存器最左边时,控制电路进行最后一次移位。当RI=0,且SM2=0(或接收到的停止位为1)时,将接收到的9位数据的前8位数据装入接收SBUF,第9位(停止位)进入RB8,并置RI=1,向CPU请求中断。
波特率计算公式:
方式0的波特率 = fosc/12
方式2的波特率 =(2SMOD/64)· fosc
方式1的波特率 =(2SMOD/32)·(T1溢出率)
方式3的波特率 =(2SMOD/32)·(T1溢出率)
当T1作为波特率发生器时,最典型的用法是使T1工作在自动再装入的8位定时器方式(即方式2,且TCON的TR1=1,以启动定时器)。这时溢出率取决于TH1中的计数值。
T1 溢出率 = fosc /{12×[256 -(TH1)]}
对于以上计算初值,通常用初值计算工具完成;
串口工作编程:
1.确定定时器的工作方式:TMOD; 一般选择定时器1;
2.计算定时器的初值;装载THn,TLn的初值;(一般选择方式1的冲转载);
3.启动定时器Tn;(变成TCON的TR1位);
4.确定串行口控制;(变成SCON);
5.串行口在中断方式工作时,要注意终端设置;(变成IE和IP寄存器);串口的中断号是4

也就是说,在串口通信时,定时器+中断+串口的要用起来的,对于相关寄存器的总结,见文章:
编程
利用51单片机和PC进行通信:
#include<reg51.h>
//利用51单片机和PC通信
void UART()
{
TMOD=0X20;//设置定时器1工作模式为 模式2;
TH1=0XF3;//定义定时器1寄存器高位
TL1=0XF3; //低位
PCON=0X80;//PCON 中为是否能设置倍频,但PCON不是可以位寻址嘛?为甚么不能用SMOD=1;
TR1=1;//打开定时器1
REN=1;//scon寄存器之一,由软件置1,则可以接受,清零无法接受;
SM1=1;
SM0=0; //设置SCON的工作模式为1,发送8位数据,包含起始位和截至位
RI=1;//接受中断标志位
ES=1;//IE寄存器中的,串口使能中断
EA=1;//TCON寄存器,开总中断
T1=1;//发送中断标志位
}
int main()
{
UART();//调用串口函数
while(1);
}
void usart() interrupt 4
{
char i;
i=SBUF;//把传送完的数据存贮在sbuf;sbuf寄存器可以位寻址;
RI=0;//接受完后会置1,软件清0;
SBUF=i;
while(!TI);//当没发送完一直运行
TI=0;
}
利用串行通信控制流水灯
#include<reg51.h>
#include<intrins.h>
#define led P2
char b;
void UART()
{
TMOD=0X20;//选择8位重装
TH1=0XF3;
TL1=0XF3;
PCON=0X80;
ET1=0;//禁止T1定时器中断
TR1=1;//打开T1中断
REN=1;//
SM1=1;
SM0=0;//选择模式1模式
RI=1;
TI=1;
ES=1;
EA=1;
}
void delay(int i)
{
while(i--);
}
//void LED() //函数名不能和宏定义一样
void LED()
{
int count=0,i=0;
while(1)
{
for(i=0;i<=16;i++)
{
if(i<=8)
{
led=(0xfe<<count);
delay(5000);
count++;
if(count>=8)
{
count=0;
}
}
else
{
led=(0x7f>>count);
delay(5000);
count++;
if(count>=8)
{
count=0;
i=0;
}
}
}
}
}
int main()
{
UART();//调用函数
while(1);
return 0;
}
void UARTintrrupt () interrupt 4
{
while(!RI);
b=SBUF;//将数据暂存在SBUF
RI=0;
SBUF=b;
while(!TI);
TI=0;
if(b=='1')
{
LED();
}
}
网友评论