|
用了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;
}
|
|