PIC18F计时器分钟和小时

时间:2014-11-19 16:15:36

标签: c microcontroller pic

#include<p18f452.h>
void T0_init(); 
void main()
{
    TRISC=0;        // Configure PortB as output Port.
    LATC=0x01;
    T0CON=0x07;     // Prescaler= 1:256, 16-bit mode, Internal Clock
    T0_init();
    while(1)
    {
            // Initialize Timer0
            LATC=0x00;
            T0_init();      //Delay for 1 sec
            LATC=0x01;
            T0_init();     //Again delay for 1 sec
    }
}

void T0_init()
{
    int a=0;

    //while(a<2)   // {
    TMR0H=0xF0;    // Values calculated for 1 second delay with 4MHz crystal
    TMR0L=0xBD;    //4/4MHz =1us=1us*prescaler=256us=1sec/256u=0xF42-(FFFF)=F0BD
    T0CONbits.TMR0ON=1;         // Timer0 On
    while(INTCONbits.TMR0IF==0);        // Wait until TMR0IF gets flagged
    T0CONbits.TMR0ON=0;                 // Timer0 Off
    INTCONbits.TMR0IF=0;                // Clear Timer0 interrupt flag
    //   a++;
    //  }
}

这是非常准确的延迟,它正在开展工作,但我想要更长的延迟,如小时或分钟。那么,如何处理更长的延误。我尝试使用计数器,每增加一个标记,但它不起作用。

3 个答案:

答案 0 :(得分:0)

秒是1000000微秒,小于256 * 256 * 256 = 16777216。因此,256预分频的16位定时器足以计数一秒。但这还不足以算一分钟。

解决方案是添加for循环来计算秒数。另外一个是分钟,另一个是几个小时,正如@Andrew所建议的那样。

不确定性的来源是在while()循环中检查定时器溢出一次。因此,如果在该循环中执行长计算,则精度将降低。为了克服这个问题,使用中断是可行的方法。无论发生什么,随着定时器的溢出发生,中断标志被提升,中断功能在几个周期内执行。

由于while(1)循环中没有任何操作,我想使用SLEEP()命令来节省一些能量。不幸的是,{0}}命令关闭了timer0。这不是timer1的情况,但是timer1是一个8预分频的16位定时器......所以需要一个for循环来计算一秒钟。

这是由XC8编译并使用MPLAB X的模拟器进行测试的代码......

SLEEP()

“秒”的持续时间会受到警惕......可能需要使用#include <xc.h> #pragma config WDT=OFF volatile unsigned char nb; volatile unsigned char seconds; volatile unsigned char minutes; volatile unsigned char hours; void interrupt high_isr (void) { if(PIR1bits.TMR1IF) //interrupt flag of TIMER1 { if(nb==0){ TMR1H=0; // Values calculated for 1 second delay with 4MHz crystal TMR1L=0; nb=1;//4/4MHz =1us=1us*prescaler=8us=1sec/8u=... }else{ TMR1H=23; TMR1L=184; nb=0; } if(nb==1){ seconds++; if(seconds==60){ seconds=0; minutes++; if(minutes==60){ minutes=0; hours++; } } } PIR1bits.TMR1IF=0; //erase interrupt flag of TIMER1 } } void interrupt low_priority low_isr (void) { } void main(void) { //OSCCON=0x7D;//Internal oscillator, 8Mhz T1CONbits.RD16=1; //timer1 is a 16-bit timer T1CONbits.T1CKPS1=1; //prescaler 11 -> 8-prescaled T1CONbits.T1CKPS0=1; T1CONbits.TMR1ON=1;// switch on timer1 TMR1H=0x00; //setting timer1 : high bit first TMR1L=0x00; // TMR0H=0; // TMR0L=0; TRISC=0; LATC=0x00; INTCON2bits.TMR0IP=0; // low priority interuption timer0 IPR1bits.TMR1IP=1; // high priority interuption timer1 INTCONbits.TMR0IF=0;//erase interruption flap if set PIR1bits.TMR1IF=0; //erase interruption flag if set RCONbits.IPEN=1;// Interruption prioritaires INTCONbits.TMR0IE=0;// interuption activation on timer0 (0=no active) PIE1bits.TMR1IE=1;//enable interupt on timer1 nb=1; seconds=0; minutes=0; hours=0; PORTCbits.RC0=0; PORTCbits.RC1=0; PORTCbits.RC2=0; INTCONbits.GIEH=1;// autorise interuptions INTCONbits.GIEL=1; // INTCONbits.GIE=1; while(1){ //problem with modulo and pic...do not use % if(seconds-2*(seconds/2)==1){ PORTCbits.RC0=1; }else{ PORTCbits.RC0=0; } if(minutes-2*(minutes/2)==1){ PORTCbits.RC1=1; }else{ PORTCbits.RC1=0; } if(hours-2*(hours/2)==1){ PORTCbits.RC2=1; }else{ PORTCbits.RC2=0; } SLEEP(); } return; } TMR1HTMR1L

使用外部时钟源(石英)更好:How to make Timer1 more accurate as a real time clock?

答案 1 :(得分:0)

我不是一个经验丰富的程序员,也不确定你想要使用延迟的确切位置,但我曾尝试用pic18f4550进行长时间的延迟,但它没有工作,即几分钟和几小时。但我考虑使用像CD4060或DS1307这样的IC。你可以点击此链接获取CD4060:http://dmohankumar.wordpress.com/2012/05/13/design-your-circuit-part-ii-cd-4060-timer/。对于DS1307,您可以在studentcompanion网站上查看:http://www.studentcompanion.co.za/post/Digital-Clock-using-PIC-Microcontroller-and-the-DS1307-Real-Time-Clock-XC8-Compiler/。祝你成功,谢谢

答案 2 :(得分:0)

忘记内部计时器并自己做一个繁忙的等待程序:先做一个1秒的延迟程序(非常简单,准确地完成它,处理调用和retf执行时间!),然后做一个1-在第一个上面的分钟延迟例程,然后在1分钟的顶部进行1小时的延迟例程......你明白了。