原创 HD7279的驱动程序和使用方法

2014-9-16 09:10 3053 18 21 分类: MCU/ 嵌入式 文集: 硬件小模块

以前用HD7279搭了一个“数码管+按键”的小模块,最近新做了一版更加通用的,因为HD7279本身能够驱动8个共阴极段选数码管和64个按键,而每次使用的数码管大小可能不一样,按键可能这次用得多下次用得少,因此不如只把接口留出来,用什么就往上接什么,自己在家DIY点东西就很方便。

原理图(DIP封装和SOP封装可以任选其一焊上去):

screenshot from 2014-09-15 23:27:18-.jpg


PCB板:

screenshot from 2014-09-15 23:27:34-.jpg


实物图:

p40915-231101-.jpg


接线图:

p40914-155835-.jpg


驱动的.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接到单片机的外部中断。)
 

PARTNER CONTENT

文章评论3条评论)

登录后参与讨论

用户377235 2015-9-15 21:23

不会用eagle画出很好的板子,不知道为什么。

DiracFatCat 2014-12-24 12:54

就价格来讲的话,Eagle还是可以接受的。

用户1543914 2014-12-24 11:19

对比了一下eagle个人感觉还是pads好用,呵呵
相关推荐阅读
DiracFatCat 2018-09-05 12:14
【博客大赛】卡尔曼滤波学习笔记(11)从位置估计速度
卡尔曼滤波器,不仅仅是一个低通滤波器,否则也不会持续发展50年。 示例:桑先生需要测试高速列车的性能。测试的目的是判断列车在直线上能否保持80m/s的速度。速度和位置每0.1秒测量一次,但是由于...
DiracFatCat 2018-08-31 19:32
【博客大赛】卡尔曼滤波学习笔记(10)一个简单的示例
《Kalman Filtering: Theory and Practice Using MATLAB》第三章,看不懂,暂时略过。《Kalman Filtering: Theory and Pract...
DiracFatCat 2018-07-19 15:09
对sed命令的练习
sed是流编辑器。它每次处理一个输入,因此很有效率。官方手册:https://www.gnu.org/software/sed/manual/sed.html学习Linux命令,当然要阅读官方手册,所...
DiracFatCat 2018-06-19 15:10
【博客大赛】卡尔曼滤波学习笔记(八)可观测性和可控制性 ...
可观测性是指,在给定模型的情况下,动力学系统的状态是否由它的输入输出唯一确定。可观测性是系统模型的特征。如果传感器矩阵H是可逆的,则本系统可观测,因为有:如果传感器矩阵H某些时候是不可逆的,则本系统仍...
DiracFatCat 2018-06-19 10:56
【博客大赛】卡尔曼滤波学习笔记(七)Z变换
如果我们仅仅对离散线性系统感兴趣,那么就使用下面这个表达式:如果u是常量,那么可以写成:为了简化表达式,我们可以将上面写成:离散线性时不变系统的Φ求解,可以使用Z变换。(* 由于本人已经忘记了Z变换的...
DiracFatCat 2018-06-19 10:54
【博客大赛】卡尔曼滤波学习笔记(六)拉普拉斯变换
对于线性时变/时不变系统,求解Φ(t)有多种方式,拉普拉斯变换是其中一种。(* 由于本人已经忘记了拉普拉斯变换的内容,因此本节待续。)...
我要评论
3
18
关闭 站长推荐上一条 /3 下一条