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);
}