sm1668驱动

        很多时候我们单片机入门都是从流水灯到数码管显示矩阵键盘然后基本单片机就算入门了。但在实际应用中真正用单片机直接去扫描数码管和矩阵按键的情况还是比较少的,直接扫描按键显示扫描输出占用CPU资源比较高且占用比较多的IO口。在有些实际应用中本身8位的单片机本身资源有限如STM8大部分16pin和20pin此时显示不能同时支持按键和显示。
所以专用的数码键盘IC可以很方便地和小型单片机结合使用非常方便,流行的有pd650、pt6958、sm1668等ic可以说在小家电,机顶盒,电子称等上得到广泛的使用。

最近在用做机顶盒的时候用了sm1668,感觉使用起来挺简单方便的,先将驱动记下来方便以后移植使用。

将驱动分为设备层sm1668.c sm1668.h 驱动层driver_frontpanl.c driver_frontpanl.h

/* sm1668.h */
#ifndef _SM1668_H_
#define _SM1668_H_

typedef unsinged char U8
typedef unsinged char BOOL
typedef char S8
typedef unsinged short U16
typedef short S8
typedef unsinged int U32
typedef int S32

//===================== MARCOS FOR SM1668 BEGIN ===================================

#define LED_NUM                  (4)
#define DOT_ENABLE_CODE          (0x80)

#define CMD_SET_DISP_MODE        (0x00)
#define CMD_SET_DATA             (0x40)
#define CMD_SET_ADDR             (0xC0)
#define CMD_DISP_CTRL            (0x80)

#define OPT_WRITE_SM1668_RAM     (0x00)
#define OPT_READ_SM1668_KEYVAL   (0x02)
#define ADDR_NOT_INC             (0x04)
#define ADDR_AUTO_INC            (0x00)

#define BRIGHTNESS_LEVEL1       (0x08)
#define BRIGHTNESS_LEVEL2       (0x09)
#define BRIGHTNESS_LEVEL3       (0x0A)
#define BRIGHTNESS_LEVEL4       (0x0B)
#define BRIGHTNESS_LEVEL5       (0x0C)
#define BRIGHTNESS_LEVEL6       (0x0D)
#define BRIGHTNESS_LEVEL7       (0x0E)
#define BRIGHTNESS_LEVEL8       (0x0F)

#define SM1668_DISP_ON           (CMD_DISP_CTRL | BRIGHTNESS_LEVEL6)
#define SM1668_DISP_OFF          (0x87)

#define G_LED_ON                 0x10//0x80
#define G_LED_OFF                0x00
#define G_LED_ADDR               0x08

#define COLON_UP_DOT_ADDR        0x03
#define COLON_UP_DOT_ENABLE      0x01
#define COLON_UP_DOT_DISABLE     0x00

#define COLON_DOWN_DOT_ADDR      0x05
#define COLON_DOWN_DOT_ENABLE    0x01
#define COLON_DOWN_DOT_DISABLE   0x00
#define CLK_DELAY_TIME           50
enum
{
    DISP_MODE_4BITS_13SEG = 0,
    DISP_MODE_5BITS_12SEG,
    DISP_MODE_6BITS_11SEG,
    DISP_MODE_7BITS_10SEG,
};      //显示段数宏
//=====================MARCOS FOR SM1668 END===================================

typedef struct
{
    U8 ledBitPos;
    U8 ledCharDisp;
    U8 enableDisp;
}LED_DISP_INFO;


typedef struct
{
    U8 u8Char;
    U8 lowByte;
    U8 highByte;
}Char2Segment;

#define KEY_16      16
#define KEY_11      11
#define KEY_19      19
#define KEY_4       4
#define KEY_1       1
#define KEY_9       9
#define KEY_POWER   
#define KEY_EXIT    

U8    SM1668_Init(void);
void  TestKey(void);
U8    SM1668_DispStr(const U8* str);
U8    UpdateLedDisp(U8 ledPos, U8 ch, U8 bEnableDot);
U16   GetKeyValue(void);
void  TimeColonEn(U8 bEnable);
void  work_status_OnOff(BOOL bLightOn);
void  Signal_lock_OnOff(BOOL bLightOn);
void  SM1668_Cls(void);
void  SM1668_RamUpg(void);
void  DisplayOFF(void);
void Mdrv_delay(void);

#endif /* _SM1668_H_ */

/*  sm1668.h */
#include "sm1668.h"

#ifndef TRUE
#define TRUE 1
#define FALSE !TRUE
#endif

static MS_BOOL GRID1_REG = 0;

#define GPIO_ENABLE         
#define SM1668_STB_H       
#define SM1668_STB_L       
#define SM1668_CLK_H        
#define SM1668_CLK_L       
#define SM1668_DATA_H      
#define SM1668_DATA_L       
#define SM1668_DIN_LEVEL    
#define SM1668_DIN_INPUT   
#define SM1668_DIN_OUTPUT   
  
#define CLK_DELAY_TIME 50
static const Char2Segment _char2SegmentTable[] =
{
   //seg A B C D E F G H
   //SEG 0 1 2 3 4 5 6 7
   {'0',0x3F,0x00/*0*/},
   {'1',0x06,0x00/*1*/},
   {'2',0x5B,0x00/*2*/},
   {'3',0x4F,0x00/*3*/},
   {'4',0x66,0x00/*4*/},
   {'5',0x6D,0x00/*5*/},
   {'6',0x7D,0x00/*6*/},
   {'7',0x07,0x00/*7*/},
   {'8',0x7F,0x00/*8*/},
   {'9',0x6F,0x00/*9*/},
   {'A',0x77,0x00/*A*/},
   {'b',0x7C,0x00/*b*/},
   {'C',0x39,0x00/*C*/},
   {'D',0x3F,0x00/*D*/},
   {'c',0x58,0x00/*c*/},
   {'d',0x5E,0x00/*d*/},
   {'E',0x79,0x00/*E*/},
   {'F',0x71,0x00/*F*/},
   {'H',0x76,0x00/*H*/},
   {'h',0x74,0x00/*h*/},
   {'L',0x38,0x00/*L*/},
   {'n',0x54,0x00/*n*/},
   {'N',0x37,0x00/*N*/},
   {'o',0x5C,0x00/*o*/},
   {'P',0x73,0x00/*P*/},
   {'q',0x67,0x00/*q*/},
   {'r',0x50,0x00/*r*/},
   {'t',0x78,0x00/*t*/},
   {'U',0x3E,0x00/*U*/},
   {'y',0x6E,0x00/*y*/},
   {'S',0x6D,0x00/*5*/},
   {'s',0x6D,0x00/*5*/},
   {'-',0x40,0x00/*-*/}
};

/
//SM1668 turn on display
/

static void _delaySomeNop(MS_U16 cnt)
{
    while (cnt-->0)
    {
        _nop_;
        _nop_;
        _nop_;
        _nop_;
        _nop_;
    }
}
/*
**@function :
**@params   : value 
**@return   :
*/
static void __WriteByte_2_SM1668(MS_BOOL value)
{
    MS_U8 i;
    SM1668_CLK_H;
    _delaySomeNop(CLK_DELAY_TIME);
    for (i = 8; i != 0; i--)
    {
        if(value & 0x01)
            SM1668_DATA_H;
        else
            SM1668_DATA_L;

        SM1668_CLK_L;
        _delaySomeNop(CLK_DELAY_TIME);
        SM1668_CLK_H;
        _delaySomeNop(CLK_DELAY_TIME);
        value >>= 1;
    }
}

/*
**@function : enable sm1668 disp
**@params   : void
**@return   : void
*/
static void __SM1668_DispOn(void)
{
    SM1668_STB_L;_delaySomeNop(CLK_DELAY_TIME);
    __WriteByte_2_SM1668(SM1668_DISP_ON);
    SM1668_STB_H;_delaySomeNop(CLK_DELAY_TIME);
}

/*
**@function : write data to the specific ram address of SM1668
**@params   : value 
**@return   :
*/
static void __WriteData_2_SM1668_Addr(MS_BOOL value, MS_BOOL addr)
{
    _delaySomeNop(CLK_DELAY_TIME);
    
    SM1668_STB_L; _delaySomeNop(CLK_DELAY_TIME);
    __WriteByte_2_SM1668(CMD_SET_DATA | ADDR_NOT_INC);
    SM1668_STB_H;_delaySomeNop(CLK_DELAY_TIME);

    __WriteByte_2_SM1668(CMD_SET_ADDR | addr);
    __WriteByte_2_SM1668(value);

    SM1668_STB_H;_delaySomeNop(CLK_DELAY_TIME);
    __SM1668_DispOn();
    _delaySomeNop(CLK_DELAY_TIME);
}
/*
**@function : clear all the SM1668 ram, if we want to display a new char
**@params   : no 
**@return   : no
*/
static void Mdrv_Clear_sm16668_RAM(void)
{
    MS_U16 i;

    SM1668_STB_L;
    _delaySomeNop(CLK_DELAY_TIME);
    __WriteByte_2_SM1668(CMD_SET_DATA | ADDR_AUTO_INC);
    SM1668_STB_H;
    _delaySomeNop(CLK_DELAY_TIME);

    SM1668_STB_L;
    _delaySomeNop(CLK_DELAY_TIME);
    __WriteByte_2_SM1668(CMD_SET_ADDR | 0x00);
    for (i = 14; i != 0; i--)
    {
        __WriteByte_2_SM1668(0x00);
    }
    SM1668_STB_H;
    _delaySomeNop(CLK_DELAY_TIME);

}
BOOL    SM1668_Init(void)
{
    volatile MS_U16 i;

    SM1668_STB_H;
    SM1668_CLK_H;
    SM1668_DATA_H;
    for (i = 10000; i != 0; i--)
        _delaySomeNop(CLK_DELAY_TIME);

    Mdrv_FP_SM1668_Cls();
    Mdrv_Clear_CT16668_RAM();

    SM1668_STB_L;
    _delaySomeNop(CLK_DELAY_TIME);
    __WriteByte_2_SM1668(0x03);
    SM1668_STB_H;
    _delaySomeNop(CLK_DELAY_TIME);

    __SM1668_DispOn();
    GRID1_REG = 0;
    return TRUE;
}

/*
**@function : get CD code for led disp
**@params   : whilch char want to disp 
**@return   : char's BCD code
*/
static MS_BOOL __GetCharCode(MS_BOOL ch)
{
    const Char2Segment *ptbl;

    for (ptbl = _char2SegmentTable;\
        ptbl < (_char2SegmentTable + sizeof(_char2SegmentTable) / sizeof(Char2Segment)); ptbl++)
    {
        if (ch == ptbl->u8Char)
        {
            return ptbl->lowByte;
        }
    }
    //need promt invalid char?
    return 0xFF;
}

/*  disp function */
U8  dispBuf[8];         //disp buffer
void sm1668_clear_dispbuf(void)
{
    MS_U8        i;
    for (i = 0; i < 8; i++)
    {
        dispBuf[i] = 0x00;
    }

}
/*
**@function : disp string
**@params   : no 
**@return   : no
*/
BOOL sm1668_DispStr(const MS_U8* str)
{
    MS_U8   charPos = 4;
    const MS_U8 *pStrEnd;

    for (pStrEnd = str; '\0' != *pStrEnd; pStrEnd++);

    Mdrv_FP_SM1668_Cls();

    while (pStrEnd > str && charPos > 0)
    {
        if (':' == pStrEnd[-1])
        {
            dispBuf[COLON_UP_DOT_ADDR] = COLON_DOWN_DOT_ENABLE;
            dispBuf[COLON_DOWN_DOT_ADDR] = COLON_DOWN_DOT_ENABLE;
        }
        else if ('.' == pStrEnd[-1])
        {
            dispBuf[(charPos-1) * 2] = DOT_ENABLE_CODE;
        }
        else
        {
            dispBuf[(charPos-1) * 2] |= __GetCharCode(pStrEnd[-1]);
            charPos -= 1;
        }
        pStrEnd--;
    }

    Mdrv_FP_SM1668_RamUpg();
    return TRUE;
}
/*
**@function : display buffer data
**@params   : no 
**@return   : no
*/
void Mdrv_FP_SM1668_RamUpg(void)
{
    MS_U8   i = 0, j = 0;
    SM1668_STB_L;_delaySomeNop(CLK_DELAY_TIME);
    __WriteByte_2_SM1668(SM1668_DISP_OFF);
    SM1668_STB_H;_delaySomeNop(CLK_DELAY_TIME);

    SM1668_STB_L;_delaySomeNop(CLK_DELAY_TIME);
    __WriteByte_2_SM1668(CMD_SET_ADDR|ADDR_NOT_INC);
    SM1668_STB_H;_delaySomeNop(CLK_DELAY_TIME);

    for (i = 0, j = 0; i < 8; i ++, j ++)
    {
            SM1668_STB_L;_delaySomeNop(CLK_DELAY_TIME);
            __WriteByte_2_SM1668(CMD_SET_ADDR | j);

            if((i%2)==0)
            {
                __WriteByte_2_SM1668(dispBuf[i]);
            }

        SM1668_STB_H;_delaySomeNop(CLK_DELAY_TIME);
    }

    SM1668_STB_H;_delaySomeNop(CLK_DELAY_TIME);
    SM1668_STB_L;_delaySomeNop(CLK_DELAY_TIME);
    __WriteByte_2_SM1668(0x02);
    SM1668_STB_H;_delaySomeNop(CLK_DELAY_TIME);
    __SM1668_DispOn();
}
/*
**@function : update a specified led display buffer data
**@params   : no 
**@return   : no
*/
MS_BOOL Mdrv_FP_UpdateLedDisp(MS_BOOL ledPos, MS_BOOL ch, MS_BOOL bEnableDot)
{
    MS_U8 charCode;

    charCode = __GetCharCode(ch);
    if (bEnableDot)
    {
        charCode |= DOT_ENABLE_CODE;
    }

    __WriteData_2_SM1668_Addr(charCode, ledPos * 2);
    __WriteData_2_SM1668_Addr(0x00, ledPos * 2 + 1);
    __SM1668_DispOn();

    return TRUE;
}
static MS_BOOL __Get_SM1668_KeyVal(void)
{
    MS_U8 i;
    MS_U8 bitLevel;
    SM1668_DATA_H;        //释放总线
    _delaySomeNop(CLK_DELAY_TIME);
    SM1668_DIN_INPUT;
    _delaySomeNop(CLK_DELAY_TIME);
    SM1668_DIN_LEVEL;
    for (i = 0; i < 40; i++)
    {
        SM1668_CLK_L;
        _delaySomeNop(CLK_DELAY_TIME);
         bitLevel = SM1668_DIN_LEVEL;
        if (bitLevel != 0)
        {
            SM1668_CLK_H;
            _delaySomeNop(CLK_DELAY_TIME);
            return (i);
        }
        SM1668_CLK_H;
        _delaySomeNop(CLK_DELAY_TIME);
    }
    return (0xFF);
}

MS_U16 Mdrv_FP_GetKeyValue(void)
{
    MS_U16 keyval = 0xFF;
    _delaySomeNop(CLK_DELAY_TIME);
    SM1668_STB_L;        
    _delaySomeNop(CLK_DELAY_TIME);
    __WriteByte_2_SM1668(CMD_SET_DATA | OPT_READ_SM1668_KEYVAL);
    _delaySomeNop(CLK_DELAY_TIME);
    keyval = (MS_U16)__Get_SM1668_KeyVal(); 
    SM1668_STB_H;
    _delaySomeNop(CLK_DELAY_TIME);
    return keyval;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值