玩过51单片机的都应该用过串口,把单片机的数据发送到电脑的串口助手进行显示。今天我们讲一下怎么用两个单片机的串口进行通信,也就是一个单片机采集数据,通过串口发送到另一个单片机进行显示数据,仿真如上图,想要仿真和程序的,可以回复“双机通信程序”来获取。
这个接线也简单,需要注意的是一个单片机的RX要接另一个单片机的TX哦,而不是RX接RX。
下面我简单讲一下51单片机的串口通信程序,供大家参考。
我们串口波特率配置成9600、8位数据位,无校验,1位停止位,也就是我们经常说的8N1.
================================
接下来讲一下串口要用到的寄存器:
(1)SCON控制寄存器:
SCON: D7 D6 D5 D4 D3 D2 D1 D0
SM0 SM1 SM2 REN TB8 RB8 TI RI
(1).SM0、SM1:串行口工作方式控制位。
SM0 SM1 工作方式 功能 波特率
0 0 方式0 8位同步移位寄存器 F/12
0 1 方式1 10位UART 可变
1 0 方式2 11位UART F/64或F/32
1 1 方式3 11位UART 可变
我们选择方式1,10位UART。啥不是8位数据吗?怎么变成10位了。
哈哈哈,是8位数据位,加1位停止位,在加1位起始位,就是10位咯。
(2).SM2:多机通信控制位。
(3).REN:允许接收位。
(4).TB8:发送接收数据位8。
(5).RB8:接收数据位8。
(6).TI:发送中断标志位。
(7).RI:接收中断标志位。
SCON当然可以根据通讯需要设置的,
SCON=0x50是SM1=1和REN=1,设置串口方式1且允许串口接收。
一般配合TMOD=0x20作串口中断程序初始化。
=================================
(2)TMOD寄存器
TMOD寄存器
B7 B6 B5 B4 B3 B2 B1 B0
GATE C/T M1 M0 GATE C/T M1 M0
M1 M0 工作模式
0 0 13位计数/计时器
0 1 16位计数/计时器
1 0 8位自动加载计数/计时器
1 1 定时器1停止工作,定时器0分为两个独立的8位定时器TH0及TL0
TMOD=0X20:使用定时器1,8位自动加载计时器
=====================================
串口波特率计算
和波特率有关的还有一个寄存器PCON,这个寄存器的最高位置1就可以把波特率提高一倍,即PCON|=0x80,波特率计算公式为TH1 = TL1 = 256 – 晶振值/12/16/波特率
我们以晶振为12M,波特率为9600为例子,如下
TH1 = TL1 = 256 –12000000/12/16/9600 = 250 = 0xfa
=========================================
好有了上面的基础,我们就开始写程序,如下
1、串口初始化程序
void Init_USART()
{
SCON=0x50; //串口方式1,使能接收
TMOD|=0x20; //定时器1工作方式2(8位自动重装初值)
TMOD&=~0x10;
TH1=0xfa; //9600bps
TL1=0xfa;
PCON|=0x80; //SMOD=1
TI=0; //发送中断标志位
RI=0; //接收中断标志位
ES=1; //开启串口中断使能
TR1=1; //启动定时器1
EA = 1; //开启总中断
}
TMOD|= 0x20和TMOD= 0x20有什么区别啊,为什么使用前者呢??
TMOD|= 0x20等价于,TMOD= TMOD|0x20
表示将TMOD的第5位置1,而后者表示直接赋值。所以只让TMOD的第5位置1而不改变其他位的值就用TMOD|= 0x20
2、串口发送数据程序
void send_data(unsigned char *TXStr,char num)
{
char i;
ES=0;
for(i = 0; i < num; i++)
{
SBUF=*TXStr;
while(TI==0);
TI=0;
TXStr++;
}
ES=1;
}
3、串口接收数据程序
char g_recstr;
void USART() interrupt 4
{
g_recstr=SBUF;
RI=0;
}
==============================
好了,今天先讲这么多,接下来我们会讲一下双机通信的通信协议哦,如果对你有用请给《嵌入式单片机设计》点个关注哦。也欢迎大家在嵌入式单片机设计吧发帖分享你的学习心得,大家一起交流学习。