单片机串口实验.docx
《单片机串口实验.docx》由会员分享,可在线阅读,更多相关《单片机串口实验.docx(16页珍藏版)》请在冰豆网上搜索。
单片机串口实验
单片机课程设计报告
实验一串口通信实验
系别
年级专业
班级班
学号
学生姓名
指导教师
设计时间
2.1实验目的............................2
2.2实验内容............................2
1.题目
串口通信实验
2.实验要求
2.1:
实验目的
1、掌握8051单片机串行口工作原理;
2、掌握串口编程与调试方法;
3、了解Modbus协议及其应用;
4、了解数据传输的可靠性措施与CRC校验实现方法;
5、掌握8051单片机的Modbus编程;
2.2:
实验内容
1、串口功能验证:
PC机与8051单片机通信实验:
若PC机发送数据a,则单片机接收到a后向PC机发送a+1;用串口工具软件(sscom32)观察通信结果。
设计思路:
PC机采用主动方式,单片机为被动方式,因单片机端不知道PC何时发数据,若单片机采用查询方式接收,会产生接收不到PC数据而“死等”的现象。
因此为了不影响单片机端的主程序运行,单片机应采用中断方式接收;
参考源码:
//中断服务程序
unsignedcharRxd_Data;//串口接收数据
unsignedcharRxd_Over;//串口接收完成标志
//串口初始化函数9600bps
voidSbuf_Init(void)
{
SCON=0x50;//10位方式
//波特率设置
PCON=0x00;//波特率不倍增
TMOD=(TMOD&0x0f)|0x20;//T1方式2
TH1=0xfd;//T1计数初值
TL1=0xfd;
ES=1;EA=1;//串口中断使能
TR1=1;//启动定时器
}
voidUART_ISR(void)interrupt4
{
if(RI)//接收产生的中断
{
RI=0;//清接收标志
Rxd_Data=SBUF;//接收数据
Rxd_Over=1;//置Rxd_Over标志
}
}
voidmain(void)
{
Sbuf_Init();//串口初始化
while
(1)
{
if(Rxd_Over)//若接收完成
{
//串口数据发送
SBUF=a+1;//串口发送
while(TI==0);//等待发送完成
TI=0;//清发送标志
Rxd_Over=0;//清Rxd_Over标志
}
}
}
利用此程序可以判断串口通信是否正常。
串口通信失败的原因有如下几种情况:
(1)串口线未连接,用一根导线将串口线2,3脚短接,scomm32工具发送数据,根据能否接收数据判断串口线连接是否正常;
(2)最小系统板硬件故障:
借助示波器观察单片机的串口接收与发送CMOS电平与RS232电平可排查硬件故障;
(3)软件问题。
2、类Modbus协议实现
(1)上位机发送:
字节1
字节2
字节3
字节4
字节5
字节6
字节7
字节8
0x01
0x03
0x02
a
数据2
数据3
CRC16_L
CRC16_H
上位机按如上8字节定长方式发送数据a,采用CRC16检验,CRC16检验可采用查表法或即时计算法(已在CRC16.c与CRC16.h中提供,可直接调用),其中上位机的CRC16可采用提供的ModBusCRC校验码计算程序工具先计算得到。
(2)下位机接收后回送
下位机中断方式接收到8字节数据后进行CRC计算并与接收的CRC16数据进行比较,若一致则回应:
字节1
字节2
字节3
字节4
字节5
字节6
字节7
字节8
0x01
0x03
0x02
a+1
数据2
0(成功)
CRC16_L
CRC16_H
若接收数据错误则回应
字节1
字节2
字节3
字节4
字节5
字节6
字节7
字节8
0x01
0x03
0x02
*
数据2
0xff(失败)
CRC16_L
CRC16_H
校验可采用查表法或即时计算法得到。
unsignedshortintCRC16_S(unsignedchar*buf,unsignedcharlength)//查表法
unsignedshortintCRC16_C(unsignedchar*buf,unsignedcharlength)//即时计算法
3.总体设计
3.1硬件设计
1.串口结构
TB8(TransmitBit8)在方式2、3中,将被发送数据的第9位(奇偶校验位等);
RB8(ReceiveBit8-第9位)
TI、RI发送/接收结束标志位,软件(手工)清零
方式0:
移位寄存器输入/输出方式。
数据通过RXD输入/输出,TXD输出移位脉冲CP。
该方式下,收发数据为8位,低位在前。
波特率固定(fosc/12)。
方式1:
10位异步方式。
10位=1位起始位(0)+8位数据位+1位停止位
(1)。
其中起始位和停止位在发送时自动插入。
发送:
SBUF=a;发送条件:
TI=0,发送完TI=1。
接收:
b=SBUF;接收条件:
SCON中的REN=l;RI=0;SM2=0或接收到的停止位为l。
本次接收有效,将接收到的8位数据装入SBUF中,并将停止位
(1)装入RB8中;否则放弃接收结果。
发送与接收结束标志必须手工清0:
TI=0;RI=0;方式1的波特率可变,计算公式:
Baud=2^SMOD×(T1的溢出率)/32。
方式2、3:
相同:
都是11位异步方式。
11位=1位起始位(0)+9位数据位+1位停止位
(1)。
其中第9位数据放在TB8、RB8中,发送前可通过软件对TB8赋值(奇偶校验位等)。
它们的操作过程完全一样。
不同:
波特率可变否。
方式2Baud=2^SMOD×fosc/64;方式3Baud=2^SMOD×(T1溢出率/32)。
发送:
SBUF=a;第9位数据(TB8)输出之后,置位TI=1。
接收:
b=SBUF;接收前提:
REN=1;接收到第9位数据后,如果同时满足:
(1)RI=0;
(2)SM2=0或接收到的第9位为1,则将已接收的数据装入SBUF和RB8,并置位RI;如果条件不满足,则接收无效。
8051第9位可作为数据的奇偶校验位、多机通信中的地址、数据标志位等。
(4)串行中断原理
执行串口发送指令SBUF=a;通过TXD口发送串行数据,发送结束后CPU自动产生发送结束标志(TI=1);此时若串行中断使能,则程序立即停止当前程序,跳转置中断号为4的串行口中断入口地址(0x0023),执行中断服务程序voidUART_ISR(void)interrupt4,CPU不具有自动清零功能;同样,若串口在RXD引脚接收到数据,硬件自动产生接收结束标志(RI=1),若此时若串行中断使能(ES=1,EA=1),则程序立即停止当前程序,跳转置中断号为4的串行口中断入口地址(0x0023),执行中断服务程序voidUART_ISR(void)interrupt4,CPU不具有自动清零功能,可通过b=SBUF;指令取出暂存在数据缓冲区内的数据。
因为接收与发送结束都能进入同一中断,因此在不具有自动清标志功能,需加判断标志语句。
4.串口操作步骤
使用串口前,应对它进行初始化。
设置串行口工作方式控制(SCON);
设置串口通信波特率:
T1(TMOD、TH1、TL1、ET1、EA、TR1、PCON);
串口中断使能(ES、EA)。
具体步骤如下:
(1)设置串行口工作方式控制(SCON)
如11位波特率可变的异步通信方式:
SCON
SM0
SM1
SM2
REN
TB8
RB8
TI
RI
SCON=0xd0;(11010000)
(2)借助T1初使化通信波特率(TMOD)
PCON
SMOD
-
-
-
-
-
-
-
87H
TMOD
GATE
C/T#
M1
M0
GATE
C/T#
M1
M0
89H
Baud=2^SMOD×(T1溢出率/32)
令SMOD=0,则9600=1/(n*12/fosc*32),若fosc=11.0592则n=3
T1:
采用方式2(8位自动载入)
即:
PCON=0x00;
TMOD=(TMOD&0x0f)|0x20;
TH1=0xfd;
TL1=0xfd;
TR1=1;
3.2软件设计
源程序:
#include"reg51.h"
#include"crc16.h"
externunsignedshortintCRC16_S(unsignedchar*buf,unsignedcharlength);
externunsignedshortintCRC16_C(unsignedchar*buf,unsignedcharlength);
unsignedcharRxd_buf[8],Txd_buf[8];
//中断服务程序
//unsignedcharRxd_Data;//串口接收数据
unsignedcharRxd_Over;//串口接收完成标志
//串口初始化函数9600bps
voidSbuf_Init(void)
{
SCON=0x50;//10位方式
//波特率设置
PCON=0x00;//波特率不倍增
TMOD=(TMOD&0x0f)|0x20;//T1方式2
TH1=0xfd;//T1计数初值
TL1=0xfd;
ES=1;EA=1;//串口中断使能
TR1=1;//启动定时器
}
voidUART_ISR(void)interrupt4
{
staticunsignedcharcount=0;
staticunsignedcharpre_data=0,mid_data=0,now_data;
if(RI)//接收产生的中断
{
RI=0;//清接收标志
now_data=SBUF;
if(pre_data==0x01&&mid_data==0x03&&now_data==0x02)
{
Rxd_buf[0]=0x01;
Rxd_buf[1]=0x03;
Rxd_buf[2]=0x02;
count=3;
}
else
{
Rxd_buf[count]=now_data;
count++;
if(count==8)
{
count=0;
Rxd_Over=1;
}
}
pre_data=mid_data;
mid_data=now_data;
}
}
voiddelay(unsignedintn)
{
unsignedinti;
for(i=0;i;
}
voidmain(void)
{
unsignedchari;
unsignedintcrc_value;
Sbuf_Init();//串口初始化
while
(1)
{
//串口数据发送
if(Rxd_Over)//若接收完成
{
crc_value=CRC16_S(Rxd_buf,6);
Rxd_Over=0;
if(crc_value%256==Rxd_buf[6]&&crc_value/256==Rxd_buf[7])
//if
(1)
{
Txd_buf[0]=0x01;
Txd_buf[1]=0x03;
Txd_buf[2]=0x02;
Txd_buf[3]=Rxd_buf[3]+1;
Txd_buf[4]=0x00;
Txd_buf[5]=0x00;
crc_value=CRC16_S(Txd_buf,6);
Txd_buf[6]=crc_value%256;
Txd_buf[7]=crc_value/256;
for(i=0;i<8;i++)
{
SBUF=Txd_buf[i];
while(TI==0)
{
;
}
T1=0;
delay(20);
}
}
else
{
Txd_buf[0]=0x01;
Txd_buf[1]=0x03;
Txd_buf[2]=0x02;
Txd_buf[3]=Rxd_buf[3]+1;
Txd_buf[4]=0x00;
Txd_buf[5]=0xff;
crc_value=CRC16_S(Txd_buf,6);
Txd_buf[6]=crc_value%256;
Txd_buf[7]=crc_value/256;
for(i=0;i<8;i++)
{
SBUF=Txd_buf[i];
while(TI==0)
{
;
}
T1=0;
delay(20);
}
}
}
}
}
4.运行结果
正确串口输出错误的串口输出
5.结论
利用单片机进行串口的连接,输入与输出。
编写程序,实现加一功能,当输入错误时,串口输出FF,当输入正确时,输出自动加一,并且显示输出00,表示输入的结果是正确的。
这样就实现了串口之间的连接与信息的传递。
6.心得体会
通过此次设计,我们了解到单片机的工作原理,已经串口通信的工作方式,加深了对单片机的掌握。
掌握8051单片机串行口工作原理,掌握串口编程与调试方法,了解Modbus协议及其应用,了解数据传输的可靠性措施与CRC校验实现方法,掌握8051单片机的Modbus编程。
7.参考文献
单片机的C语言应用程序设计主编孙娟马忠梅北京航空航天大学出版社
新概念51单片机C语言教程主编郭天祥电子工业出版社社