近日做一个小项目,要用到3位双色数码管。马云家双色数码管品种不多,受客观条件限制选择一款0.8吋双色数码管,其产品只有共阳没有阴。3位双色数码管按6位算选择驱动芯片TM1639。硬件电路设计好后着手写代码。此时发现TM1639驱动共阳数码管有点麻烦,遂想在网上搜索案例参考。不料TM1639驱动共阳数码管案例极其匮乏。天微公司网站也不提供示例代码。只得根据产品手册自己写驱动代码。项目现已完成。经整理将TM1639驱动共阳数码管的C代码选出写一个示例以飨坛友。
- //测试MCU型号:STC8G1K08A-8PIN
- #include <STC8G.H>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit DIO=P3^3;//数据口
- sbit CLK=P5^4;//时钟口
- sbit SBT=P5^5;//片选口
- uchar code table[]={//共阴数码管段码"0~f-."
- 0x3f,0x06,0x5b,0x4f,
- 0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,
- 0x39,0x5e,0x79,0x71,0x40,0x80};
- uchar data dis_buf[8]; //数码管缓存数组
- uchar data doc_buf[3]; //数据分解缓存数组
- uchar bright=5;//亮度0~7
- uchar Key_value;//键值
- uchar num; //计数
- uint count;//计数
- void Delay1us(uchar i)//延时函数us @12.000MHz
- {
- i*= 2;
- while(--i);
- }
- void Delay_ms(uint t)//1T@12MHz
- {
- uint i,j;
- for(i=t;i>0;i--)
- for(j=1200;j>0;j--);
- }
- void Write_TM1639_date(uchar date)//写数据到TM1639,由低位到高位
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- CLK=0;
- if((date & 0x01) !=0)
- DIO=1;
- else
- DIO=0;
- _nop_();_nop_();
- CLK=1;
- date=date>>1;
- }
- }
- char Read_TM1639_date()//读取TM1639数据,由低位到高位
- {
- uchar i,date;
- DIO=1;
- for(i=0;i<8;i++)
- {
- CLK=0;
- date=date>>1;
- CLK=1; //送时钟的上升沿
- if(!DIO)date=date & 0x7f;
- else date=date | 0x80;
- }
- return date;
- }
- /******************************************************/
- //指令格式
- //指令 空位 正常/测试模式 自加/固定地址 读/写模式
- // 01 00 0/1 0/1 10/00
- //
- //指令 空位 开/关显示 亮度等级
- // 10 00 1/0 000/111
- //
- //指令 空位 显示地址
- // 11 00 0000/1111
- //
- //指令 空位 数据低4位/ 高4位 先传低4位,后传高4位
- // 00 00 0000xxxx/0000xxxx x=有效数据
- /*******************************************************/
- void Init_TM1639()//初始化TM1639
- {
- uchar i;
- SBT=0;
- Write_TM1639_date(0x40);//普通模式、自增地址、写模式
- SBT=1;
- SBT=0;
- Write_TM1639_date(0xc0);//显示地址
- for(i=0;i<16;i++)//16个显示寄存器的所有低4位有效,高4位无效
- Write_TM1639_date(0x00);//显示内容(清显存)
- SBT=1;
- SBT=0;
- Write_TM1639_date(0x88+bright);//开显示、0~7级亮度
- SBT=1;
- }
- char Scan_TM1639_Key()//扫描1639按键函数
- {
- uchar rekey,H_key,L_key;
- SBT=0;
- Write_TM1639_date(0x42); //写入读按键命令 0100 0010
- Delay1us(5);//小延时
- DIO=1;
- L_key=Read_TM1639_date();
- Delay1us(5);//小延时
- H_key=Read_TM1639_date();
- SBT=1;
- rekey=H_key<<4|L_key;//合并8位有效键值
- return rekey; //返回键值
- }
- void key_service() //按键服务函数
- {
- static uint time=0; //消抖计数变量
- static bit sign_Key=0; //按键状态标志
- uchar Key_value;
- Key_value=Scan_TM1639_Key(); //读取键值
- if(Key_value==0x80||Key_value==0x08) //有按键按下
- {
- if(++time>=10 && sign_Key==0)//消抖
- {
- sign_Key=1; //按键状态标志置1
- if(Key_value==0x80)
- {
- if(bright<7)bright++; //亮度+
- }
- if(Key_value==0x08)
- {
- if(bright>0)bright--; //亮度-
- }
- SBT=0;
- Write_TM1639_date(0x88+bright);//刷新亮度设置
- SBT=1;
- }
- }
- else //松手
- {
- sign_Key=0; //按键状态标志清0
- time=0; //计数变量清0
- }
- }
- //用于共阴码转换为共阳管显示 即 SEG接位选 GRID接段选。
- //共阴数码管段码的8个位拆解分别存入8个TM1639显示寄存器的同一位。
- //所以要正确显示需要8个8位二进制的数中各取同一位来显示一个数。
- void data_split(uchar s) //数据处理函数
- {
- uchar i,j;
- doc_buf[0]=table[s/100%10];//百位
- doc_buf[1]=table[s/10%10]; //十位
- doc_buf[2]=table[s%10]; //个位
- doc_buf[3]=table[0]; //显示"0"
- doc_buf[4]=table[0];
- doc_buf[5]=table[0];
- doc_buf[6]=table[0];
- doc_buf[7]=table[0];
- for(j=0;j<8;j++)
- {
- for(i=0;i<8;i++)
- {
- dis_buf[i]|=((doc_buf[j]&0x01)<<j);
- doc_buf[j]>>=1;
- }
- }
- }
- void display_TM1639()//显示函数
- {
- uchar i;
- SBT=0;
- Write_TM1639_date(0xc0);//显示寄存器首地址
- for(i=0;i<8;i++)
- {
- Write_TM1639_date(dis_buf[i]&0x0f);//低位地址
- Write_TM1639_date(dis_buf[i]>>4&0x0f);//高位地址
- }
- SBT=1;
- }
- void main(void)
- {
- P3M0 = 0x00; //P3准双向
- P3M1 = 0x00;
- P5M0 = 0x00; //P5准双向
- P5M1 = 0x00;
- Init_TM1639(); //初始化TM1639
- while(1)
- {
- if(++count>=1000)//约1秒
- {
- count=0;
- num++;
- }
- data_split(num);//数据处理函数
- display_TM1639();//显示函数
- key_service(); //读键函数
- Delay_ms(1); //延时控制主循环周期约1ms
- }
- }
复制代码
|