本帖最后由 不亦心 于 2009-11-11 17:04 编辑
上面是一张关键的图。
R-red(秒),B-blue(分),G-green(时),数字是LED的编号,数字后的AB分别代表LED的正负极,cp1到cp12代表12个i/o端口。
下面是俺的仿真源程序,新手拿来练手的,程序肯定很多不足,别把我砸晕了。(那个网友的源程序很不错,我现在达不到那个水平)
/*********************************************/
//模块名:LED模拟怀表
//模块功能:简单的时钟功能,有调时功能,尚未添加定闹功能
//硬件型号:pic18f4520,4MHZ,MCC18编译软件
//编写者:buyixin(不亦心)
//编写日期:2009年11月8日 15:27:39
//修改调试于:2009年11月10日
//不亦心的博客:http://hi.baidu.com/不亦心/
/********************************************/
#include<p18f4520.h>
#include"led_clock.h" //LED 显示驱动
unsigned char second=1,minute=1,hour=1;//时间变量=实际值+1
void timr0 (void); //tmr0中断函数声明
#pragma code timr0_duan=0x08 //中断入口
void timr0_rukou (void)
{
_asm goto timr0 _endasm;
}
#pragma code
//======TMR0中断函数====================
#pragma interrupt timr0
void timr0 (void)
{
TMR0H=0x0b;//赋初值,定时1S
TMR0L=0xdd;
INTCONbits.TMR0IF=0;//清楚中断标示位
++second; //时间刷新
if(second>60)
{
second=1;
++minute;
if(minute>60)
{
minute=1;
++hour;
if(hour>=12)
hour=1;
led_hour(hour);//时间显示刷新
}
led_minute(minute);
}
led_second(second);
}
//======TMR0初始化===========================
void tmr0_init(void)
{
ADCON1=0xff;//置为数字I/O口
RCONbits.IPEN=1;//开中断优先级
T0CON=0x03;//TMR0预分频器置为1:16
TMR0H=0x0b;//赋初始值,定时1S
TMR0L=0xdd;
INTCON2bits.TMR0IP=1;
INTCONbits.TMR0IF=0;
INTCONbits.TMR0IE=1;//开TMR0中断
T0CONbits.TMR0ON=1;//启动TMR0
INTCONbits.GIE=1;//开全局中断
WDTCON=0;//关WDT
}
//=====10MS延时函数================
void delay(void)
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<81;j++);
}
//==========主函数====================
void an_jian(void);
void main(void)
{
TRISB=0xff;
PORTB=0xff;
tmr0_init();//tmr0初始化
while(1)
{
led_second(second);//秒显
led_minute(minute);//分显
led_hour(hour);//时显
an_jian();//调时按键检测函数
}
}
//=====调时按键检测函数===================
unsigned char i=0;
void an_jian(void)
{
unsigned int j;
if(PORTBbits.RB5==0)//调时按键检测
{
delay();
if(PORTBbits.RB5==0)
{
while(PORTBbits.RB5==0);//等待按键松开
i++;//标志变量加1
}
}
if(i==1) //第一次按键,秒归0,分自动跑
{
T0CONbits.TMR0ON=0;//调时期间关TMR0
TMR0H=0x0b;//赋初始值
TMR0L=0xdd;
second=1;
minute++;
if(minute>60)
{
minute=1;
hour++;
if(hour>12) hour=1;
}
for(j=0;j<1000;j++)
{
led_second(second);//刷新显示并延时
led_minute(minute);
led_hour(hour);
// delay();
if(PORTBbits.RB5==0)//调时按键检测
{
delay();
if(PORTBbits.RB5==0)
{
while(PORTBbits.RB5==0);//等待按键松开
i++;//标志变量加1
}
}
}
}
if(i==2)//第两次按键,时分秒停止,等待
{
led_second(second);//显示时间
led_minute(minute);
led_hour(hour);
}
if(i==3)//第三次按键,退出调试状态
{
T0CONbits.TMR0ON=1;//退出调时,启动TMR0
i=0;
}
}
以下是LED时间显示驱动部分,没有加注释,具体看上一篇硬件介绍,找规律。
void led_second(unsigned char second)
{
unsigned int i,j,m;
unsigned char flag,portl,x;
flag=second&0x01;
if(second<=22)
{
portl=0x01;
i=0x0001;
m=0xfffe;
x=0;
}
else
{
if(second<=42)
{
portl=0x02;
i=0x0002;
m=0xfffd;
x=22;
}
else
{
portl=0x04;
i=0x0004;
m=0xfffb;
x=42;
}
}
if(flag==1)
{
TRISD=0xff;//切换显示的时候所有I/O高阻态,以免误显示
TRISC=0xff;
PORTD=portl;
PORTC=0x00;
TRISD=(unsigned char)(m&(~(i<<(1+(second-x-1)/2))));
TRISC=(unsigned char)((m&(~(i<<(1+(second-x-1)/2))))>>8);
}
else
{
TRISD=0xff;
TRISC=0xff;
PORTD=(unsigned char)(i<<((second-x)/2));
PORTC=(unsigned char)((i<<((second-x)/2))>>8);
TRISD=(unsigned char)(m&(~(i<<(second-x)/2)));
TRISC=(unsigned char)((m&(~(i<<(second-x)/2)))>>8);
}
}
void led_minute(unsigned char minute)
{
unsigned int i,j,m;
unsigned char flag,portl,x;
flag=minute&0x01;
if(minute<=16)
{
portl=0x08;
i=0x0008;
m=0xfff7;
x=0;
}
else
{
if(minute<=30)
{
portl=0x10;
i=0x0010;
m=0xffef;
x=16;
}
else
{
if(minute<=42)
{
portl=0x20;
i=0x0020;
m=0xffdf;
x=30;
}
else
{
if(minute<=52)
{
portl=0x40;
i=0x0040;
m=0xffbf;
x=42;
}
else
{
portl=0x80;
i=0x0080;
m=0xff7f;
x=52;
}
}
}
}
if(flag==1)
{
TRISD=0xff;
TRISC=0xff;
PORTD=portl;
PORTC=0x00;
TRISD=(unsigned char)(m&(~(i<<(1+(minute-x-1)/2))));
TRISC=(unsigned char)((m&(~(i<<(1+(minute-x-1)/2))))>>8);
}
else
{
TRISD=0xff;
TRISC=0xff;
PORTD=(unsigned char)(i<<((minute-x)/2));
PORTC=(unsigned char)((i<<((minute-x)/2))>>8);
TRISD=(unsigned char)(m&(~(i<<(minute-x)/2)));
TRISC=(unsigned char)((m&(~(i<<(minute-x)/2)))>>8);
}
}
void led_hour(unsigned char hour)
{
unsigned int i,j,m;
unsigned char flag,porth,x;
flag=hour&0x01;
if(hour<=6)
{
porth=0x01;
i=0x0100;
m=0xfeff;
x=0;
}
else
{
if(hour<=10)
{
porth=0x02;
i=0x0020;
m=0xfdff;
x=6;
}
else
{
porth=0x04;
i=0x0040;
m=0xfbff;
x=10;
}
}
if(flag==1)
{
TRISD=0xff;
TRISC=0xff;
PORTD=0x00;
PORTC=porth;
TRISD=(unsigned char)(m&(~(i<<(1+(hour-x-1)/2))));
TRISC=(unsigned char)((m&(~(i<<(1+(hour-x-1)/2))))>>8);
}
else
{
TRISD=0xff;
TRISC=0xff;
PORTD=(unsigned char)(i<<((hour-x)/2));
PORTC=(unsigned char)((i<<((hour-x)/2))>>8);
TRISD=(unsigned char)(m&(~(i<<(hour-x)/2)));
TRISC=(unsigned char)((m&(~(i<<(hour-x)/2)))>>8);
}
}
以下是LED时间显示驱动头函数
#ifndef LED_CLOCK_H
#define LED_CLOCK_H
void led_second(unsigned char second);
void led_minute(unsigned char minute);
void led_hour(unsigned char hour);
#endif
|