文档库 最新最全的文档下载
当前位置:文档库 › 点亮VFD屏

点亮VFD屏

点亮VFD屏
点亮VFD屏

VFD的实现原理和驱动设计

单片机音响技术网2008/2/21

VFD 的简单介绍

VFD 是指真空荧光显示器,是Vacuum Fluorescent Display 的缩写,利用电子撞击玻璃基板上的荧光粉而发光,通过VFD上面的各个亮点的组合一起发亮来显示字符,数字,特定的图标等等。由于VFD的显示,清晰明亮低工耗等特点被广泛用于家用电器,仪器设备,自动动化设备等上面,用来显示数字信息如温度,字符信息如:名称和一些标记指示信息。有关VFD的硬件结构,工作原理,在网上有很多的介绍,在官方网站可以很容易的找到非常准确的介绍。VFD原理及使用请在本站下载

DVD视盘机的VFD显示典型硬件电路

VFD的硬件电路可根据VFD屏的SPEC了解其需要驱动的段,位,选择相应的驱动IC,常用的包括PT6312,PT6311,PT6311相对驱动的段,位多些,可连接的按键也多些。驱动电路的外围元件参数参照PT6311,PT6312的SPEC即可,需要注意的是,6312,6311有很多品牌均可通用,不同品牌的驱动注意其振荡电阻阻值的差异,其余基本相同,另外在电路半设计中驱动电压+5V的去藕电容尽量靠近IC,驱动数据线(DATA,STB,CLK)各连接一个101瓷片到地,保证IC,数据线不受干扰或减轻干扰。

VFD显示屏的供电

VFD显示屏的供电包括交流~3V3灯丝电压和驱动芯片需要的-21V~-27V以及+5V,上图是典型的变压器次级供电处理电路。

还有一种方法是用直流逆变得到或者使用开关电源,现在市场上很多专门的DVD开关电源,满足DVD解码板以及VFD 显示的电源要求,电源组包括:+5V,±12V,-21V,~3V3,有些还带常用集成功放的电源,使用他们也非常方便。笔者设计的TOPAV-2008开发平台,其VFD供电采用了直流逆变交流的方式,结构非常简洁,使用方便,详细可到单片机音响技术网了解。

VFD 的软件控制驱动设计

前面说过VFD用途广泛,所以就非常有必要搞清楚如何通过软件去驱动它了,怎样让VFD显示我们要显示的内容,这就是一个程序员要思考的问题了,也是本文的目力所在。市场上有很多电子产品都要用到VFD,其中目前比较火热的数字电视,机顶盒(DVB)还有DVD上面都在使用VFD显示。要想让VFD正常的工作还要依赖一个工作的平台,比如说,你是在Sunplus平台上,还是在Cheertek,Ali,ST,MTK,ESS的等平台上做。要让程序能高效的工作,并且具备最大可能性的移植和扩展性是非常重要的,例如让一个VFD的驱动模块同时可以在Sunplus,cheertek,Ali等多个平台上工作,也可以能在其它单片机上工作,只要它能支持C语言编程。为了让整个模块更加的模块化,我们就需要对整个模块进行进一步的细份。哎!废话少说,太激动了。

驱动三步走

我们把VFD的驱动分成三步或三部分来实现,各个部分实现相应的功能:

第一步:上层接口,用于适应市场上不同公司和种类的VFD。

第二步:中间层,VFD各中显示功能的的实现,用语满足显示需求。例如:一般显示,闪动,滚动,旋转,等....

第三步:平台接口,用于实现和各个平台之间的接口,主要是和CPU的通信。

基于上面的构想,下面就来分步实现它

简单的介绍一下实现环境:

编译环境:GCC

语言:C

测试平台:Cheertek(CT219,909),和Ali(Ali3330,3329)(DVB的外部显示,用来显示电台名称等等…)

VFD硬件:CS16312。

第一步:建立通用接口:用于适应市场上不同公司和种类的VFD 8段编码在开始写成程序实现之前,先了解字符显示的原理,字符是根据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 : 1000 0000 ---> 0x80

g : 0100 0000 ---> 0x40

f : 0010 0000 ---> 0x20

e : 0001 0000 ---> 0x10

d : 0000 1000 ---> 0x08

c : 0000 0100 ---> 0x04

b : 0000 0010 ---> 0x02

a : 0000 0001 ---> 0x01

根据上面的每段编码,如果要显示字符'A' 需要同时点亮a,b,c,e,f,g段并且d段熄灭,这样一个'A' 的字符轮廓就出来了,如上图”AbCd”中的'A',所以的字母A的编码是0111 0111 也就是把相应要点亮的段编码或起来就可以了'A'的编码值= a|b|c|e|f|g 各个段的对应关系如下:

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

根据上面的分析定义,我可以为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|SEG_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

#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_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_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|SEG_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_hw[11]={CHAR_H,CHAR_e,CHAR_l,CHAR_l,CHAR_BLANK,CHAR_w,CHAR_O

CHAR_r,CHAR_l,CHAR_d};

显示原理

到目前为止,我们还只是对基本字符和数字进行了逻辑上的编码,和怎样生成一个字符串,这些多还仅仅是个开始,要想在VFD上面显示”hello world” 还有很多事情要做,接下来我们就要了解VFD是如何显示字符的。

VFD要显示字符还要通过一块VFD驱动芯片来实现,VFD本身只能显示就像电脑的显示器一样,要想让它显示内容还要通过驱动芯片加上周边驱动电路共同来完成显示的任务。在DVB,DVB和其它用到VFD的电子产品中都会有一块VFD的电路板,通常叫VFD板(VFD panel)或前面板(Front panel)这块电路板就是由VFD驱动芯片,周边驱动电路和VFD组成。在目前的市场中VFD驱动芯片种类很多,但标准一样。VFD通过驱动电路与驱动芯片相连,来完成驱动芯片的显示任务,而驱动芯片的的任务是通过平台系统(如Ali的3329主芯片)获得的。在实际的编程过中,只需要通过平台系统上的主芯片(CPU)来控制VFD板上的驱动芯片从而完成一个显示任务,或其他任务,平台系统上的主芯片(CPU)一般是通过一个标准的三线串口来与VFD驱动芯片连接。上面简单的介绍了主板CPU,驱动芯片和VFD 之间的关系,具体的细节可以在相应的DATA SHEET或spec.中找到,或从硬件工程师那看到详细的电路连接状况,对相互协调工作就会有比较深刻的认识。哎!又罗嗦了

透过CPU控制VFD驱动芯片,VFD驱动芯片(16312)的内部框图如下:

在上面的框图中,可以看到一个显示存储器(Display RAM)正是通过这个显示寄存器来实现显示功能的,显示寄存器中的一个字节可以描述一个字符,显示寄存器中的一位映射到VFD显示屏中的一个亮点,也就是说如果向显示寄存器中的一个被映射的位写1,那么在VFD显示屏中的相应的亮点就会被点亮,相反写0 VFD显示屏中的相应的亮点就会被熄灭。通过向显示寄存器中写入一个字节,来显示一个基本字符,写入若干个字节可以显示一个字符串。显示寄存器透过段位在芯片外引出引脚然后连到VFD上,显示寄存器到VFD的映射就是这样通过硬件连接来实现的,通常由于驱动芯片的各个引脚可以根据自己的需要有选择的选用,线路的连接会有细微的变化,使得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

//上面定义的意思是:

//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。

//注意:关于宏定义的值(如: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 0x04

#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 0x00

#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_DATA,N1_SEG_E_DATA,

N1_SEG_F_DATA,N1_SEG_G_DATA,0,

.................

.................

};

根据三部分的驱动设计思想,我们把VFD驱动芯片通过串行接口与CPU的通信划分到整个驱动设计的第三部分,第一步所要做的是建立一个逻辑上与硬件无关公共接口。根据上面对显示寄存器的分析,我们可以建立一个数组用来映射驱动芯片中的显示寄存器,上面的16 X 11 显示存储器可以显示22 个字节,所以我们可以做如下定义:

BYTE 16312_DisplayRam[22];

第二步:中间层:VFD各种显示功能的的实现,用于满足显示需求。

在这部分主要根据第一层的公共接口和在第三层的驱动的基础上来实现VFD的各种显示功能,所以这部分主要是调用第三层的驱动函数来处理第一层的数据,或着说是将第一层的信息根据显示需求通过第三层发送给VFD驱动芯片中去。对于一个VFD首先要具备对一个条信息的基本显示功能,下面将介绍如何显示一个字符串”Hello world”,要想同时完全显示这个字符串,首先VFD上面必须要有11个8段,就是硬件支持同时显示11个字符的VFD,如果不够后面的字符就回丢失。

实现一个过程将字符串解析到16312_DisplayRam 中。

void ParseStringToRamMapping(char *Str,BYTE Strcount)

{

BYTE i,j;

for(i=0;i {

for(j=0;j<8;j++)

{

if(Str[i+1] & (0x01 << j))

16312_DisplayRam[ ADDRESS_MAPPING[i*16+j] ] |= ADDRESS_MAPPING[i*16+8+j];

else

16312_DisplayRam[ ADDRESS_MAPPING[i*16+j] ] &= ~ADDRESS_MAPPING[i*16+8+j];

}

}

}

//得到当前在VFD上正在显示的信息

void ParseRamMappingToString()

{

}

//将"Hello world"解析到16312_DisplayRam中。

ParseStringToRamMapping(str_hw,11);

//将16312_DisplayRam 写到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 Strcount)

{

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驱动芯片通过串行接口通信的问题。

CPU通过串行接口控制VFD的关闭和显示,VFD的亮度,显示存储器的读写,按键扫描等。在上面的图中可以看到,串口有四线,STB,CLK,Din,Dout但在实际电路中Din和Dout连接在一起使用,所有又叫三线串口。

STB :片选信号线在上升或下降沿初始化串行接口随后等待接收

指令STB 为低后的第一个字节作为指令,当处

理指令时当前其它处理被终止,当STB 为高

时CLK被忽略。

CLK :时钟信号线。在上升沿读取串行数据下降沿输出数据。

Din :数据输入。

Dout :数据输出。

串口通信和GPIO

了解VFD 用到的IO 口,通过一台整机的电路图,或从PCB板上用万能表测出VFD串行接口连接到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 17

VFD SDA 连接到了主板CPU 上的IO 22

VFD CLK 连接到了主板CPU 上的IO 16

知道了连接所用的IO后,就可以同过VFD串行接口向VFD驱动芯片发送收据和控制信息,向显示寄存器,键扫寄存器读写数据但,但首先要能够通过软件控制各个IO接口,也就是可以通过软件设置各个GIO的电位,例如:把GPIO 17 拉高到+5伏,或拉低到-5伏,如果有确定的平台系统,则相应的平台会提供相应的GPIO操作接口

例如Cheertek909

HAL_WriteGPIO(GPIO_VFD_STB,1); //向PGIO 17 写1 输出高电位

HAL_WriteGPIO(GPIO_VFD_STB,0); //向PGIO 17 写0 输出低电位

HAL_ReadGPIO(GPIO_VFD_SDA)?1:0; //读GPIO

Ali3330

#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 << (pos - 32))) | ((val) << (pos - 32)))); /

osal_interrupt_enable(); /

} while (0)

如没有完成的平台系统,没有GPIO接口,就需要首先根据CPU的SPEC,实现GPIO的输入输出子程序,这部分程序因主IC不同而不同,也不是本文讨论的重点。

例如:Cheertek909

void HAL_WriteGPIO(BYTE bGroup, DWORD dwPort, BYTE bValue)

{

.............

dwDesiredPort = (dwDesiredPort << 8);

.............

REG_PLAT_GPA_IO_DIR_CONTROL &= ~(dwDesiredPort);

............

}

// 909S: define GPIO registers

#define REG_PLATFORM_GPIO_BASE (IO_START+0x330)

// 80000330

#define REG_PLAT_GPA_CLEAR (*((volatile DWORD *) (REG_PLATFORM_GPIO_BASE+0x00))) //

0330 (909S)

#define REG_PLAT_GPA_SET (*((volatile DWORD *) (REG_PLATFORM_GPIO_BASE+0x04))) //

0334 (909S)

#define REG_PLAT_GPA_IO_DIR_CONTROL (*((volatile DWORD *) (REG_PLATFORM_GPIO_BASE+0x08))) // 0338 (909S)

#define REG_PLAT_GPIO_INT_CONFIGURATION (*((volatile DWORD *) (REG_PLATFORM_GPIO_BASE+0x0c))) //

033c

#define REG_PLAT_GPCDE_CLEAR (*((volatile DWORD *) (REG_PLATFORM_GPIO_BASE+0x10))) //

0340 (909S)

#define REG_PLAT_GPCDE_SET (*((volatile DWORD *) (REG_PLATFORM_GPIO_BASE+0x14))) //

0344 (909S)

#define REG_PLAT_GPCDE_IO_DIR_CONTROL (*((volatile DWORD *) (REG_PLATFORM_GPIO_BASE+0x18))) // 0348 (909S)

#define REG_PLAT_GPF_CLEAR (*((volatile DWORD *) (REG_PLATFORM_GPIO_BASE+0x1c))) //

034c (909S)

#define REG_PLAT_GPF_SET (*((volatile DWORD *) (REG_PLATFORM_GPIO_BASE+0x20))) //

0360 (909S)

通过上面的了解,假设现在用的是ALI的平台,我们就可以定义如下的宏来操作GPIO的状态

#Define ALI_SET_GPIO_HEIGHT(GPIO) /

HAL_GPIO_BIT_SET(GPIO,1)

#Define ALI_SET_GPIO_LOW(GPIO) /

HAL_GPIO_BIT_SET(GPIO,0)

接下来我们就可以测试上面的代码了,可以分别对三个GPIO分别输出高低电位,然后用示波器观察波形,是否正确。如果工作正常,接下来就可以根据串行协议实现数据传输了。其中主要实现两个函数,一次传输一个二进制位即一个BIT和一次传输一个字节。

从图中可以看出,根据串行协议,在传输开始要用STB选通,让STB进入低电位状态,说明串口数据传输开始,CLK 有效,SDA上的数据有效果,为高电位,传输终止SDA,SDA无效,当STB从一个低电位到一个高电位的过程中,SDA传输一个或多字节,SCK为高电位时即上升沿时,SDA接收数据即CPU向VFD CHIP DRIVER写入数据,SDA 传输一个BIT。STB控制信号控制字节的传输,SCK时钟信号控制位的传输,一个STB周期,传输一个或多个字节,一个CLK周期为一个BIT的读写信号。根据上面的分析,我们可以写出如下代码:

写一个位:

ALI_SET_GPIO_LOW(GPIO_VFD_CLK);

ALI_SET_GPIO_HEIGHT(GPIO_VFD_SDA);

ALI_SET_GPIO_HEIGHT(GPIO_VFD_CLK);

写入一个字节:

void Write_OneByte(BYTE bValue)

{

BYTE i=0;

ALI_SET_GPIO_LOW(GPIO_VFD_STB); //传输多个字节,STB控制移到函数外,即传输

//没有终止。

for(i=0;i<8;i++)

{

ALI_SET_GPIO_LOW(GPIO_VFD_CLK);

if(bValue & 0x01)

ALI_SET_GPIO_HEIGHT(GPIO_VFD_SDA);

else

ALI_SET_GPIO_Low(GPIO_VFD_SDA);

ALI_SET_GPIO_HEIGHT(GPIO_VFD_CLK);

bValue>>=1;

}

ALI_SET_GPIO_HEIGHT(GPIO_VFD_STB); //传输多个字节,STB控制移到函数外。

}

一次传输多个字节:

void Write_Datas(BYTE bcount,BYTE *pBValue)

{

BYTE i;

ALI_SET_GPIO_LOW(GPIO_VFD_STB);

for(i=0;i {

Write_OneByte(pBValue[bcount]);

}

ALI_SET_GPIO_HEIGHT(GPIO_VFD_STB);

}

上面的代码实现了如何根据串口协议传输数据即向串口发送数据的过程,但这还不是一个完整的传输过程,一个完整的数据传输过程应该是,一个具体的数据块从一个地方传输到一个指定的地方,一般数据的传输都是从一个芯片中的一个寄存器传输到另一个寄存器或从RAM的一个地方到另一个地方,和从不同芯片中的不同寄存器互相传输,通信协议用的最多的是I2C协议这里重点是串口协议,无论用什么协议,多需要知道目地地址,这些都可以从相关芯片SPEC中得到,在串行协议中,一个STB的上升或下降沿初始化串行接口,当STB为低电位后,CLK有效,SDA开始接收数据并且第一个字节为指令。有关16312的个指令定义如下:

#define COMMAND_WRITEDISPLAY 0x40

#define COMMAND_READKEY 0x42

#define COMMAND_ADDRESS 0xc0

#define COMMAND_DISP_MODE 0x02

#define COMMAND_CTRL_MODE 0x8f

//重写上面的函数

void Write_Datas(BYTE *pSour,BYTE *pDest,BYTE bcount)

{

BYTE i;

ALI_SET_GPIO_LOW(GPIO_VFD_STB); //如果已经在下降沿,移去

Write_OneByte(COMMAND_WRITEDISPLAY);

ALI_SET_GPIO_HEIGHT(GPIO_VFD_STB);

for(i=0;i<4;i++){}

ALI_SET_GPIO_LOW(GPIO_VFD_STB); //如果已经在下降沿,移去

Write_OneByte(COMMAND_ADDRESS); //参数也可以由pDest取得

ALI_SET_GPIO_HEIGHT(GPIO_VFD_STB);

for(i=0;i<4;i++){}

ALI_SET_GPIO_LOW(GPIO_VFD_STB);

for(i=0;i {

Write_OneByte(pBValue[bcount]);

}

ALI_SET_GPIO_HEIGHT(GPIO_VFD_STB);

for(i=0;i<4;i++){}

}

//设置VFD工作模式,和开启VFD。

void Start_VFD(void)

{

BYTE i;

ALI_SET_GPIO_LOW(GPIO_VFD_STB); //如果已经在下降沿,移去

Write_OneByte(COMMAND_DISP_MODE);

ALI_SET_GPIO_HEIGHT(GPIO_VFD_STB);

for(i=0;i<4;i++){}

ALI_SET_GPIO_LOW(GPIO_VFD_STB); //如果已经在下降沿,移去

Write_OneByte(COMMAND_DISP_MODE);

ALI_SET_GPIO_HEIGHT(COMMAND_CTRL_MODE);

for(i=0;i<4;i++){}

}

到现在我们已基本实现了串行通信的部分基本功能主要是向串口发送数据,接下来将实现如何从串行总线上接收数据另外有关VFD的各种显示功能将在第二部分实现。

VFD驱动的完整代码文件

详见单片机音响技术网TOPAV-2008配套程序(51汇编代码)

一些常用VFD驱动IC的SPEC请在本站首页下载

VFD串行通信的其他扩展功能

v

相关文档