/******************************************************************************
- @file IO.C (for HT66F018)
- @author 徐永强
- @version V1.0
- @date 19-Nov-2015
- @brief This file contains the main function for IO input/output example.
*******************************************************************************/
//======================================================================
#include “HT66F018.h”
#define u8 unsigned char
#define u16 unsigned int
#define BIT(n) (1 << n)
#define HT162X_CS _pb0
#define HT162X_WR _pa4
#define HT162X_DAT1 _pb1
#define HT162X_DAT2 _pb2
#define KEY_PIN _pa5
#define TEST_MODE _pa6
#define Bias13Com4 0x52 //0b1000 0101 0010 1/3duty 4com
#define SysDis 0X00 //0b1000 0000 0000 关振系统荡器和LCD偏压发生器
#define SysEn 0X02 //0b1000 0000 0010 打开系统振荡器
#define LCDOFF 0X04 //0b1000 0000 0100 关LCD偏压
#define LcdOn 0X06 //0b1000 0000 0110 打开LCD偏压
#define XTAL 0x28 //0b1000 0010 1000 外部接时钟
#define RC256K 0X30 //0b1000 0011 0000 内部时钟
#define TONEON 0X12 //0b1000 0001 0010 打开声音输出
#define TONEOFF 0X10 //0b1000 0001 0000 关闭声音输出
#define WDTDis 0X0A //0b1000 0000 1010 禁止看门狗
#define TimerEn 0X0C //0b1000 0000 1100 使能时基输出
#define BUFFLEN 64 //显示缓冲区长度
u8 DisplayDataTabel[BUFFLEN];
unsigned char gc_Loop;//程序while循环使用
//====================================================================
void IO_Init()
{
//设定PB0,PB1,PB2,PA4, PA5,PA6,PA7,PB3 作为IO口
_acerl = 0x00;//设定相关IO口不作为ADC输入口,缺省是ADC输入口
//设定PA3,PB6,PB5作为IO口
_csel = 0;//设定比较器引脚作为IO口,缺省是比较器引脚
_cos = 1;
//IO 口上拉设定
_papu = 0xFF;
_pbpu = 0x7F;
_pcpu = 0x07;
//设定PA为输出口,缺省为输入口
_pac = 0x00;
//设定PB为输出口,缺省为输入口
_pbc = 0x00;
//设定PC为输出口,缺省为输入口
_pcc = 0x00;
}
const u8 LcdCmd[]=
{
6,
0xE3,
0x01,
0x02,
0x18,
0x29,
0x03,
};
//-----------------------------------------------------------------------------------------
//函数名称:DelayMS()
//功 能:延时子程序
//-----------------------------------------------------------------------------------------
void DelayMS(u16 iMs)
{
u16 i,j;
for(i=0;i<iMs;i++)
for(j=0;j<100;j++)
{
_clrwdt();
_nop();
}
}
//-----------------------------------------------------------------------------------------
//函数名称:Ht1621Wr_Data()
//功 能:写数据函数,cnt为传送数据位数,数据传送为低位在前
//-----------------------------------------------------------------------------------------
void Ht162XWr_Data(u8 Data,u8 cnt,u8 chipx)
{
u8 i;
for (i=0;i<cnt;i++)
{
HT162X_WR=0;
_nop();
_nop();
_nop();
_nop();
if((Data & 0x80)==0x80)
{
if(chipx)
{
HT162X_DAT2=1;
}else{
HT162X_DAT1=1;
}
}
else
{
if(chipx)
{
HT162X_DAT2=0;
}else{
HT162X_DAT1=0;
}
}
HT162X_WR=1;
_nop();
_nop();
_nop();
_nop();
Data<<=1;
}
}
//-----------------------------------------------------------------------------------------
//函数名称:void Ht1621WrCmd(uchar Cmd)
//功能描述: HT1621命令写入函数
//参数说明:Cmd为写入命令数据
//说 明:写入命令标识位100
//-----------------------------------------------------------------------------------------
void Ht162XWrCmd(u8 Cmd,u8 chipx)
{
HT162X_CS=0;
Ht162XWr_Data(0x80,3,chipx); //写入命令标志100
Ht162XWr_Data(Cmd,8,chipx); //写入命令数据
HT162X_WR=0;
HT162X_DAT1 = 0;
HT162X_DAT2 = 0;
_nop();
_nop();
_nop();
_nop();
HT162X_WR=1;
_nop();
_nop();
_nop();
_nop();
HT162X_CS=1;
}
/----------------------------------------------------------------------------/
/**@brief 发送数据
@param
index: 将DisplayDataTabel[index]的数据传送给屏,显示
@return
@note
/
/----------------------------------------------------------------------------*/
void Ht162XWriteData(u8 index,u8 chipx)
{
u8 temp;
u8 adder;
adder = index;
adder <<= 2;
HT162X_CS=0;
Ht162XWr_Data(0xa0,3,chipx); //写入数据标志101
Ht162XWr_Data(adder,6,chipx); //register address A5-A0 SEG0
temp = DisplayDataTabel[index] << 4;//lcd buffer low addr
Ht162XWr_Data(temp,4,chipx); //data D3~D0
HT162X_CS=1;
}
/----------------------------------------------------------------------------/
/@brief 更新显示,将DisplayDataTabel的数据更新到屏幕上
@param none
@return none
@note
DisplayDataTabel的低四位对应4个com,最高位为1就更新,否则不更新
/
/----------------------------------------------------------------------------/
void LCDUpdate_Display(void)
{
u8 i;
for(i=0;i<BUFFLEN/2;i++)
{
if((DisplayDataTabel[i]&BIT(7))BIT(7))
{//已经写入的数据不需要再进行写入
Ht162XWriteData(i,0);
DisplayDataTabel[i] &= ~BIT(7);
}
}
for(;i<BUFFLEN;i++)
{
if((DisplayDataTabel[i]&BIT(7))BIT(7))
{//已经写入的数据不需要再进行写入
Ht162XWriteData(i,1);
DisplayDataTabel[i] &= ~BIT(7);
}
}
}
/----------------------------------------------------------------------------*/
/@brief 全显或者清除所有显示
@param flag:1 全显 flag:0 清除
@return
@note
/
/----------------------------------------------------------------------------*/
void LCDDispAllAndClear(u8 flag)
{
u8 i;
for(i=0;i<BUFFLEN;i++)
{
DisplayDataTabel[i] = BIT(7);
if(flag)
{
DisplayDataTabel[i] = 0x8f;
}
}
}
//==========================================================================
void LCDDispComNumber(u8 tc_Num)
{
volatile u8 i,tempvalue,tempvalue1;
switch(tc_Num)
{
case 0:
tempvalue = 0x81;
tempvalue1 = 0x80;
break;
case 1:
tempvalue = 0x82;
tempvalue1 = 0x80;
break;
case 2:
tempvalue = 0x84;
tempvalue1 = 0x80;
break;
case 3:
tempvalue = 0x88;
tempvalue1 = 0x80;
break;
case 4:
tempvalue = 0x80;
tempvalue1 = 0x81;
break;
case 5:
tempvalue = 0x80;
tempvalue1 = 0x82;
break;
case 6:
tempvalue = 0x80;
tempvalue1 = 0x84;
break;
case 7:
tempvalue = 0x80;
tempvalue1 = 0x88;
break;
}
for(i=0;i<BUFFLEN;i=i+2)
{
DisplayDataTabel[i] = tempvalue;
DisplayDataTabel[i+1] = tempvalue1;
}
}
void LCDDispCom(u8 flg) //flg=0显偶数,flg=1显奇数
{
u8 i,tempvalue;
if(flg==0)
{
tempvalue = 0x8A;
}
else
{
tempvalue = 0x85;
}
for(i=0;i<BUFFLEN;i++)
{
DisplayDataTabel[i] = tempvalue;
}
}
void LCDDispSegNumber(u8 tc_SegNumber)
{
DisplayDataTabel[tc_SegNumber] =0x8f;
}
void LCDDispSeg(u8 odd) //odd=0显示偶数的SEG,odd=1显示奇数的SEG,
{
u8 i;
for(i=odd;i<BUFFLEN;i=i+2)
{
DisplayDataTabel[i] =0x8f;
}
}
void LCD_INITIAL()
{
u8 i;
HT162X_CS=1;
HT162X_WR=1;
HT162X_DAT1=1;
HT162X_DAT2=1;
HT162X_CS=0;
Ht162XWr_Data(0x90,4,0); //写入命令标志1001
Ht162XWr_Data(0X10,8,0); //写入命令数据irqen
Ht162XWr_Data(0x90,4,1); //写入命令标志1001
Ht162XWr_Data(0X10,8,1); //写入命令数据irqen
HT162X_CS=1;
for(i = 1; i <= LcdCmd[0]; i++)
{
Ht162XWrCmd(LcdCmd[i],0);//chip1
Ht162XWrCmd(LcdCmd[i],1);//chip2
}
DelayMS(100);
}
//-----------------------------------------------------------------------------------------
//函数名称:DelayMS()
//功 能:延时子程序
//-----------------------------------------------------------------------------------------
void KeyDelayMS(u16 iMs)
{
u16 i;
u8 j;
for(i=0;i<iMs;i++)
for(j=0;j<250;j++)
{
_clrwdt();
_nop();
while(!KEY_PIN)
{
_clrwdt();
}
}
}
//=====================================================================================
void LCD_Send_Data(u8 index,u8 chipx,u8 tcData)
{
u8 adder;
adder = index;
adder <<= 2;
HT162X_CS=0;
Ht162XWr_Data(0xa0,3,chipx); //写入数据标志101
Ht162XWr_Data(adder,6,chipx); //register address A5-A0 SEG0
Ht162XWr_Data(tcData,4,chipx); //data D3~D0
HT162X_CS=1;
}
//=====================================================================================
const u8 gc_NumData[][2]=
{
{0x50,0xF0},//数字0
{0x50,0x00},//数字1
{0x30,0xD0},//数字2
{0x70,0x90},//数字3
{0x70,0x20},//数字4
{0x60,0xB0},//数字5
{0x60,0xF0},//数字6
{0x50,0x10},//数字7
{0x70,0xF0},//数字8
{0x70,0xB0},//数字9
};
const u8 gc_DigAddr[][3]=
{
{6,7,1},//第1个8断码所在的seg位置(两字节) 和 位于那个芯片(一字节)
{4,5,1},//第2个8断码所在的seg位置(两字节) 和 位于那个芯片(一字节)
{2,3,1},//第3个8断码所在的seg位置(两字节) 和 位于那个芯片(一字节)
{0,1,1},//第4个8断码所在的seg位置(两字节) 和 位于那个芯片(一字节)
{16,17,1},//第5个8断码所在的seg位置(两字节) 和 位于那个芯片(一字节)
{14,15,1},//第6个8断码所在的seg位置(两字节) 和 位于那个芯片(一字节)
{12,13,1},//第7个8断码所在的seg位置(两字节) 和 位于那个芯片(一字节)
{10,11,1},//第8个8断码所在的seg位置(两字节) 和 位于那个芯片(一字节)
{7,8,0},//第9个8断码所在的seg位置(两字节) 和 位于那个芯片(一字节)
{5,6,0},//第10个8断码所在的seg位置(两字节) 和 位于那个芯片(一字节)
{3,4,0},//第11个8断码所在的seg位置(两字节) 和 位于那个芯片(一字节)
{1,2,0},//第12个8断码所在的seg位置(两字节) 和 位于那个芯片(一字节)
};
void LCD_Disp_DigNum(u8 tcAdr,u8 tcNum)
{
if(tcAdr)
{
tcAdr = tcAdr-1;
}
LCD_Send_Data(gc_DigAddr[tcAdr][0],gc_DigAddr[tcAdr][2],gc_NumData[tcNum][0]);
LCD_Send_Data(gc_DigAddr[tcAdr][1],gc_DigAddr[tcAdr][2],gc_NumData[tcNum][1]);
}
//=====================================================================================
void main()
{
u8 tcAdr;
u8 tcNum;
_wdtc = 0xA8;//关闭看门狗,缺省是开的,如果不清看门狗会引起复位
IO_Init();
LCD_INITIAL();
LCDDispAllAndClear(0);//全清除,把RAM全部填0
LCDUpdate_Display();
for(tcNum=0;tcNum<10;tcNum++)
{
for(tcAdr=1;tcAdr<13;tcAdr++)
{
LCD_Disp_DigNum(tcAdr,tcNum);
}
_nop();
}
while(1);
if(TEST_MODE)//判断是快速测试模式,还是精细测试模式
{
while(1)
{
_clrwdt();
LCD_INITIAL();
LCDDispAllAndClear(1);//全显示,把RAM全部填1
LCDUpdate_Display();
KeyDelayMS(500);//按键按住,可以暂停显示
LCD_INITIAL();
LCDDispAllAndClear(0);//全清除,把RAM全部填0
LCDUpdate_Display();
KeyDelayMS(500);//按键按住,可以暂停显示
LCD_INITIAL();
LCDDispAllAndClear(0); //全清除,把RAM全部填0
LCDDispCom(0);//显示COM0,2,4,6,...
LCDUpdate_Display();
KeyDelayMS(500); //按键按住,可以暂停显示
LCD_INITIAL();
LCDDispAllAndClear(0);
LCDDispCom(1);//显示COM1,3,5,7,...
LCDUpdate_Display();
KeyDelayMS(500); //按键按住,可以暂停显示
LCD_INITIAL();
LCDDispAllAndClear(0);
LCDDispSeg(0);//显示SEG0,2,4,6,...
LCDUpdate_Display();
KeyDelayMS(500); //按键按住,可以暂停显示
LCD_INITIAL();
LCDDispAllAndClear(0);
LCDDispSeg(1);//显示SEG1,3,5,7,...
LCDUpdate_Display();
KeyDelayMS(500); //按键按住,可以暂停显示
}
}else{
while(1)
{
_clrwdt();
LCD_INITIAL();
LCDDispAllAndClear(1);//全显示,把RAM全部填1
LCDUpdate_Display();
KeyDelayMS(500);//按键按住,可以暂停显示
LCD_INITIAL();
LCDDispAllAndClear(0);//全清除,把RAM全部填0
LCDUpdate_Display();
KeyDelayMS(500);//按键按住,可以暂停显示
for(tcNum=0;tcNum<8;tcNum++)
{//每次显示一个com
LCD_INITIAL();
LCDDispAllAndClear(0); //全清除,把RAM全部填0
LCDDispComNumber(tcNum);//显示COMi
LCDUpdate_Display();
KeyDelayMS(500); //按键按住,可以暂停显示
}
for(tcNum=0;tcNum<BUFFLEN;tcNum++)
{//每次显示一个seg
LCD_INITIAL();
LCDDispAllAndClear(0); //全清除,把RAM全部填0
LCDDispSegNumber(tcNum);//显示Segi
LCDUpdate_Display();
KeyDelayMS(500); //按键按住,可以暂停显示
}
}
}
}