找回密码
 立即注册
查看: 853|回复: 12

STC8H64KTLCD驱动断码LCD的寄存器咨询

[复制链接]

该用户从未签到

1

主题

5

回帖

31

积分

新手上路

积分
31
发表于 2023-5-18 13:50:47 | 显示全部楼层 |阅读模式
1. 下载了官网提供的 断码LCD程序,发现里面对显示寄存器操作有点复杂。

  1. /****************** 对第1~5数字装载显示函数 ***************************/
  2. u8 code t_display[]={                                                //标准字库
  3. //         0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  4.         0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
  5. //black         -     H    J         K          L           N        o   P         U     t    G    Q    r   M    y
  6.         0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e};
  7. u8        code T_LCD_mask[7]  = {0x00,0x0C,0x30,0xC0,0x03,0x0C};
  8. u8        code T_LCD_mask7[7] = {0x00,0x04,0x10,0x40,0x01,0x04};
  9. u8        code T_SEG_ABC[7]   = {0x00,0x08,0x20,0x80,0x02,0x08};
  10. u8        code T_SEG_DEFG[7]  = {0x00,0x04,0x10,0x40,0x01,0x04};
  11. /********************** 装载显示5个8字 *****************************/
  12. void        LCD_load(u8 n, u8 dat)                //n为第几个数字,为1~5,dat为要显示的数字
  13. {
  14.         u8        i,k;
  15.         if((n == 0) || (n >= 6))        return;        //合法值 1~5
  16.         dat =  t_display[dat]; //3F
  17.         k   = ~T_LCD_mask[n]; //FF
  18.         if(n <= 3)        //1~3
  19.         {
  20.                 LCD_buff[0] &= ~T_LCD_mask7[n]; //FF
  21.                 LCD_buff[2] &= k; //NC
  22.                 LCD_buff[4] &= k; //NC
  23.                 LCD_buff[6] &= k; //NC  
  24.                 i = T_SEG_ABC[n];  //00
  25.                 k = T_SEG_DEFG[n];  //00
  26.                 if(dat & 0x01)                LCD_buff[6] |= i;        //T_SEG_ABC[n];                //A
  27.                 if(dat & 0x02)                LCD_buff[4] |= i;        //T_SEG_ABC[n];                //B
  28.                 if(dat & 0x04)                LCD_buff[2] |= i;        //T_SEG_ABC[n];                //C
  29.                 if(dat & 0x08)                LCD_buff[0] |= k;        //T_SEG_DEFG[n];        //D
  30.                 if(dat & 0x10)                LCD_buff[2] |= k;        //T_SEG_DEFG[n];        //E
  31.                 if(dat & 0x20)                LCD_buff[6] |= k;        //T_SEG_DEFG[n];        //F
  32.                 if(dat & 0x40)                LCD_buff[4] |= k;        //T_SEG_DEFG[n];        //G
  33.         }
  34.         else        // n=4 or 5
  35.         {
  36.                 LCD_buff[1] &= ~T_LCD_mask7[n];
  37.                 LCD_buff[3] &= k;
  38.                 LCD_buff[5] &= k;
  39.                 LCD_buff[7] &= k;
  40.                 i = T_SEG_ABC[n];
  41.                 k = T_SEG_DEFG[n];
  42.                 if(dat & 0x01)                LCD_buff[7] |= i;        //T_SEG_ABC[n];                //A
  43.                 if(dat & 0x02)                LCD_buff[5] |= i;        //T_SEG_ABC[n];                //B
  44.                 if(dat & 0x04)                LCD_buff[3] |= i;        //T_SEG_ABC[n];                //C
  45.                 if(dat & 0x08)                LCD_buff[1] |= k;        //T_SEG_DEFG[n];        //D
  46.                 if(dat & 0x10)                LCD_buff[3] |= k;        //T_SEG_DEFG[n];        //E
  47.                 if(dat & 0x20)                LCD_buff[7] |= k;        //T_SEG_DEFG[n];        //F
  48.                 if(dat & 0x40)                LCD_buff[5] |= k;        //T_SEG_DEFG[n];        //G
  49.         }
  50. }
  51. /********************** 将显示内容导入显存 *****************************/
  52. void        LoadToLcd(void)
  53. {
  54.         C0SEGV1 = LCD_buff[0];    // C0SEG 15~8数据寄存器
  55.         C0SEGV2 = LCD_buff[1];    // C0SEG 23~16数据寄存器
  56.         C1SEGV1 = LCD_buff[2];    // C1SEG 15~8数据寄存器
  57.         C1SEGV2 = LCD_buff[3];    // C1SEG 23~16数据寄存器
  58.         C2SEGV1 = LCD_buff[4];    // C2SEG 15~8数据寄存器
  59.         C2SEGV2 = LCD_buff[5];    // C2SEG 23~16数据寄存器
  60.         C3SEGV1 = LCD_buff[6];    // C3SEG 15~8数据寄存器
  61.         C3SEGV2 = LCD_buff[7];    // C3SEG 23~16数据寄存器
  62. }
复制代码
前面对buf的数据处理逻辑比较复杂,最后将数据传入到 CxSEGVx寄存器中。 这段过程一直没有理解;
2. 之前用过TM1621这类的驱动,不知道咱们的这个驱动方式是否和这类芯片类似?如果不相同,应该怎么理解 这些寄存器的作用? 尤其是CxSEGVx寄存器。
回复 送花

使用道具 举报

  • TA的每日心情
    开心
    前天 07:59
  • 签到天数: 101 天

    [LV.6]常住居民II

    41

    主题

    1016

    回帖

    6971

    积分

    荣誉版主

    冲哥视频教程和各种开源资料QQ交流群884047237,可群

    积分
    6971
    QQ
    发表于 2023-5-18 14:11:25 | 显示全部楼层
    区别于数码管,段码的连接一般不是整组接在位或者段上的。
    数码管可能八个段码刚好占用一个P1端口,但是LCD你仔细看提供的段码表,你可以推理下如果要点亮一个数字2需要哪几个位输出,算出来了这个数值,在来看这个程序你就懂了
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    1

    主题

    5

    回帖

    31

    积分

    新手上路

    积分
    31
     楼主| 发表于 2023-5-18 16:24:32 | 显示全部楼层
    电子DIY小家 发表于 2023-5-18 14:11
    区别于数码管,段码的连接一般不是整组接在位或者段上的。
    数码管可能八个段码刚好占用一个P1端口,但是LCD ...

    数码管是了解的;TM1621这类专用LCD断码驱动屏,是每次发4个bit数据,发两次正好可以对应一个显示数字;但是STC的驱动方式好像不一样。感觉驱动起来就比TM1621要麻烦点

    点评

    一样的,其实我们的比HT1621要方便得多,传送速度快得多。 例子为什么看起来复杂?其实是因为例子用的屏是网上买来的,并且是在通用测试板上测试的,所以每一段对应显存有点乱,实际工程会自己设计LCD,排列有规律,  详情 回复 发表于 2023-5-18 22:02
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    9

    主题

    299

    回帖

    1740

    积分

    版主

    积分
    1740
    QQ
    发表于 2023-5-18 17:12:57 | 显示全部楼层
    1.png
    QQ:1463035472,微信:19952583954
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    半小时前
  • 签到天数: 158 天

    [LV.7]常住居民III

    3

    主题

    216

    回帖

    1465

    积分

    金牌会员

    积分
    1465
    发表于 2023-5-18 19:35:57 | 显示全部楼层
    本帖最后由 xuzeabc 于 2023-5-18 19:39 编辑
    zl_diy 发表于 2023-5-18 16:24
    数码管是了解的;TM1621这类专用LCD断码驱动屏,是每次发4个bit数据,发两次正好可以对应一个显示数字; ...

    刚使用TLCD给一朋友开发的段码液晶摩托车仪表。用惯了1621驱动,刚开始感觉有点不适应,诚如楼主所言。慢慢的使用过程中,感觉操作起来比1621便宜不少。使用1621为了驱动不同种类的8,用了很多数组,使用单片机,一个数组完成工作。
    把段码的数据定义在了bdata处,用联合体和结构体,可以进行位操作,也可以进行字节操作,方便多多。希望对楼主有参考。
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    46

    主题

    3043

    回帖

    6859

    积分

    超级版主

    积分
    6859
    发表于 2023-5-18 22:02:28 | 显示全部楼层
    zl_diy 发表于 2023-5-18 16:24
    数码管是了解的;TM1621这类专用LCD断码驱动屏,是每次发4个bit数据,发两次正好可以对应一个显示数字; ...

    一样的,其实我们的比HT1621要方便得多,传送速度快得多。
    例子为什么看起来复杂?其实是因为例子用的屏是网上买来的,并且是在通用测试板上测试的,所以每一段对应显存有点乱,实际工程会自己设计LCD,排列有规律,连到MCU的LCD驱动脚也按屏设计,就会有规律。

    下面是我某个测试用的HT1621,2个数码管,也一样的复杂:
    /****************** 对第1 2数字装载显示函数 ***************************/
    u8 code t_display[]={                                                //标准字库
    //         0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
            0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
    //black         -     H    J         K          L           N        o   P         U     t    G    Q    r   M    y
            0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
            0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};        //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
    void        LCD_load(u8 n, u8 dat)                //n为第几个数字,为1~2,dat为要显示的数字
    {
            u8        i;
           
            if(n == 1)
            {
                    LCD_buff[1] &= 0x0f;        LCD_buff[2] &= 0xf8;
                    i = t_display[dat];
                    if(i & 0x01)        LCD_buff[1] |= 0x10;        //A
                    if(i & 0x02)        LCD_buff[2] |= 0x01;        //B
                    if(i & 0x04)        LCD_buff[2] |= 0x04;        //C
                    if(i & 0x08)        LCD_buff[1] |= 0x80;        //D
                    if(i & 0x10)        LCD_buff[1] |= 0x40;        //E
                    if(i & 0x20)        LCD_buff[1] |= 0x20;        //F
                    if(i & 0x40)        LCD_buff[2] |= 0x02;        //G
                    HT1621_write_byte(2,LCD_buff[1]);
                    HT1621_write_byte(4,LCD_buff[2]);
            }
            else if(n == 2)
            {
                    LCD_buff[2] &= 0x0f;        LCD_buff[3] &= 0xf8;
                    i = t_display[dat];
                    if(i & 0x01)        LCD_buff[2] |= 0x10;        //A
                    if(i & 0x02)        LCD_buff[3] |= 0x01;        //B
                    if(i & 0x04)        LCD_buff[3] |= 0x04;        //C
                    if(i & 0x08)        LCD_buff[2] |= 0x80;        //D
                    if(i & 0x10)        LCD_buff[2] |= 0x40;        //E
                    if(i & 0x20)        LCD_buff[2] |= 0x20;        //F
                    if(i & 0x40)        LCD_buff[3] |= 0x02;        //G
                    HT1621_write_byte(4,LCD_buff[2]);
                    HT1621_write_byte(6,LCD_buff[3]);
            }
    }

    为什么会这样?因为LCD的段码排列和HT1621的引线是工程师乱连的结果。

    如果是下面的内存映射表,则不管是HT1621还是STC8H4K64TLCD,只要规划好COM线和SEG线,则会很简单的,所以最关键的是映射表是否有规律,没有规律,用哪个IC都恼火。
                   RAM地址  B7                B6                B5                B4                B3                B2                B1                B0
    LCD_buff[3]:        19,18        3D                3E                3G                3F                3H                3C                3B                3A
    LCD_buff[0]:        21,20        --                --                --                --                61                -                LB                Kg                61为右上角到E显示1
    LCD_buff[5]:        23,22        5D                5E                5G                5F                --                5C                5B                5A                5为右下角小8
    LCD_buff[4]:        25,24        4D                4E                4G                4F                三                4C                4B                4A
    LCD_buff[2]:        29,28        2D                2E                2G                2F                2H                2C                2B                2A
    LCD_buff[1]:        31,30        1D                1E                1G                1F                --                1C                1B                1A
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    1

    主题

    5

    回帖

    31

    积分

    新手上路

    积分
    31
     楼主| 发表于 2023-5-19 14:31:40 | 显示全部楼层



    如上图中的寄存器,我一开始是没有理解这个表格中CxSEGVx寄存器的作用,后来反复琢磨,猜想到他的对饮关系 是不是:例如  C0SEGV0 寄存器对用的 COM0 线上的SEG0~SEG7 的这7个段,哪一个位为1,对应的LCD哪一段就亮起来。  不知道是不是这样理解的?
    1684477491834.png
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    1

    主题

    5

    回帖

    31

    积分

    新手上路

    积分
    31
     楼主| 发表于 2023-5-19 14:40:36 | 显示全部楼层
    xuzeabc 发表于 2023-5-18 19:35
    刚使用TLCD给一朋友开发的段码液晶摩托车仪表。用惯了1621驱动,刚开始感觉有点不适应,诚如楼主所言。慢 ...

    非常感谢,您的思路,我试试是否可以做到。
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    1

    主题

    5

    回帖

    31

    积分

    新手上路

    积分
    31
     楼主| 发表于 2023-5-19 14:43:41 | 显示全部楼层
    1684478551090.png

    这就有点麻烦了;LCD屏也是按照HT1621这类驱动来做的引脚。

    点评

    所以说,屏的真值表很关键,基本都是确定了驱动IC,再画图设计段码,排列有规律,如果买个乱排的,用HT1621也一样要按我那样复杂处理。  详情 回复 发表于 2023-5-19 17:33
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    46

    主题

    3043

    回帖

    6859

    积分

    超级版主

    积分
    6859
    发表于 2023-5-19 17:33:53 | 显示全部楼层
    zl_diy 发表于 2023-5-19 14:43
    这就有点麻烦了;LCD屏也是按照HT1621这类驱动来做的引脚。

    所以说,屏的真值表很关键,基本都是确定了驱动IC,再画图设计段码,排列有规律,如果买个乱排的,用HT1621也一样要按我那样复杂处理。
    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-19 06:52 , Processed in 0.081917 second(s), 74 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表