PDA

View Full Version : TMR1 - strange behaviour when toggeling a BIT variable on overflow



flotulopex
- 15th May 2023, 20:35
Hello There,

This piece of code is meant to flash a LED every second.

In my mind, and since the TMR1 is setup to overflow every 0.5 second, toggeling a BIT variable and checking when it is set should do the trick.

First, as long as the variable is not reset, the LED will do weird and never really go OFF.

Second, when I reset this variable (Flag = 0), it does kind of work, still not with a one second delay but 0.5 second instead.

What is the explanation please? What is wrong with my code?


' PIC 16F690

@ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_INTRC_OSC_NOCLKOUT &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF

OPTION_REG = %10000000 '
OSCCON = %01100000 ' Internal oscillator 4MHz
ANSEL = %00000000 ' analog inputs Channels 0 to 7
ANSELH = %00000000 ' analog inputs Channels 8 to 11
INTCON = %11000000 ' INTerrupts CONtrol; GIE=1, T0IE=1
T1CON = %00110001 ' <5:4> prescaler 1:8, <1> Timer1 enabled

DEFINE OSC 4

Flag VAR BIT
CAL_H CON 11
CAL_L CON 219

MAIN:
IF PIR1.0 THEN
PIR1.0 = 0
TOGGLE Flag
TMR1H = CAL_H : TMR1L = CAL_L
ENDIF

IF Flag THEN
Flag = 0
TOGGLE PORTC.0
ENDIF

GOTO MAIN

END

tumbleweed
- 15th May 2023, 22:13
First off, get rid of this:


INTCON = %11000000 ' INTerrupts CONtrol; GIE=1, T0IE=1


You're polling the TMR1F flag (PIR1.0), so you don't want to enable interrupts since there's no ISR to handle them.
Weird things are going to happen.

Secondly, with this


IF Flag THEN
Flag = 0
TOGGLE PORTC.0
ENDIF

You're only going to toggle PORTC.0 when Flag=1. Setting Flag back to 0 is going to screw with the next time TMR1IF gets set since it's now 0 (again).

If you want to use 'Flag' then you could do


IF Flag THEN
PORTC.0 = 1
ELSE
PORTC.0 = 0
ENDIF


or


PORTC.0 = Flag

HenrikOlsson
- 16th May 2023, 05:40
Flag VAR BIT

TOGGLE Flag

Don't do this!
It might work now but it will mess you up. TOGGLE is ONLY meant to be used on PORT and LAT registers. Look it up in the manual for more details.

You can easily toggle a bit variable by doing either one of

Flag = !Flag
Flag = ~Flag

Ioannis
- 16th May 2023, 08:20
On top of the other replies, why not do this:




IF PIR1.0 THEN
PIR1.0 = 0
TOGGLE portc.0
TMR1H = CAL_H : TMR1L = CAL_L
ENDIF



Toggle directly port insted of flag and then port.

Not tested though.

Ioannis

flotulopex
- 16th May 2023, 22:54
Hi All,

Thanks for all ideas and suggestions ;)

I tried them all except the one toggeling the port since I need to read that flag for different actions in the full program.

Unfortunately, none of them work in a "one second ON - a second OFF" rhythm.

Anyway, the way I found to make it work is to change the Flag BIT var to a BYTE one and sum up the number of PIR1.0 changes into the Flag var to trigger a port TOGGLE.

Still, I don't understand why this code doesn't work (it actually works, but in a 0.5 sec rhythm)

' PIC 16F690

@ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_INTRC_OSC_NOCLKOUT &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF

OPTION_REG = %10000000
OSCCON = %01100000 ' Internal oscillator 4MHz
ANSEL = %00000000 ' analog inputs Channels 0 to 7
ANSELH = %00000000 ' analog inputs Channels 8 to 11
T1CON = %00110001 ' <5:4> prescaler 1:8, <1> Timer1 enabled

DEFINE OSC 4

Flag VAR BIT
CAL_H CON 11
CAL_L CON 219

Flag = 0

MAIN:
IF PIR1.0 THEN
PIR1.0 = 0
Flag = Flag + 1
TMR1H = CAL_H : TMR1L = CAL_L
ENDIF

IF Flag THEN
Flag = 0
TOGGLE PORTC.0
ENDIF

GOTO MAIN

END



...while this one will light the LED for one second and switch it OFF for another second (= what I finally want):

' PIC 16F690

@ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_INTRC_OSC_NOCLKOUT &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF

OPTION_REG = %10000000
OSCCON = %01100000 ' Internal oscillator 4MHz
ANSEL = %00000000 ' analog inputs Channels 0 to 7
ANSELH = %00000000 ' analog inputs Channels 8 to 11
T1CON = %00110001 ' <5:4> prescaler 1:8, <1> Timer1 enabled

DEFINE OSC 4

Flag VAR BYTE
CAL_H CON 11
CAL_L CON 219

Flag = 0

MAIN:
IF PIR1.0 THEN
PIR1.0 = 0
Flag = Flag + 1
TMR1H = CAL_H : TMR1L = CAL_L
ENDIF

IF Flag > 1 THEN
Flag = 0
TOGGLE PORTC.0
ENDIF

GOTO MAIN

END

tumbleweed
- 16th May 2023, 23:49
Maybe because TMR1 is set for a 500ms interval?

richard
- 18th May 2023, 11:31
if you use a chip with clc module you can blink a led with no code at all
its all in hardware once configured



'************************************************* ***************
'* Name : hw-blinky.BAS *
'* Author : richard *
'* Notice : Copyright (c) 2023 caveat emptor *
'* : All Rights Reserved *
'* Date : 18/05/2023 *
'* Version : 1.0 *
'* Notes : pic16f18875@4mhz *
'* : led portb.0 blink @1hz *
'************************************************* ***************
#CONFIG
__config _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT1 & _CLKOUTEN_OFF & _CSWEN_ON & _FCMEN_ON
__config _CONFIG2, _MCLRE_ON & _PWRTE_OFF & _LPBOREN_OFF & _BOREN_ON & _BORV_LO & _ZCD_OFF & _PPS1WAY_OFF & _STVREN_ON & _DEBUG_OFF
__config _CONFIG3, _WDTCPS_WDTCPS_11 & _WDTE_ON & _WDTCWS_WDTCWS_7 & _WDTCCS_LFINTOSC
__config _CONFIG4, _WRT_OFF & _LVP_OFF
__config _CONFIG5, _CP_OFF & _CPD_OFF


#ENDCONFIG
ANSELB = 0
trisb=$fe 'led var portb.0
OSCCON1 = $60
OSCCON3 = 0
OSCEN = 0
OSCFRQ = 2
OSCTUNE = 0

'led var portb.0
gosub set_blinky



loopy:
; look no hands
goto loopy



end

set_blinky:
;// Set the CLC1 to the options selected in the User Interface
;// LC1G1POL not_inverted; LC1G2POL inverted; LC1G3POL not_inverted; LC1G4POL not_inverted; LC1POL not_inverted;
CLC1POL = $02;
;// LC1D1S T1_overflow;
CLC1SEL0 = $0B;
;// LC1D2S CLC1_OUT;
CLC1SEL1 = $20;
;// LC1D3S CLC1_OUT;
CLC1SEL2 = $20;
;// LC1D4S CLC1_OUT;
CLC1SEL3 = $20;
;// LC1G1D3N disabled; LC1G1D2N disabled; LC1G1D4N disabled; LC1G1D1T enabled; LC1G1D3T disabled; LC1G1D2T disabled; LC1G1D4T disabled; LC1G1D1N disabled;
CLC1GLS0 = $02;
;// LC1G2D2N disabled; LC1G2D1N disabled; LC1G2D4N disabled; LC1G2D3N disabled; LC1G2D2T enabled; LC1G2D1T disabled; LC1G2D4T disabled; LC1G2D3T disabled;
CLC1GLS1 = $08;
;// LC1G3D1N disabled; LC1G3D2N disabled; LC1G3D3N disabled; LC1G3D4N disabled; LC1G3D1T disabled; LC1G3D2T disabled; LC1G3D3T disabled; LC1G3D4T disabled;
CLC1GLS2 = $00;
;// LC1G4D1N disabled; LC1G4D2N disabled; LC1G4D3N disabled; LC1G4D4N disabled; LC1G4D1T disabled; LC1G4D2T disabled; LC1G4D3T disabled; LC1G4D4T disabled;
CLC1GLS3 = $00;
;// LC1EN enabled; INTN disabled; INTP disabled; MODE 1-input D flip-flop with S and R;
CLC1CON = $84;

;// Set the CLC3 to the options selected in the User Interface
;// LC3G1POL not_inverted; LC3G2POL inverted; LC3G3POL not_inverted; LC3G4POL not_inverted; LC3POL not_inverted;
CLC3POL = $02;
;// LC3D1S CLC1_OUT;
CLC3SEL0 = $20;
;// LC3D2S CLC3_OUT;
CLC3SEL1 = $22;
;// LC3D3S CLC3_OUT;
CLC3SEL2 = $22;
;// LC3D4S CLC3_OUT;
CLC3SEL3 = $22;
;// LC3G1D3N disabled; LC3G1D2N disabled; LC3G1D4N disabled; LC3G1D1T enabled; LC3G1D3T disabled; LC3G1D2T disabled; LC3G1D4T disabled; LC3G1D1N disabled;
CLC3GLS0 = $02;
;// LC3G2D2N disabled; LC3G2D1N disabled; LC3G2D4N disabled; LC3G2D3N disabled; LC3G2D2T enabled; LC3G2D1T disabled; LC3G2D4T disabled; LC3G2D3T disabled;
CLC3GLS1 = $08;
;// LC3G3D1N disabled; LC3G3D2N disabled; LC3G3D3N disabled; LC3G3D4N disabled; LC3G3D1T disabled; LC3G3D2T disabled; LC3G3D3T disabled; LC3G3D4T disabled;
CLC3GLS2 = $00;
;// LC3G4D1N disabled; LC3G4D2N disabled; LC3G4D3N disabled; LC3G4D4N disabled; LC3G4D1T disabled; LC3G4D2T disabled; LC3G4D3T disabled; LC3G4D4T disabled;
CLC3GLS3 = $00;
;// LC3EN enabled; INTN disabled; INTP disabled; MODE 1-input D flip-flop with S and R;
CLC3CON = $84;

RB0PPS = $03; //RB0->CLC3:CLC3OUT;
T1CLK = 1
T1CON = $31;
return

Ioannis
- 18th May 2023, 12:12
Nice one Richard! It good to refresh these ideas based on hardware peripherals.

But I am sure F690 does not have CLC nor he (Roger) uses MCC.

Ioannis

tumbleweed
- 18th May 2023, 13:46
... nor he (Roger) uses MCC.

There's an updated version of the standalone CLC Designer Tool over on the Swordfish site at CLCDesignerTool (https://www.sfcompiler.co.uk/wiki/pmwiki.php?n=SwordfishUser.CLCDesignerTool).
It can produce code in C or various dialects of BASIC. There's even a simple interactive simulator to explore the basic functions.

It's pretty up to date for the 18F family, but the list of supported 16F's hasn't been updated in a while.
If you use it and need something, just let me know...

Ioannis
- 18th May 2023, 14:23
Thanks for the tip!

Ioannis

Acetronics2
- 19th May 2023, 19:42
BTW ...

I remember Melanie posted ( long, long time ago :chargrined: ) about such a very simple blink trick ... with " classical " PIC's ....

Alain

flotulopex
- 23rd May 2023, 15:10
Bravo Alain, excellente mémoire :wink:

I think I found the thread you're referring to and this is the post that is what I'm doing too:
https://www.picbasic.co.uk/forum/sho...5912#post75912

I have to compare Sayzer's code and I find out what's wrong with mine.

Acetronics2
- 24th May 2023, 07:23
RTFM Datasheet § 6.5.1 ...



For writes, it is recommended that the user simply stop
the timer and write the desired values. A write
contention may occur by writing to the timer registers,
while the register is incrementing. This may produce an
unpredictable value in the timer register.


Might be a good reason ...

Alain