本帖最后由 zhaor 于 2011-9-17 10:50 编辑
准备最少发4个心得帖子,都在一个主题里,所以预留2、3、4楼!
注意:程序正在优化中!每优化一次都会说明的!逐渐增加按键程序(能调时间、调闹铃);增加USB程序(能和电脑的时间同步)等。准备打造新塘RTC最强时钟程序!大家多多支持啊!
程序借用lixiaoxu2men的组织结构,表示谢意!
实际效果
电路图
数码管驱动电路清晰PDF格式图
8LED2803.pdf
(44.74 KB)
595程序int8_t const table[11] = { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//共阴
int8_t const dig[8] ={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
uint8_t blink; //闪烁标志位
void hc595enb(void) //数据选通
{
hc595_cs_clr;
hc595_cs_set;
hc595_cs_clr;
}
void hc595rst(void) //595复位
{
hc595_rst_set;
hc595_clk_clr;
hc595_rst_clr;
hc595_rst_set;
hc595enb();
}
void hc595outbyte(int8_t disdata) //595输出数据 单字节
{
int8_t dl; //显示数据移位
for(dl=0;dl<=7;dl++)
{
if(disdata&0x80) hc595_data_set;
else
hc595_data_clr;
disdata<<=1;
hc595_clk_set;
hc595_clk_clr;
}
}
void hc595out(int8_t data_h,int8_t data_l) //数据输出 高位在前,低位在后。低位为第一通道输出
{
hc595outbyte(data_h);
hc595outbyte(data_l);
hc595enb();
}
void display(int8_t buffer[8])
{
static unsigned char scan;
switch(scan)
{
case 0x00:
hc595out(dig[scan],table[buffer[scan]]);
scan++;
break;
case 0x01:
hc595out(dig[scan],table[buffer[scan]]);
scan++;
break;
case 0x02:
if(blink)
{
hc595out(dig[scan],table[10]);
}
else
{
hc595out(dig[scan],table[buffer[scan]]);
}
scan++;
break;
case 0x03:
hc595out(dig[scan],table[buffer[scan]]);
scan++;
break;
case 0x04:
hc595out(dig[scan],table[buffer[scan]]);
scan++;
break;
case 0x05:
if(blink)
{
hc595out(dig[scan],table[10]);
}
else
{
hc595out(dig[scan],table[buffer[scan]]);
}
scan++;
break;
case 0x06:
hc595out(dig[scan],table[buffer[scan]]);
scan++;
break;
case 0x07:
hc595out(dig[scan],table[buffer[scan]]);
scan=0;
break;
default:
break;
}
}
595头文件#ifndef __HC595_H__
#define __HC595_H__
#define hc595_data_set DrvGPIO_SetBit(E_GPA,9)
#define hc595_data_clr DrvGPIO_ClrBit(E_GPA,9)
#define hc595_clk_set DrvGPIO_SetBit(E_GPA,8)
#define hc595_clk_clr DrvGPIO_ClrBit(E_GPA,8)
#define hc595_cs_set DrvGPIO_SetBit(E_GPA,7)
#define hc595_cs_clr DrvGPIO_ClrBit(E_GPA,7)
#define hc595_rst_set DrvGPIO_SetBit(E_GPA,9)
#define hc595_rst_clr DrvGPIO_ClrBit(E_GPA,9)
void hc595enb(void);
void hc595rst(void);
void hc595outbyte(int8_t disdata);
void hc595out(int8_t data_h,int8_t data_l);
void display(int8_t buffer[8] );
#endif
主程序调用: TimeEnable();
if(SYSTime)
{
display(disp_buffer); //显示
if(++SYSms==500)
{
SYSms=0;
DrvRTC_Read(DRVRTC_CURRENT_TIME, &sCurTime); // (读取当前时间,存放指针)
disp_buffer[6]= sCurTime.u32cHour/10;
disp_buffer[7]= sCurTime.u32cHour%10;
disp_buffer[4]= sCurTime.u32cMinute/10 ;
disp_buffer[3]= sCurTime.u32cMinute%10 ;
disp_buffer[1]= sCurTime.u32cSecond/10;
disp_buffer[0]= sCurTime.u32cSecond%10;
if (DrvGPIO_GetBit(E_GPA,5))
DrvGPIO_ClrBit(E_GPA,5);
else
DrvGPIO_SetBit(E_GPA,5);
}
}
}
}
全部程序:
yin-TIMER.rar
(1.07 MB)
代码简要分析
int8_t SYS1ms,SYSTime; //
int16_t SYSms;
#define TimeEnable() SYSTime=0; if(SYS1ms){ SYSTime=1; SYS1ms=0; }
TimeEnable()在死循环程序中使用
每一次执行的时候SYSTime都清零,但是如果SYS1ms置位的时候SYSTime也就置位了
if(SYSTime)
{
display(disp_buffer); //显示
}
这个时候就调用数码管显示函数了。
SYS1ms什么时候置位呢?
是在定时器中断里:
void Timer0_Callback (void)
{
SYS1ms=1;
}
如果我们定时器设置10毫秒中断一次,那么数码管显示函数就是10毫秒调用一次
数码管扫描的频率就是100HZ,超过人眼的视觉暂留的了,数码管显示的就很稳定,没有闪烁感了!
有的朋友可能会说为什么不在定时器中断直接调用显示函数呢?
这样做的好处在那里呢?
大家可以搜索一下以前牛人农民讲习所所长的大作。
我们后来加按键检测程序也要用到它的! |