原理图(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接到单片机的外部中断。)