1、HT1621电路分析 HT1621为32×4即128点内存映像LCD驱动器,包含内嵌的32×4位显示RAM内存和时基发生器以及WDT看门狗定时器. HT1621驱动电路如下图所示:
图1 与单片机相连接控制的有9脚CS,3脚WR,12脚DATA,其功能描述如下表。
图2 2、字符显示原理 液晶管点亮和熄灭原理分别为在对应的RAM地址中写1和写0.首先需要清楚所驱动控制的液晶的COM-SEG对应关系,然后需要了解HT1621的32×4RAM地址映射。 例如要控制的液晶的装脚成品图部分如下:
图3 着重看一个液晶数码管,我们了解原理就行。可以看到图3中是第2个液晶数码管,有7段,分别为A,B,C,D,E,F,G。也就分别为下面COM\SEG地址对应关系图中的2A,2B,2C,2D,2E,2F,2G。 液晶的显示字符的部分COM公共端输出口和SEG段输出口的分布如下表所示,同理我们可以看到例如:2D对应(SEG5,COM0),2E对应(SEG5,COM1),2F对应(SEG5,COM2),2A对应(SEG5,COM3),2C对应(SEG4,COM1),2G对应(SEG4,COM2),2B对应(SEG4,COM3)。
图4 搞清楚我们要控制的对象之后那, HT1621的RAM 地址映射如下图所示:
图5 可以清楚的看到要控制液晶段对应SEG号作为6位地址,COM号对应作为4位数据写入,此时注意4位数据的高低位。写数据到RAM命令格式为:101+6位RAM地址+4位数据,其中RAM地址为SEG序号. 例如我们在图3的第二个液晶数码管上显示数字,首先我们根据图3得到地址映射关系,先写入地址SEG4中的四位数据(COM3,COM2,COM1,COM0),再写如地址SEG5中的四位数据(COM3,COM2,COM1,COM0),对应关系如下: SEG4 | SEG5 | COM3 | COM2 | COM1 | COM0 | COM3 | COM2 | COM1 | COM0 | 2B | 2G | 2C | T10 | 2A | 2F | 2E | 2D |
所以如果在图3中显示“5”,则在显示的液晶段对应地址上写1,不显示写0,如下图所示。所以SEG4地址应写入的数据为0110 ,SEG5地址应写入数据1101。
图6 3、显示的保持 写数据过程需要保证写前无关位数据的保持,因此在单片机程序中开辟32×4数组作为虚拟ARM,存储写前LCD显示数据.通过与清零,或置位操作实现,例如6位地址Address当前显示的数据为Data_last .若Xi(i=0,1,2,3) 位需要保持,则Xi为1,否则Xi为0.写入的数据为Data_now,变换公式为:
4、程序 主要的程序编写流程如下:
图7 程序的参考步骤:①Display_Wendu_1②write_addr_dat_n_wendu③write_mode④write_address⑤write_data_4bit,其中Lcdram数组为建立的虚拟数组。
- unsigned char Lcdram[32]=
- {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
- };
- const unsigned char Wendu[] = //温度0-9
- {
- 0X5F, 0X50, 0X3D, 0X79, 0X72, 0X6B, 0X6F, 0X51, 0X7F, 0X7B
- };
- ///////////////////////////////////////////////////驱动函数
- /*
- * LCD 模式写入
- * 入口:MODE :COM(命令模式) DAT(数据模式)
- * 出口:void
- */
- void write_mode(unsigned char MODE) //写入模式,数据or命令
- {
- GPIO_ResetBits(GPIOB, HT1621_WR); // RW = 0;
- delay_us(10);
- GPIO_SetBits(GPIOB, HT1621_DATA); // DA = 1;
- GPIO_SetBits(GPIOB, HT1621_WR); // RW = 1;
- delay_us(10);
- GPIO_ResetBits(GPIOB, HT1621_WR); // RW = 0;
- delay_us(10);
- GPIO_ResetBits(GPIOB, HT1621_DATA); // DA = 0;
- GPIO_SetBits(GPIOB, HT1621_WR); // RW = 1;
- delay_us(10);
- GPIO_ResetBits(GPIOB, HT1621_WR); // RW = 0;
- delay_us(10);
- if (0 == MODE)
- {
- GPIO_ResetBits(GPIOB, HT1621_DATA); // DA = 0;
- }
- else
- {
- GPIO_SetBits(GPIOB, HT1621_DATA); // DA = 1;
- }
- delay_us(10);
- GPIO_SetBits(GPIOB, HT1621_WR); // RW = 1;
- delay_us(10);
- }
- /*
- * LCD 命令写入函数
- * 入口:cbyte ,控制命令字
- * 出口:void
- */
- void write_command(unsigned char Cbyte)
- {
- unsigned char i = 0;
- for (i = 0; i < 8; i++)
- {
- GPIO_ResetBits(GPIOB, HT1621_WR);
- if ((Cbyte >> (7 - i)) & 0x01)
- {
- GPIO_SetBits(GPIOB, HT1621_DATA);
- }
- else
- {
- GPIO_ResetBits(GPIOB, HT1621_DATA);
- }
- delay_us(10);
- GPIO_SetBits(GPIOB, HT1621_WR);
- delay_us(10);
- }
- GPIO_ResetBits(GPIOB, HT1621_WR);
- delay_us(10);
- GPIO_ResetBits(GPIOB, HT1621_DATA);
- GPIO_SetBits(GPIOB, HT1621_WR);
- delay_us(10);
- }
- /*
- * LCD 地址写入函数
- * 入口:cbyte,地址
- * 出口:void
- */
- void write_address(unsigned char Abyte)
- {
- unsigned char i = 0;
- Abyte = Abyte << 2;
- for (i = 0; i < 6; i++)
- {
- GPIO_ResetBits(GPIOB, HT1621_WR);
- //delay_us(10);
- if ((Abyte >> (7 - i)) & 0x01)
- {
- GPIO_SetBits(GPIOB, HT1621_DATA);
- }
- else
- {
- GPIO_ResetBits(GPIOB, HT1621_DATA);
- }
- delay_us(10);
- GPIO_SetBits(GPIOB, HT1621_WR);
- delay_us(10);
- }
- }
- /*
- * LCD 数据写入函数
- * 入口:Dbyte,数据
- * 出口:void
- */
- void write_data_8bit(unsigned char Dbyte)
- {
- int i = 0;
- for (i = 0; i < 8; i++)
- {
- GPIO_ResetBits(GPIOB, HT1621_WR);
- delay_us(10);
- if ((Dbyte >> (7 - i)) & 0x01)
- {
- GPIO_SetBits(GPIOB, HT1621_DATA);
- }
- else
- {
- GPIO_ResetBits(GPIOB, HT1621_DATA);
- }
- delay_us(10);
- GPIO_SetBits(GPIOB, HT1621_WR);
- delay_us(10);
- }
- }
- void write_data_4bit(unsigned char Dbyte)
- {
- int i = 0;
- for (i = 0; i < 4; i++)
- {
- GPIO_ResetBits(GPIOB, HT1621_WR);
- //delay_us(10);
- if ((Dbyte >> (3 - i)) & 0x01)
- {
- GPIO_SetBits(GPIOB, HT1621_DATA);
- }
- else
- {
- GPIO_ResetBits(GPIOB, HT1621_DATA);
- }
- delay_us(10);
- GPIO_SetBits(GPIOB, HT1621_WR);
- delay_us(10);
- }
- }
- //1621初始化
- void ht1621_init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;// declare the structure
- GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
- memset(&GPIO_InitStructure, 0, sizeof(GPIO_InitTypeDef));
- GPIO_InitStructure.GPIO_Pin = HT1621_WR | HT1621_DATA ;//| HT1621_IRQ
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- memset(&GPIO_InitStructure, 0, sizeof(GPIO_InitTypeDef));
- GPIO_InitStructure.GPIO_Pin = HT1621_CS ;//| HT1621_IRQ
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- }
- /*
- * LCD 初始化,对lcd自身做初始化设置
- * 入口:void
- * 出口:void
- */
- void lcd_init(void)
- {
- //////////////////////////////////////////////////////
- GPIO_SetBits(GPIOA, HT1621_CS);
- GPIO_SetBits(GPIOB, HT1621_WR);
- GPIO_SetBits(GPIOB, HT1621_DATA);
- for (ii=0;ii<10000;ii++)
- {for(j=10;j>0;j--);}
- //////////////////////////////////////////////////////
- GPIO_ResetBits(GPIOA, HT1621_CS); //CS = 0;
- //delay_us(10);
- for (ii=0;ii<10000;ii++)
- {for(j=10;j>0;j--);}
- write_mode(COMMAND); //命令模式
- write_command(0x01); //Enable System
- write_command(0x03); //Enable Bias
- write_command(0x04); //Disable Timer
- write_command(0x05); //Disable WDT
- write_command(0x08); //Tone OFF
- write_command(0x18); //on-chip RC震荡
- write_command(0x29); //1/4Duty 1/3Bias
- write_command(0x80); //Disable IRQ
- write_command(0x40); //Tone Frequency 4kHZ
- write_command(0xE3); //Normal Mode
- GPIO_SetBits(GPIOA, HT1621_CS); //CS = 1;
- }
- /*
- * LCD 清屏函数
- * 入口:void
- * 出口:void
- */
- void lcd_clr(void)
- {
- write_addr_dat_n(0x0, 0x00, 32);//15
- }
- //用于温度区域写数据
- void write_addr_dat_n_wendu(unsigned char _addr, unsigned char _dat, unsigned char n)
- {
- unsigned char i = 0;
- unsigned char _dat_temp1,_dat_temp2;
- //WriteLcdram(_addr, _dat);
- GPIO_ResetBits(GPIOA, HT1621_CS); // CS = 0;
- write_mode(DAT);
- if(Lcdram[_addr]==0x00)
- {
- WriteLcdram(_addr, _dat);
- }
- if((_addr%2)==0)
- {
- _dat_temp1=Lcdram[_addr];
- _dat_temp2=(_dat_temp1&0x08)|_dat;
- write_address(_addr);
- for (i = 0; i < n; i++)
- {
- write_data_4bit(_dat_temp2);
- }
- GPIO_SetBits(GPIOA, HT1621_CS); //CS = 1;
- }
- else if((_addr%2)!=0)
- {
- write_address(_addr);
- for (i = 0; i < n; i++)
- {
- write_data_4bit(_dat);
- }
- GPIO_SetBits(GPIOA, HT1621_CS);
- }
- WriteLcdram(_addr, _dat_temp2);
- }
- //用于湿度区域写数据
- void write_addr_dat_n_shidu(unsigned char _addr, unsigned char _dat, unsigned char n)
- {
- unsigned char i = 0;
- unsigned char _dat_temp1,_dat_temp2;
- //WriteLcdram(_addr, _dat);
- GPIO_ResetBits(GPIOA, HT1621_CS); // CS = 0;
- write_mode(DAT);
- if(Lcdram[_addr]==0x00)
- {
- WriteLcdram(_addr, _dat);
- }
- if((_addr%2)==0)
- {
- _dat_temp1=Lcdram[_addr];
- _dat_temp2=(_dat_temp1&0x01)|_dat;
- write_address(_addr);
- for (i = 0; i < n; i++)
- {
- write_data_4bit(_dat_temp2);
- }
- GPIO_SetBits(GPIOA, HT1621_CS); //CS = 1;
- }
- else if((_addr%2)!=0)
- {
- write_address(_addr);
- for (i = 0; i < n; i++)
- {
- write_data_4bit(_dat);
- }
- GPIO_SetBits(GPIOA, HT1621_CS);
- }
- WriteLcdram(_addr, _dat_temp2);
- }
- //用于底部数字写数据
- void write_addr_dat_n_others(unsigned char _addr, unsigned char _dat, unsigned char n)
- {
- unsigned char i = 0;
- unsigned char _dat_temp1,_dat_temp2;
- GPIO_ResetBits(GPIOA, HT1621_CS); // CS = 0;
- write_mode(DAT);
- if(Lcdram[_addr]==0x00)
- {
- WriteLcdram(_addr, _dat);
- }
- if((_addr%2)==0)
- {
- _dat_temp1=Lcdram[_addr];
- _dat_temp2=(_dat_temp1&0x01)|_dat;
- write_address(_addr);
- for (i = 0; i < n; i++)
- {
- write_data_4bit(_dat_temp2);
- }
- GPIO_SetBits(GPIOA, HT1621_CS); //CS = 1;
- }
- else if((_addr%2)!=0)
- {
- write_address(_addr);
- for (i = 0; i < n; i++)
- {
- write_data_4bit(_dat);
- }
- GPIO_SetBits(GPIOA, HT1621_CS);
- }
- //WriteLcdram(_addr, _dat);
- WriteLcdram(_addr, _dat_temp2);
- }
- //用于字符写数据
- void write_addr_dat_n_char(unsigned char _addr, unsigned char _dat, unsigned char state)
- {
- unsigned char i = 0;
- unsigned char _dat_temp1,_dat_temp2;
- GPIO_ResetBits(GPIOA, HT1621_CS); // CS = 0;
- write_mode(DAT);
- _dat_temp1=Lcdram[_addr];
- if(state==1)
- {
- _dat_temp2=(_dat_temp1|_dat);
- }
- else if(state==0)
- {
- _dat_temp2=(_dat_temp1&(~_dat));
- }
- write_address(_addr);
- for (i = 0; i < 1; i++)
- {
- write_data_4bit(_dat_temp2);
- }
- GPIO_SetBits(GPIOA, HT1621_CS); //CS = 1;
- WriteLcdram(_addr, _dat_temp2);
- }
- //显示温度
- //入口:pos,显示位置,地址0、2、4分别为从右到左的三个数字
- // num:要显示的一位数
- void Display_Wendu_1(unsigned char add, unsigned char num )
- {
- unsigned char n,i,j;
- n=getChr_Wendu(num);
- i=(n&0xF0)>>4;
- j=n&0x0F;
- write_addr_dat_n_wendu(add,i,1);
- write_addr_dat_n_wendu(add+1,j,1);
- }
- //温度数据转换,lcd.c内部使用
- unsigned char getChr_Wendu(unsigned char c)
- {
- unsigned char i;
- for ( i = 0; i < 10; ++i)
- {
- if (c == i)
- {
- return Wendu[i];
- }
- }
- }
- //更新lcdram数组
- void WriteLcdram(unsigned char add, unsigned char data)
- {
- Lcdram[add]=data;
- }
复制代码
|
ST有自带段码液晶驱动型号吗?