程式設計實戰之:段碼屏的程式設計
阿新 • • 發佈:2018-12-27
條件:中穎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();
}