上述方法逐次给P0或者P2赋值一方面程序的复杂程度增_第1页
上述方法逐次给P0或者P2赋值一方面程序的复杂程度增_第2页
上述方法逐次给P0或者P2赋值一方面程序的复杂程度增_第3页
上述方法逐次给P0或者P2赋值一方面程序的复杂程度增_第4页
免费预览已结束,剩余4页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、上述方法逐次给 P0 或者 P2 赋值,一方面程序的复杂程度增加, 另外一方面会使得程序的灵活性降低。如果要改变显示的数字, 程序改动起来很麻烦。 所以要用 51 单片机中常用的一种方法:查表法 。例如 P0 口输出段码时,我们可以把要显示的段码放在一个表格中,然后每次从这个表格里面取数,送到 P0 口即可。 P2 口输出位码时,可以把要用的位码放在另一个表格里,每次从此表中取数,送入 P2 口。这样,如果要改变显示的数字,只需要改变表格里面的数。org0000hstart: movr7,#0ffh;r7,r6查表时送入变址寄存器a ( 因自加 1 后为 0, 所以预置 ffh)movr6,#

2、0ffhloop:lcall play1; 调用显示段码子程序lcall play2; 调用显示位码子程序lcall delay_1mscjnea,#80h,loop; 判断是否到了最左边的数,即第 8个位码ajmpstartplay1:; 查表求段码子程序;mova,r7;inca;movr7,aincr7; 这 2 句和上面三条语句实现功能相同mova,r7;a 在这里做变址寄存器movdptr,#table1; 表首址送 dptr , dptr做基址寄存器movca,a+dptr; 基址寄存器加变址寄存器寻址movp0,aretplay2:; 查表求位码子程序 ( 原理同 play1)m

3、ova,r6incamovr6,amovdptr,#table2movca,a+dptrmovp2,arettable1: db 08h,0abh,12h,22h,0a1h,24h,04h,0aahtable2: db 01h,02h,04h,08h,10h,20h,40h,80h; 段码表; 位码表delay_1ms:movr5,#02h; 延时1ms 子程序temp:movr4,#0ffhdjnzr4,$djnzr5,tempretend下载到板上验证得到预想结果。C51 实现如下 ( 参考了AS的例程 ):i nclude <reg51.h>i nclude <intr

4、ins.h>/包含了左移函数_crol_()void delayms(unsigned char ms); /延时子程序unsigned char data dis_digit;/位选通值 ,传送到P2 口用于选通当前数码管的数值,/如等于 0x01 时 , 选通 P2.0 口数码管unsigned char code dis_code11=0x08,0xab,0x12,0x22,0xa1,/ 0,1,2,3,40x24,0x04,0xaa,0x00,0x20, 0xff; / 5,6,7,8,9, offunsigned char data dis_buf8;/ dis_buf显于缓冲

5、区基地址unsigned char data dis_index;/显示索引 ,用于标识当前显示的数码管和缓冲区的偏移量void main()P0 = 0xff;/关闭所有数码管P2 = 0x00;dis_buf0 = dis_code0;dis_buf1 = dis_code1;dis_buf2 = dis_code2;dis_buf3 = dis_code3;dis_buf4 = dis_code4;dis_buf5 = dis_code5;dis_buf6 = dis_code6;dis_buf7 = dis_code7;dis_digit = 0x01;/首先选通P2.0dis_ind

6、ex = 0;/当前偏移量为0while(1)P0 = dis_bufdis_index;/段码送P0 口P2 = dis_digit;/选能位 ( 即位码)delayms(1);/延时dis_digit = _crol_(dis_digit, 1); /位选通左移,下次选通下一位dis_index+;/下一个段码dis_index &= 0x07;/见注释void delayms(unsigned char ms)/延时子程序 ( 晶振 12M)unsigned char i;while(ms-)for(i = 0; i < 120; i+); 注释 : 此句作用是 8 个数码

7、管全部扫描完一遍之后,再回到第一个开始下一次扫描。写回一般形式: dis_index = dis_index & 0x07。这种方法挺新,第一次见到,十六进制的07就是二进制的 00000111 ,这样通过与操作可能控制循环了。比如dis_index 经第一次循环后值为00000001 ,和 0x07 与操作后值不变仍为0x01 ,第二次循环时,其值为0 为 0x02 ,与 0x07 后仍为 0x02,一直到其值增为 0x07 时还是不变的,但再次循环后其值为0x80 ,再与 0x07后就变成 0x00了,这样又从初始循环了。此句可用if (dis_index = 8) dis_ind

8、ex = 0代替,效果一样。 通过 C51 用上述方法实现时,其段码放在了数组dis_code11中,再通过缓冲区数组dis_buf 将程序中要调用的值装入,这样就可以用下标(偏移量)访问了。这样看上去有些繁锁,但其思路比较清楚,结构上也很明了,具有通用性,便于扩展。 另外只要把程序中的延时加长,如 delayms(1000) ,下载到板上就可以看到实际上数码管是由低位到高位逐位显示的。若单单就实现这个功能而言, 可以直接调入段码数组而不必再设置缓冲数组 dis_buf ,实现如下:dis_code11中下标从0到 7的值,i nclude <reg51.h>i nclude &l

9、t;intrins.h>/_crol_()用void delayms(unsigned char ms); /延时子程序unsigned char data dis_digit;/位选通值,传送到P2 口用于选通当前数码管的数值,/如等于 0x01 时 , 选通P2.0口数码管unsigned char code dis_code11=0x08,0xab,0x12,0x22,0xa1, 4/ 0,1,2,3,0x24,0x04,0xaa,0x00,0x20, 0xff; / 5,6,7,8,9,offunsigned char data dis_index;/显示索引,用于标识当前显示的

10、数码管和缓冲区的偏移量void main()P0 = 0xff;P2 = 0x00;/关闭所有数码管dis_index = 0;/当前偏移量为0dis_digit = 0x01; /选通P2.0while(1)P0 = dis_codedis_index; /段码送P0 口P2 = dis_digit;/位码送P2 口delayms(1);dis_digit = _crol_(dis_digit, 1); /位选通左移,下次选通下一位dis_index+;dis_index &= 0x07;void delayms(unsigned char ms)/延时子程序 ( 晶振 12M)un

11、signed char i;while(ms-)for(i = 0; i < 120; i+); 通本来是想通过以下方式实现一次循环的:for (dis_index = 0; dis_index < 8; dis_index+)P0= dis_codedis_index; /段码送P0 口P2= dis_index+1;/位码送 P2 口delayms(1);可得到的总是错误的结果:第0位到第 2位这三位显示的是三个8,第 3 位显示的是7,高四位没有显示。加长延时逐位观察也没有发现错误的规律,对Keil的调试也不熟悉,先把问题留到这,待找出原因后再补上。2006.5.2找出原因啦

12、,补上:今天又看了一下,找到上面的错误出在哪了。当时是想用dis_index 的值做为位码的, 即第一位显示 0 时, 段码为 dis_code0,即 dis_index 值为 0,此时位码值为 1。第二位显示1时,段码为 dis_code1, 即 dis_index值为 1, 此时位码值为 2。所以就简单用了个加1 运算,将 P0 口的偏移值与P2 口的位码联系起来。但仔细想一下位码的原理,上述方法显然是错的,只要再验证一步就明白了,即当第3 位显示2 时,段码为 dis_code2, dis_index值为 2,加 1后为 3,按上述方法时就将这个3 作为了位码,而正确的位码应该是4 (0

13、0000100B)。所以出错。实际上这个对应关系是有的,但不是简简单单的加1,位码应该是2 的 dis_index次幂。即:0 11 22 43 84 16幂次运算函数 flaot pow(float x, float y)包含在 math.h 中 , 返回值为 xy(float型 ):for (dis_index = 0; dis_index < 8; dis_index+)P0 = dis_codedis_index; /段码送 P0 口P2 = (char)pow(2, dis_index);/位码送P2口delayms(255);再次下载到板上发现仍有问题,即延时很小的时候显示混

14、乱, 但加大延时时间( 如程序中的值) 可以观查到数码管是按位正确显示的。另外用这种方法产生的代码量也很大 ( 从写入速度看 , 很明显) 。这里仅提出了一个思路,只在此实验中适用,意义不大,到此为止。 补充结束 AS中绐出的例程是利用定时中断做的延时,参考修改到我的板上,程序如下:i nclude <reg51.h>i nclude <intrins.h>/包含了左移函数_crol_()unsigned char data dis_digit;/位选通值,传送到P2 口用于选通当前数码管的数值,/如等于0x01时 ,选通P2.0口数码管unsigned char co

15、de dis_code11=0x08,0xab,0x12,0x22,0xa1, 4/ 0,1,2,3,0x24,0x04,0xaa,0x00,0x20, 0xff; / 5,6,7,8,9,offunsigned char data dis_buf8;/ dis_buf显于缓冲区基地址unsigned char data dis_index;/显示索引,用于标识当前显示的数码管和缓冲区的偏移量void main()P0 = 0xff;P2 = 0x00;/关闭所有数码管TMOD = 0x01;/ 00000001B定时计数器0 工作在方式1, 16位定时器/ 计数器TH0 = 0xFC;TL0

16、 = 0x17;/预置初值FC17H=64535D, 216-64535=1001us=1msIE = 0x82;/ 10000010B T0溢出中断允许dis_buf0 = dis_code0x0;dis_buf1 = dis_code0x1;dis_buf2 = dis_code0x2;dis_buf3 = dis_code0x3;dis_buf4 = dis_code0x4;dis_buf5 = dis_code0x5;dis_buf6 = dis_code0x6;dis_buf7 = dis_code0x7;dis_digit = 0x01;dis_index = 0;/选通第 0 位

17、数码管/偏移初值为0TR0 = 1;/启动T0while(1);/循环等待中断void timer0() interrupt 1/定时器0 中断服务程序,用于数码管的动态扫描TH0 = 0xFC;/发生中断定时/ 计数器重装初值TL0 = 0x17;/感觉此处 ( 及上 ) 应该是 0x18, 而不是17,分析如下P2 = 0x00;/先关闭所有数码管P0 = dis_bufdis_index;/段码送P0 口P2 = dis_digit;/位码送 P2 口dis_digit = _crol_(dis_digit,1);/位选通值左移,下次中断时选通下一位数码管dis_index+;dis_i

18、ndex &= 0x07;/ 8个数码管全部扫描完一遍之后,再回到第一个开始下一次扫描 定时器 / 计数器的输入脉冲周期与机器周期一样,为时钟振荡频率的1/12 。晶振用12M 时,输入脉冲周期间隔为 1us 。机器周期为 1us 。设 T0 的初值为 X,计算初值的方法: 本例中定时器用方式 1,是 16 位的定时器,即最大值为 216 65536 ,超过此值将发生溢出,引起中断,进入中断处理程序。这里要让其延时1ms,即 1000us,则有式216 X 1000 ,可得 X 64536 ,换算为16 进制为 FC18,即初值 TH0=0xFC,TL0=0x18。即定时器由 64536 开始计数,经 1000 次计数后值为 65536,将发生定时中断,再进入中断处理子程序后,重新装和初值,如此循环下去。而在上例中其装入的初值并非FC

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论