搜索
bottom↓
回复: 20
打印 上一主题 下一主题

请教白沙HT1621驱动笔段式液晶原理

[复制链接]

出0入0汤圆

跳转到指定楼层
1
发表于 2013-3-3 21:19:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 风云天 于 2013-3-3 21:19 编辑

     HT1621的驱动程序我根据坛里和合泰官方的修改了,可以一位一位的显示,就是4位动态刷新的时候会闪烁,不管怎么改延时,都不行。感觉是驱动方法不对。
也看了笔段式液晶的驱动原理,要用交流驱动,就是搞不懂1/3偏置的原理,具体实现原理。
    我的想法是这样,跟数码管显示原理差不多:既然我能一次显示一位(一个8字)0-9的数字,那么我第一次显示COM0口,第二次显示COM1口,依次下去,应该可以的,为什么动态刷新时会闪烁,看了白沙这个版的很多贴了,都没有能详细解释的。
    我的段式液晶是4个COM口,8个Seg位的,可显示4位数字,如图:
程序如下:#include "HT1621.h"
//#define         POWER_TO_IO       

uchar const NUM_Table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
uchar const seg_table[]={
0x77,0x22,0xDB,
0x97,0x2E,0x6D,
0x7C,0x23,0xFF,0x2F
};
/**************************
函数:delay_us(uchar us)
功能:us延时
*************************/
void delay_us(uchar us)  //5,7,9
{
  while(us--);  
}



//ms延时
void Delayms(uint ms)
{
          uint i,j;
            for(i=0;i<ms;i++)
              for(j=0;j<10;j++);
}

//端口初始化
void Port_Init(void)
{
        HT1621_DDRX_OUT;        //设为输出
        HT1621_CS_1;
           HT1621_WR_1;
           HT1621_DO_1;
}

/****************************
函数:Ht1621Wr_Data(uchar data,uchar num)  
功能:向HT1621发送num个bit的data数据
参数:data; num;
返回:无
****************************/
void Ht1621Wr_Data(uchar data,uchar num)
{
  uchar i;
  for (i=0;i<num;i++)
  {   
    HT1621_WR_0;
   delay_us(1);        //稍微延时
    if(data&0x80)
          HT1621_DO_1;
    else  
          HT1621_DO_0;
    delay_us(1);
    HT1621_WR_1;
    delay_us(1);
    data<<=1;  
  }
}

/***************************
函数:void Ht1621WrCmd(uchar cmd)
功能:HT1621写命令函数
参数:cmd:命令
返回:无
******************************/
void Ht1621WrCmd(uchar cmd)
{
   HT1621_CS_0;   //CS
   //delay_us(5);
   Ht1621Wr_Data(0x80,4);               //写入命令标志100
   Ht1621Wr_Data(cmd,8);                //写入命令数据
   HT1621_CS_1;
  // delay_us(5);
}

/*************************
函数:void Ht1621WrOneData(uchar addr,uchar data)
功能:写地址及数据,数据为低4位
参数:addr:HT1621 RAM地址:0-31;数据:data赋给COM0-COM3
返回:无
*************************/
void Ht1621WrOneData(uchar addr,uchar data)
{
   HT1621_CS_0;
   Ht1621Wr_Data(0xa0,3);              //写入数据标志101
   Ht1621Wr_Data(addr<<2,6);           //写入地址数据
   Ht1621Wr_Data(data<<4,4);           //写入数据
   HT1621_CS_1;   
   //delay_us(5);
}


/*************************
函数:void Ht1621WrOneData(uchar addr,uchar data)
功能:写地址及数据,数据为低4位
参数:addr:HT1621 RAM地址:0-31;数据:data赋给COM0-COM3
返回:无
*************************/
void Ht1621WrOneData(uchar addr,uchar data)
{
   HT1621_CS_0;
   Ht1621Wr_Data(0xa0,3);              //写入数据标志101
   Ht1621Wr_Data(addr<<2,6);           //写入地址数据
   Ht1621Wr_Data(data<<4,4);           //写入数据
   HT1621_CS_1;   
   //delay_us(5);
}               

/************************
函数:void Clear(void)
功能:清屏
参数:无
返回:无
**************************/
void Clear(void)
{
   uchar i;

   HT1621_CS_0;
   Ht1621Wr_Data(0xa0,3);            //写入数据标志101
   Ht1621Wr_Data(0<<2,6);         //写入地址数据
   for(i=0;i<32;i++)                        //清32个RAM地址数据
        {
                        Ht1621Wr_Data(0,8);
        }
   HT1621_CS_1;   
}


/*************************
函数:void Ht1621_Init(void)  
功能:HT1621初始化
参数:无
返回:无
****************************/
void Ht1621_Init(void)
{        
        #ifdef        POWER_TO_IO               
        HT1621_GND_0;       //HT1621 power on
          HT1621_VCC_1;
        #endif
        Port_Init();                     
        Delayms(1);                         //延时使LCD工作电压稳定
           Ht1621WrCmd(BIAS);
           Ht1621WrCmd(RC256);              //使用内部振荡器
           Ht1621WrCmd(SYSDIS);                 //关振系统荡器和LCD偏压发生器
           Ht1621WrCmd(WDTDIS1);                         //关闭开门狗
           Ht1621WrCmd(SYSEN);                                 //打开系统振荡器
           Ht1621WrCmd(LCDON);                                //打开LCD偏压
       
}

其他大部分都一样了,增加了一个函数,将0-F编码写入seg0-seg7中:
/******************************
函数:void Ht1621_Display_Num(uchar const *pt,uchar port)
功能:LCD显示编码数字0-F
参数:uchar const *pt:数组编码指针; COM:需显示的端口
返回值:无
******************************/
void Ht1621_Display_Num(uchar const *pt,uchar COM)
{
        uchar i,RAM_addr=0,z=0x01;
        for(i=0;i<8;i++)
        {       
                        if(*pt&z)//低位先与,a->dp
                        {       
                                Ht1621WrOneData(RAM_addr,COM);
                        }                               
                        z<<=1;                        //bit0-bit7进行与
                        RAM_addr++;                //写下一个RAM地址
        }
}

比如我要显示COM0口为1:
则:Ht1621_Display_Num(&NUM_Table[1],0x01);//0x01为COM0选中
现在我的main程序为:
void main(void)
{
         

          WDTCTL = WDTPW + WDTHOLD;
        Set_MSP430_Clock(); //设置430时钟
           Delayms(1);
       
          Ht1621_Init();        //上电初始化LCD
          Delayms(20);          //延时一段时间
        Clear();    //清HT1621的RAM数据
        while(1)
        {       
                Ht1621_Display_Num(&NUM_Table[1],0x01);//COM0显示1
                Delayms(1);
                Ht1621_Display_Num(&NUM_Table[2],0x02);        //COM0显示2
                Delayms(1);
                Ht1621_Display_Num(&NUM_Table[3],0x04);////COM0显示3       
                Delayms(1);
                Ht1621_Display_Num(&NUM_Table[4],0x08);        ////COM0显示4
                Delayms(1);        
        }
}
我用的是数码管的动态扫描方法,可以段式液晶不管怎么调延时,总会闪烁,COM0-COM3的1/3偏置方法有谁能讲得比较清楚些?谢谢了
电路图:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

来自 9楼
 楼主| 发表于 2013-3-4 21:31:16 | 只看该作者
本帖最后由 风云天 于 2013-3-4 21:41 编辑

sf49ers 发表于 2013-3-3 23:10
仔细看了你的程序,你是对1621的用法还没理解
程序大概应该是这样的


嗯,谢谢你的提醒了,我知道什么意思了,之前我的编码是先seg0-seg7,而HT1621的是COM0-COM3编码的。
假设要在4位液晶上显示1234,1、2、3、4的seg0-seg7的阳极编码分别为0x06,0x5b,0x4f,0x66,
则HT1621的解法如下图:
     如此,可求得seg0-seg7依次发送的COM数据为uchar const table_com[]={0X06,0X0F,0X0B,0X06,0X04,0X01,0X07,0X00};
则写一个LCD4位同时显示1,2,3,4的测试程序如下,
void Ht1621_Write_Num(uchar const *pt)
{
        uchar i;
        for(i=0;i<8;i++)
        {
                Ht1621WrOneData(i,pt);
        }
       
}
void main()
{
     Ht1621_Init();        //上电初始化LCD
     Clear();        //清液晶屏
     Ht1621_Write_Num(table_com);
     while(1);
}
Ht1621WrOneData(uchar const *p,uchar com);已在前面定义.
我看了阿莫里的所有的关于HT1621的贴子,都没有这样讲解的,初学者一时很难理解HT1621的编码是怎样来得,深有痛感,在此给初学HT1621的童鞋们抛砖引玉,少走弯路。
又看了http://www.amobbs.com/thread-3702274-1-1.html

采用对所写段位先读后写的方式,每次只读写4bit,对数字位,只读写8bit,提高速度。


照他说法,每次写一个COM数据都要先读,对HT1621的操作不是又多了好多行代码,也一样占用单片机很多的执行时间啊(多了操作读-修改-写HT1621,且HT1621的时钟频率只有256KHz的),大大降低了MCU执行速度,而且也不易理解,还定义了两个数据的容量,一样占用空间,当然是ROM了
定义两个数组

const unsigned int BUFFER0[10]={0xEB00,0x6000,0xC700,0xE500,0x6C00,0xAD00,0xAF00,
                                0xE000,0xEF00,0xED00};
const unsigned int BUFFER1[10]={0x0D70,0x0060,0x0E30,0x0A70,0x0360,0x0B50,0x0F50,
                                0x0070,0x0F70,0x0B70};

我修改的HT1621优化如下:
首先定义2个数组:即用于显示数码管的阳极编码,一个不带点,一个带点
uchar const Num_Table0[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};

/***************带dp点的0-F的显示编码***************/
uchar const Num_Table1[]={
0xbf,0x86,0xdb,0xcf,
0xe6,0xed,0xfd,0x87,
0xff,0xef,0xf7,0xfc,
0xb9,0xde,0xf9,0xf1};

然后将这些编码进行转换为HT1621显示:
定义一个显示结构体,因为我是用液晶显示时间的,这样比较方便
typedef struct
{
      uchar first;        //LCD液晶前2位数据
        uchar second;        //LCD液晶后2位显示数据
}Struct_Dis_Value;

/******************************
函数:void Ht1621_Display_Num(uchar const *pt,Struct_Dis_Value *S_Value)
功能:LCD显示编码数字0-F,4位
参数:uchar const *pt编码数组;*S_Value:结构体存储待显示的数据
返回值:无
******************************/
void Ht1621_Display_Num(uchar const *pt,Struct_Dis_Value *S_Value)
{
        uchar i,j=0x01,senddata=0; //senddat为HT162的COM0数据
        uchar ten1=0,ge1=0,ten2=0,ge2=0;        //十位和个位
       
        ten1=S_Value->first/10;   //十位
        ge1=S_Value->first%10;   //个位
        ten2=S_Value->second/10;
        ge2=S_Value->second%10;
        for(i=0;i<8;i++)
        {
                if(ten1!=0) //如first=7,只显示7,不显示07
                {
                    if(pt[ten1] & j)
                        senddata|=0x08;        //COM3-COM0,bit3=1;
                }
                if(pt[ge1] & j)
                {  
                          senddata|=0x04;        //bit2=1;
                }
                if(ten2!=0)
                {
                    if(pt[ten2] & j)
                        senddata|=0x02;       
                }
                if(pt[ge2] & j)
                {
                        senddata|=0x01;
                }
                Ht1621WrOneData(i,senddata);//向seg0-seg7地址发送COM口数据
                j<<=1;        //
                senddata=0;
        }
}

然后将可使用了
main中:
void main(void)
{
         
      Display_Value.first=12; //初始化显示数据
        Display_Value.second=34;
          WDTCTL = WDTPW + WDTHOLD;
        Set_MSP430_Clock();

       
          Ht1621_Init();        //上电初始化LCD
          Delayms(20);          //延时一段时间
        Clear();
        while(1)
        {       
                Ht1621_Display_Num(Num_Table1,&Display_Value);
        }
}

硬件图,电路连接图如下:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

2
 楼主| 发表于 2013-3-3 21:26:21 | 只看该作者
请白沙能帮忙讲解笔段式液晶驱动原理吗?谢谢了!

出0入0汤圆

3
发表于 2013-3-3 21:55:53 | 只看该作者
甭管DUTY,BIAS什么的,不用搞那么细,1621帮你搞定。你只需写1621显示RAM,告诉它哪个SEG亮哪个灭就行

出0入0汤圆

4
 楼主| 发表于 2013-3-3 22:03:04 | 只看该作者
恩,我可以显示出来了,一共有4位,一个一个显示啊,想显示哪段也可以啊,关键是4位要同时显示不同的数字,就是动态刷新的问题,比如同时显示1234,就闪烁的很厉害了,估计是我按照数码管的扫描原理方法不对

出0入0汤圆

5
 楼主| 发表于 2013-3-3 22:05:38 | 只看该作者
sf49ers 发表于 2013-3-3 21:55
甭管DUTY,BIAS什么的,不用搞那么细,1621帮你搞定。你只需写1621显示RAM,告诉它哪个SEG亮哪个灭就行 ...

我的硬件原理图限定了不能用静态显示的方法的,笔段式液晶只有COM0-COM3,seg0-seg7管脚的,就是一个时刻只能显示1位数字啊

出0入0汤圆

6
 楼主| 发表于 2013-3-3 22:06:09 | 只看该作者
风云天 发表于 2013-3-3 22:05
我的硬件原理图限定了不能用静态显示的方法的,笔段式液晶只有COM0-COM3,seg0-seg7管脚的,就是一个时刻 ...

恩,我可以显示出来了,一共有4位,一个一个显示啊,想显示哪段也可以啊,关键是4位要同时显示不同的数字,就是动态刷新的问题,比如同时显示1234,就闪烁的很厉害了

出0入0汤圆

7
发表于 2013-3-3 22:09:44 | 只看该作者
你不是用了1621吗,还管什么静态动态,只要1621配置和实际液晶一致就行,你只关心显示RAM更新

出0入0汤圆

8
发表于 2013-3-3 23:10:41 | 只看该作者
风云天 发表于 2013-3-3 22:06
恩,我可以显示出来了,一共有4位,一个一个显示啊,想显示哪段也可以啊,关键是4位要同时显示不同的数字 ...

仔细看了你的程序,你是对1621的用法还没理解
程序大概应该是这样的

for(i=0;i<8;i++)
{
    Ht1621WrOneData(i,SEGdata);
}

其中SEGdata[0]~SEGdata[8]对应LCD pin5~12显示的内容,bit0是COM0。应事先准备好,译码稍稍繁琐些

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

10
发表于 2013-7-18 17:35:15 | 只看该作者
合泰全线产品代理(有代理证),联系人田生 QQ773890956

出0入0汤圆

11
发表于 2013-7-23 15:56:13 | 只看该作者
风云天 发表于 2013-3-4 21:31
嗯,谢谢你的提醒了,我知道什么意思了,之前我的编码是先seg0-seg7,而HT1621的是COM0-COM3编码的。
假设 ...

楼主的编码和我写的不一样,我想请教下!!
分别亮1 2 3 4 比如为什么楼主第二段是1011 代表了1f 2f也亮了 1,2,3,4这四个数亮并不会1f 2f也亮啊 后面也是一样的
还有void Ht1621_Write_Num(uchar const *pt)
{
        uchar i;
        for(i=0;i<8;i++)
        {
                Ht1621WrOneData(i,pt);
        }
        
}
这个函数我没看懂什么意思,为什么地址加一数据地址不加一呢?而且ram地址没必要加一吧,如果是连续模式的话不是可以自动加一的吗?

出0入0汤圆

12
发表于 2013-7-30 17:22:07 | 只看该作者
你好,最近我也在用笔段式LCD,显示不清楚,请问1/3偏压、1/2偏压、1/4偏压是怎么定义的,请指教,谢谢!

出0入0汤圆

13
发表于 2013-8-2 23:34:41 | 只看该作者
以后慢慢学.............

出0入0汤圆

14
发表于 2013-8-3 09:02:54 | 只看该作者
看了关于楼主的帖子,大概理解所以让液晶显示的工作都是由1621来执行的,单片机只负责写数据命令。

出0入0汤圆

15
发表于 2013-11-6 15:56:29 | 只看该作者
大神们帮我看看种的,我怎么都看不出来啊,com一般是4口吗?这个变8口了,用的是HT1622的,现在这个断码库我怎么建立显示起来啊,已经可以点亮了,用的是一位大神的程序:http://www.amobbs.com/forum.php? ... mp;highlight=HT1622

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

16
发表于 2014-4-23 15:09:40 | 只看该作者
最近正要用到,学习一下。

出0入4汤圆

17
发表于 2014-9-28 11:07:18 | 只看该作者
有用,谢谢。

出0入0汤圆

18
发表于 2014-9-29 15:14:51 | 只看该作者
一般而言,Bias和Duty之间是有一定关系的,duty数越多,每根COM对应的扫描时间变短,而要达到同样的显示亮度和显示对比度,VON的电压就要提高,选电平和非选电平的差异需要加大,即Bias需要加大,Duty和Bias间有一经验公式,即
Bias=1/(sqrt(Duty)+1)

出0入0汤圆

19
发表于 2014-9-29 15:15:19 | 只看该作者
sbgavin 发表于 2013-7-30 17:22
你好,最近我也在用笔段式LCD,显示不清楚,请问1/3偏压、1/2偏压、1/4偏压是怎么定义的,请指教 ...

一般而言,Bias和Duty之间是有一定关系的,duty数越多,每根COM对应的扫描时间变短,而要达到同样的显示亮度和显示对比度,VON的电压就要提高,选电平和非选电平的差异需要加大,即Bias需要加大,Duty和Bias间有一经验公式,即
Bias=1/(sqrt(Duty)+1)

出0入0汤圆

20
发表于 2014-11-20 22:39:22 | 只看该作者
snfjhudng 发表于 2014-9-29 15:15
一般而言,Bias和Duty之间是有一定关系的,duty数越多,每根COM对应的扫描时间变短,而要达到同样的显示 ...


请问如何对某个seg(也就是某个ADDRESS)的4位数据中的某一位进行写0或1而不影响另外三位?


比如修改SEG0的D3写1(显示),而原来D0-D2也可能有显示

可能手册上的描述,Read-Modify-Write应该可以

但是看图4个RD上升沿后4个WR上升沿,RD、WR之间应该就是程序修改数据的时间了吧?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

21
发表于 2016-5-13 07:50:03 | 只看该作者
谢谢楼主,学习了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 15:00

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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