Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

how to use TMR0 to generate precise 1ms delay? in assembly

Status
Not open for further replies.

sky60717

Newbie level 3
Newbie level 3
Joined
Nov 19, 2011
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,306
how to use TMR0 to generate precise 1ms delay? in assembly

dear all wanna ask about how to use TMR0 to get precise 1ms?

TMR0 rate is
1:2
1:4
1:8
1:16
1:32
1:64
1:128
1:256

and its working with 4MHZ(must)

what i know now is 4MHZ/4= 1000000
1000000/256=3906.25
1/3906.25=0.000256s
but how can i get 1ms?

plz give me some example and tell me how to set for tmr0
from my lecture notes: i should use banksel option?
is that rite?

thank you very much!
 

1. I'm guessing you are using a PIC. What type is it?
2. Always use banksel, it will save you hours of debugging.

In general, use a suitable prescaler to lower the speed the timer increments. For example if you use 1:8 it will count at 1/8 of the internal clock rate. Then work out the value you need to load into TMR0 so that after 1mS it rolls over from it's maximum value of 255 back to zero. You can test this by polling the TMR0 register or better still by enabling the timer interrupt.

For example, using a PIC16F877A:

You could prescale by 1:4 and pre-load TMR0 with 6
or you could prescale by 1:8 and pre-load TMR0 with 125.

Note that the timer counts up from 0 to 255 so loading a small number means it has more counts and therefore takes longer to roll over.

Brian.
 
1. I'm guessing you are using a PIC. What type is it?
2. Always use banksel, it will save you hours of debugging.

In general, use a suitable prescaler to lower the speed the timer increments. For example if you use 1:8 it will count at 1/8 of the internal clock rate. Then work out the value you need to load into TMR0 so that after 1mS it rolls over from it's maximum value of 255 back to zero. You can test this by polling the TMR0 register or better still by enabling the timer interrupt.

For example, using a PIC16F877A:

You could prescale by 1:4 and pre-load TMR0 with 6
or you could prescale by 1:8 and pre-load TMR0 with 125.

Note that the timer counts up from 0 to 255 so loading a small number means it has more counts and therefore takes longer to roll over.

Brian.

Thank you Brian

Im using PIC16F62X. but can you give me some example for the coding, im new to using this...
also about what you said :You could prescale by 1:4 and pre-load TMR0 with 6
what is pre-load TMR0 with 6? 6 is ....?

Sorry about this
please help
 

pre-loading is like - you have a 8 bit counter with period of overload of 100 ms, you need a period of 10 ms, so each time you have overload you have to write 230 in the counter - your counter will not start from 0 but from 230 and by this you will effectively shorten the overload period from 100ms to 10ms. this is simplified example, in practice it is a bit more complicated - writing in register takes time too, at least one cycle, in case you have 16bit counter - it is 2 cycles if you write both LSB and MSB, interrupt handling takes time too, ...
 

can someone give me an example on coding.....
 

only in c, sorry about that, tmr0 is the same, this example run on its own rc oscillator, which is 4MHz :

I think it is not so hard to read it and to convert to asm :)

DPRG.c
IR obstacle detector for PIC12F629 and IR Remote Control Receiver RPM7138 (by Tsvetelin Velkov).

#include <system.h>

//======================================
// Setting Configuration and ID Bits
//======================================
#pragma DATA 0x2007, _CPD_OFF & _CP_OFF & _BODEN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_ON & _INTRC_OSC_NOCLKOUT
#pragma DATA 0x2000, 0x0C, 0x0E, 0x0C, 0x00
#pragma DATA 0x03FF, 0x3444 // modify this value to be the same as on your pic controller
#pragma CLOCK_FREQ 4000000

char count,pulse,mils,stot,sec,ratio;

//======================================
//Interrupt Routine
//======================================
void interrupt(void)
{
mils++; // counts milliseconds
tmr0 = 131; // set TMR0
clear_wdt(); // clear WDT -> don't forget to do that ;->>
clear_bit(intcon,T0IF); // clear interrupt flag
}

//=======================================
//Internal Oscillator Calibration Routine
//=======================================
inline void init(void)
{
asm
{
bsf _status,RP0
call 0x3FF
movwf _osccal
bcf _status,RP0
}
}

//=======================================
//IR Right Checking Routine
//=======================================
char IRRCheck(void)
{
char WAIT,prob;
prob = 0;

asm
{
MOVLW 23
MOVWF _WAIT
loop1:
BSF _gpio,2
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
BCF _gpio,2
NOP
NOP
NOP
NOP
NOP
NOP
BTFSS _gpio, 1 // Look for a detection
INCF _prob,F
NOP
NOP
DECFSZ _WAIT,F
GOTO loop1
}

asm
{
MOVLW 23
MOVWF _WAIT
loop2:
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
DECFSZ _WAIT,F
GOTO loop2
}

return prob;
}

//=======================================
//IR Left Checking Routine
//=======================================
char IRLCheck(void)
{
char WAIT,prob;
prob = 0;

//high modulated signal for 300us
//modulation is on 38KHz
asm
{
MOVLW 23
MOVWF _WAIT
loop1:
BSF _gpio,0
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
BCF _gpio,0
NOP
NOP
NOP
NOP
NOP
NOP
BTFSS _gpio, 1 // Look for a detection
INCF _prob, F
NOP
NOP
DECFSZ _WAIT,F
GOTO loop1
}

// low signal for 300us
asm
{
MOVLW 23
MOVWF _WAIT
loop2:
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
DECFSZ _WAIT,F
GOTO loop2
}

return prob;
}

//=======================================
// Check for noises routine
//=======================================
char NLCheck(void)
{
char WAIT,prob;
prob = 0;

//==================================
//just count 46 times x 26us = 600us
//and watch GP1, this have to detect the noise level
asm
{
MOVLW 46
MOVWF _WAIT
loop1:
BCF _gpio, 0
BCF _gpio, 2
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
BTFSS _gpio, 1 // Look for a detection
INCF _prob, F
NOP
NOP
DECFSZ _WAIT,F
GOTO loop1
}

return prob;
}

//=====================================================
// Detect a obstacle on Right also detect the noise
//=====================================================
char RCheck(void)
{
char detect,noise,i;

for(i=0;i<10;i++)
{
noise += NLCheck();
noise /= 2;
}

for(i=0;i<10;i++)
{
detect += IRRCheck();
detect /= 2;
}

if(detect > noise)
{
detect -= noise;
}
else
{
detect = 0;
}

return detect;
}

//===============================================
// Detect a obstacle on Left
//===============================================
char LCheck(void)
{
char detect,noise,i;
//detect noise
//10x600us = 6ms !
for(i=0;i<10;i++)
{
noise += NLCheck();
noise /= 2;
}
//detect obstacle
//10x600us = 6ms !
for(i=0;i<10;i++)
{
detect += IRLCheck();
detect /= 2;
}
// if detect > noise -> we have obstacle
if(detect > noise)
{
detect -= noise;
}
else
{
detect = 0;
}

return detect;
}

//=======================================
//Main Routine
//=======================================
void main()
{
option_reg = 00000010b; //set prescaller to 1:8 this means 125000 pulses per second and weak pull-up enable
trisio = 11001010b; //set GP1,GP3 as input ,others output
cmcon = 00000111b; //set GP0,GP1,GP2 as a digital IO
init(); //Calibration
tmr0 = 131; //1000000/8=125000/125=1000 cycles per second or 1ms with 4MHz clock freq, 24 extra cycles added for ISR processing
intcon = 0xA0; //enable GIE & TMR0 interrupt

// real time clock example

count = 0;
pulse = 0;
mils = 0; //this counts milliseconds
stot = 0; //this counts hundreds of milliseconds
sec = 0; //this counts seconds
ratio = 0; //modify here to adjust the detection to the noise ratio, i.e. like squelch, to set the noise floor threshold

while(1)
{
if(mils > 99)
{
mils = 0;
stot++;
}

if(stot > 9)
{
stot = 0;
sec++;
}

pulse = gpio;
if(((pulse & 0x08) == 0x08) || (sec > 2))
{
//===================
// Checking on right
count = RCheck();
if(count > ratio)
{
set_bit(gpio,GP4); // if there is a obstacle on right -> turn the right led on
}
else
{
clear_bit(gpio,GP4);
}

//===================
// Checking on left
count = LCheck();
if(count > ratio)
{
set_bit(gpio,GP5); // if there is a obstacle on left -> turn the left led on
}
else
{
clear_bit(gpio,GP5);
}

//============================
// it should check every 3 sec
sec = 0;
}
}
}
 
Last edited:

As simply as I can say it:

The TMR0 register counts upward at a constant speed. The speed is set by the system clock and by the prescaler ratio.

TMR0 has 8 bits so it can only hold values from (binary) 00000000 to 11111111 which in decimal is 0 to 255. When it has reached 255 it's next count sets it back to zero again and at the same time a circuit inside the PIC sets the TMR0IF bit.

To see if it rolled over from 255 back to zero there are three methods:
1. you can read TMR0 and see if it contains zero
2. you can keep checking the TMR0IF bit
3. you can enable interrupts (TMR0IE bit) and it will jump to a special routine called an ISR which you have to write yourself.

The number already in TMR0 decides how many more counts it will take to roll over. Remember it counts up to 255 before rolling over so if you load 250 into it in your program, it will roll over in 6 timer intervals. If you loaded 10 into it, it would take a further 246 intervals. So you can set the delay by loading a number into TMR0 to give it a 'head start', bigger numbers mean less counts remain before roll over.

For example, to load TMR0 with 6 like I mentioned earlier, you code it like this:
movlw 6 ;load the value 6 into the W register
movwf TMR0 ;copy the value in the W register to the TMR0 register

Brian.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top