热度 21
2014-9-16 09:10
3056 次阅读|
3 个评论
以前用HD7279搭了一个“数码管+按键”的小模块,最近新做了一版更加通用的,因为HD7279本身能够驱动8个共阴极段选数码管和64个按键,而每次使用的数码管大小可能不一样,按键可能这次用得多下次用得少,因此不如只把接口留出来,用什么就往上接什么,自己在家DIY点东西就很方便。 原理图(DIP封装和SOP封装可以任选其一焊上去): PCB板: 实物图: 接线图: 驱动的.h文件: /* * HD7279.h * * Created on: Semptember 12, 2014 * Author: Marianna Zhu */ #ifndef HD7279_H #define HD7279_H #include //msp430f2616.h,尖括号可能无法显示在网页上 #include "timedelay.h" #define HD7279_KEY_H() P2OUT |= (1 0) #define HD7279_KEY_L() P2OUT = ~(1 0) #define HD7279_DATA_H() P2OUT |= (1 1) #define HD7279_DATA_L() P2OUT = ~(1 1) #define HD7279_CLK_H() P2OUT |= (1 2) #define HD7279_CLK_L() P2OUT = ~(1 2) #define HD7279_CS_H() P2OUT |= (1 3) #define HD7279_CS_L() P2OUT = ~(1 3) #define HD7279_KEY_DIR_OUT() P2DIR |= (1 0) #define HD7279_KEY_DIR_IN() P2DIR = ~(1 0) #define HD7279_DATA_DIR_OUT() P2DIR |= (1 1) #define HD7279_DATA_DIR_IN() P2DIR = ~(1 1) #define HD7279_CLK_DIR_OUT() P2DIR |= (1 2) #define HD7279_CLK_DIR_IN() P2DIR = ~(1 2) #define HD7279_CS_DIR_OUT() P2DIR |= (1 3) #define HD7279_CS_DIR_IN() P2DIR = ~(1 3) #define HD7279_DATA_HIGH P2IN (1 1) #define HD7279_KEY_IO (1 0) #define HD7279_CMD_RESET 0xA4 #define HD7279_CMD_TEST 0xBF #define HD7279_RTL_UNCYL 0xA1 #define HD7279_RTR_UNCYL 0xA0 #define HD7279_RTL_CYCLE 0xA3 #define HD7279_RTR_CYCLE 0xA2 #define HD7279_DECODE0 0x80 #define HD7279_DECODE1 0xC8 #define HD7279_UNDECODE 0x90 #define HD7279_BLINKCTL 0x88 #define HD7279_ACTCTL 0x98 #define HD7279_SEGON 0xE0 #define HD7279_SEGOFF 0xC0 #define HD7279_CMD_READ 0x15 extern int key_flag; extern void HD7279_send_com(uint8_t com); extern void HD7279_send_com_data(uint8_t com, uint8_t data); extern uint8_t HD7279_read_key(void); extern void HD7279_init(void); extern void HD7279_led_demo(void); #endif 驱动的.c文件: /* * HD7279.c * * Created on: Semptember 12, 2014 * Author: Marianna Zhu */ #include //msp430f2616.h,尖括号可能无法显示在网页上 #include "timedelay.h" #include "HD7279.h" int key_flag = 0; void HD7279_send_com(uint8_t com) { int i; uint8_t byte = com; HD7279_DATA_DIR_OUT(); HD7279_CS_L(); Delay10Us_xt2(5); for (i = 0; i 8; i++) { if (byte 0x80) HD7279_DATA_H(); else HD7279_DATA_L(); byte = 1; HD7279_CLK_H(); Delay10Us_xt2(1); HD7279_CLK_L(); Delay10Us_xt2(1); } HD7279_CS_H(); Delay10Us_xt2(1); } void HD7279_send_com_data(uint8_t com, uint8_t data) { int i; uint16_t bytes = com; bytes = (bytes 8) + data; HD7279_DATA_DIR_OUT(); HD7279_CS_L(); Delay10Us_xt2(5); for (i = 0; i 16; i++) { if (bytes 0x8000) HD7279_DATA_H(); else HD7279_DATA_L(); bytes = 1; HD7279_CLK_H(); Delay10Us_xt2(1); HD7279_CLK_L(); Delay10Us_xt2(1); if (i == 7) Delay10Us_xt2(2); } HD7279_CS_H(); Delay10Us_xt2(1); } uint8_t HD7279_read_key(void) { int i; uint8_t byte = HD7279_CMD_READ, key = 0; HD7279_DATA_DIR_OUT(); HD7279_CS_L(); Delay10Us_xt2(5); for (i = 0; i 8; i++) { if (byte 0x80) HD7279_DATA_H(); else HD7279_DATA_L(); byte = 1; HD7279_CLK_H(); Delay10Us_xt2(1); HD7279_CLK_L(); Delay10Us_xt2(1); } HD7279_DATA_DIR_IN(); Delay10Us_xt2(2); for (i = 0; i 8; i++) { HD7279_CLK_H(); Delay10Us_xt2(1); key = key 1; if (HD7279_DATA_HIGH) key += 1; HD7279_CLK_L(); Delay10Us_xt2(1); } HD7279_CS_H(); Delay10Us_xt2(1); return key; } void HD7279_init(void) { DelayMs_xt2(25); HD7279_DATA_DIR_OUT(); HD7279_CS_DIR_OUT(); HD7279_CLK_DIR_OUT(); HD7279_KEY_DIR_IN(); HD7279_DATA_H(); HD7279_CS_H(); HD7279_CLK_L(); HD7279_KEY_H(); P2IE |= HD7279_KEY_IO; P2IES = ~HD7279_KEY_IO; P2IFG = ~HD7279_KEY_IO; HD7279_send_com(HD7279_CMD_RESET); HD7279_send_com_data(HD7279_BLINKCTL, 0xFF); HD7279_send_com_data(HD7279_ACTCTL, 0xFF); } #pragma vector=PORT2_VECTOR __interrupt void PORT2_ISR(void) { P2IFG = ~HD7279_KEY_IO; key_flag = sTRUE; } void HD7279_led_demo(void) { int i, j; HD7279_send_com(HD7279_CMD_TEST); DelayMs_xt2(2000); HD7279_send_com(HD7279_CMD_RESET); for (i = 0; i 16; i++) { for (j = 0; j 8; j++) HD7279_send_com_data(HD7279_DECODE0 + j, i); DelayMs_xt2(500); } for (i = 0; i 16; i++) { for (j = 0; j 8; j++) HD7279_send_com_data(HD7279_DECODE1 + j, i); DelayMs_xt2(500); } } /* the end */ 很多硬件的驱动程序,会有一个问题是,添加了策略进去,下面这段话来自《Linux设备驱动程度》,但我觉得对于单片机的硬件驱动,也是成立的: “编写访问硬件的内核代码时,不要给用户强加任何特定策略。因为不同的用户有不同的需求,驱动程序应该处理如何使硬件可用的问题,而将怎样使用硬件的问题留给上层应用程序。因此,当驱动程序只提供了访问硬件的功能而没有附加任何限制时,这个驱动程序就比较灵活。然而,有时候我们也需要在驱动程序中实现一些策略。例如,某个数字I/O只提供以字节为单位访问硬件的方法,这样就可避免编写额外代码来处理单个数据位的麻烦。” 写这个HD7279的驱动程序的时候,同样面临:是提供完善的使用策略,还是只写出实现(因为不确定实际使用的时候到底用的是LED还是数码管,KEY又有几个)? 这里暂时选择了后者,如果你对HD7279很熟悉的话,可能会发现这几个函数刚好是你需要的;如果你对HD7279不熟悉,可能会找不到使用的方法。所以这个README也是关于使用方法的小tip。 首先是初始化: HD7279_init(); 以译码方式0在第n位上显示byte(译码方式1/2和它类似): HD7279_send_com_data(HD7279_DECODE0 + n, byte); 读取键盘值: key = HD7279_read_key(); (64个键对应0~0x3F,没有键按下时为0xFF。) (实际上你可以在任何时候读取键盘值,不管它有没有键按下。) (当有键按下时,HD7279的key引脚会拉低,因此可以把key接到单片机的外部中断。)