从零开始写驱动——vfd专用驱动芯片HT16514并行驱动程序编写

前言

一直看别人搞的 vfd 很漂亮,前段时间淘了个 vfd 模块来,但没有模块资料,还好芯片没有打磨的,良心商家啊。周末抽空来研究一下这个东西。

从零开始写驱动——vfd专用驱动芯片HT16514并行驱动程序编写 从零开始写驱动——vfd专用驱动芯片HT16514并行驱动程序编写

从零开始

打开外壳

从零开始写驱动——vfd专用驱动芯片HT16514并行驱动程序编写 从零开始写驱动——vfd专用驱动芯片HT16514并行驱动程序编写 从零开始写驱动——vfd专用驱动芯片HT16514并行驱动程序编写

测试线路

  1. 查看芯片是 HT16514,去搜索到芯片手册(博客没有找到上传附件的功能,不然肯定要放一个附件的)
  2. 根据芯片手册的引脚图,测试插针与引脚的电阻,从而确定每个引脚的功能
    从零开始写驱动——vfd专用驱动芯片HT16514并行驱动程序编写
  3. 测试后发现用的是 M68 并行接口方式,而且电路上没有做跳线开关调整功能,要是串行该多好啊,这并行接口岂不是要用光 arudino uno 的引脚了。不过反正是试着驱动它,是串行还是并行都一样,以后真有需要再改硬件
  4. 下面就是根据芯片手册来写驱动程序了
    查看电平稳定时间都是用 ns 做单位的,对于 arduino 的执行效率来说应该是不需要考虑这个问题,因此驱动程序里没有加上延时处理,如果哪天用的板子速度太快,执行结果不正常的话,那就需要考虑加上延时了。

驱动编写

最主要就是根据时序图,及命令表来设置每个引脚的电平高低,以及电平变化时间,这就完成了:

从零开始写驱动——vfd专用驱动芯片HT16514并行驱动程序编写 从零开始写驱动——vfd专用驱动芯片HT16514并行驱动程序编写

驱动程序

没有找到上传附件的功能,那就把程序完整贴出来喽。

把驱动写成一个类的形式,方便使用。并行接口有 8 位和 4 位两种模式,用不同的构造函数来初始化实例来实现两种模式的区分。8 位模式的话,反正都要用这么多引脚了,直接使用 uno 的 PORTD 来当数据 IO 口,方便写程序操作,但下载程序的时候要注意拔掉 0 1 两脚接线以免下载失败。

头文件:

// ----------------------------------------------------------------------------
// driverHT16514Parallel.h
//
// Created 2015-07-04
// By seesea <seesea2517#gmail#com>
//
// HT16514 并行驱动
// 根据当前需要只实现部分功能
// ---------------------------------------------------------------------------- #ifndef _DRIVERHT16514PARALLEL_H_
#define _DRIVERHT16514PARALLEL_H_ #include <arduino.h> #define DATA_PORT PORTD
#define DDR_PORT DDRD class HT16514Parallel
{
private:
char RW; // RW
char E; // E
char RS; // RS
char dataPins[]; // 四位数据线的时候使用的引脚,数据引脚存放顺序由高到低,即 0:DB7 ... 3:DB4
static const byte dataPinMask[]; // 四位数据线时使用的引脚掩码 bool isDisplayOn; // 显示是否打开,是的话 true
bool isBlink; // 是否开启闪烁,是的话 true
bool isShowCursor; // 是否显示光标,是的话 true char dataLength; // 数据长度,使用 PORTD 的时候是 8 位,使用四位数据线的时候是 4 位
char rowNumber; // 显示器行数 char curRow; // 输出位置之当前行
char curCol; // 输出位置之当前列 public:
HT16514Parallel(char _RW, char _E, char _RS); // 构造函数,使用 PORTD 来做数据输出
HT16514Parallel(char _RW, char _E, char _RS, // 构造函数,使用四位并行方式,用指定的四个引脚来做数据输出
char D7, char D6, char D5, char D4); void sendCommand(byte cmd); // 发送命令
void sendData(byte data); // 发送数据 void init(char dl); // 初始化模块数据
void initDisplay(); // 初始化显示屏
void clear(); // 清屏
void moveCursorHome(); // 光标回左上角
void displayOn(); // 显示开
void displayOff(); // 显示关
void blinkOnCursor(); // 光标闪烁开
void blinkOffCursor(); // 光标闪烁关
void showCursor(); // 显示光标
void hideCursor(); // 隐藏光标
void shiftLeftDisplay(); // 左移显示内容
void shiftRightDisplay(); // 右移显示内容
void shiftLeftCursor(); // 左移光标
void shiftRightCursor(); // 右移光标
void setBrightLevel(char level); // 设置亮度,共有四级:0 级最亮,4 级最暗
void putChar(char ch, char row = -, char col = -); // 于指定位置显示指定字符,不指定位置则在当前位置显示
void print(char *str, char row = -, char col = -); // 于指定位置显示指定字符串,不指定位置则在当前位置显示
}; #endif

类实现文件:

// ----------------------------------------------------------------------------
// driverHT16514Parallel.cpp
//
// Created 2015-07-04
// By seesea <seesea2517#gmail#com>
//
// HT16514 并行驱动
// 根据当前需要只实现部分功能
// ---------------------------------------------------------------------------- #include "driverHT16514Parallel.h" const byte HT16514Parallel::dataPinMask[] = { 0x80, 0x40, 0x20, 0x10 }; // 构造函数
HT16514Parallel::HT16514Parallel(char _RW, char _E, char _RS)
{
RW = _RW;
E = _E;
RS = _RS; init();
} // 构造函数,使用四位并行方式,用指定的四个引脚来做数据输出
HT16514Parallel::HT16514Parallel(char _RW, char _E, char _RS, char D7, char D6, char D5, char D4)
{
RW = _RW;
E = _E;
RS = _RS; dataPins[] = D7;
dataPins[] = D6;
dataPins[] = D5;
dataPins[] = D4; init();
} // 发送命令给 HT16514
void HT16514Parallel::sendCommand(byte cmd)
{
char i; digitalWrite(RS, LOW);
digitalWrite(RW, LOW); if (dataLength == )
{
digitalWrite(E, HIGH);
DATA_PORT = cmd;
digitalWrite(E, LOW);
}
else
{
// 先写高四位
digitalWrite(E, HIGH);
for (i = ; i < ; ++i)
{
digitalWrite(dataPins[i], ((dataPinMask[i] & cmd) ? HIGH : LOW));
}
digitalWrite(E, LOW); // 低四位移高四位后,同上操作
cmd <<= ;
digitalWrite(E, HIGH);
for (i = ; i < ; ++i)
{
digitalWrite(dataPins[i], ((dataPinMask[i] & cmd) ? HIGH : LOW));
}
digitalWrite(E, LOW);
}
} // 发送数据给 HT16514
void HT16514Parallel::sendData(byte data)
{
char i; digitalWrite(RS, HIGH);
digitalWrite(RW, LOW); if (dataLength == )
{
digitalWrite(E, HIGH);
DATA_PORT = data;
digitalWrite(E, LOW);
}
else
{
// 先写高四位
digitalWrite(E, HIGH);
for (i = ; i < ; ++i)
{
digitalWrite(dataPins[i], ((dataPinMask[i] & data) ? HIGH : LOW));
}
digitalWrite(E, LOW); // 低四位移高四位后,同上操作
data <<= ;
digitalWrite(E, HIGH);
for (i = ; i < ; ++i)
{
digitalWrite(dataPins[i], ((dataPinMask[i] & data) ? HIGH : LOW));
}
digitalWrite(E, LOW);
}
} // 初始化
void HT16514Parallel::init(char dl)
{
pinMode(RW, OUTPUT);
pinMode(E, OUTPUT);
pinMode(RS, OUTPUT); if (dl == )
{
DDR_PORT = 0xFF;
}
else
{
for (char i = ; i < ; ++i)
{
pinMode(dataPins[i], OUTPUT);
}
} dataLength = dl;
rowNumber = ; // 针对当前的 1602 vfd 直接写 2 了,以后有需要再加扩展 curRow = ;
curCol = ; initDisplay();
} // 初始关闭闪烁和光标显示(这也是reset后的状态)
void HT16514Parallel::initDisplay()
{
isDisplayOn = true;
isBlink = false;
isShowCursor = false; // 如果是四位模式,则需要手工设置。因为默认是八位
// 并且由于初始时是八位模式,所以要先按八位发命令设置四位模式
if (dataLength == )
{
byte cmd = 0x20; if (rowNumber == )
cmd |= 0x08; // 临时设置为八位发送设置四位的命令
dataLength = ;
sendCommand(cmd);
dataLength = ;
} moveCursorHome();
displayOn(); // 开启显示,关闭闪烁和光标显示
} // 清屏
void HT16514Parallel::clear()
{
sendCommand(0x00);
} // 移动光标到左上角
void HT16514Parallel::moveCursorHome()
{
curRow = ;
curCol = ; sendCommand(0x02);
} // 开显示
void HT16514Parallel::displayOn()
{
byte cmd = 0x08; isDisplayOn = true; if (isDisplayOn)
cmd |= 0x04; if (isBlink)
cmd |= 0x01; if (isShowCursor)
cmd |= 0x02; sendCommand(cmd);
} // 关显示
void HT16514Parallel::displayOff()
{
byte cmd = 0x08; isDisplayOn = false; if (isDisplayOn)
cmd |= 0x04; if (isBlink)
cmd |= 0x01; if (isShowCursor)
cmd |= 0x02; sendCommand(cmd);
} // 光标开闪烁
void HT16514Parallel::blinkOnCursor()
{
byte cmd = 0x08; isBlink = true; if (isDisplayOn)
cmd |= 0x04; if (isBlink)
cmd |= 0x01; if (isShowCursor)
cmd |= 0x02; sendCommand(cmd);
} // 光标关闪烁
void HT16514Parallel::blinkOffCursor()
{
byte cmd = 0x08; isBlink = false; if (isDisplayOn)
cmd |= 0x04; if (isBlink)
cmd |= 0x01; if (isShowCursor)
cmd |= 0x02; sendCommand(cmd);
} // 开光标
void HT16514Parallel::showCursor()
{
byte cmd = 0x08; isShowCursor = true; if (isDisplayOn)
cmd |= 0x04; if (isBlink)
cmd |= 0x01; if (isShowCursor)
cmd |= 0x02; sendCommand(cmd);
} // 关光标
void HT16514Parallel::hideCursor()
{
byte cmd = 0x08; isShowCursor = false; if (isDisplayOn)
cmd |= 0x04; if (isBlink)
cmd |= 0x01; if (isShowCursor)
cmd |= 0x02; sendCommand(cmd);
} // 左移显示内容
void HT16514Parallel::shiftLeftDisplay()
{
sendCommand(0x18);
} // 右移显示内容
void HT16514Parallel::shiftRightDisplay()
{
sendCommand(0x1C);
} // 左移光标
void HT16514Parallel::shiftLeftCursor()
{
sendCommand(0x10);
} // 右移光标
void HT16514Parallel::shiftRightCursor()
{
sendCommand(0x14);
} // 设置亮度,共有四级:0 级最亮,4 级最暗
void HT16514Parallel::setBrightLevel(char level)
{
byte cmd = 0x20; if (level < || level > )
return; if (dataLength == )
cmd |= 0x10; if (rowNumber == )
cmd |= 0x08; cmd |= level; sendCommand(cmd);
} // 于指定位置显示指定字符,若未指定位置则以当前位置显示
void HT16514Parallel::putChar(char ch, char row, char col)
{
byte cmd = 0x80;
char pos = ;
bool isCtrlChar = false; switch(ch)
{
case '\r': curCol = ; isCtrlChar = true; break;
case '\n': ++curRow; isCtrlChar = true; break;
case '\b': --curCol; isCtrlChar = true; break;
case '\t': curCol += ; isCtrlChar = true; break;
case '\0': return;
default : break;
}; if (isCtrlChar)
{
pos = 0x40 * curRow + curCol;
sendCommand(cmd | pos);
return;
} if (row >= && col >= )
{
pos = 0x40 * row + col; sendCommand(cmd | pos); curRow = row;
curCol = col;
} sendData(ch);
++curCol;
} // 于指定位置显示指定字符串,若未指定位置则以当前位置显示
void HT16514Parallel::print(char *str, char row, char col)
{
char *p = str; putChar(*p, row, col);
for (p = str + ; *p != '\0'; ++p)
{
putChar(*p);
}
}

arduino 测试程序:

// ----------------------------------------------------------------------------
// vfdHT16514Parallel.ino
//
// Created 2015-07-04
// By seesea <seesea2517#gmail#com>
//
// HT16541 VFD 驱动测试程序
// ----------------------------------------------------------------------------
#include "driverHT16514Parallel.h" #define RW 10
#define E 9
#define RS 8 HT16514Parallel vfd(RW, E, RS, , , , );
// HT16514Parallel vfd(RW, E, RS); void setup()
{
vfd.clear();
vfd.moveCursorHome();
vfd.setBrightLevel();
vfd.print("Have a good day!", , );
vfd.print("09:45:00", , );
} void loop()
{
static unsigned char sec = ;
char str[]; sprintf(str, "%02d", sec);
vfd.print(str, , );
delay();
sec = (sec + ) % ;
}

显示效果

从零开始写驱动——vfd专用驱动芯片HT16514并行驱动程序编写
上一篇:用Java发起HTTP请求与获取状态码(含状态码列表)


下一篇:《Java设计模式》之代理模式 -Java动态代理(InvocationHandler) -简单实现