#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
}
}
|