实验二串口通讯实验.docx
《实验二串口通讯实验.docx》由会员分享,可在线阅读,更多相关《实验二串口通讯实验.docx(14页珍藏版)》请在冰豆网上搜索。
实验二串口通讯实验
北京航空航天大学
计算机测控技术实验
实验二串口通讯实验
实验报告
一、实验目的
(1)掌握单片机串行口通讯程序的编制;
(2)了解实现串行通讯的硬件环境,数据格式及数据交换的协议;
(3)了解PC机通讯的基本要求。
二、硬件原理图
2.1串口电路原理图
实验箱串口电路原理图如图所示:
注:
使用专门用于STC(宏晶)系列单片机下载的STC-ISP下载线,无需使用串口线连接电脑与单片机。
2.2实验连线图
实验接线如下图所示:
单片机通过8279芯片驱动数码管,同时以P1口扫描4*4键盘键值,串口中断接收发送显示数据。
三、软件流程图
3.0单片机资源分配
内容
中断方式
定时\计数器
引脚
数码管显示
定时器中断
Timer0
P0P2.2P2.3
扫描键盘
无
无
P1P3.2
串口通讯
串口中断
Timer1
ISP
3.1主程序流程图
3.2串口发送子程序流程图
3.3串口接收子程序流程图
3.6定时器中断子程序流程图
四、实验步骤
⑴参照实验指导书连接杜邦线
⑵编写程序,并用KeilC软件调试程序
⑶程序编译无错后使用S51ISP下载软件将程序下载到单片机中
⑷观察实验现象,如果实验现象与预期不符则可以使用KeilC的软件仿真调试功能,通过软件仿真使程序单步运行,从中找到编程错误
⑸向实验指导老师讲解程序原理,整理仪器离开实验室
五、软件源码
#include//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#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&&j<=15)
j=j+87;
SendByte(j);
}
}
}
/*------------------------------------------------
uS延时函数,含有输入参数unsignedchart,无返回值
unsignedchar是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下T=tx2+5uS
------------------------------------------------*/
voidDelayUs2x(unsignedchart)
{
while(--t);
}
/*------------------------------------------------
mS延时函数,含有输入参数unsignedchart,无返回值
unsignedchar是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
voidDelayMs(unsignedchart)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
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];//取显示数据,段码
LATCH1=1;//段锁存
LATCH1=0;
i++;
}
else
{
DataPort=0;//清空数据,防止有交替重影
LATCH1=1;//段锁存
LATCH1=0;
DataPort=dofly_WeiMa[7];//取位码
LATCH2=1;//位锁存
LATCH2=0;
DataPort=dofly_DuanMa[TempData3];//取显示数据,段码
LATCH1=1;//段锁存
LATCH1=0;
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'&&Temp<='f')
Temp=Temp-87;
TempData3=Temp;
}
if(TI)//如果是发送标志位,清零
TI=0;
}
/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsignedcharKeyScan(void)//键盘扫描函数,使用行列逐级扫描法
{
unsignedcharVal;
KeyPort=0xf0;//高四位置高,低四位拉低
if(KeyPort!
=0xf0)//表示有按键按下
{
DelayMs(10);//去抖
if(KeyPort!
=0xf0)
{//表示有按键按下
KeyPort=0xfe;//检测第一行
if(KeyPort!
=0xfe)
{
Val=KeyPort&0xf0;
Val+=0x0e;
while(KeyPort!
=0xfe);
DelayMs(10);//去抖
while(KeyPort!
=0xfe);
returnVal;
}
KeyPort=0xfd;//检测第二行
if(KeyPort!
=0xfd)
{
Val=KeyPort&0xf0;
Val+=0x0d;
while(KeyPort!
=0xfd);
DelayMs(10);//去抖
while(KeyPort!
=0xfd);
returnVal;
}
KeyPort=0xfb;//检测第三行
if(KeyPort!
=0xfb)
{
Val=KeyPort&0xf0;
Val+=0x0b;
while(KeyPort!
=0xfb);
DelayMs(10);//去抖
while(KeyPort!
=0xfb);
returnVal;
}
KeyPort=0xf7;//检测第四行
if(KeyPort!
=0xf7)
{
Val=KeyPort&0xf0;
Val+=0x07;
while(KeyPort!
=0xf7);
DelayMs(10);//去抖
while(KeyPort!
=0xf7);
returnVal;
}
}
}
return0xff;
}
/*------------------------------------------------
按键值处理函数,返回扫键值
------------------------------------------------*/
unsignedcharKeyPro(void)
{
switch(KeyScan())
{
case0x7e:
return0;break;//0按下相应的键显示相对应的码值
case0x7d:
return1;break;//1
case0x7b:
return2;break;//2
case0x77:
return3;break;//3
case0xbe:
return4;break;//4
case0xbd:
return5;break;//5
case0xbb:
return6;break;//6
case0xb7:
return7;break;//7
case0xde:
return8;break;//8
case0xdd:
return9;break;//9
case0xdb:
return10;break;//a
case0xd7:
return11;break;//b
case0xee:
return12;break;//c
case0xed:
return13;break;//d
case0xeb:
return14;break;//e
case0xe7:
return15;break;//f
default:
return0xff;break;
}
}
六、实验心得
通过本次实验,我建立起了对单片机资源分配的概念。
当程序比较复杂,要使用多种中断,多个计数器时就要合理分配资源,以解决各个功能之间的冲突。
在这次实验中,我掌握了串口通讯,编写了串口中断程序,实现了单片机与电脑的通讯。
串口通讯时要注意两个通讯的主体波特率要设置一致,这样数据位才能有条不紊地依次排队一个一个地传到对方,实现正确收发。
编写串口中断程序时要注意标志位的设置,否则会出现中断不响应的情况。
从数码管显示实验、按键实验到串口通讯实验,内容设置循序渐进,体现了分模块调试程序过程,提高了我们编写复杂程序的能力。