单片机C语言实验及实践教程2.doc
- 文档编号:2122346
- 上传时间:2023-05-02
- 格式:DOC
- 页数:33
- 大小:314.50KB
单片机C语言实验及实践教程2.doc
《单片机C语言实验及实践教程2.doc》由会员分享,可在线阅读,更多相关《单片机C语言实验及实践教程2.doc(33页珍藏版)》请在冰点文库上搜索。
51单片机C语言实验及实践教程2
8. 按键识别方法之一
1.实验任务I/O并行口直接驱动LED显示
每按下一次开关SP1,计数值加1,通过AT89S51单片机的P1端口的P1.0到P1.3显示出其的二进制计数值。
2.电路原理图
图4.8.1
3.系统板上硬件连线
(1. 把“单片机系统”区域中的P3.7/RD端口连接到“独立式键盘”区域中的SP1端口上;
(2. 把“单片机系统”区域中的P1.0-P1.4端口用8芯排线连接到“八路发光二极管指示模块”区域中的“L1-L8”端口上;要求,P1.0连接到L1,P1.1连接到L2,P1.2连接到L3,P1.3连接到L4上。
4.程序设计方法
(1. 其实,作为一个按键从没有按下到按下以及释放是一个完整的过程,也就是说,当我们按下一个按键时,总希望某个命令只执行一次,而在按键按下的过程中,不要有干扰进来,因为,在按下的过程中,一旦有干扰过来,可能造成误触发过程,这并不是我们所想要的。
因此在按键按下的时候, 图4.8.2
要把我们手上的干扰信号以及按键的机械接触等干扰信号给滤除掉,一般情况下,我们可以采用电容来滤除掉这些干扰信号,但实际上,会增加硬件成本及硬件电路的体积,这是我们不希望,总得有个办法解决这个问题,因此我们可以采用软件滤波的方法去除这些干扰信号,一般情况下,一个按键按下的时候,总是在按下的时刻存在着一定的干扰信号,按下之后就基本上进入了稳定的状态。
具体的一个按键从按下到释放的全过程的信号图如上图所示:
从图中可以看出,我们在程序设计时,从按键被识别按下之后,延时5ms以上,从而避开了干扰信号区域,我们再来检测一次,看按键是否真得已经按下,若真得已经按下,这时肯定输出为低电平,若这时检测到的是高电平,证明刚才是由于干扰信号引起的误触发,CPU就认为是误触发信号而舍弃这次的按键识别过程。
从而提高了系统的可靠性。
由于要求每按下一次,命令被执行一次,直到下一次再按下的时候,再执行一次命令,因此从按键被识别出来之后,我们就可以执行这次的命令,所以要有一个等待按键释放的过程,显然释放的过程,就是使其恢复成高电平状态。
(1. 对于按键识别的指令,我们依然选择如下指令JB BIT,REL指令是用来检测BIT是否为高电平,若BIT=1,则程序转向REL处执行程序,否则就继续向下执行程序。
或者是 JNB BIT,REL指令是用来检测BIT是否为低电平,若BIT=0,则程序转向REL处执行程序,否则就继续向下执行程序。
(2. 但对程序设计过程中按键识别过程的框图如右图所示:
图4.8.3
5.程序框图
图4.8.4
6.汇编源程序
ORG0
START:
MOVR1,#00H ;初始化R7为0,表示从0开始计数
MOVA,R1 ;
CPLA ;取反指令
MOVP1,A ;送出P1端口由发光二极管显示
REL:
JNBP3.7,REL ;判断SP1是否按下
LCALLDELAY10MS ;若按下,则延时10ms左右
JNBP3.7,REL ;再判断SP1是否真得按下
INCR7 ;若真得按下,则进行按键处理,使
MOVA,R7 ;计数内容加1,并送出P1端口由
CPLA ;发光二极管显示
MOVP1,A ;
JNBP3.7,$ ;等待SP1释放
SJMPREL ;继续对K1按键扫描
DELAY10MS:
MOVR6,#20 ;延时10ms子程序
L1:
MOVR7,#248
DJNZR7,$
DJNZR6,L1
RET
END
7.C语言源程序
#include
unsignedcharcount;
voiddelay10ms(void)
{
unsignedchari,j;
for(i=20;i>0;i--)
for(j=248;j>0;j--);
}
voidmain(void)
{
while
(1)
{
if(P3_7==0)
{
delay10ms();
if(P3_7==0)
{
count++;
if(count==16)
{
count=0;
}
P1=~count;
while(P3_7==0);
}
}
}
}
9. 一键多功能按键识别技术
1.实验任务
如图4.9.1所示,开关SP1接在P3.7/RD管脚上,在AT89S51单片机的P1端口接有四个发光二极管,上电的时候,L1接在P1.0管脚上的发光二极管在闪烁,当每一次按下开关SP1的时候,L2接在P1.1管脚上的发光二极管在闪烁,再按下开关SP1的时候,L3接在P1.2管脚上的发光二极管在闪烁,再按下开关SP1的时候,L4接在P1.3管脚上的发光二极管在闪烁,再按下开关SP1的时候,又轮到L1在闪烁了,如此轮流下去。
2.电路原理图
图4.9.1
3.系统板上硬件连线
(1. 把“单片机系统”区域中的P3.7/RD端口连接到“独立式键盘”区域中的SP1端口上;
(2. 把“单片机系统”区域中的P1.0-P1.4端口用8芯排线连接到“八路发光二极管指示模块”区域中的“L1-L8”端口上;要求,P1.0连接到L1,P1.1连接到L2,P1.2连接到L3,P1.3连接到L4上。
4.程序设计方法
(1. 设计思想由来
在我们生活中,我们很容易通过这个叫张三,那个叫李四,另外一个是王五;那是因为每个人有不同的名子,我们就很快认出,同样,对于要通过一个按键来识别每种不同的功能,我们给每个不同的功能模块用不同的ID号标识,这样,每按下一次按键,ID的值是不相同的,所以单片机就很容易识别不同功能的身份了。
(2. 设计方法
从上面的要求我们可以看出,L1到L4发光二极管在每个时刻的闪烁的时间是受开关SP1来控制,我们给L1到L4闪烁的时段定义出不同的ID号,当L1在闪烁时,ID=0;当L2在闪烁时,ID=1;当L3在闪烁时,ID=2;当L4在闪烁时,ID=3;很显然,只要每次按下开关K1时,分别给出不同的ID号我们就能够完成上面的任务了。
下面给出有关程序设计的框图。
5.程序框图
图4.9.2
6.汇编源程序
ID EQU30H
SP1 BITP3.7
L1 BITP1.0
L2 BITP1.1
L3 BITP1.2
L4 BITP1.3
ORG0
MOVID,#00H
START:
JBK1,REL
LCALLDELAY10MS
JBK1,REL
INCID
MOVA,ID
CJNEA,#04,REL
MOVID,#00H
REL:
JNBK1,$
MOVA,ID
CJNEA,#00H,IS0
CPLL1
LCALLDELAY
SJMPSTART
IS0:
CJNEA,#01H,IS1
CPLL2
LCALLDELAY
SJMPSTART
IS1:
CJNEA,#02H,IS2
CPLL3
LCALLDELAY
SJMPSTART
IS2:
CJNEA,#03H,IS3
CPLL4
LCALLDELAY
SJMPSTART
IS3:
LJMPSTART
DELAY10MS:
MOVR6,#20
LOOP1:
MOVR7,#248
DJNZR7,$
DJNZR6,LOOP1
RET
DELAY:
MOVR5,#20
LOOP2:
LCALLDELAY10MS
DJNZR5,LOOP2
RET
END
7.C语言源程序
#include
unsignedcharID;
voiddelay10ms(void)
{
unsignedchari,j;
for(i=20;i>0;i--)
for(j=248;j>0;j--);
}
voiddelay02s(void)
{
unsignedchari;
for(i=20;i>0;i--)
{delay10ms();
}
}
voidmain(void)
{while
(1)
{if(P3_7==0)
{delay10ms();
if(P3_7==0)
{
ID++;
if(ID==4)
{
ID=0;
}
while(P3_7==0);
}
}
switch(ID)
{case0:
P1_0=~P1_0;
delay02s();
break;
case1:
P1_1=~P1_1;
delay02s();
break;
case2:
P1_2=~P1_2;
delay02s();
break;
case3:
P1_3=~P1_3;
delay02s();
break;
}
}
10. 00-99计数器
1.实验任务
利用AT89S51单片机来制作一个手动计数器,在AT89S51单片机的P3.7管脚接一个轻触开关,作为手动计数的按钮,用单片机的P2.0-P2.7接一个共阴数码管,作为00-99计数的个位数显示,用单片机的P0.0-P0.7接一个共阴数码管,作为00-99计数的十位数显示;硬件电路图如图19所示。
2.电路原理图
图4.10.1
3.系统板上硬件连线
(1. 把“单片机系统”区域中的P0.0/AD0-P0.7/AD7端口用8芯排线连接到“四路静态数码显示模块”区域中的任一个a-h端口上;要求:
P0.0/AD0对应着a,P0.1/AD1对应着b,……,P0.7/AD7对应着h。
(2. 把“单片机系统”区域中的P2.0/A8-P2.7/A15端口用8芯排线连接到“四路静态数码显示模块”区域中的任一个数码管的a-h端口上;
(3. 把“单片机系统”区域中的P3.7/RD端口用导线连接到“独立式键盘”区域中的SP1端口上;
4.程序设计内容
(1. 单片机对按键的识别的过程处理
(2. 单片机对正确识别的按键进行计数,计数满时,又从零开始计数;
(3. 单片机对计的数值要进行数码显示,计得的数是十进数,含有十位和个位,我们要把十位和个位拆开分别送出这样的十位和个位数值到对应的数码管上显示。
如何拆开十位和个位我们可以把所计得的数值对10求余,即可个位数字,对10整除,即可得到十位数字了。
(4. 通过查表方式,分别显示出个位和十位数字。
5.程序框图
图4.10.2
6.汇编源程序
Count EQU30H
SP1 BITP3.7
ORG0
START:
MOVCount,#00H
NEXT:
MOVA,Count
MOVB,#10
DIVAB
MOVDPTR,#TABLE
MOVCA,@A+DPTR
MOVP0,A
MOVA,B
MOVCA,@A+DPTR
MOVP2,A
WT:
JNBSP1,WT
WAIT:
JBSP1,WAIT
LCALLDELY10MS
JBSP1,WAIT
INCCount
MOVA,Count
CJNEA,#100,NEXT
LJMPSTART
DELY10MS:
MOVR6,#20
D1:
MOVR7,#248
DJNZR7,$
DJNZR6,D1
RET
TABLE:
DB3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
END
7.C语言源程序
#include
unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f};
unsignedcharCount;
voiddelay10ms(void)
{
unsignedchari,j;
for(i=20;i>0;i--)
for(j=248;j>0;j--);
}
voidmain(void)
{
Count=0;
P0=table[Count/10];
P2=table[Count%10];
while
(1)
{
if(P3_7==0)
{
delay10ms();
if(P3_7==0)
{
Count++;
if(Count==100)
{
Count=0;
}
P0=table[Count/10];
P2=table[Count%10];
while(P3_7==0);
}
}
}
}
11. 00-59秒计时器(利用软件延时)
1. 实验任务
如下图所示,在AT89S51单片机的P0和P2端口分别接有两个共阴数码管,P0口驱动显示秒时间的十位,而P2口驱动显示秒时间的个位。
2. 电路原理图
图4.11.1
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的P0.0/AD0-P0.7/AD7端口用8芯排线连接到“四路静态数码显示模块”区域中的任一个a-h端口上;要求:
P0.0/AD0对应着a,P0.1/AD1对应着b,……,P0.7/AD7对应着h。
(2. 把“单片机系统”区域中的P2.0/A8-P2.7/A15端口用8芯排线连接到“四路静态数码显示模块”区域中的任一个a-h端口上;要求:
P2.0/A8对应着a,P2.1/A9对应着b,……,P2.7/A15对应着h。
4. 程序设计内容
(1. 在设计过程中我们用一个存储单元作为秒计数单元,当一秒钟到来时,就让秒计数单元加1,当秒计数达到60时,就自动返回到0,从新秒计数。
(2. 对于秒计数单元中的数据要把它十位数和个数分开,方法仍采用对10整除和对10求余。
(3. 在数码上显示,仍通过查表的方式完成。
(4. 一秒时间的产生在这里我们采用软件精确延时的方法来完成,经过精确计算得到1秒时间为1.002秒。
DELY1S:
MOVR5,#100
D2:
MOVR6,#20
D1:
MOVR7,#248
DJNZR7,$
DJNZR6,D1
DJNZR5,D2
RET
5. 程序框图
图4.11.2
6. 汇编源程序
Second EQU30H
ORG0
START:
MOVSecond,#00H
NEXT:
MOVA,Second
MOVB,#10
DIVAB
MOVDPTR,#TABLE
MOVCA,@A+DPTR
MOVP0,A
MOVA,B
MOVCA,@A+DPTR
MOVP2,A
LCALLDELY1S
INCSecond
MOVA,Second
CJNEA,#60,NEXT
LJMPSTART
DELY1S:
MOVR5,#100
D2:
MOVR6,#20
D1:
MOVR7,#248
DJNZR7,$
DJNZR6,D1
DJNZR5,D2
RET
TABLE:
DB3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
END
7. C语言源程序
#include
unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f};
unsignedcharSecond;
voiddelay1s(void)
{
unsignedchari,j,k;
for(k=100;k>0;k--)
for(i=20;i>0;i--)
for(j=248;j>0;j--);
}
voidmain(void)
{
Second=0;
P0=table[Second/10];
P2=table[Second%10];
while
(1)
{
delay1s();
Second++;
if(Second==60)
{
Second=0;
}
P0=table[Second/10];
P2=table[Second%10];
}
}
12. 可预置可逆4位计数器
1. 实验任务
利用AT89S51单片机的P1.0-P1.3接四个发光二极管L1-L4,用来指示当前计数的数据;用P1.4-P1.7作为预置数据的输入端,接四个拨动开关K1-K4,用P3.6/WR和P3.7/RD端口接两个轻触开关,用来作加计数和减计数开关。
具体的电路原理图如下图所示
2. 电路原理图
图4.12.1
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的P1.0-P1.3端口用8芯排线连接到“八路发光二极管指示模块”区域中的L1-L4上;要求:
P1.0对应着L1,P1.1对应着L2,P1.2对应着L3,P1.3对应着L4;
(2. 把“单片机系统”区域中的P3.0/RXD,P3.1/TXD,P3.2/INT0,P3.3/INT1用导线连接到“四路拨动开关”区域中的K1-K4上;
(3. 把“单片机系统”区域中的P3.6/WR,P3.7/RD用导线连接到“独立式键盘”区域中的SP1和SP2上;
4. 程序设计内容
(1. 两个独立式按键识别的处理过程;
(2. 预置初值读取的问题
(3. LED输出指示
5. 程序框图
图4.12.2
6. 汇编源程序
COUNT EQU30H
ORG00H
START:
MOVA,P3
ANLA,#0FH
MOVCOUNT,A
MOVP1,A
SK2:
JBP3.6,SK1
LCALLDELY10MS
JBP3.6,SK1
INCCOUNT
MOVA,COUNT
CJNEA,#16,NEXT
MOVA,P3
ANLA,#0FH
MOVCOUNT,A
NEXT:
MOVP1,A
WAIT:
J
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 语言 实验 实践 教程