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.

[PIC] setting counters with timers in assembly

Status
Not open for further replies.

eagle1109

Full Member level 6
Full Member level 6
Joined
Nov 20, 2014
Messages
393
Helped
4
Reputation
10
Reaction score
7
Trophy points
1,298
Location
Saudi Arabia
Visit site
Activity points
5,956
hi,

how to set a counter to count times of processes in assembly

should i set TIMER0 as a counter when counting and as a timer when calling delays ?


,,,,,,,,,,,,,,,

my understanding now is and i learned to set bytes in GPR for delays
then i set one byte for a counter and then used decfsz to count no. of times and it did not work

PIC16F877A


regards,View attachment code.txt
 

Timers (when set up properly) count pulses from either an external source conneced to a pin or from the PICs own internal clock. You don't need to increment or decrement them in your code, just check the value in them and it will change by itself.

Typically, the way they are used is to load a value into them then go into a program loop waiting for their value to 'roll over' (reach maximum value and restart from zero again). Bear in mind that all the counters count UP not down so for example if you want to wait 100 timer periods, you pre-load the timer with a value of 100 less than its maximum. You can check the timer values by reading them but the more normally used method is to monitor the interrupt flag associated with the timer. The flag is set as the timer rolls over so if you are repeating the process, you must reset it again in your program. The interupt flags still work if you do not have the interrupt enabled but of course you don't actually enter an interrupt routine.

Incidentally, try to use a lower case 'x' in hexadecimal numbers, I suprised the assembler accepted it in upper case.

Brian.
 

Timers (when set up properly) count pulses from either an external source conneced to a pin or from the PICs own internal clock. You don't need to increment or decrement them in your code, just check the value in them and it will change by itself.

which timer you mean ?? the timers in SFRs or the delay subroutines in GPRs ?

how to check the value ?? with btfss or btfsc ..

Typically, the way they are used is to load a value into them then go into a program loop waiting for their value to 'roll over' (reach maximum value and restart from zero again).

so this is the delay bytes in subrountines with decfsz ?? am i right ?

Bear in mind that all the counters count UP not down so for example if you want to wait 100 timer periods, you pre-load the timer with a value of 100 less than its maximum.

the maximum is whether is timer is 8 or 16 bit ? right ..


You can check the timer values by reading them but the more normally used method is to monitor the interrupt flag associated with the timer.

how ?

The flag is set as the timer rolls over so if you are repeating the process, you must reset it again in your program. The interupt flags still work if you do not have the interrupt enabled but of course you don't actually enter an interrupt routine.

which flag ? in status or option reg ?
you mean i must reset the flag bit ? how ?? i.g. clrf status,2 in the same section of the counter

yes .. if i want an interrupt, then i have to write a specific routine and connect it with interrupt flag

Incidentally, try to use a lower case 'x' in hexadecimal numbers, I suprised the assembler accepted it in upper case.

well ... it worked :)



thanks a lot
 

Lots of questions!

Timers in SFR (TMR0, TMR1, TMR2...) automatically count. TMR0 and TMR1 can be incremented by a signal on a pin or by counting clock pulses. Software counters can only be incremented by your code so you have to monitor for the process then use the incf instruction.

Use bit test instructions on the register itself or better still, OR it with itself so the value doesn't change but the flags in the STATUS register are updated. You can then use the btfsc and btfss instrcutions on the Z and C bits.

The 8 bit counters roll over at a count of 256, the 16 bit counters at 65536.

The interrupt bits are in the INTCON and PIR registers. The timer interrupt is set automatically as the timer rolls over but you have to clear it in your code. Use the btfsc/btfss instructions to check the bit. They work even when the interrupt is disabled (PIE registers) but when disabled, the interrupt routine itself is not called.

Still use lower case 'x' - it makes it easier to read, I'm not sure all assemblers/compilers are as forgiving!

Brian.
 

Lots of questions!

yeah .. because your previous reply was encouraging so thank you :)

Timers in SFR (TMR0, TMR1, TMR2...) automatically count. TMR0 and TMR1 can be incremented by a signal on a pin or by counting clock pulses. Software counters can only be incremented by your code so you have to monitor for the process then use the incf instruction.

alright, i understand they are the actual timers for the chip ..

>> in datasheet it's described that they are readable and writable.
Readable means that they provide info to get
Writable means they offer different settings
,right ?

Use bit test instructions on the register itself or better still, OR it with itself so the value doesn't change but the flags in the STATUS register are updated. You can then use the btfsc and btfss instrcutions on the Z and C bits.
you mean instead of decfsz ?

The interrupt bits are in the INTCON and PIR registers. The timer interrupt is set automatically as the timer rolls over but you have to clear it in your code. Use the btfsc/btfss instructions to check the bit. They work even when the interrupt is disabled (PIE registers) but when disabled, the interrupt routine itself is not called.
why to do this ? is this in specific block of code, in main code or in the subroutine ?



Still use lower case 'x' - it makes it easier to read, I'm not sure all assemblers/compilers are as forgiving!

Brian.

alright .. thanks again :)
 

Ah! less questions...

Readable means you can read the value in the timer at any time, it is just like any other register, it just changes it's value automatically if set to count clock pulses or external events.

Writable means you can put a new value in the counter at any time. Again, they behave just like any other register. When using them to create delays you will find that writing to them is essential to 'pre-load' a value so that roll over happens after fewer events/clocks. For example, if you write 100 (decimal) to TMR0 it will only need another 156 events/clocks before it reaches 255 and rolls over back to zero.

decfsz is a software decrement and check for zero. If you use your own counters in software you have to change their values yourself. That instruction gives you an easy way to count down and do something when zero is reached. The hardware timers count up by themselves, you don't increment them or decrement them yourself, technically there is nothing stopping you doing that but it defeats the object of them being independent of your program.

One of the tricks you can use to check if any register holds zero is to 'OR' it with itself. All the logical operations make the bits in the STATUS register update so you can then check the Z flag in the STATUS register to see if it held zero or not.

You can read the interrupt flags at any time in your program, they are simply bits in the INTCON and PIR registers that get updated when a hardware event occurs. One such event is the roll-over of one of the timers. So if you check if the bits are set you know a roll over has happened without having to read and check the timer value. The catch is that the bit stays set until you clear it yourself.

If you feel ambitious, you can turn on the timer interrupt bits in INTCON/PIE registers and also turn on the GIE bit in INTCON. What happens then is when a timer rolls over or any other enabled event takes place, the program will suspend and jump to an interrupt routine. In the routine you do whatever has to be done then clear the interrupt bit and use a RETFIE instruction to return and resume what you were originally doing. Interrupts are incredibly useful and well worth learning.

For example, some of my programs have several delays, some running simultaneously and all running for different periods. You can't do that with software delays but with interrupts it is easy.

Brian.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top