![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
mka879
Joined: 30 Oct 2015 Posts: 34
|
PortB Interrupt on Change Strange Problem |
Posted: Thu Mar 31, 2016 6:28 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9177 Location: Greensville,Ontario
|
|
Posted: Thu Mar 31, 2016 6:40 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19381
|
|
Posted: Thu Mar 31, 2016 7:34 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9177 Location: Greensville,Ontario
|
|
Posted: Thu Mar 31, 2016 8:03 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
mka879
Joined: 30 Oct 2015 Posts: 34
|
|
Posted: Mon Apr 04, 2016 2:18 am |
|
|
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? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19381
|
|
Posted: Mon Apr 04, 2016 2:25 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
jeremiah
Joined: 20 Jul 2010 Posts: 1329
|
|
Posted: Thu Apr 07, 2016 1:30 pm |
|
|
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 |
|
![](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
|