最近在用做机顶盒的时候用了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;
}