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 support@ccsinfo.com

PortB Interrupt on Change Strange Problem

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



Joined: 30 Oct 2015
Posts: 34

View user's profile Send private message

PortB Interrupt on Change Strange Problem
PostPosted: Thu Mar 31, 2016 6:28 am     Reply with quote

Here is a strange problem.

I am using PCWHD version 5.015 and PIC16f877A. Hardware is as follows:

Portb.4 and Portb.7 are connected to the output of LM324. Inputs of LM324 is connected to two switches which connects ground in close state. Inverting input of LM324 is connected to 5V while non-inverting input is pulled to 12V up by 10k resistor.

When I initialize the board without the switches connected, Portb.4 and Portb.7 are in high state then the program runs fine. But when the board is initialized with switches connected, SMS is sent twice and Portb ISR is executed at the time of sending SMS resulting in another message to be sent.

The code is as follows:

Code:
#include <16F877A.h>
#device ADC=10;
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or (PIC18) used for I/O
#use delay(crystal=20000000)

#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,PARITY=N,BITS=8,STOP=1,ERRORS)

char flag[80];
char check;
int counter = 0;
int16 overflow = 0;
int16 fuel_level,vol_batt;
int16 temp = 0;
int16 temp1 = 0;
int16 tmpr = 0;
//int32 ac_v_offset = 0;
//int32 ac_i_offset = 0;
int1 flag_else = 0;
int mod_test();
void init_CS5463();
int send_sms1(int32,int32,int32,int16,int16,int1,int1,int32);
int send_sms2(int32,int32,int32,int32,int16,int16,int1,int1,int32);
void init_pic1();
void init_pic2();
void init_gsm_mod();
int1 w,y,z;
int1 flag_b4,flag_b6,flag_relay;
int1 flag_sec = 0;

#include<math.h>
#define i_thresh  419430
#define v_thresh  1471686
#define CS     PIN_D1
#define RESET  PIN_B5
#define LED_Blink PIN_B0
#define CS5463_CONFIG_REG  0
#define AC_I_Gain_Reg 2
#define AC_V_Gain_Reg 4
#define CS5463_TEMP_REG    19
#define CS5463_CYCLE_COUNT_REG    5
#define CS5463_EPILSON_REG 13
#define AC_I_Offset_Reg 16
#define AC_V_Offset_Reg 17
#define OPERATION_REG 18
#define PF_Reg 25
#define PActive_Reg 10
#define Vrms_Reg 12
#define Irms_Reg 11
#define sync 0xFF
#define ovr_sec   2304
#define ovr_min   9155   

#bit sspbuf0 = 0x13.0
#byte sspbuf = 0x13

#int_rb
void rb_isr(void)
{       
   output_high(pin_b6);
   output_bit(pin_d2,!input_state(pin_d2));
   if(input(pin_b7) && w == 0)
   {
      w = 1;
      flag_b4 = 1;     
   }
   if(!input(pin_b7) && w == 1)
   {
      w = 0;
     
   }     
   if(!input(pin_b4) && y == 1)
   {   
      y = 0;
     
     
   }
   if(input(pin_b4) && y == 0)
   {
      y = 1;
      flag_b6 = 1;
   }   
   output_low(pin_b6);
  // delay_ms(500);
}

#int_rda
void isr_rda(void)
{   
   output_high(pin_b6);
   flag[counter] = getchar();
   counter++;
   output_low(pin_b6);
}

#int_timer0
void isr_timer0(void)
{
 
   output_high(pin_b6);
   overflow++;
   
   if(flag_sec == 1)//if genset is running
   {
      if(overflow > ovr_sec + 130)//reset overflow flag
      {       
         overflow = 0;
      }
      if(overflow < ovr_sec - 119)//led blinking   
      {   
         temp1++;
         if(temp1 == 78)
         {
            flag_else = 1; //1 second delay for lED0 high
         }
         if(temp1 == 156)
         {
            flag_else = 0; //1 second delay for LED0 low
            temp1 = 0;     //reset timer
         }
      }
      if(overflow < ovr_sec - 154)//adc reading
      {   
         temp++;
         if(temp == 39)
         {
            set_adc_channel(0);
         }
         if(temp == 78)
         {
            fuel_level = read_adc(); 
            //if (flag_relay == 1)
            //output_high(pin_d0);
         }
         if (temp == 116)
         {
            set_adc_channel(1);
         }
         if(temp == 307)
         { 
            vol_batt = read_adc();
            //output_low(pin_d0);
            //flag_relay = 0;//temp = 0;
         }
         if(temp == 346)
         {
            set_adc_channel(4);
         }
         if(temp == 728)//536 )
         {
            tmpr = read_adc();
            // temp = 0;
         }
      }
   }
   else//genset is at rest
   {
      if(overflow > ovr_min + 130)//reset overflow
      {         
         overflow = 0;
      }
   
      if(overflow < ovr_min - 119)//led blinking   
      {   
         temp1++;
         if(temp1 == 78)
         {
            flag_else = 1; //1 second delay for lED0 high
         }
         if(temp1 == 156)
         {
            flag_else = 0; //1 second delay for LED0 low
            temp1 = 0;     //reset timer
         }
      }
      if(overflow < ovr_min - 154)//adc reading
      {   
         temp++;
         if(temp == 4578)
         {
            set_adc_channel(0);
         }
         if(temp == 4617)
         {
            fuel_level = read_adc(); 
            //if (flag_relay == 1)
            output_high(pin_d0);
         }
         if (temp == 4655)
         {
            set_adc_channel(1); 
         }
         if(temp == 4846)
         {
            vol_batt = read_adc();
            output_low(pin_d0);
            //flag_relay = 0;//temp = 0;
         }
         if(temp == 4885)
         {
            set_adc_channel(3);     
         }
         if(temp == 5267)//536 )
         {
            tmpr = read_adc();
            // temp = 0;
         }
      }
   }
   
  // int tmr = get_timer0();
  output_low(pin_b6);
   clear_interrupt(int_timer0);
}


//#use delay(crystal=20000000)
//---------------------------------
int32 CS5463_read_reg(int8 reg)
{
   int8 msb, mid, lsb,temp;
   int32 retval;
   
 
   output_low(CS);   //slave select     
   temp = spi_read(reg << 1);     //send read command
   msb = spi_read(sync);   //read msb mid and lsb by sending sync commands
   mid = spi_read(sync);
   lsb = spi_read(sync);
   output_high(CS);
   retval = make32(0, msb, mid, lsb);
   
   return(retval);
}
//---------------------------------
void CS5463_write_reg(int8 reg, int8 msb, int8 mid, int8 lsb)
{
output_low(CS);
spi_write((reg << 1) | 0x40);   // OR with Write bit
spi_write(msb);
spi_write(mid);
spi_write(lsb);
output_high(CS);
}

//---------------------------------
void sync_port(void)
{
   output_low(CS);
   spi_write(0xFF);
   spi_write(0xFF);
   spi_write(0xFF);
   spi_write(0xFE);
   output_high(CS);
}

//---------------------------------
void start_conv(void)
{
   output_low(CS);
   spi_write(0xE8);
   output_high(CS);
}

//---------------------------------
void ac_offset_calibration(void)
{
   CS5463_write_reg(AC_V_Offset_Reg,0,0,0);
   CS5463_write_reg(AC_I_Offset_Reg,0,0,0);
   output_low(CS);
   spi_write(0xDD);  //voltage and current ac offset command 
   output_high(CS);
}
//---------------------------------
void ac_gain_calibration(void)
{
    CS5463_write_reg(AC_V_Gain_Reg,64,0,0);
    CS5463_write_reg(AC_I_Gain_Reg,64,0,0);
    output_low(CS);
    spi_write(0xDE);    //AC V and I Gain Calibration command
    output_high(CS);
}

//---------------------------------

//===============================
void main()
{
   //output_high(pin_d0);
   int32 v,i,ccr;
   int32 pf;
   int1 pressure_sw,temp_sw;
   int16 overflow_dig1 = 0;
   int16 overflow_dig2 = 0;
   v = 0; i = 0; ccr =0; pf = 0;
   fuel_level = 0;vol_batt = 0; pressure_sw = 0; temp_sw = 0;temp = 0;
   flag_b4 = 0;flag_b6 = 0;
   flag_relay = 0;
   float pf_sqr= 0.00 ;
   init_pic1();
   
   init_gsm_mod();
   
   while (!mod_test())
   {
   }
   init_CS5463();
 
   w = input(pin_b7);
   y = input(pin_b4);
   z = input(pin_d4);
   init_pic2();
 
   while(TRUE)
   {                 
      v = CS5463_read_reg(Vrms_Reg);
      if (flag_b4 == 1)
      {
         output_low(pin_b0);
         output_high(pin_b1);
         if (overflow_dig1 == 0)
         {
            output_high(pin_b2);
            while (!send_sms1(v,i,pf,fuel_level,vol_batt,pressure_sw,temp_sw,ccr))
            {
            }
            output_low(pin_b2);
            /*while (!send_sms2(v,i,p_signed,pf_signed,fuel_level,vol_batt,pressure_sw,temp_sw,ccr))
            {
            }*/
            output_high(pin_b1);
            overflow_dig1 = overflow;
         }
         if (overflow >= overflow_dig1 + 76 && overflow < overflow_dig1 + 80)//delay_ms(1000);
            output_low(pin_b1);
         if (overflow >= overflow_dig1 + 152 && overflow < overflow_dig1 + 156)//delay_ms(1000);
         {
            flag_b4 = 0;
            overflow_dig1 = 0;
         }       
         output_low(pin_b1);
      }
      else if (flag_b6 == 1)
      {
         output_high(pin_b3);
         output_low(pin_b0);
         if (overflow_dig2 == 0)
         {
            output_high(pin_b2);
            while (!send_sms1(v,i,pf,fuel_level,vol_batt,pressure_sw,temp_sw,ccr))
            {
            }
            output_low(pin_b2);
            /*while (!send_sms2(v,i,p_signed,pf_signed,fuel_level,vol_batt,pressure_sw,temp_sw,ccr))
            {
            }*/
            output_high(pin_b3);
            overflow_dig2 = overflow;
         }
         else if (overflow >= overflow_dig2 + 76 && overflow < overflow_dig2 + 80)//delay_ms(1000);
         {
            output_low(pin_b3);
         }
         else if (overflow >= overflow_dig2 + 152 && overflow < overflow_dig2 + 156)//delay_ms(1000);
         {   
            flag_b6 = 0;
            overflow_dig2 = 0;
         }
         //output_low(pin_b3);
      }
      else
      {
         
         if (v >= v_thresh)
         {
            flag_sec = 1;
            if (overflow > 2304)//send sms at 30s interval
            {
               output_high(pin_b1);
               temp = 0;
               i = CS5463_read_reg(Irms_Reg);
               //v = CS5463_read_reg(Vrms_Reg);
               if (i <= i_thresh)
               {
                  i = 0;
                  pf = 0;
               }
               else
               {
                  pf = CS5463_read_reg(PF_Reg);   
               }
               ccr = CS5463_read_reg(CS5463_CYCLE_COUNT_REG);
               //pf = CS5463_read_reg(PF_Reg);             
               pf_sqr = ((float)pf / 8388608) * ((float)pf / 8388608);
               pf_sqr = sqrt(1 - pf_sqr);
               pressure_sw = input(pin_b7);
               temp_sw = input(pin_b4);   
               output_high(pin_b2);
               while (!send_sms1(v,i,pf,fuel_level,vol_batt,pressure_sw,temp_sw,ccr))
               {
               }
               output_low(pin_b2);
            }
            else
            {
               if (flag_else == 1)
                  output_high(LED_Blink);
               else
                  output_low(LED_Blink);
            }
         }
         else
         {
            flag_sec = 0;
            if (overflow > 9155)//send sms at 2mins interval
            {
               output_high(pin_b1);
               temp = 0;
               i = 0;
               v = 0;
               pf = 0;
               //i = CS5463_read_reg(Irms_Reg);
               //v = CS5463_read_reg(Vrms_Reg);
               ccr = CS5463_read_reg(CS5463_CYCLE_COUNT_REG);
               //pf = CS5463_read_reg(PF_Reg);         
               pf_sqr = ((float)pf / 8388608) * ((float)pf / 8388608);
               pf_sqr = sqrt(1 - pf_sqr);           
               pressure_sw = input(pin_b7);
               temp_sw = input(pin_b4);                       
               output_high(pin_b2);
               while (!send_sms1(v,i,pf,fuel_level,vol_batt,pressure_sw,temp_sw,ccr))
               {
               }
               output_low(pin_b2);
            }
            else
            {
               if (flag_else == 1)
                  output_high(LED_Blink);
               else
                  output_low(LED_Blink);
            }
         }
      }     
   }
}


int mod_test()
{
         int index = 0;
         counter = 0;
         strcpy(flag,"no");
         printf("AT+CMGF=1");
         putchar(0x0D);
         output_bit(pin_b5,1);
         delay_ms(500);
         while (counter <= 7)
         {
         }
         output_bit(pin_b5,0);
         
         for (index = 0; index <= 12; index++)
         {
            if (flag[index] == 'O' && flag[index + 1] == 'K')
            {
               delay_ms(500);
               return 1;
            }
         }
         delay_ms(500);
         return 0;   
}

int send_sms1(int32 v, int32 i, int32 pf, int16 fuel_level, int16 vol_batt, int1 pressure_sw, int1 temp_sw,int32 ccr)
{
         int index = 0;
         counter = 0;
         strcpy(flag,"no");
         //printf("AT+CMGS=\"03012118327\"");//Riaz sahab ufone sim
         printf("AT+CMGS=\"03332097014\"");         
         putchar(0x0D);
         delay_ms(500);
         float vfinal = ((float)v / 16777216)*355.38;
         float ifinal = ((float)i / 16777216)*90.6;
   
         while (counter <= 7)
         {
         }               
         
         for (index = 0; index <= 28; index++)
         {
            if (flag[index] == '>')
            {
              // printf("kuch din baad");               
             //  if(tmpr < 933)
                  printf("%fV,%fA,%fkW,%f,%fC,%f%%,%fV,%u,%u,%lu\r\n",vfinal,ifinal,vfinal*ifinal*pf/1000,(float)pf / 8388608,-34 * log((float)vol_batt*5/1023) + 48,(((float)fuel_level*5/1023)*187.41)-7.38,((float)tmpr*16/1023),temp_sw,pressure_sw,ccr);
              // else
                //  printf("%fV,%fA,%fkW,%f,%f,%fC,%f%%,%fV,%u,%u,%lu\r\n",((float)v / 16777216)*378.3,((float)i / 16777216)*90.6,((float)v / 16777216)*378.3*((float)i / 16777216)*90.6*pf_corr/1000,(float)pf / 8388608,pf_corr,-34 * log((float)vol_batt*5/1023) + 84,(((float)fuel_level*5/1023)*63.83)-5.32,((float)tmpr*16/1023) - 0.6,temp_sw,pressure_sw,ccr);   
                //printf("%fV,%fA,%fkW,%f,%f,%fC,%f%%,%fV,%u,%u,%lu\r\n",((float)v / 16777216)*378.3,((float)i / 16777216)*90.6,((float)v / 16777216)*378.3*((float)i / 16777216)*90.6*((float)pf_signed / 8388608)/1000,(float)pf_signed / 8388608,pf_corr,-33 * log((float)vol_batt*5/1023) + 81,(((float)fuel_level*5/1023)*63.83)-5.32,(float)tmpr*16/1023,temp_sw,pressure_sw,ccr);
                //printf("%fV,%fA,%fkW,%f,%fC,%f%%,%u,%u,%lu\r\n",((float)v / 16777216)*378.3,((float)i / 16777216)*90.6,((float)v / 16777216)*378.3*((float)i / 16777216)*90.6*((float)pf_signed / 8388608)/1000,(float)pf_signed / 8388608,-34 * log((float)vol_batt*5/1023) + 87,(((float)fuel_level*5/1023)*63.83)-5.32,temp_sw,pressure_sw,ccr);
               delay_ms(500);
               putchar(0x1A);
               return 1;
            }
         }
         delay_ms(500);
         return 0;   
}

void init_gsm_mod()
{
   output_bit(pin_b6,1);
   
   delay_ms(11000);
   output_bit(pin_b6,0);

   strcpy(flag,"no");
   counter = 0;
}
void init_CS5463()
{
   setup_spi(SPI_MASTER|SPI_SCK_IDLE_LOW|SPI_CLK_DIV_64|SPI_XMIT_L_TO_H);  //set up spi module
   sync_port();
   CS5463_write_reg(CS5463_EPILSON_REG,1,163,111); 
   CS5463_write_reg(OPERATION_REG,0,0,96);  // turn high pass filter on
   delay_ms(500);   
   CS5463_write_reg(CS5463_CONFIG_REG,1,0,1);
   delay_ms(1000);
   //CS5463_write_reg(CS5463_CYCLE_COUNT_REG,0,30,133);
   //delay_ms(1000);
   //ac_offset_calibration();
   //delay_ms(7000);
   //CS5463_write_reg(AC_V_Offset_Reg,253,248,0); //FDF800
   //CS5463_write_reg(AC_I_Offset_Reg,254,164,0); //FEa400
   CS5463_write_reg(AC_I_Gain_Reg,70,134,146);
   CS5463_write_reg(AC_V_Gain_Reg,63,25,194);
   
  // delay_ms(1000);
  // ac_offset_calibration();
  // delay_ms(7000);
 
   //ac_offset_calibration();
   //delay_ms(7000);
   start_conv();
   delay_ms(500);
   output_low(CS);             // turn high pass filter on
   CS5463_write_reg(OPERATION_REG,0,0,97);
}
void init_pic1()
{
   setup_adc_ports(AN0_AN1_AN2_AN3_AN4);
   setup_adc(ADC_CLOCK_DIV_32);
   output_high(RESET);
   output_high(CS);
   enable_interrupts(global);
   enable_interrupts(int_rda);
   port_b_pullups(false);
}

void init_pic2()
{
   enable_interrupts(int_rb);
   setup_timer_0(T0_DIV_256);
   enable_interrupts(INT_TIMER0);
}


Is it the problem with firmware or hardware? Please help
temtronic



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

View user's profile Send private message

PostPosted: Thu Mar 31, 2016 6:40 am     Reply with quote

With a quick look at your code ( too much really...)
my 'gut' feeling is that you're supposed to read PortB within the ISR to clear the interrupt condition. The 877 is an old PIC and that's what I've always done. That's in the datasheet/ CCS manuals/FAQ section somewhere....

also...

Your ISR for timer0 is way too 'complicated' and you do not need to clear it as the compiler does that for you.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19381

View user's profile Send private message

PostPosted: Thu Mar 31, 2016 7:34 am     Reply with quote

This is one of those 'beware' ones.....

There are some PIC18's, which won't actually reset the latches on a read of port B. On these a bit access instead has to be used!.

However on the older chips (this is one), the data sheet refers to a read or write of port B being needed. Like Temtronic, I've always used a simple read as being the safest thing to do.

However I'd suspect this might well simply be switch bounce. Switches (except for some special designs like mercury wetted switches), will _always_ exhibit bounce. Single physical make actually appears electrically as a sequence of make, break, make, break etc.. As you have an op-amp buffer, add some positive feedback round the op-amp, and capacitance to this circuit, to make a hardware debounce.
temtronic



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

View user's profile Send private message

PostPosted: Thu Mar 31, 2016 8:03 am     Reply with quote

Another simple 12 v to 5 v level converter is a 78L05 voltage regulator !

Not exactly a 'normal' use for the device but I've used them for decades in automotive applications.

4 regs take up less space than a 324, easy PCB traces, kinda bullet proof.

Options, think outside the box....

Jay
mka879



Joined: 30 Oct 2015
Posts: 34

View user's profile Send private message

PostPosted: Mon Apr 04, 2016 2:18 am     Reply with quote

Thank you everyone. As stated the problem only arises when sending SMS using SIM900a, I suspected it was noisy ground issue. As the switches are normally closed which connects ground to portB, therefore I changed the wires connecting battery ground of Genset to the circuit and the problem vanishes.

I recently came across volatile type qualifier. I understand their utility and importance. Despite of not using it in my code, the code works fine. Why is that so?
Ttelmah



Joined: 11 Mar 2010
Posts: 19381

View user's profile Send private message

PostPosted: Mon Apr 04, 2016 2:25 am     Reply with quote

CCS has no handling of 'volatile'. Volatile is for things like 16bit variables, where they may be updated by (for example) other code inside an interrupt at the same time as the 'main' code is also accessing the variable. You have to do this yourself. So (for instance), if you have a variable that you read from an interrupt, you would either disable interrupts, copy it to a local version, then re-enable the interrupts, or do an operation like:
Code:

   int16 local_variable;
   while (local_variable != interrupt_variable)
      local_variable=interrupt_variable;

This sees if the variable has changed, and if it has, copies it, and keeps on copying it till it matches.

Plus side - interrupts don't have to be disabled.

Nothing you do, uses variables larger than 8bits, so there is inherently no problem.
jeremiah



Joined: 20 Jul 2010
Posts: 1329

View user's profile Send private message

PostPosted: Thu Apr 07, 2016 1:30 pm     Reply with quote

I'll have to check the CCS manual, but in standard C volatile merely tells the compiler not to optimize out reads/write to variables it deems unused. It doesn't have any affect on atomic access. Normal uses in other compilers are for global variables used by interrupts or variables mapped to hardware registers...basically any variable that can be modified outside the current context.

I have had other compilers like GCC, for example, do this:


Code:

uint8_t * const g_ptr = 0x000000800;  //some hardware register

void main(void){
   //stuff
   
   //GCC sometimes will optimize this next line out if *g_ptr isn't read at some point
   g_ptr->some_field = 0x02; 

}


by making the variable g_ptr defined as:
Code:

volatile uint8_t * const g_ptr = 0x000000800;  //some hardware register


GCC will not optimize out the write.

CCS isn't as aggressive as other compilers though. I don't think I have ever seen CCS optimize out a line like that. I still use the volatile keyword as good practice for any of my globals or register variables

This is a good info source on the subject:
http://www.barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword
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