|
用了5個74hc595芯片級聯,控制27位數碼管,數碼管閃爍,懷疑是寫入74HC595數據的時間太長導致的,現在很怕是本來硬件設計的缺陷。
我的程序大概是這樣的,先用定時器0來計時,再用定時器1來刷新數碼管的刷新,因為用到5塊595芯片,所以寫了一個函數來寫入595的數據,高32位是位選,低八位是段選。
數碼管顯示單片機程序:
#include "display.h"unsigned char code leddata[]={
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40
};/*數碼管顯示數字0,1,2,3,4,5,6,7,8,9,-*/
unsigned char LEDBuf[] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7};//數據顯示緩沖區
unsigned long code PLACE_CODE[] =
{0xFFFFFFFE,0xFFFFFFFD,0xFFFFFFFB,0xFFFFFFF7,0xFFFFFFEF,0xFFFFFFDF,0xFFFFFFBF,0xFFFFFF7F,0xFFFFFEFF,0xFFFFFDFF,0xFFFFFBFF,0xFFFFF7FF,0xFFFFEFFF,0xFFFFDFFF,0xFFFFBFFF,0xFFFF7FFF,0xFFFEFFFF,0xFFFDFFFF,0xFFFBFFFF,0xFFF7FFFF,0xFFEFFFFF,0xFFDFFFFF,0xFFBFFFFF,0xFF7FFFFF,0xFEFFFFFF,0xFDFFFFFF,0xFBFFFFFF}
;// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 位選信號1-27位數碼管
unsigned char digdot0 = 0,digdot1 = 0,digdot2 = 0,digdot3 = 0;//小數點控制變量
unsigned char digdot4 = 0,digdot5 = 0,digdot6 = 0,digdot7 = 0;
void Display()
{
static unsigned char i = 0;//靜態變量,只會賦值一次
unsigned char temp;
switch(i) //逐位輸入數據
{
case 0:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[0]];
if(digdot0 == 1)
{
temp = leddata[LEDBuf[0]] | 0x80; //控制小數點閃爍
}
led_hc595_drive(PLACE_CODE[0],temp);//高位字節是位選 低位字節是斷碼
led_hc595_off(0x00);
i++;
break;
case 1:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[1]];
if(digdot1 == 1)
{
temp = leddata[LEDBuf[1]] | 0x80;
}
led_hc595_drive(PLACE_CODE[1],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 2:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[2]];
if(digdot2 == 1)
{
temp = leddata[LEDBuf[2]] | 0x80;
}
led_hc595_drive(PLACE_CODE[2],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 3:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[3]];
if(digdot3 == 1)
{
temp = leddata[LEDBuf[3]] | 0x80;
}
led_hc595_drive(PLACE_CODE[3],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 4:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[4]];
if(digdot4 == 1)
{
temp = leddata[LEDBuf[4]] | 0x80;
}
led_hc595_drive(PLACE_CODE[4],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 5:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[5]];
if(digdot5 == 1)
{
temp = leddata[LEDBuf[5]] | 0x80;
}
led_hc595_drive(PLACE_CODE[5],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 6:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[6]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[6]] | 0x80;
}
led_hc595_drive(PLACE_CODE[6],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 7:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[7]];
if(digdot7 == 1)
{
temp = leddata[LEDBuf[7]] | 0x80;
}
led_hc595_drive(PLACE_CODE[7],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 8:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[8]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[8]] | 0x80;
}
led_hc595_drive(PLACE_CODE[8],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 9:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[9]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[9]] | 0x80;
}
led_hc595_drive(PLACE_CODE[9],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 10:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[10]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[10]] | 0x80;
}
led_hc595_drive(PLACE_CODE[10],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 11:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[11]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[11]] | 0x80;
}
led_hc595_drive(PLACE_CODE[11],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 12:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[12]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[12]] | 0x80;
}
led_hc595_drive(PLACE_CODE[12],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 13:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[13]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[13]] | 0x80;
}
led_hc595_drive(PLACE_CODE[13],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 14:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[14]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[14]] | 0x80;
}
led_hc595_drive(PLACE_CODE[14],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 15:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[15]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[15]] | 0x80;
}
led_hc595_drive(PLACE_CODE[15],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 16:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[16]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[16]] | 0x80;
}
led_hc595_drive(PLACE_CODE[16],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 17:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[17]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[17]] | 0x80;
}
led_hc595_drive(PLACE_CODE[17],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 18:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[18]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[18]] | 0x80;
}
led_hc595_drive(PLACE_CODE[18],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 19:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[19]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[19]] | 0x80;
}
led_hc595_drive(PLACE_CODE[19],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 20:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[20]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[20]] | 0x80;
}
led_hc595_drive(PLACE_CODE[20],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 21:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[21]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[21]] | 0x80;
}
led_hc595_drive(PLACE_CODE[21],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 22:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[22]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[22]] | 0x80;
}
led_hc595_drive(PLACE_CODE[22],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 23:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[23]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[23]] | 0x80;
}
led_hc595_drive(PLACE_CODE[23],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 24:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[24]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[24]] | 0x80;
}
led_hc595_drive(PLACE_CODE[24],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 25:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[25]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[25]] | 0x80;
}
led_hc595_drive(PLACE_CODE[25],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i++;
break;
case 26:
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
temp = leddata[LEDBuf[26]];
if(digdot6 == 1)
{
temp = leddata[LEDBuf[26]] | 0x80;
}
led_hc595_drive(PLACE_CODE[26],temp);//高位字節是位選 低位字節是斷碼
led_hc595_drive(0xffffffff,0x00);//消影 放前還是放后 要試
i=0;
break;
default:break;
}
}
5塊595級聯寫入程序:
#include "hc595.h"
#include "reg51.h"
void hc_595_init()
{
//HC595_OE = 1;
HC595_SH_CP = 0;
HC595_ST_CP = 0;
HC595_DS = 0;
//HC595_OE = 0;
}
void led_hc595_drive(unsigned long datH,unsigned char datL)
{
unsigned char i;
unsigned long temp;
unsigned char temp2;
temp = datH;
for(i = 0;i<32;i++)
{
//第一步準備數據,放到數據IO上
if(temp >= 0x80000000) //大概是比較這部分錯了
{
HC595_DS = 1;
}
else
{
HC595_DS = 0;
}
HC595_SH_CP = 0;//上升沿 移位寄存器的數據移到存儲寄存器
HC595_SH_CP = 1;
temp <<=1;
}
temp2 = datL;
for(i = 0;i<8;i++)
{
//第一步準備數據,放到數據IO上
if(temp2 >= 0x80)
{
HC595_DS = 1;
}
else
{
HC595_DS = 0;
}
HC595_SH_CP = 0;//上升沿 移位寄存器的數據移到存儲寄存器
HC595_SH_CP = 1;
temp2 <<=1;
}
HC595_ST_CP = 0;//上升沿 移位寄存器的數據移到存儲寄存器
HC595_ST_CP = 1;
HC595_SH_CP = 0;//拉低,提高抗干擾
HC595_ST_CP = 0;
HC595_DS = 0;
}
void led_hc595_off(unsigned char dat1)
{
unsigned char temp3;
unsigned char i;
temp3 = dat1;
for(i = 0;i<8;i++)
{
//第一步準備數據,放到數據IO上
if(temp3 >= 0x80)
{
HC595_DS = 1;
}
else
{
HC595_DS = 0;
}
HC595_SH_CP = 0;//上升沿 移位寄存器的數據移到存儲寄存器
HC595_SH_CP = 1;
temp3 <<=1;
}
HC595_ST_CP = 0;//上升沿 移位寄存器的數據移到存儲寄存器
HC595_ST_CP = 1;
HC595_SH_CP = 0;//拉低,提高抗干擾
HC595_ST_CP = 0;
HC595_DS = 0;
}
主函數程序:
#include "reg51.h"
#include "hc595.h"
#include "display.h"
#include "key.h"
void Timer0Init(void);
void Timer1Init(void);
void showNormal();
unsigned char timerCnt;
unsigned char sec;
unsigned char min;
unsigned char hour;
void main()
{
hc_595_init();
Timer0Init();
Timer1Init();
EA=1;
while(1)
{
TR0=1;
showNormal();
}
}
void showNormal()
{
LEDBuf[0] = min/10;
LEDBuf[1] = min%10;
LEDBuf[2] = sec/10;
LEDBuf[3] = sec%10;
LEDBuf[4] = min/10;
LEDBuf[5] = min%10;
LEDBuf[6] = sec/10;
LEDBuf[7] = sec%10;
LEDBuf[8] = min/10;
LEDBuf[9] = min%10;
LEDBuf[10] = sec/10;
LEDBuf[11] = sec%10;
LEDBuf[12] = min/10;
LEDBuf[13] = min%10;
LEDBuf[14] = sec/10;
LEDBuf[15] = sec%10;
LEDBuf[16] = min/10;
LEDBuf[17] = min%10;
LEDBuf[18] = sec/10;
LEDBuf[19] = sec%10;
LEDBuf[20] = min/10;
LEDBuf[21] = min%10;
LEDBuf[22] = sec/10;
LEDBuf[23] = sec%10;
LEDBuf[24] = 0;
LEDBuf[25] = 1;
LEDBuf[26] = 2;
}
void Timer0Init(void) //50微秒@12.000MHz
{
// AUXR &=0x7F; //定時器時鐘12T模式
TMOD &= 0xF0; //設置定時器模式
TMOD |= 0x01; //設置定時器模式
TL0 = 0xB0; //設置定時器初始值
TH0 = 0x3C; //設置定時器初始值
TF0 = 0; //清除TF0標志
ET0 = 1;
EA = 1;
}
void Timer1Init(void) //300微秒@12.000MHz
{
// AUXR &=0xBF; //定時器時鐘12T模式
//AUXR &= 0xBF; //定時器時鐘12T模式
TMOD &= 0x0F; //設置定時器模式
TMOD |=0x10; //設置定時器模式
TL1 = 0xFF; //設置定時器初始值
TH1 = 0xFF; //設置定時器初始值
TF1 = 0; //清除TF1標志
ET1 = 1;
TR1 = 1;
}
void timer0_ISR(void)interrupt 1
{
timerCnt++;
if(timerCnt >= 20)//20次1ms中斷,即1S時間到
{
timerCnt = 0;
sec++;
if(sec >= 60)
{
sec = 0;
min++;
if(min >=60)
{
min = 0;
hour++;
if(hour >=24)
{
hour = 0;
}
}
}
}
TL0 = 0xB0; //設置定時器初始值
TH0 = 0x3C; //設置定時器初始值
}
void timer1_ISR(void)interrupt 3
{
TR1 =0;
Display();
TL1 = 0xFF; //設置定時器初始值
TH1 = 0xFF; //設置定時器初始值
TR1 = 1;
}
|
-
圖片1.png
(26.58 KB, 下載次數: 76)
下載附件
2024-4-12 15:47 上傳
-
-
27位數碼管.rar
2024-4-12 15:47 上傳
點擊文件名下載附件
52.79 KB, 下載次數: 7
|