/************* 本程序功能说明 **************
用STC的MCU的IO方式控制74HC595驱动8位数码管。
用户可以修改宏来选择时钟频率.
用户可以在"用户定义宏"中选择共阴或共阳. 推荐尽量使用共阴数码管.
显示效果为: 上电显示一下0~7, 1秒后显示时间或8个数码管循环显示0,1,2...,A,B..F,消隐 (编译选择).
使用Timer0的16位自动重装来产生1ms节拍,程序运行于这个节拍下, 用户修改MCU主时钟频率时,自动定时于1ms.
******************************************/
#include "config.H"
/****************************** 用户定义宏 ***********************************/
#define RTC_ENABLE 1 //1:显示时间,0:8个数码管循环显示0,1,2...,A,B..F,消隐
#define LED_TYPE 0x00 //定义LED类型,0x00--共阴,0xff--共阳
#define Timer0_Reload (65536UL-(MAIN_Fosc/1000)) //Timer0中断频率,1000次/秒
/************* 本地常量声明 **************/
u8 code t_display[]={ //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
/************* IO口定义 **************/
sbit P_HC595_SER =P4^0; //pin 14 SER data input
sbit P_HC595_RCLK =P5^4; //pin 12 RCLk store (latch) clock
sbit P_HC595_SRCLK=P4^3; //pin 11 SRCLK Shift data clock
/************* 本地变量声明 **************/
u8 LED8[8]; //显示缓冲
u8 display_index; //显示位索引
bit B_1ms; //1ms标志
u8 hour,minute,second;
u16 msecond;
/********************** 显示时钟函数 ************************/
void DisplayRTC(void)
{
if(hour>=10)LED8[0]=hour/10;
else LED8[0]=DIS_BLACK;
LED8[1] = hour % 10;
LED8[2] = DIS_;
LED8[3] = minute / 10;
LED8[4] = minute % 10;
LED8[5] = DIS_;
LED8[6] = second / 10;
LED8[7] = second % 10;
}
/********************RTC演示函数 *********************/
void RTC(void)
{
if(++second>=60)
{
second=0;
if(++minute>=60)
{
minute=0;
if(++hour>=24) hour=0;
}
}
}
/********************** 主函数 ************************/
void main(void)
{
u8 i,k;
display_index = 0;
Timer0_1T();
Timer0_AsTimer();
Timer0_16bitAutoReload();
Timer0_Load(Timer0_Reload);
Timer0_InterruptEnable();
Timer0_Run();
EA=1; //打开总中断
hour = 11; //初始化时间值
minute = 59;
second = 58;
RTC();
DisplayRTC();
for(i=0;i<8;i++) LED8[i]=i; //显示01234567
k = 0;
while(1)
{
if(B_1ms) //1ms到
{
B_1ms = 0;
if(++msecond >= 9) //1秒到
{
msecond = 0;
#if (RTC_ENABLE>0)
RTC();
DisplayRTC();
#else
for(i=0;i<8;i++) LED8[i] = k; //刷新显示
if(++k>0x10) k = 0; //8个数码管循环显示0,1,2...,A,B..F,消隐.
#endif
}
}
}
}
/**************** 向HC595发送一个字节函数 ******************/
void Send_595(u8 dat)
{
u8 i;
for(i=0;i<8;i++)
{
dat <<= 1;
P_HC595_SER = CY;
P_HC595_SRCLK = 1;
P_HC595_SRCLK = 0;
}
}
/********************** 显示扫描函数 ************************/
void DisplayScan(void)
{
Send_595(~LED_TYPE ^ T_COM[display_index]); //输出位码
Send_595( LED_TYPE ^ t_display[LED8[display_index]]); //输出段码
P_HC595_RCLK = 1;
P_HC595_RCLK = 0; //锁存输出数据
if(++display_index >= 8) display_index = 0; //8位结束回0
}
/********************** Timer0 1ms中断函数 ************************/
void timer0 (void) interrupt TIMER0_VECTOR
{
DisplayScan(); //1ms扫描显示一位
B_1ms = 1; //1ms标志
}