基于CS16312控制芯片的VFD显示屏STC51单片机驱动程序

/*
    CS16312作为主控芯片的 VFD 显示屏驱动程序


    Coder   : Farman
    Version : 2018-01-07
*/ 




#include <STC89C5xRC.H>
#include "Delay.h"


sbit CS16312_SDA     = P2^0; // SPI 数据线
sbit CS16312_SCLK    = P2^1; // SPI 串行时钟
sbit CS16312_STB     = P2^2; // 片选信号,0-不选 1-选中。


#define CS16312_SDA_HIGH  1
#define CS16312_SCLK_HIGH 1
#define CS16312_STB_HIGH  1


//--------------------------------------------------------




void CS16312_delay()
{
    nop_();
    //Delay1ms();
}




//----------------------------------------------------------




void CS16312_enable()
{
    CS16312_STB  = !CS16312_STB_HIGH; 
    CS16312_delay();
}


void CS16312_disable()
{
    CS16312_STB = CS16312_STB_HIGH;
    CS16312_delay();
}


void CS16312_write_byte(unsigned char byte_to_write)
{
    unsigned char mask = 0x01;
    unsigned char n;


    for(n=0; n<8; n++)
    {
        CS16312_SCLK =!CS16312_SCLK_HIGH;
        CS16312_delay();

        CS16312_SDA = (mask & byte_to_write) ? 1 : 0; CS16312_delay();

        CS16312_SCLK = CS16312_SCLK_HIGH; 
        CS16312_delay();


        mask += mask;
    }


    return;
}




void CS16312_write_command_byte(unsigned char command_byte)
{
    CS16312_enable();
    CS16312_write_byte(command_byte);
    CS16312_disable();
}




//----------------------------------------------------------




// digits_could_display : 8 - 16
// 命令前必须有一次 STB 有效,
// 命令后必须有一次 STB 释放。
void CS16312_command1(unsigned char digits_could_display)
{
    CS16312_write_command_byte(digits_could_display - 4);
}


// 命令前必须有一次 STB 有效,
// 命令后必须有一次 STB 释放。
void CS16312_command2(bit enable_inc_addr_after_write)
{
    unsigned char command = 0x40;


    command += enable_inc_addr_after_write ? 0x00 : 0x04;
    CS16312_write_command_byte(command);  
}




// addr : 0x00 - 0x15
// 该命令后面要紧跟写入显示RAM的数据,且该命令与数据之间不允许有 STB 释放操作
// 数据与数据之间也不允许有 STB 释放。
// 
// 所以,在该命令前要 调用一次 CS16312_enable()
// 所有的显示RAM传输结束后,调用一次 CS16312_disable().
void CS16312_command3(unsigned char RAM_addr_to_write)
{
    CS16312_write_byte(0xC0 + RAM_addr_to_write);
}


// 命令前必须有一次 STB 有效,
// 命令后必须有一次 STB 释放。
// bright : 0 - 7
void CS16312_command4(bit enable_display, unsigned char bright)
{
    CS16312_write_command_byte((enable_display ? 0x88 : 0x80) + bright);
}




//----------------------------------------------------------




void CS16312_write_display_RAM(unsigned char addr, unsigned char display_data_byte)
{
    CS16312_enable();
    CS16312_command3(addr);
    CS16312_write_byte(display_data_byte);
    CS16312_disable();
}


void CS16312_fill_display(unsigned char pattern)
{
    unsigned char m;


    CS16312_command2(1);


    CS16312_enable();
    CS16312_command3(0);


    for(m=0x00; m<0x16; m++)
    {
        CS16312_write_byte(pattern);
    }


    CS16312_disable();
}




//----------------------------------------------------------


code unsigned char CS16312_8seg_digit[] = 
{
    0x77, 0x24, 0x6B, 0x6D, 0x3C, 0x5D, 0x5F, 0x64, 0x7F, 0x7D
};




// pos 0-6 digit:0-9
// 因为倒数第2个数字的段码与其他的不同,需要单独处理。此处未处理。
// 在 CS1632_show_byte_as_BCD 中进行了处理
void CS16312_show_8seg_digit(unsigned char pos, unsigned char digit, bit with_dot)
{
    if(pos == 2 || pos == 4)
    {
        CS16312_write_display_RAM(6-pos, CS16312_8seg_digit[digit] + (with_dot ? 0x80 : 0x00));
    }
    else
    {
        CS16312_write_display_RAM(6-pos, CS16312_8seg_digit[digit]);
    }
}


code unsigned char CS16312_special_digit[] = 
{
    0x77, 0x24, 0x6B, 0x6D, 0x3C, 0x5D, 0x5F, 0x64, 0x7F, 0x7D
};


// pos 0-3 BCD:0x00-0x99
void CS1632_show_byte_as_BCD(unsigned char pos, unsigned char bcd, bit with_dot)
{
    if(pos == 0)
    {
        CS16312_show_8seg_digit(0, bcd&0x0F, 0);
    }
    else if(pos == 3)
    {  
        // 写右边起第2个数字
        CS16312_write_display_RAM(1, CS16312_special_digit[bcd>>4]>>1);


        // 写右边起第1个数字
        CS16312_write_display_RAM(0, (CS16312_special_digit[bcd>>4] & 0x01) ? 
        (CS16312_8seg_digit[bcd&0x0F] | 0x80) : (CS16312_8seg_digit[bcd&0x0F] | 0x00));
    }
    else
    {
        CS16312_show_8seg_digit(2*pos-1, bcd>>4, with_dot);
        CS16312_show_8seg_digit(2*pos, bcd&0x0F, with_dot);
    }
}




void CS16312_show_disk(unsigned int pattern)
{
    CS16312_write_display_RAM(8, pattern>>8);
    CS16312_write_display_RAM(9, pattern>>8);
}


//----------------------------------------------------------


void CS16312_init()
{
    CS16312_disable();
    CS16312_SCLK = 0;
    CS16312_SDA  = 1;


    Delay200ms();


    CS16312_command1(5);
    CS16312_command2(1);
    CS16312_fill_display(0xFF);
    CS16312_command4(1, 3);
}




//----------------------------------------------------------




void CS16312_main()  
{
    unsigned char m, n, seg;


    CS16312_init();
    CS16312_fill_display(0xFF); Delay200ms();
    CS16312_fill_display(0x00); Delay200ms();
    CS16312_fill_display(0xFF); Delay200ms();
    CS16312_fill_display(0x00); Delay200ms();
    CS16312_fill_display(0xFF); Delay200ms();
    CS16312_fill_display(0x00); Delay200ms();


    while(0)
    {
        CS16312_show_disk(0x5555); Delay200ms();
        CS16312_show_disk(0xAAAA); Delay200ms();
    }


    while(1)
    {
        seg = 0x01;


        for(m=0; m<10; m++)
        {
            CS1632_show_byte_as_BCD(0, m*0x11, 1); 
            CS1632_show_byte_as_BCD(1, m*0x11, 1); 
            CS1632_show_byte_as_BCD(2, m*0x11, 1); 
            CS1632_show_byte_as_BCD(3, m*0x11, 1);


            Delay1s();
        } 

        Delay1s();
    }  
}














 

前言: 今天的主角其实是好多朋友都应该已经熟悉的8位米字VFD显示屏,由YLEEE老板一年前“隆重”推出,期间很多朋友都做过,各种各样的实现和驱动方法都有,这里我就不做评价。我的主要思路是:简单、可靠,有专门驱动就用专门驱动,当然最重要的是要时间精准:1、和我之前的同步母钟同步(推荐)2、使用GPS模块校时。 八位米字VFD显示屏实物截图: 这个屏从图片上可以看出,做时钟屏是非常合适的,唯一的缺点就是稍微小点,不过瑕不掩瑜,量多价优呀! 尺寸图: 先说说规划的功能和特点: 1、从上面数据手册可以知道,这个屏是8位16段,使用PT6311可以了,专用芯片稳定、可靠、驱动效果好,这是我的一贯的原则,大家也可以使用几十个三极管做动态扫描驱动,反正是折腾,咋么搞亮都行; 2、还是使用绕制的高频变压器做灯丝、负压、隔离电源,优点:简单、稳定、可靠,灯丝交流、负压一次产生,不需要再利用系统其它资源。缺点:变压器虽然是EE13,可也不能能做的超薄; 3、3组硬件自动开关机,这个我之前的很多时钟上面都有。就是可以设置几组自动开 关时间,控制VFD 的灯丝、负压电源,做到节能,延长屏寿命; 4、3组闹钟,每组可单独设置开启、关闭,闹铃响铃长度1-99秒,周末闹铃是否开启; 5、星期是程序根据年月日自动计算的,不需要设置; 6、12小时/24小时时间显示模式选择;(遥控器上F1快捷功能有效) 7、温度显示;(遥控器上TEMP快捷功能有效) 8、日期 星期显示;(遥控器上DATE快捷功能有效) 9、固定显示时间/或者循序显示:时间1分钟-星期、日期显示5秒、温度显示5秒,2种显示模式可选。(遥控器上F2快捷功能有效) 10、光控自动调节或手动亮度调节,1-8级,设置00就是光控自动调节。自动开关机时段,也能手动或自动亮度控制; 11、红外遥控功能,也带红外学习功能,可以使用你自己的遥控器学习、控制; 12、有DS1302实时时钟芯片(正宗的能弄到只有拆机的了),外接正品日本KDS 5ppm晶振(这个好不容易找工厂朋友弄到,厂家仪表进行过筛选) 13、母钟的同步子钟/GPS同步时钟/普通时钟,大家可以根据自己的需要,选择不同的功能应用; 子母钟同步时,可以使用我之前介绍的2种,具体可参考之前的文章: https://www.yeyudo.cn/article.asp?id=254 https://www.yeyudo.cn/article.asp?id=259 https://www.yeyudo.cn/article.asp?id=260 8位米字VFD屏制作的同步子钟/GPS时钟电路设计包括MCU控制板+驱动板2部分。 见PCB实物截图: 实物购买链接:https://item.taobao.com/item.htm?spm=2013.1.0.0.lJN4W6&id=15071361340
通用VFD显示模块的设计原理说明与制作过程讲解,展示如何在业余条件下完成一个通用的VFD显示模块的设计与制作过程。 制作特点 使用大尺寸的优质VFD显示屏,屏幕包含9位带小数点、逗号及下指针的标准8字笔段结构字符,通用性强,可以取代大部分LED数字显示屏模块; 使用无变压器的驱动电路,板上电路独立完交流灯丝电压与负高压驱动阳极与栅极,符合VFD驱动规范,显示效果优良无闪烁; 全板采用全贴片零件制作,所有零件全部藏于显示屏下方机,实现了超薄外观; 模块主设计使用单片机驱动方案,板上自带的单片机不仅可以完成各驱动功能,同时也具备了模块自检功能,可在无外部单片机驱动的情况下,自主完成自检显示; 程序已经预写入单片机内,用户无需配备专用的写入器设备。模块制作容易,调试简单,仅需配备普通万用表即可,适合初级电子爱好者自制; 公开源码的Arduino驱动程序,仅需添加几行应用代码即可实现显示显示过程中不消耗单片机资源,简单易用;源码使用纯C语言编写,移植简单,完全可支持51、STM等单片机; 所有接口引线全部通过插针引出,可选择单排针或双排针连接方式。模块与单片机的接口引线仅3根,节约单片机I/O口资源。 模块与ARDUINO UNO线路连接图 模块焊接对照图 ARDUINO VFD显示模块演示视频 电路城语:免费分享设计资料,不提供技术支持,请大家使用前验证资料的正确性! 附件包含以下资料: 模块电路图 模块焊接对照图 BOM元件表 INRC09SS49T ARDUINO VFD显示模块源代码 通用VFD显示模块设计原理说明 亚克力外壳设计文件(其中边条部分请使用2.8mm厚度的亚克力板激光切割,上下板及边板使用1.8mm厚度的亚克力板激光切割。组装请使用M2螺丝与螺母)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值