找回密码
 立即注册
查看: 93|回复: 9

关于STC8H4K64TLCD的断码液晶驱动代码问题

[复制链接]
  • TA的每日心情
    开心
    2024-4-26 16:14
  • 签到天数: 2 天

    [LV.1]初来乍到

    1

    主题

    5

    回帖

    23

    积分

    新手上路

    积分
    23
    发表于 2024-4-24 16:21:10 | 显示全部楼层 |阅读模式
    本帖最后由 zcb18969755773 于 2024-4-24 16:31 编辑

    我手里有一个项目用到LCD断码液晶驱动,之前用到的友商一款MCU也是带LCD液晶断码驱动的,
    现在想转用STC的MCU,于是特意研究了一下8H4K64TLCD这款芯片关于LCD驱动逻辑;

    首先讲一下我们这款LCD断码液晶屏,他是由4COM口组合2个SEG口对应一个数字8,如下图所示:
    断码液晶屏-断码示意图.png
    COM1至COM4的工作逻辑我们可以忽略,主要是对SEG1与SEG2的显存赋值问题;

    1.友商的方案如下:
    //LCD的初始化就省略不写了,硬件连接是COMx对应COMx,SEGx对应SEGx,一一对应;
    uchar xdata LCD_buf[30] _at_  0x1000;    //指定显存地址


    //地址1000H SEG1的bit[3:0]
    //地址1001H SEG2bit[3:0]  以此类推

    //要显示一个数字“1”,则建立一个断码真值表0-9
    uchar code numtab[11]={0xAF,0xA0,0xCB,0xE9,0xE4,0x6D,0x6F,0xA8,0xEF,0xED};

    uchar show_num = 1;
    LCD_buf[0] = numtab[show_num] & 0x0f;           //0000赋值给SEG1的显存,DEFA位断全部被关闭

    LCD_buf[1] = (numtab[show_num]>>4) & 0x0f;  //1010赋值给SEG2的显存,因此BC断被点亮,显示数字"1"

    由于每个SEGx口在COM1-COM4启动期间有4种电平状态来使能对应的LCD对应的断,到此显示目的已达成;
    2.接下来在讲STC这款LCD驱动方案,
    //首先LCD初始化依旧省略,硬件连接同等对应如上所述;
    //显存数组建立我列举对应8个SEGx端口 :SEG0-7
    STC 显存.png

    由图可见,SEG0对应的C0S0、C1S0、C2S0、C3S0与SEG1对应的C0S1、C1S1、C2S1、C3S1组成的一个字节(A-dp)8位的显存变量
    无法通过字节赋值将numtab[show_num] 这样一个8位的变量通过1次或者两次赋值给SEG0与SEG1的显存,
    而是需要将numtab[show_num] 这个变量的每一位分别赋值给对应的显存位,这个显存位是离散的,因此需要用到数据转换,
    这个问题比较困扰我,C语言基础没到位,如果单独每次赋值某一位,这样写出来的代码可能就是传说中的屎山代码,因为我
    的这款LCD来说粗略讲有120个点,当然Ua/Ia这样的字算一个小数点,如下图所示:
    断码屏幕-实物示意图.png
    在论坛中我也看到过一些遇到同样问题没弄清楚的朋友,我觉得都是我这样没搞懂数据转换的情况,
    我本人是非常喜欢STC的单片机,寄存器比较熟悉,抗干扰能力强,不易破解,
    我是非常希望将STC的MCU推向我司各类产品的应用,市场上我这样的LCD断码液晶也非常流行,
    希望官方的专业大神能将我图中这种类型的LCD断码液晶驱动示例代出一个数据的转换函数,感谢指导!!!!

    回复 送花

    使用道具 举报

  • TA的每日心情
    慵懒
    3 天前
  • 签到天数: 68 天

    [LV.6]常住居民II

    4

    主题

    414

    回帖

    1122

    积分

    金牌会员

    积分
    1122
    发表于 2024-4-24 17:21:23 | 显示全部楼层
    自己写很简单,直接写对应的寄存器就可以,也可以参考例程
    截图202404241721218532.jpg
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-26 16:14
  • 签到天数: 2 天

    [LV.1]初来乍到

    1

    主题

    5

    回帖

    23

    积分

    新手上路

    积分
    23
     楼主| 发表于 2024-4-24 18:23:34 | 显示全部楼层
    小飞侠 发表于 2024-4-24 17:21
    自己写很简单,直接写对应的寄存器就可以,也可以参考例程

    感谢您的回复,这个代码我已经看过了,没吃透笔断赋值的那个函数,没达到改写的能力
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    慵懒
    3 天前
  • 签到天数: 68 天

    [LV.6]常住居民II

    4

    主题

    414

    回帖

    1122

    积分

    金牌会员

    积分
    1122
    发表于 2024-4-25 07:47:59 | 显示全部楼层
    可以每个寄存器赋不同数值,每次只赋值1个bit,看看那个段码显示,然后就明白了
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-26 16:14
  • 签到天数: 2 天

    [LV.1]初来乍到

    1

    主题

    5

    回帖

    23

    积分

    新手上路

    积分
    23
     楼主| 发表于 2024-4-25 09:31:05 | 显示全部楼层
    今天上午又研究了一下,把LCD_buff[0]的表格从新做了一遍,然后瞬间看懂了,
    原因就在于一个数码管的8,对应2个SEG线,注释的时候像我这样去表示就好理解一点,
    原代码的注释,需要自己去找SEG对应的断,如下:
    /*
                        B7                B6                B5                B4                B3                B2                B1                B0
                                   
    LCD_buff[0]:        2H                3D                1H                2D                左下        1D                B1                B0                左下为左下角的箭头, B0为电池框, B1为电量1
    LCD_buff[1]:        --                --                --                --                4H                5D                3H                4D
    LCD_buff[2]:        3C                3E                2C                2E                1C                1E                B2                右上        右上为右上角的箭头, B2为电量2
    LCD_buff[3]:        --                --                --                --                5C                5E                4C                4E
    LCD_buff[4]:        3B                3G                2B                2G                1B                1G                B3                -                B3为电量3, -为左边符号
    LCD_buff[5]:        --                --                --                --                5B                5G                4B                4G
    LCD_buff[6]:        3A                3F                2A                2F                1A                1F                B4                左上        左上为左上角的箭头
    LCD_buff[7]:        --                --                --                --                5A                5F                4A                4F
    */
    早上自己整理了一下,然后我的注释如下:
    //                                   第3个8                       第2个8                    第1个8             电池电量显示
    //                          |    SEG15    SEG14     |    SEG13    SEG12    |   SEG11  SEG10    |    SEG9  SEG8     |       
    // LCD_buff[0] = |C0S15-2H C0S14-3D  |C0S13-1H C0S12-2D |C0S11-LD C0S10-1D| C0S9-B1 C0S8-B0|
    // LCD_buff[2] = |C1S15-3C C1S14-3E  |C1S13-2C C1S12-2E |C1S11-1C C1S10-1E| C1S9-B2 C1S8-RU|
    // LCD_buff[4] = |C2S15-3B C2S14-3G  |C2S13-2B C2S12-2G |C2S11-1B C2S10-1G| C2S9-B3 C2S8-* |
    // LCD_buff[6] = |C3S15-3A C3S14-3F  |C3S13-2A C3S12-2F |C3S11-1A C3S10-1F| C3S9-B4 C3S8-LU|

    //                                        空                            空                       第5个8                   第4个8
    //                          |   SEG23  SEG22        |      SEG21   SEG20   |   SEG19  SEG18      |    SEG17  SEG16    |       
    // LCD_buff[1] = |C0S23-NC C0S22-NC  |C0S21-NC C0S20-NC |C0S19-4H C0S18-5D| C0S17-3H C0S16-4D|
    // LCD_buff[3] = |C1S23-NC C1S22-NC  |C1S21-NC C1S20-NC |C1S19-5C C1S18-5E| C1S17-4C C1S16-4E|
    // LCD_buff[5] = |C2S23-NC C2S22-NC  |C2S21-NC C2S20-NC |C2S19-5B C2S18-5G| C2S17-4B C2S16-4G|
    // LCD_buff[7] = |C3S23-NC C3S22-NC  |C3S21-NC C3S20-NC |C3S19-5A C3S18-5F| C3S17-4A C3S16-4F|
    这样一来就可以识别SEG线对应数码管的段,根据示例代码所示,继续往下看
    u8        code T_LCD_mask[7]  = {0x00,0x0C,0x30,0xC0,0x03,0x0C};//选中对应的SEG线CxSx横向2断(CE、BG、AF)填0
    u8        code T_LCD_mask7[7] = {0x00,0x04,0x10,0x40,0x01,0x04};//选中对应的SEG线C0Sx断,D断 填0
    u8        code T_SEG_ABC[7]   = {0x00,0x08,0x20,0x80,0x02,0x08};//选中对应SEG线的C0Sx断,(dp、C、B、A)填1
    u8        code T_SEG_DEFG[7]  = {0x00,0x04,0x10,0x40,0x01,0x04};//选中对应SEG线的C0Sx断,(D、E、F、G)填1
    上面这个数组,定义了每个SEG线纵向给LCD断码填0和填1的对应bit位;
    下面这个函数,则根据所需要的对应n个数码管,选中对应的显存LCD_buff[x],去对LCD进行填0,然后需要显示的断填1;
    详细可见如下我代入的试数值:
    /********************** 装载显示5个8字 *****************************/
    void        LCD_load(u8 n, u8 dat)                //n为第几个数字,为1~5,dat为要显示的数字
    {
            u8        i,k;

            if((n == 0) || (n >= 6))        return;        //合法值 1~5

            dat =  t_display[dat];        //取数字库真值:0-y; 设dat=1,真值=0x06  二进制:0000 0110
           
            k   = ~T_LCD_mask[n];        //设n=1 取反0x0c :k = 1111 0011,将LCD_buff[0、2、4、6]对应的第1个8两位对应的SEG10-11位置0
                                                            //设n=2 取反0x30 :k = 1100 1111,将LCD_buff[0、2、4、6]对应的第2个8两位对应的SEG12-13位置0
                                                            //意为将选中的缓存数组的SEG线,对应8的A-G断 清零
           
            if(n <= 3)//选第1~3个数码管,SEG<=15:对应SEG线为: SEG10-11, SEG12-13, SEG14-15
            {        //将A-G 断码清零
                    LCD_buff[0] &= ~T_LCD_mask7[n]; //04H取反:1111 1011 为    1D 清零
                    LCD_buff[2] &= k;                                //设n=1则k=1111 0011 为 1C 1E 清零                                                 
                    LCD_buff[4] &= k;                                //                 同上 1B 1G 清零
                    LCD_buff[6] &= k;                                //                 同上 1A 1F 清零
                   
                    //设n=1,i设为SEG11线对应的 LD、1C、1B、1A断码 填1;
                    i = T_SEG_ABC[n];                                //i=08H=0000 1000
                   
                    //设n=1,i设为SEG10线对应的 1D、1E、1G、1F断码 填1;
                    k = T_SEG_DEFG[n];                                //k=04H=0000 0100
                    //设dat=06H = 0000 0110 :BC段点亮 显示数字"1"
                    if(dat & 0x01)                LCD_buff[6] |= i;        //T_SEG_ABC[n];                //A
                    if(dat & 0x02)                LCD_buff[4] |= i;        //T_SEG_ABC[n];                //B       
                    if(dat & 0x04)                LCD_buff[2] |= i;        //T_SEG_ABC[n];                //C
                    if(dat & 0x08)                LCD_buff[0] |= k;        //T_SEG_DEFG[n];        //D
                    if(dat & 0x10)                LCD_buff[2] |= k;        //T_SEG_DEFG[n];        //E
                    if(dat & 0x20)                LCD_buff[6] |= k;        //T_SEG_DEFG[n];        //F
                    if(dat & 0x40)                LCD_buff[4] |= k;        //T_SEG_DEFG[n];        //G
            }
            else//第4 or 5个数码管,上面指定SEG<=19:对应SEG线为: SEG16-17, SEG18-19
            {        //将A-G 断码清零
                    LCD_buff[1] &= ~T_LCD_mask7[n];        //设n=4 取反01H=1111 1110 断码4D 清零
                    LCD_buff[3] &= k;                                //设n=4则k=1111 1100 为 4C 4E 清零       
                    LCD_buff[5] &= k;                                //                                   同上 4B 4G 清零
                    LCD_buff[7] &= k;                                //                 同上 4A 4F 清零
                    i = T_SEG_ABC[n];                                //设n=4,i=02H=0000 0010  断码H C B A 填1
                    k = T_SEG_DEFG[n];                                //设n=4,k=01H=0000 0001  断码D E G F 填1
                    if(dat & 0x01)                LCD_buff[7] |= i;        //T_SEG_ABC[n];                //A
                    if(dat & 0x02)                LCD_buff[5] |= i;        //T_SEG_ABC[n];                //B
                    if(dat & 0x04)                LCD_buff[3] |= i;        //T_SEG_ABC[n];                //C
                    if(dat & 0x08)                LCD_buff[1] |= k;        //T_SEG_DEFG[n];        //D
                    if(dat & 0x10)                LCD_buff[3] |= k;        //T_SEG_DEFG[n];        //E
                    if(dat & 0x20)                LCD_buff[7] |= k;        //T_SEG_DEFG[n];        //F
                    if(dat & 0x40)                LCD_buff[5] |= k;        //T_SEG_DEFG[n];        //G
            }
    }
    回复 支持 1 反对 0 送花

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-26 16:14
  • 签到天数: 2 天

    [LV.1]初来乍到

    1

    主题

    5

    回帖

    23

    积分

    新手上路

    积分
    23
     楼主| 发表于 2024-4-25 09:42:21 | 显示全部楼层
    zcb18969755773 发表于 2024-4-25 09:31
    今天上午又研究了一下,把LCD_buff[0]的表格从新做了一遍,然后瞬间看懂了,
    原因就在于一个数码管的8,对 ...

    我从新整理的这个代码注释,不是说我这个方式比源示例代码好,而是我个人C语言代码的基础不深,这样的注释便于个人的理解,感谢阅读!
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    46

    主题

    2934

    回帖

    6617

    积分

    超级版主

    积分
    6617
    发表于 2024-4-25 12:24:57 | 显示全部楼层
    本帖最后由 梁工 于 2024-4-25 12:28 编辑

    昨天忙到没空回复。
    楼主的LCD段码的排列方式跟STC LCD的排列方式对应起来,8个段分散到4个寄存器了,LCD段码的COM与SEG的排列一般会根据LCD驱动的具体连接和显存映射来设计,这样对应起来操作方便。
    但是不管怎么排列,都是将段码对应的显存(显示数据寄存器)里的位写1显示写0不显示,就这么简单。
    具体到某个屏,与COM和SEG的连接一旦确定,则显存与段码对应关系就确定了。
    假设楼主的COM1~COM4对应STC的COM0~COM3,楼主的SEG1~SEG8对应STC的SEG0~SEG7,则楼主的屏有4个8的话,安排如下(比我买的屏有规律、映射简单得多):
                               SEG7  SEG6   SEG5  SEG4  SEG3  SEG2  SEG1  SEG0
    COMx       显存      bit7    bit6     bit5    bit4     bit3    bit2     bit1    bit0
    COM0    C0SEGV0   P4      D4      P3      D3      P2      D2      P1      D1
    COM1    C1SEGV0   C4      E4      C3      E3      C2      E2      C1      E1
    COM2    C2SEGV0   G4      F4      G3      F3      G2      F2      G1      F1
    COM3    C3SEGV0   B4      A4      B3      A3      B2      A2      B1      A1

    4个8对应序号n=1~4,dat为第n个数字显示的内容:
    先清除第n个数字对应显存的8个bit:
    i = ~(0x03<<((n-1)*2));
    C0SEGV0 &= i;  //清除Pn Dn
    C1SEGV0 &= i;  //清除Cn En
    C2SEGV0 &= i;  //清除Gn Fn
    C3SEGV0 &= i;  //清除Bn An
    然后将新显示的内容填入即可。
    i = 1<<((n-1)*2);   //D E F A
    j = 2<<((n-1)*2);   //P C G B
    if(dat & 0x01)  C3SEGV0 |= i;  //A
    if(dat & 0x02)  C3SEGV0 |= j;  //B
    if(dat & 0x04)  C1SEGV0 |= j;  //C
    if(dat & 0x08)  C0SEGV0 |= i;  //D
    if(dat & 0x10)  C1SEGV0 |= i;  //E
    if(dat & 0x20)  C2SEGV0 |= i;  //F
    if(dat & 0x40)  C2SEGV0 |= j;  //G
    if(dat & 0x80)  C0SEGV0 |= j;  //P

    其实很多时候我都是用一个数组处理好,再写入显存寄存器,连接好屏后,用串口一个个点亮段码,就知道了数组与段码的对应关系,不需要花时间去分析真值表与显存对应关系,这个方法请参考我的例程。
    回复 支持 1 反对 0 送花

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-26 16:14
  • 签到天数: 2 天

    [LV.1]初来乍到

    1

    主题

    5

    回帖

    23

    积分

    新手上路

    积分
    23
     楼主| 发表于 2024-4-26 09:03:35 | 显示全部楼层
    梁工 发表于 2024-4-25 12:24
    昨天忙到没空回复。
    楼主的LCD段码的排列方式跟STC LCD的排列方式对应起来,8个段分散到4个寄存器了,LCD段 ...

    收到,这个代码省很多内存!非常感谢梁工的指导!!!

    点评

    我只说明原理,我没有实物屏验证,你可以按此原理处理。  详情 回复 发表于 2024-4-26 10:38
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    46

    主题

    2934

    回帖

    6617

    积分

    超级版主

    积分
    6617
    发表于 2024-4-26 10:38:10 | 显示全部楼层
    zcb18969755773 发表于 2024-4-26 09:03
    收到,这个代码省很多内存!非常感谢梁工的指导!!!

    我只说明原理,我没有实物屏验证,你可以按此原理处理。
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-26 16:14
  • 签到天数: 2 天

    [LV.1]初来乍到

    1

    主题

    5

    回帖

    23

    积分

    新手上路

    积分
    23
     楼主| 发表于 2024-4-26 16:13:04 | 显示全部楼层
    梁工 发表于 2024-4-26 10:38
    我只说明原理,我没有实物屏验证,你可以按此原理处理。

    是这样的,一点没错,非常理想
    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-5-5 00:45 , Processed in 0.072779 second(s), 69 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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