1. 程式人生 > >程式設計實戰之:段碼屏的程式設計

程式設計實戰之:段碼屏的程式設計

條件:中穎SH88F4051晶片 + HT1621 + 自己開模段碼LCD屏
段碼屏的驅動程式跟數碼管的靜態驅動程式一樣,只要我們弄懂了怎樣顯示一個基本單位,根據此基本單位編寫一個字型檔表,然後用與(&)和或(|)這兩種位運算子就可以隨心所欲編寫我們要顯示的數字或者形狀。驅動方案為:微控制器用3個IO口跟HT1621進行通訊,用 HT1621驅動段碼屏。
HT1621有4個COM,分別是com3,com2,com1,com0。有32個SEG,分別是SEG0,SEG1….SEG31。
什麼是COM,什麼是SEG?我的思路解釋是: COM就是橫向上的X座標,SEG就是縱向上的Y座標。X座標與Y座標組合成一張表格,每格代表一個顯示點。比如HT1621,有4個COM,32個SEG,組成一個32行,每行裝4個點的表格,一共有128個點,也就是最多可以顯示128個點,用數碼管的思路,最多可以顯示128個LED燈。128個點已經可以滿足大多數的段碼屏了。
一、 硬體連線


這裡寫圖片描述

二、 看規格書,查段碼快取資料表


這裡寫圖片描述

三、 程式設計

1、 初始化

/********************************************************
系統初始化
********************************************************/
void system_ini()
{
    RSTSTAT = 0;                                    //清看門狗
    IO_ini();                                       // I/O口初始化
ht1621_Init(); // 1621初始化 } /************************************************************ I/O口初始化 ************************************************************/ void IO_ini() { CLKCON &= 0x8f; //系統時鐘分頻為1:1 P1M0 = 0x00; //普通I/O口 P1M1 = 0x00; //普通I/O口
P1 = 0x80; //P1.7為模擬串列埠輸入RX,接收腳。 P3M0 = 0x00; P3M1 = 0x0fc; //除了P3.0之外都設為推輓輸出 P3 = 0x01; //P3.0設為輸入,因為P3.0是RX腳 P4M0 = 0x00; P4M1 = 0x00; P4 = 0xFF; } /******************************************************** h1621初始化 ********************************************************/ #define ht1621_cs_high() (P3_5 = 1) #define ht1621_cs_low() (P3_5 = 0) #define ht1621_dat_high() (P3_4 = 1) #define ht1621_dat_low() (P3_4 = 0) #define ht1621_wr_high() (P3_7 = 1) #define ht1621_wr_low() (P3_7 = 0) void ht1621_Init( void ) { ht1621_cs_high(); ht1621_wr_high(); ht1621_dat_high(); delayms(200); ht1621wr_cmd(BIAS); ht1621wr_cmd(RC256); ht1621wr_cmd(SYSDIS); ht1621wr_cmd(SYSEN); ht1621wr_cmd(LCDON); }

注:ht1621wr_data和ht1621wr_cmd 這兩個函式就不寫了,相信網上會有很多。
2、 顯示段跟顯示快取的對應關係
說明:根據上面的段碼快取資料表製作一個buf[N]的快取。

unsigned char idata  buf[16] = {0}; 
#define S1a_ON()        buf[0] |= 1<<3   
#define S1a_OFF()   buf[0] &= ~(1<<3)
#define S1b_ON()        buf[0] |= 1<<2
#define S1b_OFF()   buf[0] &= ~(1<<2)
#define S1c_ON()        buf[0] |= 1<<1
#define S1c_OFF()   buf[0] &= ~(1<<1)
#define S1d_ON()        buf[0] |= 1<<0
#define S1d_OFF()   buf[0] &= ~(1<<0)
#define S1e_ON()        buf[0] |= 1<<4
#define S1e_OFF()   buf[0] &= ~(1<<4)
#define S1f_ON()        buf[0] |= 1<<6
#define S1f_OFF()   buf[0] &= ~(1<<6)
#define S1g_ON()        buf[0] |= 1<<5
#define S1g_OFF()   buf[0] &= ~(1<<5)
。。。

3、數碼管段碼快取

#define Sa  3  
#define Sb  2  
#define Sc  1  
#define Sd  0  
#define Se  4
#define Sf  5
#define Sg  6
const unsigned char segment [] = {
    (1<<Sa)|(1<<Sb)|(1<<Sc)|(1<<Sd)|(1<<Se)|(1<<Sf),        //0
    (1<<Sb)|(1<<Sc),                                        //1
    (1<<Sa)|(1<<Sb)|(1<<Sd)|(1<<Se)|(1<<Sg),                //2
    (1<<Sa)|(1<<Sb)|(1<<Sc)|(1<<Sd)|(1<<Sg),                //3
    (1<<Sb)|(1<<Sc)|(1<<Sf)|(1<<Sg),                        //4
    (1<<Sa)|(1<<Sc)|(1<<Sd)|(1<<Sf)|(1<<Sg),                //5
    (1<<Sa)|(1<<Sc)|(1<<Sd)|(1<<Se)|(1<<Sf)|(1<<Sg),        //6
    (1<<Sa)|(1<<Sb)|(1<<Sc),                                //7
    (1<<Sa)|(1<<Sb)|(1<<Sc)|(1<<Sd)|(1<<Se)|(1<<Sf)|(1<<Sg),//8
    (1<<Sa)|(1<<Sb)|(1<<Sc)|(1<<Sd)|(1<<Sf)|(1<<Sg),        //9
    (1<<Sa)|(1<<Sb)|(1<<Sc)|(1<<Se)|(1<<Sf)|(1<<Sg),        //a
    (1<<Sc)|(1<<Sd)|(1<<Se)|(1<<Sf)|(1<<Sg),                //b
    (1<<Sa)|(1<<Sd)|(1<<Se)|(1<<Sf),                        //c
    (1<<Sb)|(1<<Sc)|(1<<Sd)|(1<<Se)|(1<<Sg),                //d
    (1<<Sa)|(1<<Sd)|(1<<Se)|(1<<Sf)|(1<<Sg),                //e
    (1<<Sa)|(1<<Se)|(1<<Sf)|(1<<Sg),                        //f 
    0,                                                      //0x10 
    (1<<Sb)|(1<<Sc)|(1<<Sd)|(1<<Se)|(1<<Sf),                //0x11 
    (1<<Sd)|(1<<Se)|(1<<Sf)|(1<<Sg),                        //0x12 
    0,                                                      //0x13  
    0,                                                      //0x14 
    0,                                                      //0x15 
    0,                                                      //0x16 
    0,                                                      //0x17 
    0,                                                      //0x18 
    0,                                                      //0x19 
    0,                                                      //0x1a 
    0,                                                      //0x1b 
    0,                                                      //0x1c 
    0,                                                      //0x1d 
    0,                                                      //0x1e 
    0,                                                      //0x1f 
    0,                                                      //0x20 
    0,                                                      //0x21 
};

4、在指定位置顯示一個字元

void DispChar (unsigned char BCD,unsigned char x)  
{
    unsigned char seg;
    seg = segment[BCD]; 
    switch(x)
    {       
        case 0:
            break;      
        case 1:                                     
            if(seg & (1<<Sa))
            {
                S1a_ON();
            }
            else
            {
                S1a_OFF();
            }       
            if(seg & (1<<Sb))
            {
                S1b_ON();
            }
            else
            {
                S1b_OFF();
            }   
            if(seg & (1<<Sc))
            {
                S1c_ON();
            }
            else
            {
                S1c_OFF();
            }
            if(seg & (1<<Sd))
            {
                S1d_ON();
            }
            else
            {
                S1d_OFF();
            }
            if(seg & (1<<Se))
            {
                S1e_ON();
            }
            else
            {
                S1e_OFF();
            }       
            if(seg & (1<<Sf))
            {
                S1f_ON();
            }
            else
            {
                S1f_OFF();
            }
            break;
    。。。
    default:
        break;
    }
}

5、顯示固定的字元
例如固定顯示“W”,共4個段碼。

void display_w()
{
    T0_ON();S16_ON();
    K6_ON();S15_ON();
}

6、顯示重新整理

void main()
{   
    system_ini();  
    while(1)
{
    display_w();
        。。。
    RefreshDisp( buf );         //  顯示重新整理
}
}
/********************************************************
重新整理全部液晶的顯示
/********************************************************/
void  RefreshDisp(unsigned char *p)
{   
    unsigned char i;
    ht1621_cs_low();
    ht1621wr_data(0xa0,3);                      //寫入命令標誌101,寫資料方式
    ht1621wr_data(0,6);                             //發寫資料地址,
    for ( i = 0; i < 16;i++)
    {
        ht1621wr_data(*p++,8);                  
    }
    ht1621_cs_high();
}