1、点亮VFD屏VFD的实现原理和驱动设计单片机音响技术网 2008/2/21VFD 的简单介绍VFD 是指真空荧光显示器,是 Vacuum Fluorescent Display 的缩写,利用电子撞击玻璃基板上的荧光粉而发光,通过VFD上面的各个亮点的组合一起发亮来显示字符,数字,特定的图标等等。由于VFD的显示,清晰 明亮 低工耗等特点被广泛用于家用电器,仪器设备,自动动化设备等上面,用来显示数字信息如温度,字符信息 如:名称 和一些标记指示信息。有关VFD的硬件结构,工作原理,在网上有很多的介绍,在官方网站可以很容易的找到非常准确的介绍。VFD原理及使用请在本站下载DVD视盘机的VFD显示典
2、型硬件电路VFD的硬件电路可根据VFD屏的SPEC了解其需要驱动的段,位,选择相应的驱动IC,常用的包括PT6312,PT6311,PT6311相对驱动的段,位多些,可连接的按键也多些。驱动电路的外围元件参数参照PT6311,PT6312的SPEC即可,需要注意的是,6312,6311有很多品牌均可通用,不同品牌的驱动注意其振荡电阻阻值的差异,其余基本相同,另外在电路半设计中驱动电压+5V的去藕电容尽量靠近IC,驱动数据线(DATA,STB,CLK)各连接一个101瓷片到地,保证IC,数据线不受干扰或减轻干扰。VFD显示屏的供电VFD显示屏的供电包括交流3V3灯丝电压和驱动芯片需要的-21V-
3、27V以及+5V,上图是典型的变压器次级供电处理电路。还有一种方法是用直流逆变得到或者使用开关电源,现在市场上很多专门的DVD开关电源,满足DVD解码板以及VFD显示的电源要求,电源组包括:+5V,12V,-21V,3V3,有些还带常用集成功放的电源,使用他们也非常方便。笔者设计的TOPAV-2008开发平台,其VFD供电采用了直流逆变交流的方式,结构非常简洁,使用方便,详细可到单片机音响技术网了解。VFD 的软件控制驱动设计前面说过VFD用途广泛,所以就非常有必要搞清楚如何通过软件去驱动它了,怎样让VFD显示我们要显示的内容,这就是一个程序员要思考的问题了,也是本文的目力所在。市场上有很多电
4、子产品都要用到VFD,其中目前比较火热的数字电视,机顶盒(DVB)还有DVD上面都在使用VFD显示。要想让VFD正常的工作还要依赖一个工作的平台,比如说,你是在 Sunplus平台上,还是在Cheertek,Ali,ST,MTK,ESS的等平台上做。要让程序能高效的工作,并且具备最大可能性的移植和扩展性是非常重要的,例如让一个VFD的驱动模块同时可以在 Sunplus,cheertek,Ali等多个平台上工作,也可以能在其它单片机上工作,只要它能支持 C语言编程。为了让整个模块更加的模块化,我们就需要对整个模块进行进一步的细份。哎!废话少说,太激动了。驱动三步走我们把VFD的驱动分成三步或三部
5、分来实现,各个部分实现相应的功能:第一步:上层接口,用于适应市场上不同公司和种类的VFD。第二步:中间层 ,VFD各中显示功能的的实现,用语满足显示需求。例如:一般显示,闪动, 滚动,旋转,等.第三步:平台接口,用于实现和各个平台之间的接口,主要是和CPU的通信。基于上面的构想,下面就来分步实现它 简单的介绍一下实现环境:编译环境:GCC 语言 :C 测试平台:Cheertek(CT219,909),和Ali(Ali3330,3329)(DVB的外部显示,用来显示电台名称等等) VFD硬件:CS16312。第一步:建立通用接口:用于适应市场上不同公司和种类的VFD 8段编码在开始写成程序实现之
6、前,先了解字符显示的原理,字符是根据8段编码的方式在VFD上面显示的,当然也有更多段的编码方式。8段编码用一个字节来描述一个ASCII字符,对扩展的ASCII 码如包含德语,法语等就要用到更多段的编码,也就是用多个字节来表示一个字符。 在一个八段编码的VFD中,把8段分别定义为 a,b,c,d,e,f,g,h段,用一个字节来表示就是 h g f e d c b a h是字节的最高位,a是字节的最低位。显示字符的原理如下:VFD常用字母的写法“米”字8和8的区别请注意有不同根据上面的原理,0 表示熄灭,1 表示点亮,可以得出,8段分别点亮后的对应编码是: 8段的每一段对应一个字节的一个位的:h
7、: 1000 0000 - 0x80g : 0100 0000 - 0x40f : 0010 0000 - 0x20e : 0001 0000 - 0x10d : 0000 1000 - 0x08c : 0000 0100 - 0x04b : 0000 0010 - 0x02a : 0000 0001 - 0x01根据上面的每段编码,如果要显示字符 A 需要同时点亮a,b,c,e,f,g段并且d段熄灭,这样一个 A 的字符轮廓就出来了,如上图”AbCd”中的A,所以的字母A的编码是0111 0111 也就是把相应要点亮的段编码或起来就可以了A的编码值 = a|b|c|e|f|g 各个段的对应关
8、系如下: 7 6 5 4 3 2 1 0 h g f e d c b a 0 1 1 1 0 1 1 1 通过上面的分析可以在程序中用如下宏来重新定义VFD的8段 #define SEG_A 0x01#define SEG_B 0x02#define SEG_C 0x04#define SEG_D 0x08#define SEG_E 0x10#define SEG_F 0x20#define SEG_G 0x40#define SEG_H 0x80通过上面的分析和段定义可以为字符A 做如下定义:#define CHAR_A SEG_A|SEG_B|SEG_C|SEG_E|SEG_F|SEG_G
9、 根据上面的分析定义,我可以为26个字母,和10个数字字符做完整的定义 如下:#define NUM_0 SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F#define NUM_1 SEG_B|SEG_C#define NUM_2 SEG_A|SEG_B|SEG_D|SEG_E|SEG_G#define NUM_3 SEG_A|SEG_B|SEG_C|SEG_D|SEG_G#define NUM_4 SEG_B|SEG_C|SEG_F|SEG_G#define NUM_5 SEG_A|SEG_C|SEG_D|SEG_F|SEG_G#define NUM_6 SEG_A|S
10、EG_C|SEG_D|SEG_E|SEG_F|SEG_G#define NUM_7 SEG_A|SEG_B|SEG_C#define NUM_8 SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G#define NUM_9 SEG_A|SEG_B|SEG_C|SEG_D|SEG_F|SEG_G#define CHAR_A SEG_A|SEG_B|SEG_C|SEG_E|SEG_F|SEG_G#define CHAR_a CHAR_A #define CHAR_B SEG_C|SEG_D|SEG_E|SEG_F|SEG_G#define CHAR_b CHAR_B
11、#define CHAR_c SEG_D|SEG_E|SEG_G#define CHAR_C SEG_A|SEG_D|SEG_E|SEG_F#define CHAR_d SEG_B|SEG_C|SEG_D|SEG_E|SEG_G#define CHAR_D CHAR_d #define CHAR_E SEG_A|SEG_D|SEG_E|SEG_F|SEG_G#define CHAR_e CHAR_E#define CHAR_F SEG_A|SEG_E|SEG_F|SEG_G #define CHAR_f CHAR_F #define CHAR_g NUM_9#define CHAR_G NUM
12、_9#define CHAR_H SEG_B|SEG_C|SEG_E|SEG_F|SEG_G#define CHAR_h CHAR_H#define CHAR_I NUM_1#define CHAR_i NUM_1#define CHAR_L SEG_D|SEG_E|SEG_F#define CHAR_l CHAR_L #define CHAR_N SEG_A|SEG_B|SEG_C|SEG_E|SEG_F#define CHAR_n SEG_B|SEG_C|SEG_E|SEG_F|SEG_H#define CHAR_O NUM_0#define CHAR_o SEG_C|SEG_D|SEG_
13、E|SEG_G#define CHAR_P SEG_A|SEG_B|SEG_E|SEG_F|SEG_G#define CHAR_p LETT_P#define CHAR_r SEG_E|SEG_G#define CHAR_R CHAR_r#define CHAR_S SEG_A|SEG_C|SEG_D|SEG_F|SEG_G#define CHAR_t SEG_D|SEG_E|SEG_F|SEG_G#define CHAR_T LETT_t#define CHAR_U SEG_B|SEG_C|SEG_D|SEG_E|SEG_F#define CHAR_Y SEG_B|SEG_C|SEG_D|S
14、EG_F|SEG_G#define CHAR_G SEG_G #define CHAR_BLANK 0x00 上面为基本的字符数字都做了编码定义,以后就可以通过编码来指代这些字符,如一个字符串 “Hello world” 等于 CHAR_H+CHAR_e+CHAR_l+CHAR_l+CHAR_BLANK+CHAR_w+CHAR_O CHAR_r+CHAR_l+CHAR_d. 用数组表示:char str_hw11=CHAR_H,CHAR_e,CHAR_l,CHAR_l,CHAR_BLANK,CHAR_w,CHAR_O CHAR_r,CHAR_l,CHAR_d; 显示原理到目前为止,我们还只是对
15、基本字符和数字进行了逻辑上的编码,和怎样生成一个字符串,这些多还仅仅是个开始,要想在VFD上面显示”hello world” 还有很多事情要做,接下来我们就要了解 VFD是如何显示字符的。VFD要显示字符还要通过一块VFD驱动芯片来实现,VFD本身只能显示就像电脑的显示器一样,要想让它显示内容还要通过驱动芯片加上周边驱动电路共同来完成显示的任务。在DVB,DVB和其它用到VFD的电子产品中都会有一块VFD的电路板,通常叫VFD板(VFD panel)或前面板(Front panel)这块电路板就是由VFD驱动芯片,周边驱动电路和VFD组成。在目前的市场中VFD驱动芯片种类很多,但标准一样。VF
16、D通过驱动电路与驱动芯片相连,来完成驱动芯片的显示任务,而驱动芯片的的任务是通过平台系统(如 Ali的 3329主芯片)获得的。在实际的编程过中,只需要通过平台系统上的主芯片(CPU)来控制VFD板上的驱动芯片从而完成一个显示任务,或其他任务,平台系统上的主芯片(CPU)一般是通过一个标准的三线串口来与VFD驱动芯片连接。上面简单的介绍了主板CPU,驱动芯片和VFD之间的关系,具体的细节可以在相应的DATA SHEET或spec.中找到,或从硬件工程师那看到详细的电路连接状况,对相互协调工作就会有比较深刻的认识。哎!又罗嗦了 透过CPU控制VFD驱动芯片,VFD驱动芯片(16312)的内部框图
17、如下: 在上面的框图中,可以看到一个显示存储器(Display RAM)正是通过这个显示寄存器来实现显示功能的,显示寄存器中的一个字节可以描述一个字符,显示寄存器中的一位映射到VFD显示屏中的一个亮点,也就是说如果向显示寄存器中的一个被映射的位写 1,那么在VFD显示屏中的相应的亮点就会被点亮,相反写 0 VFD显示屏中的相应的亮点就会被熄灭。通过向显示寄存器中写入一个字节,来显示一个基本字符,写入若干个字节可以显示一个字符串。显示寄存器透过段位在芯片外引出引脚然后连到VFD上,显示寄存器到VFD的映射就是这样通过硬件连接来实现的,通常由于驱动芯片的各个引脚可以根据自己的需要有选择的选用,线路
18、的连接会有细微的变化,使得VFD的各个亮点映射到显示寄存器的具体的地址也会有一些细微差别,想要在VFD上任意位置为开始显示一个任意一个字符串,和点亮VFD上面的任意一点,程序员必须就必须知道和计算出在一块确定的VFD驱动板上,VFD上的每个亮点映射到了显示寄存器中的什么地址位,从而决定向显示寄存器的什么地址写数据,所以定义VFD上面的每个亮点在DISPLAY RAM中的地址,从右往左,VFD上面的所有亮点由若干个8段和icon组成:例如: 下面 N1_ 代表第一个8段#define N1_SEG_A_ADDR 0x02 #define N1_SEG_A_DATA 0x04 /上面定义的意思是:
19、/1. 8段中 A 段在显示寄存器中的字节地址即这个亮点映射到了显示存储器中的第几个字/ 节 (例如 0x02 第二个字节)./2. A段映射到显示寄存器的某个字节的第几位(例如:0x04 即 0000 0100 8位中的第/ 三位,也就是有置 1 的位)/上面的定义描述了,从左往右,VFD第一个8段中的 A段映射到显示寄存器中第2个字节中的/第三位,也就说,如果把显示寄存器中的第二个字节中的第三位置 1,那么VFD第一个8段中/的 A段就会被点亮,即向显示寄存器中的 N1_SEG_A_ADDR 地址处 写入N1_SEG_A_DATA。/下面可以依次定义VFD上面的各个亮点和ICON。/注意:
20、关于宏定义的值(如:0x02,0x04)从哪里来,将会在后面讲到,其实是要再写程序/来测试出各个亮点对应的地址,或从相关SPEC中得到。驱动完成以后,对于不不同的VFD只/要添上值就可以了。#define N1_SEG_B_ADDR 0x02#define N1_SEG_B_DATA 0x08#define N1_SEG_C_ADDR 0x02#define N1_SEG_C_DATA 0x40#define N1_SEG_D_ADDR 0x03#define N1_SEG_D_DATA 0x08#define N1_SEG_E_ADDR 0x03#define N1_SEG_E_DATA 0
21、x04#define N1_SEG_F_ADDR 0x03#define N1_SEG_F_DATA 0x40#define N1_SEG_G_ADDR 0x03#define N1_SEG_G_DATA 0x30#define N1_SEG_H_ADDR 0x00#define N1_SEG_H_DATA 0x00./ Icon Define#define VFD_TITLE_ADDR 0x00#define VFD_TITLE 0x00#define VFD_CHAPTER_ADDR 0x00#define VFD_CHAPTER 0x00#define VFD_HOUR_ADDR 0x0
22、0#define VFD_HOUR 0x00#define VFD_HOUR_COL_ADDR 0x02#define VFD_HOUR_COL 0x01.上面对VFD上的各个亮点做了定义,但我们还需要建立一个映射表方便在调用各个段定义。 BYTE ADDRESS_MAPPING = N1_SEG_A_ADDR, N1_SEG_B_ADDR, N1_SEG_C_ADDR, N1_SEG_D_ADDR,N1_SEG_E_ADDR, N1_SEG_F_ADDR,N1_SEG_G_ADDR,0,N1_SEG_A_DATA, N1_SEG_B_DATA, N1_SEG_C_DATA, N1_SEG_D
23、_DATA,N1_SEG_E_DATA, N1_SEG_F_DATA,N1_SEG_G_DATA,0,.;根据三部分的驱动设计思想,我们把VFD驱动芯片通过串行接口与CPU的通信划分到整个驱动设计的第三部分,第一步所要做的是建立一个逻辑上与硬件无关公共接口。根据上面对显示寄存器的分析,我们可以建立一个数组用来映射驱动芯片中的显示寄存器,上面的 16 X 11 显示存储器可以显示 22 个字节,所以我们可以做如下定义: BYTE 16312_DisplayRam22; 第二步:中间层 :VFD各种显示功能的的实现,用于满足显示需求。在这部分主要根据第一层的公共接口和在第三层的驱动的基础上来实现V
24、FD的各种显示功能,所以这部分主要是调用第三层的驱动函数来处理第一层的数据,或着说是将第一层的信息根据显示需求通过第三层发送给VFD驱动芯片中去。对于一个VFD首先要具备对一个条信息的基本显示功能,下面将介绍如何显示一个字符串”Hello world”,要想同时完全显示这个字符串,首先VFD上面必须要有11个8段,就是硬件支持同时显示11个字符的VFD,如果不够后面的字符就回丢失。 实现一个过程将字符串解析到 16312_DisplayRam 中。 void ParseStringToRamMapping(char *Str,BYTE Strcount)BYTE i,j;for(i=0;i f
25、or(j=0;j8;j+) if(Stri+1 & (0x01 j) 16312_DisplayRam ADDRESS_MAPPINGi*16+j |= ADDRESS_MAPPINGi*16+8+j; else 16312_DisplayRam ADDRESS_MAPPINGi*16+j &= ADDRESS_MAPPINGi*16+8+j; /得到当前在VFD上正在显示的信息void ParseRamMappingToString()/将Hello world解析到16312_DisplayRam中。ParseStringToRamMapping(str_hw,11);/将 16312_D
26、isplayRam 写到 VFD的RAM中去。Write_Datas(16312_DisplayRam,NULL,22);在主程序 polling的时候 呼叫Write_Datas方法将16312_DisplayRam最终写到VFD驱动芯片的显示RAM中之后,在调用 Start_VFD();VFD上就会显示出 “Hello world” 了。 在第二层中的内容主要是显示功能的实现和逻辑控制,程序写起来可以根据实际需求灵活多变,而第一部分和第三部分的内容则相对稳定。所以也可以实现类似下面的函数来实时控制VFD的显示: void ShowMessagesOnVFD(char *Str,BYTE S
27、trcount)ParseStringToRamMapping(Str, Strcount);Write_Datas(16312_DisplayRam,NULL,22);Start_VFD();或者void PrintMessagesOnVFD(char *Str,BYTE Strcount)ParseStringToRamMapping(Str, Strcount);Write_Datas(16312_DisplayRam,NULL,22);Start_VFD();第三步:平台接口:用于实现和各个平台之间的接口,主要是和CPU的通信。在第三部分主要实现CPU与VFD驱动芯片通过串行接口通信的
28、问题。CPU通过串行接口控制VFD的关闭和显示,VFD的亮度,显示存储器的读写,按键扫描等。在上面的图中可以看到,串口有四线,STB,CLK,Din,Dout但在实际电路中 Din和Dout连接在一起使用,所有又叫三线串口。 STB :片选信号线 在上升或下降沿初始化串行接口随后等待接收指令STB 为低后的第一个字节作为指令,当处理指令时当前其它处理被终止,当STB 为高时CLK被忽略。CLK :时钟信号线。在上升沿读取串行数据下降沿输出数据。Din :数据输入。Dout :数据输出。串口通信 和 GPIO 了解VFD 用到的 IO 口,通过一台整机的电路图,或从PCB板上用万能表测出VFD串
29、行接口连接到CPU上的引脚,然后根据CPU的SPEC得到映射到的IO接口,完整的说应该是GPIO(General Purpose Input/Output的缩写即通用输入输出接口,支持 I2C, 串行总线等协议 )。 如:Ali 3330#define GPIO_VFD_STB 17#define GPIO_VFD_SDA 22 /Din 和 Dout#define GPIO_VFD_CLK 16 上面的定义可以理解为:VFD STB 连接到了 主板CPU 上的IO 17VFD SDA 连接到了 主板CPU 上的IO 22VFD CLK 连接到了 主板CPU 上的IO 16知道了连接所用的IO
30、后,就可以同过VFD串行接口向VFD驱动芯片发送收据和控制信息,向显示寄存器,键扫寄存器读写数据但,但首先要能够通过软件控制各个IO接口,也就是可以通过软件设置各个GIO的电位,例如:把 GPIO 17 拉高到+5伏,或拉低到-5伏,如果有确定的平台系统,则相应的平台会提供相应的GPIO操作接口 例如 Cheertek909HAL_WriteGPIO(GPIO_VFD_STB,1); /向PGIO 17 写 1 输出高电位HAL_WriteGPIO(GPIO_VFD_STB,0); /向PGIO 17 写 0 输出低电位HAL_ReadGPIO(GPIO_VFD_SDA)?1:0; /读GPIOAli3330#define HAL_GPIO_BIT_SET(pos, val) /do osal_interrupt_disable(); /(pos 32) /? HAL_GPIO_WRITE(HAL_GPIO_READ() & (1 (pos) | (val) (pos) /: HAL_GPIO1_WRITE(HAL_GPIO1_READ() & (1
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1