资源上来说,第二种方式比第一种方式会占用更少的 ROM 空间。
应用电路
可以根据实际使用情况取舍 COM 和增减 SEG,比如 LCD 可以是 1/2 Duty,那么只需要保留两个 COM 即可,SEG 同样可以参照范例程序扩展。
根据上述说明,分 8 次依次设置 COM0~COM3 的输出,SEG 是输出 VDD 还是输出 VSS 需要根据要显示的数字判断,使用第一种驱动方式时 I/O 详细电位设置请参考下表:
这里也可以采用扫描的方式
结论
本范例驱动 4×8 LCD 显示正常,用户只需要稍加改造即可套用到所选用的 1/2 Bias 规格的LCD 上。
我使用的是第一种扫描方式,大致流程图如下,其中有些地方对的不怎么齐
void LCD_Control(void)
{
static unsigned char state = 0;
if(!Back_Light_Is_Open) // 背光检测
{
P1CFG1 = _b01101010; // 配置COM1,COM2,COM3为高阻
P3CFG0 = _b01010110; // 配置COM4为高阻
return;
}
LCD_BACK_LIGHT_CONTROL(); // 背光控制
Refresh_Wrod(); // 刷新字幕
Refresh_Light_Flash(); // 刷新灯光动画
Refresh_Fan_Flash(); // 刷新风扇动画
Refresh_UV_Lamp_Flash();// 刷新消毒动画
Refresh_Down_Flash(); // 刷新下降动画
Refresh_Up_Flash(); // 刷新上升动画
switch(state)
{ // 01强推,10高阻
case 0: // 扫描 COM1
{
COM_L(1);
P1CFG1 = _b01100110; // 配置COM1为强推,COM2,COM3为高阻
P3CFG0 = _b01010110; // 配置COM4为高阻
COM1_SEG_SET();
state = 1;
}break;
case 1: // 扫描 COM1
{
COM_H(1);
COM1_SEG_SET_NOT();
state = 2;
}break;
case 2: // 扫描 COM2
{
COM_L(2);
P1CFG1 = _b01101001; // 配置COM2为强推,COM1,COM3为高阻
COM2_SEG_SET();
state = 3;
}break;
case 3: // 扫描 COM2
{
COM_H(2);
COM2_SEG_SET_NOT();
state = 4;
}break;
case 4: // 扫描 COM3
{
COM_L(3);
P1CFG1 = _b01011010; // 配置COM3为强推,COM1,COM2为高阻
COM3_SEG_SET();
state = 5;
}break;
case 5: // 扫描 COM3
{
COM_H(3);
COM3_SEG_SET_NOT();
state = 6;
}break;
case 6: // 扫描 COM4
{
COM_L(4);
P1CFG1 = _b01101010; // 配置COM1,COM2,COM3为高阻
P3CFG0 = _b01010101; // 配置COM4为强推
COM4_SEG_SET();
state = 7;
}break;
case 7: // 扫描 COM4
{
COM_H(4);
COM4_SEG_SET_NOT();
state = 0;
}break;
default:
{
state = 0;
}break;
}
}
代码中 COM4_SEG_SET_NOT(); 是 COM4_SEG_SET(); IO对应段取反所得
COM_L(4); 拉低 COM4口
其他类似
|
这里说明一点,我是先将 IO口电平输出再配置功能的,因为在实际操作过程中会发现从高阻态转换至强推模式时会有 零点几微秒的脉冲干扰,具体宽度根据单片机速度来决定。
大概是因为单片机在从强推模式转换至高阻态时 IO配置虽被改变,但输出寄存器中的数据还会继续保持,所以才会有脉冲干扰的吧,先将 IO口输出电平改变再将 IO口状态从高阻切换至强推时就不会有脉冲干扰了
这是先配置 IO输出状态再修改输出电平的,后来想了下,寄存器中应该是保存了最后一次 IO输出的电平,所以从高阻态切换至强推后直接将输出相应的电平,等到再次配置 IO口输出的电平时这是才会改变,所以才会在开始的时候有一个低脉冲