Continue to Site

compute TMR1L & TMR1H (PIC16F630)

Status
Not open for further replies.

Abdulkerim

Junior Member level 1
hello dear friends
I need your helps to find that formula to compute timer1 registers
for generate variable frequency... between 8Hz to 30KHz
know that the chip has not compare mode, only overflow
chip: PIC16F630
prescaler: 1, 2, 4 & 8
thank you

C:
/// header file
#define cycle_plses 4 /// EVERY 4 PULSES FROM XTAL ///
#define pulse_state 2 /// HIGH & LOW ///
#define cpu_freq 8000000 /// EXTERNAL OR ENTERNAL OSC ///

C:
/// interrupt vector

void Interrupt ()
{
if (TMR1IF_BIT)
{
TMR1IF_BIT = false;
TMR1H = high_byte;
TMR1L = low_byte;

gate ^= 1; /// toggle the mosfet
} /// if (TMR1IF_BIT)
}

C:
/// compute function
void SetFrequency (uint16_t freq)
{
bool TMR1ON_OldState, TMR1IE_OldState;
volatile uint16_t RegValue;
uint8_t prescaler;
TMR1IE_OldState = TMR1IE_BIT;
PIE1 &= ~(1<<TMR1IE);
TMR1ON_OldState = TMR1ON_BIT;
T1CON &= ~(1<<TMR1ON);
gate = false;
/// select prescaler of timer1
if (freq >= 31) prescaler = 1;
else if (freq >= 16) prescaler = 2;
else if (freq >= 8) prescaler = 4;
else if (freq >= 4) prescaler = 8;
else prescaler = 0;

/// this formula needed ///
RegValue = cpu_freq / cycle_plses / freq / pulse_state / prescaler;
low_byte = RegValue;
RegValue >>= 8;
high_byte = RegValue;
switch (prescaler)
{
case 1:
T1CON &= ~(1<<T1CKPS1);
T1CON &= ~(1<<T1CKPS0);
break;

case 2:
T1CON &= ~(1<<T1CKPS1);
T1CON |= (1<<T1CKPS0);
break;

case 4:
T1CON |= (1<<T1CKPS1);
T1CON &= ~(1<<T1CKPS0);
break;

case 8:
T1CON |= (1<<T1CKPS1);
T1CON |= (1<<T1CKPS0);
break;
}

TMR1H = high_byte;
TMR1L = low_byte;
TMR1IE_BIT = TMR1IE_OldState;
TMR1ON_BIT = TMR1ON_OldState;
}

Last edited:

Hi,

You don´t give a true description of the problem. What is the exact problem?

usually the datasheet provides all necessary informations.
--> sadly you don´t give any informations how you tried to get the values on your own.

Also there will be online calculators to assisto you with PIC setup.
--> did you try them?

Klaus

Hi,

You don´t give a true description of the problem. What is the exact problem?

usually the datasheet provides all necessary informations.
--> sadly you don´t give any informations how you tried to get the values on your own.

Also there will be online calculators to assisto you with PIC setup.
--> did you try them?

Klaus
thank ypu for reply mr klaus
really i tried by this formula
but it dosnt work fine
RegValue = cpu_freq / cycle_plses / freq / pulse_state / prescaler;

ofcourse i tried the calculator but is give the constant values
so i need to registers value every 5 second when chip are working
plz excuse me for my english
i know it is so bad
thank you
--- Updated ---

thank ypu for reply mr klaus
really i tried by this formula
but it dosnt work fine
RegValue = cpu_freq / cycle_plses / freq / pulse_state / prescaler;

ofcourse i tried the calculator but is give the constant values
so i need to registers value every 5 second when chip are working
plz excuse me for my english
i know it is so bad
thank you
Hi,

You don´t give a true description of the problem. What is the exact problem?

usually the datasheet provides all necessary informations.
--> sadly you don´t give any informations how you tried to get the values on your own.

Also there will be online calculators to assisto you with PIC setup.
--> did you try them?

Klaus
PIC16F630 DATASHEET

The data sheet recommends that you also look at https://ww1.microchip.com/downloads/en/devicedoc/33023a.pdf and in particular Section 12.
I think the problem you are encountering is that the formula use are using has a lot of integer divisions. These will round down and so your calculation will be on the 'fast' side. Also be aware of the 'natural size' of integers in your compiler. Many use 16-bit integers for constants by default so your "8000000" for the 'cpu_freq' could be seen as 4608 (only the bottom 16 bits will be used).
Personally I would 'pre-calculate' the 'cpu-freq / cycle_pulses / pulse_state' part (and yes, bring 'pulse-state' right up there) and go with that.
I don't understand how you are using the 'freq' variable. When you calculate the prescalar, you seem to be treating it as though it has units of kHz, but for the timer register calculation you are back to Hz (because your 'cpu-freq' is in Hz).
Remember that these 'old' style timers count UP and setting the interrupt flag occurs when they roll over from 0xffff to 0x0000 (in the case of Timer1 on your MCU). Therefore if you want it to trigger after (say) 20 clocks (and taking into account all of the prescaler values etc) then you need to set TMR1H/L to 65535 - 20 = 65515.
Also if you are trying to reset the timer registers in the ISR (or elsewhere to get a repetitive clock) remember that the timer will keep ticking while you enter the ISR. Therefore you need to take these 'extra' counts into account, normally by adding the 'current' count from your calculated value. (I.e. if you want to load the above 65515, then the timer registers may already be a (say) 3 to you need to put 65515 + 3 = 65518 back into the register.)
I don't know the compiler you are using but generally it is MUCH simpler to set the (for example) prescalar bits using "T1CONbits.T1CKPS = 0b10;" (check for the correct syntax in your user guide).
Susan

Status
Not open for further replies.