近日,“嫁接”了個VFD和TM1638的程序,想驅動4位(加冒號)的數碼管,顯示個時鐘,結果功能正常(暫時未加冒號顯示部分),可看到走時,但顯示有時關閉(沒顯示),有時顯示中不停、無規律閃爍。求助走過路過的給看看,是何原因?
單片機程序如下:
/************************************
20200405 嫁接了個原來顯示正常的VFD程序,結果走時正常,但無規律閃爍
*******************************/
#include "REG52.H"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define T100us (256-134)
unsigned char day,hour, minute, second;
unsigned int c100us;
#define const_time_05s 6880 //0.5秒鐘的時間需要的定時中斷次數 6881,15小時慢3秒
#define DATA_COMMAND 0X40
#define DISP_COMMAND 0x80
#define ADDR_COMMAND 0XC0
//TM1638模塊引腳定義
sbit DIO=P0^0;
sbit CLK=P0^1;
sbit STB=P0^2;
void initial_myself(); //三區之:一區 系統自身變量;
void delay_long(unsigned int uiDelaylong); //一線
void T0_time(); //定時中斷函數
//共陰數碼管顯示代碼
unsigned char code shuzi[]={0x7b,0x18,0x6d,0x3d,0x1e,0x37,0x77,0x19,0x7b,0x3f}; //0-9
void TM1638_Write(unsigned char DATA) //寫數據函數
{
unsigned char i;
for(i=0;i<8;i++)
{
CLK=0;
if(DATA&0X01)
DIO=1;
else
DIO=0;
DATA>>=1;
CLK=1;
}
}
unsigned char TM1638_Read(void) //讀數據函數
{
unsigned char i;
unsigned char temp=0;
DIO=1; //設置為輸入
for(i=0;i<8;i++)
{
temp>>=1;
CLK=0;
if(DIO)
temp|=0x80;
CLK=1;
}
return temp;
}
void Write_COM(unsigned char cmd) //發送命令字
{
STB=0;
TM1638_Write(cmd);
STB=1;
}
void Write_DATA(unsigned char add,unsigned char DATA) //指定地址寫入數據
{
Write_COM(0x44);
STB=0;
TM1638_Write(0xc0|add);
TM1638_Write(DATA);
STB=1;
}
//20200405
void write_TM1638(uchar w,uchar dat) //(Wλ:0-7 ,dat????)
{
uchar wei[]={0x00,0x02,0x04,0x06,}; //0x08,0x0a,0x0c,0x0e,這是原程序8個數碼管的
Write_DATA(wei[w],dat);
}
/**************
//清TM1638
//
void clr_tm1638()
{
uchar i;
Write_COM(0x40);
STB=0;
TM1638_Write(0xc0);
for(i=0;i<16;i++)TM1638_Write(0x00);
STB=1;
}
**************/
//TM1638初始化函數
void init_TM1638(void)
{
unsigned char i;
Write_COM(0x8b); //亮度 (0x88-0x8f)8級亮度可調
Write_COM(0x40); //采用地址自動加1
STB=0; //
TM1638_Write(0xc0); //設置起始地址
for(i=0;i<16;i++) //傳送16個字節的數據
TM1638_Write(0x00);
STB=1;
}
void main()
{
initial_myself();
delay_long(100);
while(1)
{
write_TM1638(3,shuzi[minute%10]);
write_TM1638(0,shuzi[minute/10]);
write_TM1638(1,shuzi[hour%10]);
write_TM1638(2,shuzi[hour/10]);
}
}
void T0_time() interrupt 1
{
c100us--; //c100us;主程序void main()里有此句,減一后if判斷是否為“0”
//不為零繼續減一
if(c100us==0) //為零執行下面{}
{
c100us=const_time_05s; //因為已經見到零,所以進來先重裝數tick=7554
second++; //秒加一
if(second==60) //判斷加一后second=60不,若不等跳出執行前面c100us--;若等于60了,進入下面{}
{
second=0; //因為已經見到60,所以清零
minute++; //到了60秒,就分加一
if(minute==60) //判斷加一后minute=60不,若不等跳出執行前面c100us--;若等于60了,進入下面{}
{
minute=0;
hour++;
if(hour==24)
{
hour=0;
day++;
if(day==8)
{
day=1;
}
}
}
}
}
}
void delay_long(unsigned int uiDelayLong)
{
unsigned int i;
unsigned int j;
for(i=0;i<uiDelayLong;i++)
{
for(j=0;j<500;j++) //內嵌循環的空指令數量
{
; //一個分號相當于執行一條空語句
}
}
}
void initial_myself()
{
TMOD=0x02; //設置定時器0為工作方式2
TH0=T100us;
TL0=T100us;
init_TM1638(); //ET16311_Init();
init_TM1638(); //ET16311_Init();
day=4;
hour=10;
minute=50;
second=0;
c100us=const_time_05s;
EA=1; //開總中斷
ET0=1; //允許定時中斷
TR0=1; //啟動定時中斷
}
|