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