1、根据时序图了解通讯协议格式
根据HT1622数据手册中的时序图可知:
1)从N1处可知,当CS处于低电平时,WR才有效。 2)从N2处可知,当CS处于低电平,且当WR脚处于上升沿时,DATA才有效。 3)从N3处可知,向HT1622传送指令的通讯协议格式为:3位命令标识+9位指令。 4)从N4处可知,向HT1622传送数据的通讯协议格式为:3位命令标识+6位地址+4位数据。 5)从N5处可知,向HT1622连续传送多组数据,后续数据会自动更新写入到下一个地址。 6)从N3/N4/N5处可知,向HT1622写入数据时,指令和地址是从高位写入,数据是从低位写入。 二、写驱动函数
由HT1622 RAM映射表可知,SEGx 和 其首地址Addr 的关系(Addr = SEGx * 2),是连续映射的。所以在写入数据时,可以使用SEGx代替地址,一次写入8位数据(控制SEGx下的8个COM),能更简洁直观地对断码屏进行操作。注意,有的屏幕供应商提供的DataSheet,SEG是从1开始计数,而不是0。
/***************************************************************
数据传送,其中:
ucDataValue:显示数据、命令ID码和数据ID码、初始化设置命令代码;
ucBitNum:位的长度(命令ID码和数据ID码是3位,显示数据是8位和4位,初始化设置命令代码9位);
****************************************************************/
void SendNBitToRAM(unsigned char ucDataValue, uint8_t ucBitNum)
{
unsigned char i;
for (i = 0; i < ucBitNum; i++)
{
if (ucDataValue & 0x80)
{
setb(PORT_HT1622B_DATA, Pin_HT1622B_DATA);
}
else
{
clrb(PORT_HT1622B_DATA, Pin_HT1622B_DATA);
}
clrb(PORT_HT1622B_WR, Pin_HT1622B_WR);
_delay_loop_1(2);
setb(PORT_HT1622B_WR, Pin_HT1622B_WR);
_delay_loop_1(2);
ucDataValue = ucDataValue << 1;
}
}
把地址写入RAM
void SendAddrToRAM(unsigned char ucAddrValue)
{
unsigned char i;
ucAddrValue = ucAddrValue << 2; // 地址数据只有低6位,所以要先移掉高两位
for (i = 0; i < 6; i++)
{
if (ucAddrValue & 0x80)
{
setb(PORT_HT1622B_DATA, Pin_HT1622B_DATA);
}
else
{
clrb(PORT_HT1622B_DATA, Pin_HT1622B_DATA);
}
clrb(PORT_HT1622B_WR, Pin_HT1622B_WR);
_delay_loop_1(2);
setb(PORT_HT1622B_WR, Pin_HT1622B_WR);
_delay_loop_1(2);
ucAddrValue = ucAddrValue << 1;
}
}
/**************************************************************
全屏显示,其中:
ucAddrValue:地址
ucDataValue:显示数据
ucSegNum:SEG数量,屏有多少个SEG,就传送多少次显示数据
LcdDisplay_All(0x00, LcdDisplay_On, LCD_SEG_NUM);
**************************************************************/
void LcdDisplay_All(unsigned char ucAddrValue, uint8_t ucDataValue, uint8_t ucSegNum)
{
unsigned char i;
clrb(PORT_HT1622B_CS, Pin_HT1622B_CS); // 片选,选中HT1622
SendNBitToRAM(LCD_MODE_WRITE, 3); // 发送数据码ID
SendAddrToRAM(ucAddrValue); // 发送地址
for (i = 0; i < ucSegNum; i++) // 连续传送显示数据的时候,地址自动加一
{
SendNBitToRAM(ucDataValue, 8); // 传送显示数据
}
setb(PORT_HT1622B_CS, Pin_HT1622B_CS);
}
写LCD,发送地址和数
void LcdDisplay_Single_Test()
{
clrb(PORT_HT1622B_CS, Pin_HT1622B_CS); // 片选,选中HT1622
SendNBitToRAM(LCD_MODE_WRITE, 3); // 发送数据码ID
SendAddrToRAM(0x00); // 发送地址
SendNBitToRAM(0xFF, 8); // 传送显示数据
setb(PORT_HT1622B_CS, Pin_HT1622B_CS);
}
//===========================================================================
// 函数名: WrBit_H
// 功能 : 将数据data从高位开始(高—>低),写入cnt位
// 参数 : data:写入的数据;cnt:写入位数
// 返回值: none
//===========================================================================
void WrBit_H(uint8_t data, uint8_t cnt)
{
uint8_t i;
for (i = 0; i < cnt; i++)
{
// 拉低写使能
clrb(PORT_HT1622B_WR, Pin_HT1622B_WR);
_delay_loop_1(2);
if (data & 0x80)
{
// 数据位拉高
setb(PORT_HT1622B_DATA, Pin_HT1622B_DATA);
}
else
{
// 数据线拉低
clrb(PORT_HT1622B_DATA, Pin_HT1622B_DATA);
}
_delay_loop_1(2);
setb(PORT_HT1622B_WR, Pin_HT1622B_WR);
_delay_loop_1(2);
data <<= 1;
}
}
//===========================================================================
// 函数名: WrBit_L
// 功能 : 将数据data从低位开始(高<—低),写入cnt位
// 参数 : data:写入的数据;cnt:写入位数
// 返回值: none
//===========================================================================
void WrBit_L(uint8_t data, uint8_t cnt)
{
uint8_t i;
for (i = 0; i < cnt; i++)
{
clrb(PORT_HT1622B_WR, Pin_HT1622B_WR);
_delay_loop_1(2);
if (data & 0x01)
{
// 数据位拉高
setb(PORT_HT1622B_DATA, Pin_HT1622B_DATA);
}
else
{
// 数据位拉高
clrb(PORT_HT1622B_DATA, Pin_HT1622B_DATA);
}
_delay_loop_1(2);
setb(PORT_HT1622B_WR, Pin_HT1622B_WR);
_delay_loop_1(2);
data >>= 1;
}
}
//===========================================================================
// 函数名: HT1622WrCmd
// 功能 : 向HT1622写入指令
// 参数 : Cmd:指令代码
// 返回值: none
//===========================================================================
void HT1622WrCmd(uint8_t Cmd)
{
clrb(PORT_HT1622B_CS, Pin_HT1622B_CS);
_delay_loop_1(2);
WrBit_H(0x80, 3); // 写入命令标志
WrBit_H(Cmd, 9); // 写入命令数据
setb(PORT_HT1622B_CS, Pin_HT1622B_CS);
_delay_loop_1(2);
}
//===========================================================================
// 函数名: HT1622WrData
// 功能 : 向HT1622的SEGx写入8位数据(直接控制SEGx下的所有内容)
// 参数 : SEGx:数据映射表中的SEGx列;Data:要写入的控制数据
// 返回值: none
//===========================================================================
void HT1622WrData(uint8_t SEGx, uint16_t Data)
{
uint8_t Addr;
Addr = SEGx * 2;
clrb(PORT_HT1622B_CS, Pin_HT1622B_CS); // 拉低片选
_delay_loop_1(2); // 延时一段时间
WrBit_H(0xA0, 3); // 写入数据标志
WrBit_H(Addr << 2, 6); // 写入6位地址
WrBit_L(Data, 8); // 写入8位数据
setb(PORT_HT1622B_CS, Pin_HT1622B_CS); // 拉高片选
_delay_loop_1(2); // 延时一段时间
}
//===========================================================================
// 函数名: FullScreenContent
// 功能 : 控制全屏的内容为 显示/隐藏
// 参数 : state:显示状态(DISPLAY/HIDE)
// 返回值: none
//===========================================================================
void FullScreenContent(uint8_t state)
{
clrb(PORT_HT1622B_CS, Pin_HT1622B_CS);
_delay_loop_1(2);
WrBit_H(0xA0, 3); // 写入数据标志
WrBit_H(0x00, 6); // 写入6位地址
// 对所有地址写入数据 1/0 —— DISPLAY/HIDE
for (uint16_t i = 0; i < 8 * 32; i++)
{
clrb(PORT_HT1622B_WR, Pin_HT1622B_WR);
_delay_loop_1(2);
if (state)
{
setb(PORT_HT1622B_DATA, Pin_HT1622B_DATA);
}
else
{
clrb(PORT_HT1622B_DATA, Pin_HT1622B_DATA);
}
_delay_loop_1(2);
setb(PORT_HT1622B_WR, Pin_HT1622B_WR);
_delay_loop_1(2);
}
setb(PORT_HT1622B_CS, Pin_HT1622B_CS);
_delay_loop_1(2);
}
1621/1622初始化函数
void Lcd_init(void)
{
// 片选,选中HT1622
clrb(PORT_HT1622B_CS, Pin_HT1622B_CS);
SendNBitToRAM(LCD_MODE_CMD, 3); // 发送命令ID码
SendNBitToRAM(SYS_EN, 9); // 打开系统时钟
SendNBitToRAM(LCD_DISPLAY_ON, 9); // 打开LCD偏置发生器
setb(PORT_HT1622B_CS, Pin_HT1622B_CS);
// 清屏
LcdDisplay_All(0x00, LcdDisplay_Off, LCD_SEG_NUM); // 清屏
}
void LCD_Send_Data(unsigned char address, uint16_t data)
{
clrb(PORT_HT1622B_CS, Pin_HT1622B_CS);
// 发送数据码ID
SendNBitToRAM(LCD_MODE_WRITE, 3);
// 发送地址
SendAddrToRAM(address);
// 发送数据
SendNBitToRAM(data, 8);
setb(PORT_HT1622B_CS, Pin_HT1622B_CS);
}