第4讲 单片机综合实验仪程序设计及调试实验.docx
《第4讲 单片机综合实验仪程序设计及调试实验.docx》由会员分享,可在线阅读,更多相关《第4讲 单片机综合实验仪程序设计及调试实验.docx(52页珍藏版)》请在冰豆网上搜索。
第4讲单片机综合实验仪程序设计及调试实验
第4讲单片机综合实验仪程序设计及调试
1、设计目的
了解单片机综合实验仪各模块程序设计方法。
掌握KEILC51下单片机综合实验仪各模块程序设计和调式及PROTEUS下的系统仿真方法。
通过本次课程设计,达到熟练掌握KEILC51下和PROTEUS下单片机综合实验仪各模块程序设计、调试和仿真的目的。
2、设计内容
(1)由6位同学组成单片机综合实验仪程序设计小组。
(2)从老师提供的网站上,下载本课程设计课件。
(3)根据单片机综合实验仪划分的6个模块,分别由6个同学完成6个模块程序设计、调试和仿真。
(3)在KEILC51下和PROTEUS下,按本课程设计课件的程序设计要求,每位同学主攻单片机综合实验仪一个模块的程序设计、调试和仿真。
(4)结合上次实验兼顾的单片机综合实验仪其它模块原理图设计和绘制。
完成相对应的程序模块设计、调试和仿真。
(5)单片机综合实验仪设计小组6位同学相互协作完成单片机综合实验仪所有程序模块的调试和统调及仿真。
3、使用器材
(1)Proteus系统仿真软件
(2)KEILC51程序设计仿真软件(3)计算机1台
4、单片机综合实验仪程序模块构成
5.单片机综合实验仪各模块程序设计要求
(1)单片机系统部分
●工作灯闪烁(参考书上例5-1,编写设计程序)
程序:
运行时,使P3.2接的LED发光二极管闪烁。
提示:
给出下述程序,完善main()程序。
#include
unsignedinti;
main()
{
unsignedinti;
<######>/*初始化工作灯(灭)*/
while
(1)
{
<######>/*工作灯闪烁*/
for(i=0;i<30000;i++);//延时
}
}
(2)并口接口输入输出部分
●打码开关(参考书上例5-2,编写设计程序)
程序要求:
将开关的状态反映到发光二极管上。
●流水灯(定时查询)(参考书上例7-1,编写设计程序)
程序:
采用定时查询方式,使8个管轮流点亮;开关K1的状态改变轮流点亮的顺序。
每个管亮100ms,设晶振为6MHz。
(计数时钟周期2us)
分析:
利用T1完成100ms的定时。
当P0口线输出“0”时,发光二极管亮,
每隔100ms”0”左移一次,采用定时方式1,先计算计数初值:
MC=2μs
100ms/2μs=50000=C350H
[C350H]补=10000H-C350H=3CB0H
提示:
给出下述程序,完善main()程序。
}#include
voidmain(void)
{
unsignedchartemp;
temp=1;
P0=~temp;/*第一只LED亮*/
<######>/*定时器1方式1*/
<######>/*启动T/C1*/
for(;;)
{
TH1=0x3c;TL1=0xb0;/*装载计数初值*/
do{}while(!
TF1);/*查询等待TF1置位*/
if(P2_0==1)//K1的状态为1,正序流水灯
{
<######>
<######>/*定时时间到,下一只LED亮*/
}
Else//K1的状态为0,反序流水灯
{
if(temp==0x01)temp=0x80;
elsetemp>>=1;/*定时时间到,下一只LED亮*/
}
P0=~temp;
TF1=0;/*软件清TF1*/
}
}
●流水灯(定时中断)(参考书上例7-1,编写设计程序)
程序:
采用定时中断方式,使8个管轮流点亮。
每个管亮100ms,设晶振为6MHz。
(计数时钟周期2us)
分析:
利用T1完成100ms的定时。
当P0口线输出“1”时,发光二极管灭,
每隔100ms”1”左移一次,采用定时方式1,先计算计数初值:
MC=2μs
100ms/2μs=50000=C350H
[C350H]补=10000H-C350H=3CB0H
提示:
给出下述程序,完成main()程序。
//②中断方式1
#include
Timer1()interrupt3using1/*T1中断服务程序*/
{
P0=(P0==0X80)?
0x01:
(P0<<1);/*下一只LED亮*/
TH1=0x3c;TL1=0xb0;/*计数初值重载*/
}
voidmain(void)
{
<######>/*T1工作在定时方式1*/
<######>/*第一只LED亮*/
<######>/*预置计数初值*/
<######>/*CPU开中断,允许T1中*/
<######>/*启动T1开始定时*/
do{}while
(1);/*等待中断*/
}
(3)中断、定时计数、串行通信部分
●外部中断INT1触发的计数(参考书上例6-2、例6-3、例6-4,编写设计程序)
程序要求:
对每次中断,在左边第一个LED数码显示器上进行计数。
提示:
给出下述程序,完成main()程序。
#include
chari;
codechartab[16]={0x3f,0x06,0x5b,0x4F,0x66,0x6d,0x7d,0x07,//"0~7"
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//"8~f"
int1()interrupt2
{i++;
if(i<16)P2=tab[i];//计数显示
else{i=0;P2=0x3f;}//超过15次,归0显示。
}
main()
{
<######>//开中断;允许-INT1中断;边沿触发中断。
<######>//初始中断计数变量
<######>//选择最左边LED。
<######>//初始显示“0”
while
(1);/*等待中断*/
}
●外部计数溢出中断显示LED段位(参考书上例7-1,编写设计程序)
程序要求:
计两个外部脉冲,LED数码显示段加1。
提示:
给出下述程序,完成main()程序。
#include
unsignedchara;
Timer0()interrupt1//定时器0中断服务程序
{
if(a==0x80)a=1;//当最高段位显示后,初始段位显示码
elsea<<=1;//形成下1段位显示码
P2=a;//显示段位显示码
}
main()
{
<######>/*T0方式1计数*/
<######>/*设置T0计数初值(计2脉冲溢出)*/
<######>/*开中断,允许T0中断*/
<######>/*启动定时计数器T0*/
<######>//最低位允许最左边LED显示器显示段位。
<######>//初始段位显示码
<######>//显示段位显示码
while
(1);/*等待中断*/
}
●串行查询方式自收发按键信息显示()
程序要求:
采用查询方式,在短接收发引脚的基础上,自发和收当前按键键码信息,并在LED显示器上显示接收信息。
提示:
给出下述程序,完成main()程序。
#include
#defineucharunsignedchar
#defineuintunsignedint
ucharled_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,//定义"0~7"段码
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};//定义"8~f,空格"段码
uchardisp_buf[4]={16,16,16,16};//显示缓冲区初始化为显示成空格的索引码16
ucharkey_code=10;
voiddlms(void);//延时函数说明
voiddisp(void);//显示函数说明
ucharkbscan(void);//键扫描函数说明
main()
{
ucharkey;
disp();//刷新显示
TMOD=0x20;TH1=0xcc;TL1=0xcc;//初始化T1(方式2;600波特)
TR1=1;
SCON=0x50;//设定串行口方式1,并允许接收
while
(1)
{
<######>//调键扫描函数,返回键码送key保存
if(key!
=0)//有键按下时,显示键码
{
<######>//初始显示缓冲(右端LED显示按键顺序码;其余显示空格)
RI=0;//RI清0后;只有收到新的按键值时,方显示按键值信息。
TI=0;//发送前TI清0
<######>//发送键码高4位
while(TI==0);//TI=0等待
while(RI==0);//RI=0等待
RI=0;//RI=1清RI
if(SBUF!
=0)disp_buf[0]=SBUF;//接收数据并送显示缓冲区左端第1个LED显示器
TI=0;
<######>//发送键码低4位
while(TI==0);//TI=0等?
while(RI==0);//RI=0等待
RI=0;//RI=1清RI
if(SBUF!
=0)disp_buf[1]=SBUF;//接收数据并送显示缓冲区左端第2个LED显示器
}
<######>//刷新显示
}
}
voiddlms(void){uchari;for(i=200;i>0;i--);}/*去抖延时函数*/
ucharkbscan(void)/*键盘扫描函数*/
{
ucharsccode,recode,i,j;
P0=0xf0;/*P0.0~P0.3发全0,P0.4~P0.7输入*/
if((P0&0xf0)!
=0xf0)/*如P0口高四位不全为1有键按下*/
{
dlms();/*延时去抖动*/
if((P0&0xf0)!
=0xf0)/*再读输入值*/
{
sccode=0xfe;/*最低位置为0(设置行扫描码)*/
for(i=0;i<4;i++)
{
P0=sccode;/*P0口输出行扫描码*/
if((P0&0xf0)!
=0xf0)//如P0.4~P0.7不为全1,该行有键按下
{
recode=P0&0xf0;//保留P0口高四位输入值(列码)
sccode=sccode&0x0f;/*保留扫描码低四位(行码)*/
if(P0_4==0)j=0;
if(P0_5==0)j=1;
if(P0_6==0)j=2;
if(P0_7==0)j=3;
key_code=i*4+j;
P1=0x00;//低4位关闭所有LED。
while((P0&0xf0)!
=0xf0);//等待松开键
return(sccode+recode);/*行码+列码=键编码返回主程序*/
}
elsesccode=(sccode<<1)|0x01;//如该行无键按下,查下一行,行扫描值左移一位
}
}
}
return(0);/*无键按下,返回值为0*/
}
voiddisp(void)//显示函数说明
{
staticchari=0,j=1;//定义和初始化两个静态变量(i:
显示缓冲单元计数;j:
位选码)
P1=0x00;//低4位关闭所有LED。
P2=led_code[disp_buf[i++]];//输出显示缓冲区i单元内容对应的段码,然后i计数加一。
P1=j;j<<=1;//低4位输出位选码,然后产生下一位的位选码。
if(i==4)//i等于4,重新初始化显示缓冲单元计数i和位选码j。
{
i=0;
j=1;
}
}
●串行中断方式自收发按键信息显示
程序要求:
采用中断方式,在短接收发引脚的基础上,自发和收当前按键键码信息,并在LED显示器上显示接收信息。
提示:
给出下述程序,完成main()程序。
#include
#defineucharunsignedchar
#defineuintunsignedint
ucharled_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,//定义"0~7"段码
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};//定义"8~f,空格"段码
uchardisp_buf[4]={16,16,16,16};//显示缓冲区初始化为显示成空格的索引码16
ucharkey_code=10;//按键顺序码
voiddlms(void);//延时函数说明
voiddisp(void);//显示函数说明
ucharkbscan(void);//键扫描函数说明
main()
{
ucharkey;
<######>//刷新显示
<######>//初始化T1(方式2;600波特)
<######>//启动T1计数
SCON=0x50;//设定串行口方式1,并允许接收
<######>//开中断,允许串行通信中断
while
(1)
{
<######>//调键扫描函数,返回键码送key保存
if(key!
=0)//有键按下时,显示键码
{
disp_buf[3]=key_code;disp_buf[0]=16;disp_buf[1]=16;//初始显示缓冲(右端LED显示按键顺序码;其余显示空格)
TI=0;
SBUF=key>>4;//发送键码高4位
while(TI==0);//TI=0等待
TI=0;
SBUF=key&0x0F;//发送键码低4位
while(TI==0);//TI=0等
}
<######>//刷新显示
}
}
voiddlms(void){uchari;for(i=200;i>0;i--);}/*去抖延时函数*/
ucharkbscan(void)/*键盘扫描函数*/
{
ucharsccode,recode,i,j;
P0=0xf0;/*P0.0~P0.3发全0,P0.4~P0.7输入*/
if((P0&0xf0)!
=0xf0)/*如P0口高四位不全为1有键按下*/
{
dlms();/*延时去抖动*/
if((P0&0xf0)!
=0xf0)/*再读输入值*/
{
sccode=0xfe;/*最低位置为0(设置行扫描码)*/
for(i=0;i<4;i++)
{
P0=sccode;/*P0口输出行扫描码*/
if((P0&0xf0)!
=0xf0)//如P0.4~P0.7不为全1,该行有键按下
{
recode=P0&0xf0;//保留P0口高四位输入值(列码)
sccode=sccode&0x0f;/*保留扫描码低四位(行码)*/
if(P0_4==0)j=0;
if(P0_5==0)j=1;
if(P0_6==0)j=2;
if(P0_7==0)j=3;
key_code=i*4+j;
P1=0x00;//低4位关闭所有LED。
while((P0&0xf0)!
=0xf0)disp();//等待松开键,并且刷新显示。
return(sccode+recode);/*行码+列码=键编码返回主程序*/
}
elsesccode=(sccode<<1)|0x01;//如该行无键按下,查下一行,行扫描值左移一位
}
}
}
return(0);/*无键按下,返回值为0*/
}
voiddisp(void)//显示函数说明
{
staticchari=0,j=1;//定义和初始化两个静态变量(i:
显示缓冲单元计数;j:
位选码)
P1=0x00;//低4位关闭所有LED。
P2=led_code[disp_buf[i++]];//输出显示缓冲区i单元内容对应的段码,然后i计数加一。
P1=j;j<<=1;//低4位输出位选码,然后产生下一位的位选码。
if(i==4)//i等于4,重新初始化显示缓冲单元计数i和位选码j。
{
i=0;
j=1;
}
}
serial_int()interrupt4//串口接收中断程序
{
staticbiti=0;//显示缓冲单元选择变量
if(RI)
{
RI=0;
if(SBUF!
=0)
{
disp_buf[i]=SBUF;//接收数据并送显示缓冲区左端第1(i=0)、2(i=1)个LED显示器
i=~i;
}
}
}
(4)矩阵(4X4)键盘LED显示部分
●按键键码显示(参考书上5.3.2章节,编写设计程序)
程序要求:
在LED显示器上显示当前按键的键码。
提示:
给出下述程序,完成main()程序。
#include
#defineucharunsignedchar
#defineuintunsignedint
ucharled_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,//定义"0~7"段码
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};//定义"8~f,空格"段码
uchardisp_buf[4]={16,16,16,16};//显示缓冲区初始化为显示成空格的索引码16
ucharkey_code=10;
voiddlms(void);//延时函数说明
voiddisp(void);//显示函数说明
ucharkbscan(void);//键扫描函数说明
main()
{
ucharkey;
<######>//刷新显示
while
(1)
{
<######>//调键扫描函数,返回键码送key保存
if(key!
=0)//有键按下时,显示键码
{
<######>//键码高4位送缓冲区0号单元
<######>//键码低4位送缓冲区1号单元
disp_buf[3]=key_code;
}
<######>//刷新显示
}
}
voiddlms(void){uchari;for(i=200;i>0;i--);}/*去抖延时函数*/
ucharkbscan(void)/*键盘扫描函数*/
{
ucharsccode,recode,i,j;
P0=0xf0;/*P0.0~P0.3发全0,P0.4~P0.7输入*/
if((P0&0xf0)!
=0xf0)/*如P0口高四位不全为1有键按下*/
{
dlms();/*延时去抖动*/
if((P0&0xf0)!
=0xf0)/*再读输入值*/
{
sccode=0xfe;/*最低位置为0(设置行扫描码)*/
for(i=0;i<4;i++)
{
P0=sccode;/*P0口输出行扫描码*/
if((P0&0xf0)!
=0xf0)//如P0.4~P0.7不为全1,该行有键按下
{
recode=P0&0xf0;//保留P0口高四位输入值(列码)
sccode=sccode&0x0f;/*保留扫描码低四位(行码)*/
if(P0_4==0)j=0;
if(P0_5==0)j=1;
if(P0_6==0)j=2;
if(P0_7==0)j=3;
key_code=i*4+j;
return(sccode+recode);/*行码+列码=键编码返回主程序*/
}
elsesccode=(sccode<<1)|0x01;//如该行无键按下,查下一行,行扫描值左移一位
}
}
}
return(0);/*无键按下,返回值为0*/
}
voiddisp(void)//显示函数说明
{
staticchari=0,j=1;//定义和初始化两个静态变量(i:
显示缓冲单元计数;j:
位选码)
P1=0x00;//低4位关闭所有LED。
P2=led_code[disp_buf[i++]];//输出显示缓冲区i单元内容对应的段码,然后i计数加一。
P1=j;j<<=1;//低4位输出位选码,然后产生下一位的位选码。
if(i==4)//i等于4,重新初始化显示缓冲单元计数i和位选码j。
{
i=0;
j=1;
}
}
●按EE键切换显示1234和HELL信息(参考书上例5-4,编写设计程序)
程序要求:
按下“EE”键,切换显示“1234”“HELL”字样信息。
提示:
给出下述程序,完成main()程序。
#include
#defineuintunsignedint
#defineucharunsignedchar
main()
{
ucharcodetab1[4]={0x06,0x5b,0x4f,0x66};//定义“1234”的字形码表
ucharcodetab2[4]={0x76,0x79,0x38,0x38};//定义“HELL”的字形码表
uchari,SELE_B,k=0;uintj;