段式LCD液晶顯示屏的底層驅動程式
阿新 • • 發佈:2019-01-03
本次任務用瑞賽微控制器R7C004驅動定製的段式液晶,4COM,18seg,1/3偏壓。由於微控制器本身有段式液晶驅動,根據資料手冊可以知道其工作過程及控制方法。
過程分2步:1,配置硬體驅動暫存器。2,根據具體液晶情況,取模,定義聯合結構體。
步驟1可以檢視資料手冊,根據步驟配置寫程式配置程式如下:4COM,18個seg從seg0到seg18(出去seg11)
void LCD_Init(void) { HB_LCDM1=0;nop(); HB_LCDM0=0x4D; HB_PFSEG0=0xf0;HB_PFSEG1=0xF7;HB_PFSEG2=0x07; HB_PFSEG3=0x00;HB_PFSEG4=0x00;HB_PFSEG5=0x00; HB_PFSEG6=0x00; HB_LCDC0=0x16; HB_VLCD=0X16; us_delay(100); HB_LCDM1=0x20; nop();nop();nop(); HB_LCDM1|=0xc0; HB_ISCLCD=0; }
步驟2 液晶的具體情況如下2圖
我們根據圖1來設定取模,我把 56 78 910 、、、、兩兩合為一個位元組 8位資料。 即8H 7C 7B 7A 7D 7E 7G 7F 這裡的7 即代表數碼管的位置,7代表從右往左數第2位數碼管。
這樣H 即為0x80 A為0x10 我用巨集定義設定每一段的數值
並通過巨集定義對0-f 和u 取模#define LcdSingMask 0x00 #define LcdSeg_a 0x10 #define LcdSeg_b 0x20 #define LcdSeg_c 0x40 #define LcdSeg_d 0x08 #define LcdSeg_e 0x04 #define LcdSeg_f 0x01 #define LcdSeg_g 0x02
從圖一可以看到 基本上每兩個seg能完全配置一個數碼管,值得一提的是 ,我通過union來管理他們,簡潔明瞭。#define Char_0 LcdSeg_a+LcdSeg_b+LcdSeg_c\ +LcdSeg_d+LcdSeg_e+LcdSeg_f #define Char_1 LcdSeg_b+LcdSeg_c #define Char_2 LcdSeg_a+LcdSeg_b\ +LcdSeg_d+LcdSeg_e+LcdSeg_g #define Char_3 LcdSeg_a+LcdSeg_b+LcdSeg_c\ +LcdSeg_d+LcdSeg_g #define Char_4 LcdSeg_b+LcdSeg_c\ +LcdSeg_f+LcdSeg_g #define Char_5 LcdSeg_a+LcdSeg_c\ +LcdSeg_d+LcdSeg_f+LcdSeg_g #define Char_6 LcdSeg_a+LcdSeg_g+LcdSeg_c\ +LcdSeg_d+LcdSeg_e+LcdSeg_f #define Char_7 LcdSeg_a+LcdSeg_b+LcdSeg_c #define Char_8 LcdSeg_a+LcdSeg_b+LcdSeg_c\ +LcdSeg_d+LcdSeg_e+LcdSeg_f+LcdSeg_g #define Char_9 LcdSeg_a+LcdSeg_b+LcdSeg_c\ +LcdSeg_d+LcdSeg_f+LcdSeg_g #define Char_A LcdSeg_a+LcdSeg_b+LcdSeg_c\ +LcdSeg_e+LcdSeg_f+LcdSeg_g #define Char_b LcdSeg_c\ +LcdSeg_d+LcdSeg_e+LcdSeg_f+LcdSeg_g #define Char_C LcdSeg_a+LcdSeg_f+LcdSeg_e+LcdSeg_d #define Char_d LcdSeg_b+LcdSeg_c+LcdSeg_d\ +LcdSeg_e+LcdSeg_g #define Char_E LcdSeg_a\ +LcdSeg_d+LcdSeg_e+LcdSeg_f+LcdSeg_g #define Char_F LcdSeg_a+LcdSeg_f+LcdSeg_e+LcdSeg_g #define Char_r LcdSeg_e+LcdSeg_g #define Char_H LcdSeg_b+LcdSeg_c+LcdSeg_e+LcdSeg_f+LcdSeg_g #define Char_L LcdSeg_d+LcdSeg_e+LcdSeg_f #define Char_Row LcdSeg_g #define Char_U LcdSeg_b+LcdSeg_c+LcdSeg_d+LcdSeg_e+LcdSeg_f
typedef union {
uchar LCD_LgcBuf[Gcst_LCDBufSize];
struct{
struct
{
unsigned char Sign_7F:1;
unsigned char Sign_7G:1;
unsigned char Sign_7E:1;
unsigned char Sign_7D:1;
unsigned char Sign_7A:1;
unsigned char Sign_7B:1;
unsigned char Sign_7C:1;
unsigned char Sign_8H:1;
}Sign_SEG1_2;
struct
{
unsigned char Sign_8F:1;
unsigned char Sign_8G:1;
unsigned char Sign_8E:1;
unsigned char Sign_8D:1;
unsigned char Sign_8A:1;
unsigned char Sign_8B:1;
unsigned char Sign_8C:1;
unsigned char Sign_9H:1;
}Sign_SEG3_4;
struct
{
unsigned char Sign_9F:1;
unsigned char Sign_9G:1;
unsigned char Sign_9E:1;
unsigned char Sign_9D:1;
unsigned char Sign_9A:1;
unsigned char Sign_9B:1;
unsigned char Sign_9C:1;
unsigned char Sign_kWh:1;
}Sign_SEG5_6;
struct
{
unsigned char Sign_Jiner:1;
unsigned char Sign_10H:1;
unsigned char Sign_Yuan:1;
unsigned char Sign_V:1;
unsigned char Sign_6A:1;
unsigned char Sign_6B:1;
unsigned char Sign_6C:1;
unsigned char Sign_7H:1;
}Sign_SEG7_8;
struct
{
unsigned char Sign_6F:1;
unsigned char Sign_6G:1;
unsigned char Sign_6E:1;
unsigned char Sign_6D:1;
unsigned char Sign_Dian:1;
unsigned char Sign_11H:1;
unsigned char Sign_Shengyu:1;
unsigned char Sign_Dangqian:1;
}Sign_SEG9_10;
struct
{
unsigned char Sign_5A:1;
unsigned char Sign_5B:1;
unsigned char Sign_5C:1;
unsigned char Sign_6H:1;
unsigned char Sign_5F:1;
unsigned char Sign_5G:1;
unsigned char Sign_5E:1;
unsigned char Sign_5D:1;
}Sign_SEG11_12;
struct
{
unsigned char Sign_4A:1;
unsigned char Sign_4B:1;
unsigned char Sign_4C:1;
unsigned char Sign_5H:1;
unsigned char Sign_4F:1;
unsigned char Sign_4G:1;
unsigned char Sign_4E:1;
unsigned char Sign_4D:1;
}Sign_SEG13_14;
struct
{
unsigned char Sign_3A:1;
unsigned char Sign_3B:1;
unsigned char Sign_3C:1;
unsigned char Sign_4H:1;
unsigned char Sign_3F:1;
unsigned char Sign_3G:1;
unsigned char Sign_3E:1;
unsigned char Sign_3D:1;
}Sign_SEG15_16;
struct
{
unsigned char Sign_2A:1;
unsigned char Sign_2B:1;
unsigned char Sign_2C:1;
unsigned char Sign_A:1;
unsigned char Sign_2F:1;
unsigned char Sign_2G:1;
unsigned char Sign_2E:1;
unsigned char Sign_2D:1;
}Sign_SEG17_18;
}Signs;
}UnDef_LcdBuf;
這裡初始化每個結構體時,要把低為放前邊。
我把一些特殊的值單獨賦值,比如“當前”,“金額”。因為這些不是數碼,要根據特殊情況來置位。同樣用到巨集定義。
#define Sign_Kwh_Dat GStr_LcdBuf.Signs.Sign_SEG5_6.Sign_kWh
#define Sign_V_Dat GStr_LcdBuf.Signs.Sign_SEG7_8.Sign_V
#define Sign_Yuan_Dat GStr_LcdBuf.Signs.Sign_SEG7_8.Sign_Yuan
#define Sign_A_Dat GStr_LcdBuf.Signs.Sign_SEG17_18.Sign_A
#define Sign_Shengyu_Dat GStr_LcdBuf.Signs.Sign_SEG9_10.Sign_Shengyu
#define Sign_Jiner_Dat GStr_LcdBuf.Signs.Sign_SEG7_8.Sign_Jiner
#define Sign_Dianliang_Dat GStr_LcdBuf.Signs.Sign_SEG9_10.Sign_Dian
#define Sign_Dangqian_Dat GStr_LcdBuf.Signs.Sign_SEG9_10.Sign_Dangqian
#define Sign_P4_Dat GStr_LcdBuf.Signs.Sign_SEG15_16.Sign_4H
#define Sign_P5_Dat GStr_LcdBuf.Signs.Sign_SEG13_14.Sign_5H
#define Sign_P6_Dat GStr_LcdBuf.Signs.Sign_SEG11_12.Sign_6H
#define Sign_P7_Dat GStr_LcdBuf.Signs.Sign_SEG7_8.Sign_7H
#define Sign_P8_Dat GStr_LcdBuf.Signs.Sign_SEG1_2.Sign_8H
#define Sign_P9_Dat GStr_LcdBuf.Signs.Sign_SEG3_4.Sign_9H
#define Sign_P10_Dat GStr_LcdBuf.Signs.Sign_SEG7_8.Sign_10H
#define Sign_P11_Dat GStr_LcdBuf.Signs.Sign_SEG9_10.Sign_11H
#define Dis_Kwh Sign_Kwh_Dat=1
#define Dis_Fu_V Sign_V_Dat=1
#define Dis_Yuan Sign_Yuan_Dat=1
#define Dis_An_A Sign_A_Dat=1
#define Dis_Shengyu Sign_Shengyu_Dat=1
#define Dis_Jin_e Sign_Jiner_Dat=1
#define Dis_Dianliang Sign_Dianliang_Dat=1
#define Dis_Dangqian Sign_Dangqian_Dat=1
#define Dis_Point5 Sign_P4_Dat=1
#define Dis_Point4 Sign_P5_Dat=1
#define Dis_Point3 Sign_P6_Dat=1
#define Dis_Point2 Sign_P7_Dat=1
#define Dis_Point1 Sign_P8_Dat=1
#define Dis_Point0 Sign_P9_Dat=1
#define Dis_Point10 Sign_P10_Dat=1
#define Dis_Point11 Sign_P11_Dat=1
取模和液晶對應起來後,就可以寫基礎的賦值程式了。根據瑞薩R7004資料手冊介紹,只需王顯示暫存器賦值既可以了。
賦值程式如下:
void Screen_convert(void)
{
*(LCD_StartAddr)=GStr_LcdBuf.LCD_LgcBuf[0]&0X0F;
*(LCD_StartAddr+1)=(GStr_LcdBuf.LCD_LgcBuf[0]>>4);
*(LCD_StartAddr+2)=GStr_LcdBuf.LCD_LgcBuf[1]&0X0F;
*(LCD_StartAddr+3)=(GStr_LcdBuf.LCD_LgcBuf[1]>>4);
*(LCD_StartAddr+4)=GStr_LcdBuf.LCD_LgcBuf[2]&0X0F;
*(LCD_StartAddr+5)=(GStr_LcdBuf.LCD_LgcBuf[2]>>4);
*(LCD_StartAddr+6)=GStr_LcdBuf.LCD_LgcBuf[3&0X0F];
*(LCD_StartAddr+7)=(GStr_LcdBuf.LCD_LgcBuf[3]>>4);
*(LCD_StartAddr+8)=GStr_LcdBuf.LCD_LgcBuf[4]&0X0F;
*(LCD_StartAddr+9)=(GStr_LcdBuf.LCD_LgcBuf[4]>>4);
*(LCD_StartAddr+10)=GStr_LcdBuf.LCD_LgcBuf[5]&0X0F;
*(LCD_StartAddr+12)=(GStr_LcdBuf.LCD_LgcBuf[5]>>4);
*(LCD_StartAddr+13)=GStr_LcdBuf.LCD_LgcBuf[6]&0X0F;
*(LCD_StartAddr+14)=(GStr_LcdBuf.LCD_LgcBuf[6]>>4);
*(LCD_StartAddr+15)=GStr_LcdBuf.LCD_LgcBuf[7]&0X0F;
*(LCD_StartAddr+16)=(GStr_LcdBuf.LCD_LgcBuf[7]>>4);
*(LCD_StartAddr+17)=GStr_LcdBuf.LCD_LgcBuf[8]&0X0F;
*(LCD_StartAddr+18)=(GStr_LcdBuf.LCD_LgcBuf[8]>>4);
}
LCD_StartAddr為暫存器首地址,資料手冊有。把一個位元組分為高低4位,賦值給連續的兩個顯示暫存器,就可正常顯示一個數碼管的數字了。接下來介紹怎麼王數組裡填充數值。
<pre name="code" class="objc">void Dis_1char(uchar PuB_position,uchar PuB_data)
{
uchar LuW_Dat;
LuW_Dat=GAuB_char_tbl[PuB_data];
switch(PuB_position)
{
case 0: GStr_LcdBuf.LCD_LgcBuf[2]=LuW_Dat;break;
case 1: GStr_LcdBuf.LCD_LgcBuf[1]=LuW_Dat;break;
case 2: GStr_LcdBuf.LCD_LgcBuf[0]=LuW_Dat;break;
case 3: GStr_LcdBuf.LCD_LgcBuf[3]|=(LuW_Dat&0xf0);GStr_LcdBuf.LCD_LgcBuf[4]|=(LuW_Dat&0x0f);break;
case 4: zhihuan(LuW_Dat);GStr_LcdBuf.LCD_LgcBuf[5]=LuW_Dat;break;
case 5: zhihuan(LuW_Dat);GStr_LcdBuf.LCD_LgcBuf[6]=LuW_Dat;break;
case 6: zhihuan(LuW_Dat);GStr_LcdBuf.LCD_LgcBuf[7]=LuW_Dat;break;
case 7: zhihuan(LuW_Dat);GStr_LcdBuf.LCD_LgcBuf[8]=LuW_Dat;break;
default: break;
}
}
這裡要注意GStr_LcdBuf.LCD_LgcBuf[?]的順序和要顯示的位置的關係,和圖一一一對應,比如要顯示0位置時,可根據圖1的 要用9A-9C,K那兩個seg 即GStr_LcdBuf.LCD_LgcBuf[2]。位置3,有點特殊,他分別用到了陣列3的高4位,和陣列4的低四位。位置4-7,高低四位又反過來,所以要加zhihuan(LuW_Dat);實現高低4為互換。
#define zhihuan(dat) ((dat>>4)|(dat<<4))
瞭解基本的顯示程式後,顯示的步驟為:
1,LCD_Init()
2,Dis_1char(PuB_position,PuB_data),,還可以有Sign_Kwh_Dat、Dis_Jin_e、Dis_Point0之類。
3,Screen_convert()