![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Jean FOUGERON
Joined: 30 Nov 2012 Posts: 110 Location: France
|
I think I become mad ! |
Posted: Thu Jul 30, 2015 2:08 am |
|
|
Hi boys,
I come back, since many months I was on a new project and now when the hardware runs it's time to program.
But, as usual ... something (surely here just under my eyes) happens which does not work.
Let say
To simplify, my program is as follow
Code: | #define VERT output_bit(PIN_ROUGE, FALSE); output_bit(PIN_VERT, B_LED_ON)
#define ROUGE output_bit(PIN_ROUGE, B_LED_ON); output_bit(PIN_VERT, FALSE)
boolean B_LED_ON;
void F1() //---------------------------------------
{
ROUGE;
delay_ms(10);
NOIR;
delay_ms(10);
}
void F2() //----------------------------------------
{
VERT;
delay_ms(10);
NOIR;
delay_ms(10);
}
#int_TIMER1 //------------------------------------
void Blink() // bat 53 millisecondes le 30 juillet 2015
{
F2();
}
void main() //--------------------------------------
{
B_LED_ON;
while(TRUE) // toutes les 4,2µs
{
restart_wdt(); // resetter le watch dog !
F1();
}
} |
I expect to see the Red Led blink with a period of 2x10ms, and regularly each 53ms the led light during 10ms
Well : NO, it does not !!
Only green is blinking
So a function in main does not work ?
When I see the compiled code, it has to work :
Code: | .................... void F1()
.................... {
.................... ROUGE;
0198: BTFSC 1A.0
019A: BRA 01A0
019C: BCF F89.3
019E: BRA 01A2
01A0: BSF F89.3
01A2: BCF F92.3
01A4: BCF F89.2
01A6: BCF F92.2
01A8: CLRF 19
01AA: BTFSC FF2.6
01AC: BSF 19.6
01AE: BCF FF2.6
01B0: BTFSC FF2.7
01B2: BSF 19.7
01B4: BCF FF2.7
.................... delay_ms(10);
01B6: MOVLW 0A
01B8: MOVWF 21
01BA: RCALL 00CA
01BC: BTFSC 19.6
01BE: BSF FF2.6
01C0: BTFSC 19.7
01C2: BSF FF2.7
.................... NOIR;
01C4: BCF F89.3
01C6: BCF F92.3
01C8: BCF F89.2
01CA: BCF F92.2
01CC: CLRF 19
01CE: BTFSC FF2.6
01D0: BSF 19.6
01D2: BCF FF2.6
01D4: BTFSC FF2.7
01D6: BSF 19.7
01D8: BCF FF2.7
.................... delay_ms(10);
01DA: MOVLW 0A
01DC: MOVWF 21
01DE: RCALL 00CA
01E0: BTFSC 19.6
01E2: BSF FF2.6
01E4: BTFSC 19.7
01E6: BSF FF2.7
.................... }
01E8: GOTO 0210 (RETURN)
void main()
.................... {
*
01EC: CLRF FF8
01EE: BCF F9F.0
01F0: BCF F9F.1
01F2: BSF FD0.7
01F4: BSF 07.7
01F6: CLRF FEA
01F8: CLRF FE9
01FA: BCF F92.0
01FC: BSF F89.0
01FE: BCF FC2.6
0200: BCF FC2.7
0202: MOVF FC1,W
0204: ANDLW 80
0206: IORLW 7F
0208: MOVWF FC1
020A: BRA 0174
....................
.................... while(TRUE) // toutes les 4,2µs
.................... {
.................... restart_wdt(); // resetter le watch dog !
020C: CLRWDT
.................... F1();
020E: BRA 0198
.................... }
0210: BRA 020C
....................
.................... }
0212: SLEEP |
The BRA 0198 goes to F1 function, but F1 function does not blink the red led.
And if I exchange F1 and F2 (mean F2 in main and F1 in Timer) the green red blinks but not the green.
Does somebody have an idea to help, because I lose time and time and patience, without understanding anything. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Thu Jul 30, 2015 2:13 am |
|
|
I think the phrase 'of course' would apply....
You are not setting up the timer - what clock it is to use, what prescaler etc..
You are not enabling the timer interrupt, or interrupts in general.
The timer routine will never be called. |
|
![](templates/subSilver/images/spacer.gif) |
Jean FOUGERON
Joined: 30 Nov 2012 Posts: 110 Location: France
|
|
Posted: Thu Jul 30, 2015 2:35 am |
|
|
Sorry, I will not put all the code
I set the timer (as I wrote only the timer routine works !!!)
Code: | //Initialisation--------------------------------------------------------------
void initialisation()
{
I_Compteur_Poussoir=0;
I_Intensity=I0;
//-------------------------------------------Setup des timer
setup_timer_1(T1_INTERNAL | T1_DIV_BY_4); // timer de blink
setup_timer_2(T2_DIV_BY_1,32,1);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER2);
enable_interrupts(INT_RDA);
enable_interrupts(INT_TBE);
enable_interrupts(GLOBAL);
} |
The Xtal is 20MHz |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Thu Jul 30, 2015 2:42 am |
|
|
That's even worse.
You don't show this being called.
Assuming it is, you now have four interrupts enabled, but only one handler.
Then INT_TBE, should never be enabled until there is data to be sent. If you look at ex_stisr.c, you will see that the interrupt is enabled in the routine that receives a character to send. Not in the main. |
|
![](templates/subSilver/images/spacer.gif) |
Jean FOUGERON
Joined: 30 Nov 2012 Posts: 110 Location: France
|
|
Posted: Thu Jul 30, 2015 2:59 am |
|
|
I presently do not use the RS232, so never mind INT_TBE.
The best is that I post the real code, not simplified one.
File 301501.h
Code: |
#include "18F1220.h"
#DEVICE HIGH_INTS=TRUE
#FUSES WDT32768 //Watch Dog Timer uses 1:32768 Postscale
#FUSES HS //High speed Osc (> 4mhz)
//#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPUT //No Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES NOSTVREN //Stack full/underflow will not cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No Low Voltage Programming on B3(PIC16) or B5(PIC18)
//#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOWRTC //configuration registers not write protected
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPB //No Boot Block code protection
#FUSES NOWRTB //Boot block not write protected
#use delay(clock=20000000) // informe le compilateur de la fréquence du Quartz. Utile pour la fonction delay, inutile sinon.
#use RS232(BAUD=1200,BITS=8,PARITY=N,STOP=1)
// Constantes-------------------------------------------------------------------
#define ALARM_BLINK 32
#define OPERATIONAL_BLINK 128
#define NO_BLINK 0
#define DELAI_BLINK 2
#define I0 0
#define I1 50
#define I2 100
#define I3 150
#define I4 200
#define I5 255
#define I_MANUAL FALSE
#define I_RADIO TRUE
//Variables------------------------------------------------------------------
boolean B_LED_ON; // sert au blink
int I_Periode_Blink;
int I_Valeur_Blink;
boolean B_Poussoir;
int I_Compteur_Poussoir;
int I_Intensity;
boolean B_Mode;
int I_Compteur_PWM;
// Entrées et Sorties----------------------------------------------------------
#define DSEL input(PIN_A0)
#define TSEL input(PIN_A1)
#define QSEL input(PIN_A4)
#define COM !input(PIN_B2) //remettre
//#define COM input(PIN_B2) //Supprimer
#define BATT_OK !input(PIN_B5) //remettre
//#define BATT_OK input(PIN_B5) //Supprimer
#define PIN_VERT PIN_A2
#define PIN_ROUGE PIN_A3
#define VERT output_bit(PIN_ROUGE, FALSE); output_bit(PIN_VERT, B_LED_ON)
#define ROUGE output_bit(PIN_ROUGE, B_LED_ON); output_bit(PIN_VERT, FALSE)
#define JAUNE output_bit(PIN_ROUGE, B_LED_ON); output_bit(PIN_VERT, B_LED_ON)
#define NOIR output_bit(PIN_ROUGE, FALSE); output_bit(PIN_VERT, FALSE)
#define POUSSOIR !input(PIN_B0)
#define LED(x) output_bit(PIN_B3,x)
#define TEST output_toggle(PIN_B1)
#define BLEU(x) output_bit(PIN_B1,x)
|
file 301501Init.c
Code: | // 30 15 01 Beluga
// Initialisations
// V1.00 du 27 juillet 2015
#include "301501.h"
// Gestion mémoire EEPROM-------------------------------------------------------
void Ecrit_Memoire(int Adresse, int Data)
{
write_eeprom(Adresse,Data);
}
int Lit_Memoire(int Adresse)
{
return(read_eeprom(Adresse));
}
//Initialisation--------------------------------------------------------------
void initialisation()
{
I_Compteur_Poussoir=0;
I_Intensity=I0;
B_LED_ON=FALSE;
//-------------------------------------------Setup des timer
setup_timer_1(T1_INTERNAL | T1_DIV_BY_4); // timer de blink
setup_timer_2(T2_DIV_BY_1,32,1);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER2);
enable_interrupts(INT_RDA);
enable_interrupts(INT_TBE);
enable_interrupts(GLOBAL);
}
|
file 301501.c
Code: | // 30 15 01 Beluga
// V1.00 du 27 juillet 2015
#include "301501Init.c"
void Surveille_Poussoir()
{
if(B_Poussoir && !POUSSOIR)
{
B_Poussoir=FALSE;
}
if(!B_Poussoir && POUSSOIR)
{
B_Poussoir=TRUE;
if(I_Compteur_Poussoir<6)
{
I_Compteur_Poussoir++;
B_Mode=I_MANUAL;
switch (I_Compteur_Poussoir)
{
case 1:I_Intensity=I0; break;
case 2:I_Intensity=I1; break;
case 3:I_Intensity=I2; break;
case 4:I_Intensity=I3; break;
case 5:I_Intensity=I4; break;
case 6:I_Intensity=I5; break;
}
}
else
{
B_Mode=I_RADIO;
I_Compteur_Poussoir=0;
I_Intensity=I0;
}
BLEU(B_Mode);
}
}
void Surveille_Chargeur()
{
if(COM) // si COM est en bas alors l'IC fonctionne et il y a du 24V
{
I_Intensity=I0; // éteindre la LED
if(BATT_OK) // la batterie est chargée
{
I_Valeur_Blink=ALARM_BLINK;
VERT;
}
else
{
I_Valeur_Blink=NO_BLINK;
if(QSEL) // faute, si blink alors T° problem
{
ROUGE;
}
else
{
if (DSEL) // pre-charge ou constant current
{
VERT;
}
else // maintenance
{
JAUNE;
}
}
}
}
else // on est en autonome, il n'y a pas de 24V
{
if (BATT_OK) // la batterie est bonne
{
I_Valeur_Blink=OPERATIONAL_BLINK;
VERT;
}
else // la batterie doit être rechargée
{
I_Valeur_Blink=NO_BLINK;
ROUGE;
I_Intensity=I0;
}
}
}
//gestion des LED ---------------------------------------------------
#int_TIMER1
void Blink() // bat 53 millisecondes le 30 juillet 2015
{
Surveille_Chargeur();
// Surveille_Poussoir();
if (I_Valeur_Blink==NO_BLINK)
{
B_LED_ON=TRUE;
I_Periode_Blink=0;
}
else
{
I_Periode_Blink++;
if(I_Periode_Blink>=I_Valeur_Blink)
{
if(I_Periode_Blink<=I_Valeur_Blink+DELAI_BLINK)
{
B_LED_ON=TRUE;
}
else
{
B_LED_ON=FALSE;
I_Periode_Blink=0;
}
}
else
{
B_LED_ON=FALSE;
}
}
}
#int_TIMER2
void PWM()
{
I_Compteur_PWM++;
switch(I_Intensity)
{
case I0: LED(0);Break;
case I5: LED(255);Break;
default: LED(I_Compteur_PWM<=I_Intensity);Break;
}
}
//--------------------------------------------------------------------------Main
void main()
{
initialisation();
while(TRUE) // toutes les 4,2µs
{
restart_wdt(); // resetter le watch dog !
Surveille_Chargeur();
}
}
|
The routine Surveille_Chargeur does not work in main, but work in Timer1.
When Surveille_Chargeur is in Timer1, then Surveille_Poussoir does not work in Timer1, but when Surveille_Chargeur is in main, Surveille_Poussoir works OK in Timer1. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Thu Jul 30, 2015 2:08 pm |
|
|
INT_TBE, is called _continuously_ if the transmit buffer is empty. It is at boot.
So with INT_TBE enabled, the code will never work. |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Thu Jul 30, 2015 5:01 pm |
|
|
two tips about interrurpts
1) NEVER enable an interrupt unless you have a 'handler'( ISR) for it. The PIC won't know what to do with it.....it'll either crash or do 'strange' things !!
2) Whenever using the hardware UART, ALWAYS add 'ERRORS' to the use rs232(...options...). This will allow the program to carry on when the UART gets more than 3 incoming characters( the limit of the hardware buffer.
Jay |
|
![](templates/subSilver/images/spacer.gif) |
Jean FOUGERON
Joined: 30 Nov 2012 Posts: 110 Location: France
|
|
Posted: Fri Jul 31, 2015 3:34 am |
|
|
Thanks to you two
OK, I need Serial com but I didn't implement it yet, I will do it.
For the time being, I supposed that when there was no #INT_TBE routine nothing hapened, but ... mysteries of PIC
I will add ERRORS
Nevertheless it does not explain why a routine works in a timer and not in main (even when it is surely not necessary to do the job in main because it would be done too often). It would be pleasant to understand it (French say "I don't wand to dead stupid") |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Fri Jul 31, 2015 10:57 am |
|
|
The point is that it never gets beyond the interrupt enables. Because there is no INT_TBE handler it'll be looping permanently back trying to find this handler. Except when a timer interrupt triggers, and then the timer interrupt routine gets called.
INT_TBE, says that the USART transmit buffer is empty. The routine then called loads a character to send. Since the buffer _is_ empty at boot, INT_TBE will be called, and unless a character is loaded, will be called again and again.
This is why you must have this interrupt disabled, until you have data to send, and once it is sent, then disable it again. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 31, 2015 11:08 am |
|
|
Here is a simple test program to illustrate what Ttelmah says.
Code: | #include <18F4520.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
#define LED1 PIN_B0
#define LED2 PIN_B1
#int_timer1
void timer1_isr(void)
{
output_toggle(LED1); // This will always blink at about 1 Hz
}
//===================================
void main()
{
output_low(LED1); // Initially turn both leds off
output_low(LED2);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TBE); // This will cause continuous interrupts
enable_interrupts(GLOBAL);
// The program will never reach the next line and LED2 will never
// turn on, unless you comment out enable_interrupts(INT_TBE).
output_high(LED2);
while(TRUE);
} |
|
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|