为什么Timer1不计算在PIC18? [英] Why is Timer1 not counting up on PIC18?

查看:354
本文介绍了为什么Timer1不计算在PIC18?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最初我在运行模式下使Timer0工作正常。唯一的问题是当设备进入睡眠模式时,Timer0停止计数直到唤醒。在数据表中,它说使用Timer1能够在睡眠模式下监视时间。
我将timer0的现有代码修改为timer1的新配置,其他代码几乎相同。然而,有一些我可能会错过的是与timer0不同的timer1,因为timer1根本不计数。我使用的PIC是使用MPLAB C18的 PIC18F87J11



我将分享似乎相关的代码,并根据要求,我将根据需要添加更多。



Timer0 片段代码(来自头文件)

  #define TMR_IF INTCONbits.TMR0IF 
#define TMR_IE INTCONbits.TMR0IE
#define TMR_IP INTCON2bits.TMR0IP
#define TMR_ON T0CONbits.TMR0ON
#define TMR_CON T0CON
#define TMR_L TMR0L
#define TMR_H TMR0H

Timer0(来自C文件)

  TMR_CON = 0b00000000 | CLOCK_DIVIDER_SETTING; 
TMR_IP = 1;
TMR_IF = 0;
TMR_IE = 1;
TMR_ON = 1;

Timer0(增加时间的地方)

  if(TMR_IF)
{
printf(\r\\\
Passed here);
timer_counter_high ++;
}

输出:此处传递






Timer1 片段代码(来自头文件)

  #define TMR_IF PIR1bits.TMR1IF 
#define TMR_IE PIE1bits.TMR1IE
#define TMR_IP IPR1bits.TMR1IP
#define TMR_ON T1CONbits.TMR1ON
#define TMR_CON T1CON
#define TMR_L TMR1L
#define TMR_H TMR1H

Timer1 (从C文件)

  TMR_CON = 0b11101101 | CLOCK_DIVIDER_SETTING; 
TMR_IP = 1;
TMR_IF = 0;
TMR_IE = 1;
TMR_ON = 1;

Timer1(增加时间)

  if(TMR_IF)
{
printf(\r\\\
Passed here);
timer_counter_high ++;
}
else
{
printf(\r\\\
没有通过);
}

输出:未通过



编辑:根据请求添加了CLOCK_DIVIDER_SETTING代码。这是用于timer0和timer1

  #elif(CLOCK_FREQ <= 8000000)
#定义CLOCK_DIVIDER 32
#define CLOCK_DIVIDER_SETTING 0x04
#define SYMBOL_TO_TICK_RATE 8000000

我还是在这种情况下,没有将设备置于睡眠模式下测试timer1,首先我要弄清楚为什么timer1在运行模式下不会计数。我会感谢与我的问题有关的任何帮助或想法,谢谢!



编辑2:我想回答的一些问题



Q1 :Timer1是否可以像内部振荡器一样使用,就像timer0一样?



Q2 :如何计算T1CON的正确CLOCK_DIVIDER_SETTING? (如果T1SYNC被设置和预分频器,我需要它吗?)

解决方案

根据 PIC18F87J11 FAMILY datashet ,您需要在T1OSO和T1OSI引脚上添加外部晶振,如果正在设置Timer1振荡器得到的Timer1时钟(您可以通过在T1CON寄存器中设置T1RUN位来实现)。



另请注意,尽管将CLOCK_DIVIDER_SETTING分配给T0CON寄存器正确设置时钟预分频器由于不同的位位置(在这种情况下,您有效地设置了您设置的T1SYNC位)和不同大小的预分频器,因此将相同的CLOCK_DIVIDER_SETTING分配给T1CON寄存器是错误的。



我也希望在启用定时器之前,您可以在代码中的某个位置设置寄存器TMR1H,TMR1L,TMR0L和TMR0H。



编辑添加答案额外的问题。



1:是的,Timer1有两个时钟源 - 外部振荡器和内部时钟(Fosc / 4)。要启用内部时钟,您必须清除T1CON寄存器中的TMR1CS位。



请注意,在休眠期间,除Timer1振荡器和INTRC(31 kHz时钟之外) Timer1不能使用,所以只有当Timer1由外部振荡器计时时,才能在睡眠期间测量Timer1的时间。



2: T1CKPS位是T1CON寄存器中的位4和5,所以简单地将时钟分频器设置移位四位就可以了。请记住,Timer1时钟预分频器只有两位宽,它可以将时钟除以8的最大系数。



如果使用内部时钟,则忽略T1SYNC位。如果在休眠模式下计划使用Timer1的外部振荡器,应设置T1SYNC以禁止外部时钟输入的同步(休眠期间外部时钟不能同步,因为没有内部时钟被同步并且Timer1不会计数)。 p>

Timer1的配置应该看起来像这样

  #define CLOCK_DIVIDER_SETTING_T1 0x03 / /将时钟除以8(T1_clock / 8)

// RD16清零
// T1OSCEN设置 - Timer1振荡器使能
// T1SYNC set - 不同步外部时钟输入
// TMR1CS set - 来自RC0 / T1OSO / T13CKI引脚的外部时钟(上升沿)
// TMR1ON清零 - 等待使能Timer1直到所有配置为
TMR_CON = 0b00001110 | (CLOCK_DIVIDER_SETTING_T1<< 4);
TMR_IP = 1;
TMR_IF = 0;
TMR_IE = 1;
TMR_ON = 1;

如果要使用内部时钟,则T1_clock = Fosc / 4。



如果使用内部振荡器作为系统时钟,则可以通过写入OSCCON寄存器中的IRCF位来更改系统时钟的后分频,但这将影响整个微控制器的速度。



默认设置为4 MHz,因此T1_clock将为1 MHz,T1预分频器之后将为125 kHz。


Initially I had Timer0 working fine during the run mode. The only problem is when the device goes to sleep mode, Timer0 stops counting up until awaken. In the datasheet it says to use Timer1 to be able to monitor time during sleep mode. I modified timer0 existing code to timer1 new configurations, the other code is pretty much the same. However, there is something I might have missed that is different about timer1 than timer0, since the timer1 is not counting up at all. The PIC I'm using is PIC18F87J11 with MPLAB C18.

I will share the code that seems relevant and upon request I will add more as needed.

Timer0 Snippet Code ( From Header File)

#define TMR_IF          INTCONbits.TMR0IF
#define TMR_IE          INTCONbits.TMR0IE
#define TMR_IP          INTCON2bits.TMR0IP
#define TMR_ON          T0CONbits.TMR0ON
#define TMR_CON         T0CON
#define TMR_L           TMR0L
#define TMR_H           TMR0H 

Timer0 (From C File)

TMR_CON = 0b00000000 | CLOCK_DIVIDER_SETTING;
TMR_IP = 1;
TMR_IF = 0;
TMR_IE = 1;
TMR_ON = 1;

Timer0 (Where I increment the time)

if(TMR_IF)
        {
        printf("\r\n Passed here");
        timer_counter_high++; 
        }

Output: Passed here


Timer1 Snippet Code ( From Header File)

#define TMR_IF          PIR1bits.TMR1IF
#define TMR_IE          PIE1bits.TMR1IE
#define TMR_IP          IPR1bits.TMR1IP
#define TMR_ON          T1CONbits.TMR1ON
#define TMR_CON         T1CON
#define TMR_L           TMR1L
#define TMR_H           TMR1H

Timer1 (From C File)

TMR_CON = 0b11101101 | CLOCK_DIVIDER_SETTING;
TMR_IP = 1;
TMR_IF = 0;
TMR_IE = 1;
TMR_ON = 1;

Timer1 (Where I increment the time)

   if(TMR_IF)
        {
        printf("\r\n Passed here");
        timer_counter_high++; 
        }
        else
        {
        printf("\r\n Did not come through");
        }

Output: Did not come through

Edit:Added the CLOCK_DIVIDER_SETTING code as requested. This is being used for timer0 and timer1

#elif(CLOCK_FREQ <= 8000000)
        #define CLOCK_DIVIDER 32
        #define CLOCK_DIVIDER_SETTING 0x04
        #define SYMBOL_TO_TICK_RATE 8000000

I still did not put the device on sleep mode to test timer1 in that condition, first I have to figure out why timer1 is not counting up during the run mode. I will appreciate any help or ideas related to my problem, Thanks!

Edit 2: Some questions that I like to be answered

Q1: Can Timer1 still be used with the internal oscillator just like timer0?

Q2: How do you calculate the correct CLOCK_DIVIDER_SETTING for T1CON ? (Do I need it if T1SYNC is set and the prescaler?)

解决方案

According to PIC18F87J11 FAMILY datashet, you need to add external crystal on T1OSO and T1OSI pins if you are setting Timer1 clock derived from Timer1 oscilator (which you do by setting T1RUN bit in T1CON register).

Also note, that although assigning CLOCK_DIVIDER_SETTING to T0CON register correctly sets clock prescaler, it wrong to assign the same CLOCK_DIVIDER_SETTING to T1CON register becouse of different bit locations (in this case you are effectively setting bit T1SYNC, which you already set) and different size of prescaler.

I also hope that you are setting registers TMR1H, TMR1L, TMR0L and TMR0H somewhere in code before enabling timers.

EDIT Added answers to additional questions.

1: Yes, Timer1 have two sources of clock - external oscillator and internal clock (Fosc/4). To enable internal clock you have to clear bit TMR1CS in T1CON register.

Please note, that during sleep all clocks are disabled except Timer1 oscillator and INTRC (31 kHz clock, which cannot be used by Timer1), so you can measure time with Timer1 during sleep only if Timer1 is clocked by external oscillator.

2: T1CKPS bits are bits 4 and 5 in T1CON register, so simply shifting clock divider setting by four bits should be fine. Remember, that Timer1 clock prescaler is only two bits wide, and it can divide clock by maximum factor of 8.

T1SYNC bit is ignored if you use internal clock. If you plan using external oscillator with Timer1 during sleep mode, you should set T1SYNC to disable synchronisation of external clock input (during sleep external clock cannot be synchronised becouse there is no internal clock to be synchronised to and Timer1 will not count).

Configuration of Timer1 should look something like this

#define CLOCK_DIVIDER_SETTING_T1 0x03 // divide clock by 8 (T1_clock/8)

// RD16 cleared
// T1OSCEN set - Timer1 oscillator is enabled
// T1SYNC set - Does not synchronize external clock input
// TMR1CS set - External clock from the RC0/T1OSO/T13CKI pin (on the rising edge)
// TMR1ON cleared - wait with enabling Timer1 until everything is configured
TMR_CON = 0b00001110 | (CLOCK_DIVIDER_SETTING_T1<<4);
TMR_IP = 1;
TMR_IF = 0;
TMR_IE = 1;
TMR_ON = 1;

If you want to use internal clock, then T1_clock = Fosc/4.

If you use internal oscillator as system clock, then you can change postscaler of system clock by writing to IRCF bits in OSCCON register, but this will affect speed of whole microcontroller.

The default setting is 4 MHz, so T1_clock would be 1 MHz, and after T1 prescaler it would be 125 kHz.

这篇关于为什么Timer1不计算在PIC18?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆