实验二串口通讯实验Word格式.docx
《实验二串口通讯实验Word格式.docx》由会员分享,可在线阅读,更多相关《实验二串口通讯实验Word格式.docx(14页珍藏版)》请在冰点文库上搜索。
串口通讯
串口中断
Timer1
ISP
3.1主程序流程图
3.2串口发送子程序流程图
3.3串口接收子程序流程图
3.6定时器中断子程序流程图
四、实验步骤
⑴参照实验指导书连接杜邦线
⑵编写程序,并用KeilC软件调试程序
⑶程序编译无错后使用S51ISP下载软件将程序下载到单片机中
⑷观察实验现象,如果实验现象与预期不符则可以使用KeilC的软件仿真调试功能,通过软件仿真使程序单步运行,从中找到编程错误
⑸向实验指导老师讲解程序原理,整理仪器离开实验室
五、软件源码
#include<
reg52.h>
//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#defineDataPortP0//定义数据端口程序中遇到DataPort则用P0替换
#defineKeyPortP1//定义键盘扫描端口程序中遇到KeyPort则用P1替换
sbitLATCH1=P2^2;
//定义锁存使能端口段锁存
sbitLATCH2=P2^3;
//位锁存
unsignedcharcodedofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};
//显示段码值0~F
unsignedcharcodedofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
//分别对应相应的数码管点亮,即位码
unsignedcharTempData1,TempData3;
voidDelayUs2x(unsignedchart);
//us级延时函数声明
voidDelayMs(unsignedchart);
//ms级延时
voidDisplay(void);
//数码管显示函数
unsignedcharKeyScan(void);
//键盘扫描
unsignedcharKeyPro(void);
//取键值
voidInit_Timer0(void);
//定时器初始化
voidInitUART(void);
//串口初始化
/*------------------------------------------------
发送一个字节
------------------------------------------------*/
voidSendByte(unsignedchardat)
{
SBUF=dat;
//while(!
TI);
}
主函数
voidmain(void)
unsignedcharnum,j;
Init_Timer0();
InitUART();
ES=1;
while
(1)//主循环
{
num=KeyPro();
if(num!
=0xff)
TempData1=num;
j=num;
if(j>
=0&
&
j<
=9)
j=j+48;
elseif(j>
=10&
=15)
j=j+87;
SendByte(j);
}
uS延时函数,含有输入参数unsignedchart,无返回值
unsignedchar是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下T=tx2+5uS
voidDelayUs2x(unsignedchart)
{
while(--t);
mS延时函数,含有输入参数unsignedchart,无返回值
0~255这里使用晶振12M,精确延时请使用汇编
voidDelayMs(unsignedchart)
while(t--)
//大致延时1mS
DelayUs2x(245);
显示函数,用于动态扫描数码管
voidDisplay(void)
staticunsignedchari=0;
if(i==0)
{
DataPort=0;
//清空数据,防止有交替重影
LATCH1=1;
//段锁存
LATCH1=0;
DataPort=dofly_WeiMa[0];
//取位码
LATCH2=1;
//位锁存
LATCH2=0;
DataPort=dofly_DuanMa[TempData1];
//取显示数据,段码
i++;
else
DataPort=dofly_WeiMa[7];
DataPort=dofly_DuanMa[TempData3];
i=0;
定时器初始化子程序
voidInit_Timer0(void)
TMOD|=0x01;
//使用模式1,16位定时器,使用"
|"
符号可以在使用多个定时器时不受影响
//TH0=0x00;
//给定初值
//TL0=0x00;
EA=1;
//总中断打开
ET0=1;
//定时器中断打开
TR0=1;
//定时器开关打开
串口初始化
voidInitUART(void)
SCON=0x50;
//SCON:
模式1,8-bitUART,使能接收
PCON=0x80;
//SMOD=1,波特率加倍
TMOD|=0x20;
//TMOD:
timer1,mode2,8-bit重装
TH1=0xFD;
//TH1:
重装值9600波特率晶振11.0592MHz加倍后19200波特率
TR1=1;
//TR1:
timer1打开
EA=1;
//打开总中断
}
定时器中断子程序
voidTimer0_isr(void)interrupt1
TH0=(65536-2000)/256;
//重新赋值2ms
TL0=(65536-2000)%256;
Display();
//调用数码管扫描
串口中断程序
voidUART_SER(void)interrupt4//串行中断服务程序
unsignedcharTemp;
//定义临时变量
if(RI)//判断是接收中断产生
RI=0;
//标志位清零
Temp=SBUF;
//读入缓冲区的值
if(Temp>
='
0'
Temp<
9'
)
Temp=Temp-48;
elseif(Temp>
a'
f'
Temp=Temp-87;
TempData3=Temp;
if(TI)//如果是发送标志位,清零
TI=0;
按键扫描函数,返回扫描键值
unsignedcharKeyScan(void)//键盘扫描函数,使用行列逐级扫描法
unsignedcharVal;
KeyPort=0xf0;
//高四位置高,低四位拉低
if(KeyPort!
=0xf0)//表示有按键按下
DelayMs(10);
//去抖
=0xf0)
{//表示有按键按下
KeyPort=0xfe;
//检测第一行
if(KeyPort!
=0xfe)
{
Val=KeyPort&
0xf0;
Val+=0x0e;
while(KeyPort!
=0xfe);
DelayMs(10);
returnVal;
KeyPort=0xfd;
//检测第二行
=0xfd)
Val+=0x0d;
=0xfd);
KeyPort=0xfb;
//检测第三行
=0xfb)
Val+=0x0b;
=0xfb);
KeyPort=0xf7;
//检测第四行
=0xf7)
Val+=0x07;
=0xf7);
return0xff;
按键值处理函数,返回扫键值
unsignedcharKeyPro(void)
switch(KeyScan())
case0x7e:
return0;
break;
//0按下相应的键显示相对应的码值
case0x7d:
return1;
//1
case0x7b:
return2;
//2
case0x77:
return3;
//3
case0xbe:
return4;
//4
case0xbd:
return5;
//5
case0xbb:
return6;
//6
case0xb7:
return7;
//7
case0xde:
return8;
//8
case0xdd:
return9;
//9
case0xdb:
return10;
//a
case0xd7:
return11;
//b
case0xee:
return12;
//c
case0xed:
return13;
//d
case0xeb:
return14;
//e
case0xe7:
return15;
//f
default:
return0xff;
六、实验心得
通过本次实验,我建立起了对单片机资源分配的概念。
当程序比较复杂,要使用多种中断,多个计数器时就要合理分配资源,以解决各个功能之间的冲突。
在这次实验中,我掌握了串口通讯,编写了串口中断程序,实现了单片机与电脑的通讯。
串口通讯时要注意两个通讯的主体波特率要设置一致,这样数据位才能有条不紊地依次排队一个一个地传到对方,实现正确收发。
编写串口中断程序时要注意标志位的设置,否则会出现中断不响应的情况。
从数码管显示实验、按键实验到串口通讯实验,内容设置循序渐进,体现了分模块调试程序过程,提高了我们编写复杂程序的能力。