锁存器
蓝桥杯这款单片机是用锁存器来实现引脚的复用的,所以代码写起来很麻烦,总是要开关锁存器
为了偷懒,可以用宏定义来定义每个锁存器打开的代码,也可以用函数来实现
用宏定义:
1 2 3 4 5 6
| #define Y4 P2 = (P2&0x1f)|0x80; #define Y5 P2 = (P2&0x1f)|0xa0; P0 = 0x40; P0 = 0x10; #define Y6 P2 = (P2&0x1f)|0xc0; #define Y7 P2 = (P2&0x1f)|0xe0;
|
用函数:
1 2 3 4 5 6 7 8 9 10
| void select_channel(char channel) { switch(channel) { case 4: P2 = P2&0x1f|0x80; break; case 5: P2 = P2&0x1f|0xa0; break; case 6: P2 = P2&0x1f|0xc0; break; case 7: P2 = P2&0x1f|0xe0; break; } }
|
数码管的显示问题
初学者一般都是用延时来实现动态数码管的,但是当要实现的功能多起来了,用延时来实现动态数码管,数码管很容易会闪烁,整体效果就很不好了。
另外一种方法可以是用定时器来扫描数码管,每隔一段时间就进入中断服务函数执行数码管的扫描,只要中断间隔的时间小于人眼的视觉暂留(大概是0.1~0.4s),就看不出来数码管会闪烁了。但是这个方法也有缺点,缺点是整个系统每隔这么短的时间就必须要进入这个中断服务函数,很容易会影响、打断其他程序的执行。现在也有解决方法就是在不能被中断打断的功能执行前关掉中断的开关,执行完之后再打开,显然这个解决方法也只是权宜之计,关掉中断的开关有的时候会影响这个计时器的计时,获得的时间就不是很准确,但是误差会很小吧,十行代码51单片机几毫秒甚至更短的时间就可以执行完。所以第二种方法算是比较好的一种方法了,相对于第一种方法来说。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| #include <reg52.h>
unsigned char smgd[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00}; unsigned char smgw[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; char smgbuf[8],smg_num = 0;
void select_channel(char channel) { switch(channel) { case 4: P2 = P2&0x1f|0x80; break; case 5: P2 = P2&0x1f|0xa0; break; case 6: P2 = P2&0x1f|0xc0; break; case 7: P2 = P2&0x1f|0xe0; break; } }
void init() { char i; for(i = 0;i < 8;i++) smgbuf[i] = 10; P0 = 0xff; select_channel(4); P2&= 0x1f; P0 = 0x00; select_channel(5); P2&= 0x1f; }
void init_timer() { TMOD = 0x01; TH1 = 0xf8; TL1 = 0x2f; EA = 1; ET1 = 1; TR1 = 1; }
void display() { smg_num++; if(smg_num >= 8) smg_num = 0; P0 = 0xff; select_channel(7); P2&= 0x1f; P0 = 0x00; select_channel(6); P0 = smgw[smg_num]; P2&= 0x1f; P0 = 0xff; select_channel(7); P0 = ~smgd[smgbuf[smg_num]]; P2&= 0x1f; }
void main() { char i; init(); init_timer(); while(1) { for(i=0;i<8;i++) smgbuf[i] = i; } }
void timer1() interrupt 3 { display(); }
|
上面的代码是直接在Typora上面写的,没有编译,应该没有很大问题(手动滑稽)
这样写要改变数码管的值只要改变数组smgbuf[]中的值就行了0-9的数字是和编号一一对应的,其他的特殊符号可以自己手动加。