CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I think I become mad !

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

I think I become mad !
PostPosted: Thu Jul 30, 2015 2:08 am     Reply with quote

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.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Thu Jul 30, 2015 2:13 am     Reply with quote

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.
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Thu Jul 30, 2015 2:35 am     Reply with quote

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
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Thu Jul 30, 2015 2:42 am     Reply with quote

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.
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Thu Jul 30, 2015 2:59 am     Reply with quote

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.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Thu Jul 30, 2015 2:08 pm     Reply with quote

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.
temtronic



Joined: 01 Jul 2010
Posts: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Jul 30, 2015 5:01 pm     Reply with quote

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
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Fri Jul 31, 2015 3:34 am     Reply with quote

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")
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Fri Jul 31, 2015 10:57 am     Reply with quote

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.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 31, 2015 11:08 am     Reply with quote

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);
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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