DSP28035驱动HT1621B显示段码LCD屏

     最近做的项目里面使用的控制芯片为TI公司的28035,在控制程序以外,需要用该芯片控制显示LCD屏幕,其中驱动LCD屏幕的是HT1621B芯片,由于这也是我第一次写驱动LCD的程序以及第一次接触1621这款芯片,在网上参考了很多例程,以及对DATASHEET的学习,遇到了一些问题,在下文中会详细介绍整个调试过程。

     首先对于HT1621,是一款驱动LCD屏幕常见的驱动芯片,在本项目中使用的是以下封装,48引脚,其中有SEG0~31和COM0~4,一共可以驱动32*4=128个LED灯。

DSP28035驱动HT1621B显示段码LCD屏_第1张图片

       其中CS,RD,WR,DATA ,9、10、11、12这四个引脚是HT1621与MCU之间进行通讯的媒介,在该项目中,由于不需要读LCD屏幕的数据,因此只连接了CS,WR,DATA这三条线,硬件连接原理图如图所示。

DSP28035驱动HT1621B显示段码LCD屏_第2张图片

       可以对比上面的引脚进行分析,以及针对HT1621的DATASHEET进行分析,在本项目中RD引脚没有使用直接置高,14和15引脚悬空,使用HT1621片内的RC振荡电路,而不使用外部时钟。

DSP28035驱动HT1621B显示段码LCD屏_第3张图片

DSP28035驱动HT1621B显示段码LCD屏_第4张图片

        HT1621芯片右侧接的LCD段码屏,一般情况下是厂家定制好的段码屏,厂家会提供一份原理图,引脚对应图,本项目使用的原理图如下图:

DSP28035驱动HT1621B显示段码LCD屏_第5张图片

DSP28035驱动HT1621B显示段码LCD屏_第6张图片

 包含各种图案的点亮,一共是32*4,刚好是128个,也是HT1621能够驱动的最大数量的灯管数量。针对上面厂家给的原理图和硬件原理图,需要得到具体每一个SEG和COM对应的灯管,上述表格进行对照后,会得到对应表(因为厂家给的PIN脚和SEG有时候会不对应)

DSP28035驱动HT1621B显示段码LCD屏_第7张图片

DSP28035驱动HT1621B显示段码LCD屏_第8张图片

DSP28035驱动HT1621B显示段码LCD屏_第9张图片

得到上述对应的表格后,才能精确地驱动每一个灯,对于显示数字的数码管来说:根据原理图中的映射关系,一共八个数字数码管可以得到:

DSP28035驱动HT1621B显示段码LCD屏_第10张图片

1----亮,0----灭

数字0:A B C D E F为1 其他都为0  对应SEG2:1101   SEG3:0111

高位在前 因此改为16进制为  0x0b 0x0e

数字1:B C为1 其他都为0  对应SEG2:0000  SEG3:0110    0x00   0x06

数字2:A B G E D 为1 其他为0   对应SEG2:1110  SEG3:0011   0x07   0x0c

数字3:A B C D G为1 其他为0   对应SEG2:1010  SEG3:0111    0x05    0x0e

数字4:F G B C为1 其他为0   对应SEG2:0011  SEG3:0110      0x0c    0x06

数字5:A F G C D为1 其他为0   对应SEG2:1011  SEG3:0101    0x0d    0x0a

数字6:A F G C D E为1 其他为0   对应SEG2:1111  SEG3:0101    0x0f    0x0a

数字7:A B C 为1 其他为0   对应SEG2:0000  SEG3:0111     0x00   0x0e

数字8:A B C D E G F为1 其他为0   对应SEG2:1111  SEG3:0111   0x0f    0x0e

数字9:A B C D F G为1 其他为0   对应SEG2:1011  SEG3:0111    0x0d     0x0e

 对于SEG的地址码是由6个二进制位构成 00 0000  一共有31个,可以得到下面的对应表

DSP28035驱动HT1621B显示段码LCD屏_第11张图片

如果想要点亮数字 1,那么就需要在SEG2的地址写入0x00,而在SEG3写入 0x06,即可点亮。

上述主要叙述了HT1621的基本构造和点亮数字和图案的基本原理,下文叙述HT1621的驱动程序和驱动原理。

对于HT1621,首先需要进行对其进行初始化,即对其写入命令,才能进一步给HT1621写数据点亮各种灯,因此初始化是最关键的一步。

对于HT1621,有四种模式,在本项目中只用到了命令模式和写入模式

DSP28035驱动HT1621B显示段码LCD屏_第12张图片

 针对初始化,需要写入命令集,命令的代码为100,而且存在很多不同的命令,构成了命令表格,完整的命令表格可以通过查阅1621的DATASHEET来查看。

DSP28035驱动HT1621B显示段码LCD屏_第13张图片

DSP28035驱动HT1621B显示段码LCD屏_第14张图片

 HT1621的初始化也就是对其发送一系列命令的过程,上图的CS相当于使能端,当CS处于低电平时,1621才能跟MCU进行通讯,而WR充当时钟信号,在WR的上升沿时,将DATA的电平状态传送给1621,进行数据传输。

//HT1621的初始化
void HT1621_Init(void)
{
    HT1621_CS_H();
    HT1621_WR_H();
    HT1621_DAT_H();
    DelayMs(20);
    HT1621_WriteCMD(0x52);  //0b1000 0101 0010  1/3duty 4com
    DelayMs(1);
    HT1621_WriteCMD(0x30);  //0b1000 0011 0000  内部时钟
    DelayMs(1);
    HT1621_WriteCMD(0x00);    //0b1000 0000 0000  关振系统荡器和LCD偏压发生器
    DelayMs(1);
    HT1621_WriteCMD(0x0A);   //0b1000 0000 1010  禁止看门狗
    DelayMs(1);
    HT1621_WriteCMD(0x02);   //0b1000 0000 0010 打开系统振荡器
    DelayMs(1);
    HT1621_WriteCMD(0x06);    //0b1000 0000 0110  打开LCD偏压
    DelayMs(1);
}

要形成上述的时序图,写入命令的代码为:

void HT1621_SendBit(uchar sdat,uchar cnt)
{
        uchar i;
        for(i=0;i

 对于上述的延时,在网上找到的资料中显示,如果不加延时,数据传输会有一定影响,因此在这里我加上了延时。

void HT1621_WriteCMD(uchar command)
{
        HT1621_CS_L();
        HT1621_Delay(DELAY_TEST);
        HT1621_SendBit(0x80,4);  
        HT1621_SendBit(command,8);
        HT1621_CS_H();
}

 此时需要注意的是,对于上述数据手册中,发送命令的全部数据为加起来一定是12位,可以是3+9或者4+8,但是不能小于12位,如果发送的数据位11位,即3+8,会导致下图的时序图,其中从上到下分别为CS  WR DATA。

DSP28035驱动HT1621B显示段码LCD屏_第15张图片

发现时序会乱掉,当发送位数为12位时,时序正常,因此发送命令时3+9和4+8原则上都能成功,在此我使用的是4+8,不同的格式发送的命令码也是不同的,根据位数去计算。

DSP28035驱动HT1621B显示段码LCD屏_第16张图片

 如果初始化成功,那么就可以给1621写入数据了,写入数据的命令码为101

DSP28035驱动HT1621B显示段码LCD屏_第17张图片

 其中储存地址1就是上文中的SEG的地址,而数据就是点亮COM0~3中哪一个,拿上文中举例子, 如果想要点亮数字 1,那么就需要在SEG2的地址写入0x00,而在SEG3写入 0x06,即可点亮。

 即发出的DATA为 101  000010 0000 和 101 000011 0110,具体程序代码为:

//addr为写入数据的地址,即对应的SEGx,而写入的数据sdat为数码管亮时对应的数据
void HT1621_WirteData(uchar addr,uchar sdat)
{
    //addr<<=2;//因为地址为6位 32个寄存器的地址为6位
    //sdat<<=4;//数据为4位 4位对应COM
    HT1621_CS_L();
    HT1621_SendBit(0xA0,3);//101  写命令
    HT1621_SendBit(addr<<=2,6);
    HT1621_SendBit(sdat<<=4,4);     //一次只发送四位数据,一个地址发送一次,低四位
    HT1621_CS_H();
}

 需要左移是因为,16进制的情况下地址和数据初始化,如0x02即对应的SEG2是8位,而写入1621的地址是6位,数据只有4位,因此需要左移。

最后写入地址和需要发送的数据,即可点亮LCD上对应的数字。

附上全部代码,包括GPIO的配置:


void UserInitAllGpio(void)
{
        EALLOW;
        //20230322 for LCD GPIO25、26、27
        GpioCtrlRegs.GPAPUD.bit.GPIO25 = 1; // 1禁止上拉        DATA引脚
        GpioCtrlRegs.GPAMUX2.bit.GPIO25 = 0;
        GpioCtrlRegs.GPADIR.bit.GPIO25 = 1; // 1 output
        GpioDataRegs.GPACLEAR.bit.GPIO25 = 1;

        GpioCtrlRegs.GPAPUD.bit.GPIO26 = 1; // 1禁止上拉        WR引脚
        GpioCtrlRegs.GPAMUX2.bit.GPIO26 = 0;
        GpioCtrlRegs.GPADIR.bit.GPIO26 = 1; // 1 output
        GpioDataRegs.GPACLEAR.bit.GPIO26 = 1;

        GpioCtrlRegs.GPAPUD.bit.GPIO27 = 1; // 1禁止上拉        CS引脚
        GpioCtrlRegs.GPAMUX2.bit.GPIO27 = 0;
        GpioCtrlRegs.GPADIR.bit.GPIO27 = 1; // 1 output
        GpioDataRegs.GPACLEAR.bit.GPIO27 = 1;

        EDIS;
}
#define     DELAY_TEST  10

void Delay_(uchar us)
{
    while(--us);
}

void DelayMs(Uint16 iMs)
{
    Uint16 i,j;
    for(i=0;i

主函数: 

{
    
     UserInitAllGpio();
     HT1621_Init();
    DelayMs(50);
    HT1621_WriteAllData();//清屏

while(1){
	    HT1621_WirteData(SEG_addr[2],Data_lowSEG[0]);
	    DelayMs(1);
	    HT1621_WirteData(SEG_addr[3],Data_highSEG[0]);
	    DelayMs(0xcff);
        HT1621_WirteData(SEG_addr[2],Data_lowSEG[1]);
        DelayMs(1);
        HT1621_WirteData(SEG_addr[3],Data_highSEG[1]);
        DelayMs(0xcff);
        HT1621_WirteData(SEG_addr[2],Data_lowSEG[2]);
        DelayMs(1);
        HT1621_WirteData(SEG_addr[3],Data_highSEG[2]);
        DelayMs(0xcff);
        HT1621_WirteData(SEG_addr[2],Data_lowSEG[3]);
        DelayMs(1);
        HT1621_WirteData(SEG_addr[3],Data_highSEG[3]);
        DelayMs(0xcff);
        HT1621_WirteData(SEG_addr[2],Data_lowSEG[4]);
        DelayMs(1);
        HT1621_WirteData(SEG_addr[3],Data_highSEG[4]);
        DelayMs(0xcff);
        HT1621_WirteData(SEG_addr[2],Data_lowSEG[5]);
        DelayMs(1);
        HT1621_WirteData(SEG_addr[3],Data_highSEG[5]);
        DelayMs(0xcff);
        HT1621_WirteData(SEG_addr[2],Data_lowSEG[6]);
        DelayMs(1);
        HT1621_WirteData(SEG_addr[3],Data_highSEG[6]);
        DelayMs(0xcff);
        HT1621_WirteData(SEG_addr[2],Data_lowSEG[7]);
        DelayMs(1);
        HT1621_WirteData(SEG_addr[3],Data_highSEG[7]);
        DelayMs(0xcff);
        HT1621_WirteData(SEG_addr[2],Data_lowSEG[8]);
        DelayMs(1);
        HT1621_WirteData(SEG_addr[3],Data_highSEG[8]);
        DelayMs(0xcff);
        HT1621_WirteData(SEG_addr[2],Data_lowSEG[9]);
        DelayMs(1);
        HT1621_WirteData(SEG_addr[3],Data_highSEG[9]);
        DelayMs(0xcff);

	}
}

 数组中的数据根据对应需要点亮数字的高低电平来设置

uchar SEG_addr[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1AD,0x1E,0x1F};
uchar Data_highSEG[]={ 0x0e,0x06,0x0c,0x0e,0x06,0x0a,0x0a,0x0e,0x0e,0x0e};
uchar Data_lowSEG[]={0x0b,0x00,0x07,0x05,0x0c,0x0d,0x0f,0x00,0x0f,0x0d};

最终实现的是数字从0到9的循环显示

你可能感兴趣的:(CCS系列,单片机,嵌入式硬件)