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

problem int_rda with PIC 16F688
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ftrax



Joined: 24 Sep 2013
Posts: 22
Location: España

View user's profile Send private message

problem int_rda with PIC 16F688
PostPosted: Fri Nov 22, 2013 7:20 am     Reply with quote

Hi everyone,

I'm using CCS 5.010 and I have a problem, my program doesn't work correctly, the PIC doesn't enter into the while(true).

When the code arrives at "enable_interrupt(int_rda);" , the program executes the interrupt but they never come out from there, program execution stays into the interrupt forever.
I try to solve this problem but I'm not able to find a solution.

Anyone knows what I'm doing wrong??

Well, hope someone could help me.

Here goes the code:

Code:

#include <16F688.h>
//#device adc=10

#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOPUT                      //Power Up Timer
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOPROTECT
#FUSES NOCPD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOIESO
#FUSES NOFCMEN

//////////////////////////////////////////////
//////****CONFIGURACIÓN CLOCK y RS232****/////
//////////////////////////////////////////////
#use delay(internal=4000000)         
#use rs232(baud=9600,xmit=PIN_C4,rcv=PIN_C5,parity=N)

//////////////////////////////////////////////
///////////****CONFIGURACIÓN I/O****//////////
//////////////////////////////////////////////
#use fast_io(A)
#use fast_io(C)

#define configa 0b00000110
#define configc 0b00100000

#bit  buzzer   = 0x7.0     //Es el pin C0
#bit  stolva   = 0x5.1     //Es el pin A1

//////////////////////////////////////////////
////////***** FICHEROS INCLUIDOS *****////////
//////////////////////////////////////////////
#include <stdlib.h>
#include <input_mod.c>
#include <string.h>
#include <stdio.h>
#include <lcdindif.c>

//////////////////////////////////////////////
////////******** DEFINICIONES ********////////
//////////////////////////////////////////////
#define ms1       83
#define ms10      820
#define ms100     8320

//#byte alarmas   =  0x85
//#bit alarmRPM  =  0x85.0
//#bit alarmCAR  =  0x85.1   

///////////////////////////////////////////
//////////***VARIABLES GLOBALS***//////////
///////////////////////////////////////////
short refresca=0;
short alarmRPM=0,alarmCAR=0;

int hectarees[9];

long counter=0;
long t1r=28036;
long delay=0;


float proba=0;
///////////////////////////////////////////
////////***** INTERRUPCIONES *****/////////
///////////////////////////////////////////
#int_rda
void rda_isr(void){

//if(input(pin_c5)==1){
   //get_string(hectarees,9);   
//}

output_toggle(pin_a0);
delay_ms(100);
}

//*************** INT TIMER1*********************
#int_TIMER1
void TIMER1_isr(void) {
static int cont=0;
static int auxbuzzer;

set_timer1(t1r);        // Recarga a 0.3s
cont++;

if((alarmRPM==1)||((alarmCAR==1)&&(auxbuzzer<4))){
   auxbuzzer++;
   buzzer=~buzzer;
}
if((alarmCAR==0)||(auxbuzzer>=4)){
   auxbuzzer=0;
}

if(cont==2)
{
cont=0;
counter=get_timer0();   //Lectura contador TMR0
set_timer0(0);          //Reinicia cuenta
//counter*=(100/2);     //Conversión a rpm
                        //hi ha dos polos per volta
counter*=50;
refresca=1;
}
}
////////////////////////////////////////////
//////////***PROGRAMA PRINCIPAL***//////////
////////////////////////////////////////////
void main()
{
   setup_adc(ADC_OFF);
   setup_adc_ports(no_analogs);
   setup_comparator(NC_NC_NC_NC);
   setup_counters( T0_EXT_L_TO_H | T0_DIV_1, T0_8_BIT );
   setup_oscillator(OSC_INTRC|OSC_4MHZ);
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
   setup_vref( VREF_HIGH );
   setup_wdt(WDT_OFF);
   
     
   enable_interrupts(int_timer1);     
   
   set_timer1(t1r);
   set_timer0(0);   

   set_tris_a(configa);
   set_tris_c(configc);
   
   output_a(0);
   output_c(0);
     
   enable_interrupts(int_rda);
   enable_interrupts(global);
 
   for(delay=0;delay<ms100;delay++);
   
   lcd_init();
   lcd_clear();
   
   while(true){       
   if(refresca==1){
      refresca=0;   
      lcd_erase_line(1);
      lcd_gotoxy(1,1);
      //proba=strtof(hectarees,9);
      //printf(lcd_putc, "Hect: %9.3f" ,proba);
      printf(lcd_putc,"  %6lu rpm",counter);   
      if(counter<3500)
      {
      alarmRPM=1;
      }
      else
         {
         alarmRPM=0;
         buzzer=0;
         }
         
      if(stolva==0){
         alarmCAR=1;
         lcd_gotoxy(1,2);
         printf(lcd_putc,"  NIVEL MINIMO  "); 
      }
      else
         {
         alarmCAR=0;
         lcd_erase_line(2);
         lcd_gotoxy(1,2);
         proba=strtof(hectarees,9);
         printf(lcd_putc, "Hect: %9.3f" ,proba);     
         }
      }   
   }
}
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Fri Nov 22, 2013 7:30 am     Reply with quote

You have to get the received character signaled by the interrupt for the
interrupt to be cleared. Using getc() in the interrupt routine will do that for you.

Code:
#int_rda
void rda_isr(void){
 int x;

x=getc();

//if(input(pin_c5)==1){
   //get_string(hectarees,9);   
//}

output_toggle(pin_a0);
delay_ms(100);
}

_________________
Google and Forum Search are some of your best tools!!!!
ftrax



Joined: 24 Sep 2013
Posts: 22
Location: España

View user's profile Send private message

PostPosted: Sun Nov 24, 2013 4:28 am     Reply with quote

Hi dyeatman,

I haven't try solution yet, but tomorrow I try this, the idea is not using getc() if not input in pin_c5.

There are any method to clear the interrupt without using getc().?

Thanks for all.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Sun Nov 24, 2013 5:23 am     Reply with quote

Simple answer. No.

INT_RDA, occurs, when the hardware UART has a character waiting to be read. Once this happens, there is always a 'character waiting to be read', until it is read....

There are several hardware interrupts that reflect events like this (INT_RB for example), where the hardware event _must_ be cleared, or the interrupt will trigger for ever.

Best Wishes
temtronic



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

View user's profile Send private message

PostPosted: Sun Nov 24, 2013 6:15 am     Reply with quote

also..
never put delays inside any ISR !
and..
always add 'errors' to use rs232(...) when using the hardware UART.


hth
jay
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Nov 24, 2013 7:41 am     Reply with quote

So, to clear the RDA interrupt you always have to do a getc() call. But, it is up to you what to do with the read data. If you want to throw the data away because PIN_A5 is high, then do so.

Then just a few minor comments on your coding style to make you an even better programmer.

1) In your whole program I never see you using spaces in a line, this makes it more difficult to read and has no advantages that I can think of. For example this line:
Code:
if((alarmRPM==1)||((alarmCAR==1)&&(auxbuzzer<4))){
Itisdifficulttoreadwhatiswrittenherewithoutspaces.

Another possible way to write the same line:
Code:

if (   (alarmRPM == 1)
    || ((alarmCAR == 1) && (auxbuzzer < 4))
   )
{


2) Good practice is to write all constants and #defined values in full capital names. This way you immediately see the difference between variables and constant values.
For example:
'configa' --> 'CONFIGA'
'pin_a5' --> 'PIN_A5'

3) The CCS compiler defines a 1-bit variable with the type 'short'. In other compilers the short type has a different size, for example 8 or even 16-bit. To make your program more portable it is good practice to always use types that hard code a desired bit size, that is types like: int1, int8, int16 and int32

4) When using boolean variables it is good practice to give them a name expressing an action. For example starting with the word 'is' or 'has' included.
In your original code it is not clear when the buzzer is on. Is the buzzer active when 0 or when 1?
Change the name to 'isBuzzerOn'
In code this becomes:
Code:
if (isBuzzerOn) { do something }
Now the code has become self documenting.
ftrax



Joined: 24 Sep 2013
Posts: 22
Location: España

View user's profile Send private message

PostPosted: Sun Nov 24, 2013 9:18 am     Reply with quote

Hi Ttelmah,

the problem is that the PIC executes the interrupt when I enabled with "enable_interrupts(int_rda), enable_interrupts(global)", but its impossible that the int_rda occurs because in these pin isn't connecting anything.
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Sun Nov 24, 2013 9:27 am     Reply with quote

It is NOT impossible. The pin is floating and picking up noise.

If you want to get an interrupt but not receive a character disable the USART and use a different interrupt, not int_rda.

Look at page 2 of the datasheet to see what is available. Maybe you want RA2?
_________________
Google and Forum Search are some of your best tools!!!!


Last edited by dyeatman on Sun Nov 24, 2013 9:34 am; edited 2 times in total
ftrax



Joined: 24 Sep 2013
Posts: 22
Location: España

View user's profile Send private message

PostPosted: Sun Nov 24, 2013 9:32 am     Reply with quote

Hi temtronic,

I never put delays inside ISR in a "real" source code, but in this case I needed know if the PIC entry in the ISR, and the only way I could think was put delay inside.

Thanks for the tip to add 'errors' in the directive to #use rs232.
ftrax



Joined: 24 Sep 2013
Posts: 22
Location: España

View user's profile Send private message

PostPosted: Sun Nov 24, 2013 9:41 am     Reply with quote

Hi ckielstra

Thanks for all of your comments.
I'm a novice programmer and I think your comments are good to help me correct my bad habits.
ftrax



Joined: 24 Sep 2013
Posts: 22
Location: España

View user's profile Send private message

PostPosted: Sun Nov 24, 2013 9:44 am     Reply with quote

Sorry dyeatman,

I'm forget comment that this pin is not floating, I connect them to GND with 47k resistance.

thanks for all.
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Sun Nov 24, 2013 9:49 am     Reply with quote

It needs to be pulled high, not low. High is inactive and low is the active
state so it is being seen as a start bit.
_________________
Google and Forum Search are some of your best tools!!!!
ftrax



Joined: 24 Sep 2013
Posts: 22
Location: España

View user's profile Send private message

PostPosted: Sun Nov 24, 2013 10:25 am     Reply with quote

Thanks dyeatman

tomorrow I try all solutions, and then I explain the results.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Sun Nov 24, 2013 12:05 pm     Reply with quote

As a general comment, the data sheet is your friend.

If you look at fig 10-5, the very top line shows the RX pin. Idling high, and a 'low' being the start bit.

Best Wishes
ftrax



Joined: 24 Sep 2013
Posts: 22
Location: España

View user's profile Send private message

PostPosted: Mon Nov 25, 2013 4:20 am     Reply with quote

Hi guys,

finally thanks to your assistance I have succeeded to fix the problem.

The final source code is this:
Code:

#include <16F688.h>
//#device adc=10

#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOPUT                      //Power Up Timer
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOPROTECT
#FUSES NOCPD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOIESO
#FUSES NOFCMEN

//////////////////////////////////////////////
//////****CLOCK & RS232 CONFIGURATION****/////
//////////////////////////////////////////////
#use delay(internal=4000000)         
#use rs232(baud=9600,xmit=PIN_C4,rcv=PIN_C5,parity=N,errors)

//////////////////////////////////////////////
/////////****** FILES INCLUDED ******/////////
//////////////////////////////////////////////
#include <stdlib.h>
#include <input_mod.c>
#include <string.h>
#include <stdio.h>
#include <lcdindif.c>

//////////////////////////////////////////////
///////////****I/O CONFIGURATION****//////////
//////////////////////////////////////////////
#use fast_io(ALL)

#define CONFIGA 0b00000110
#define CONFIGC 0b00100000

#bit  BUZZER   = 0x7.0     //Is pin C0
#bit  STOLVA   = 0x5.1     //Is pin A1


//////////////////////////////////////////////
/////////******** DEFINITIONS ********////////
//////////////////////////////////////////////
#define MS1       83
#define MS10      820
#define MS100     8320

//////////////////////////////////////////////
////////////***GLOBAL  VARIABLES***///////////
//////////////////////////////////////////////
int1 refresca=0;
int1 alarmRPM=0,alarmCAR=0;

int8 hectarees[9];

int16 counter=0;
int16 t1r=28036;
int16 delay=0;


float proba=0;
//////////////////////////////////////////////
//////////***** INTERRUPTIONS *****///////////
//////////////////////////////////////////////

//**************** INT RDA *****************//
#int_rda
void rda_isr(void){
int8 x=0;

if(input(PIN_C5))
   get_string(hectarees,9);   //Save the string received
else
   x=getc();   //Clear the interrupt if hasn't a character waiting to be read
   
}

//****************INT TIMER1****************//
#int_TIMER1
void TIMER1_isr(void) {
static int8 cont=0;
static int8 auxbuzzer;

set_timer1(t1r);        //Timer reloaded every 0.3s
cont++;

if((alarmRPM==1) || ((alarmCAR==1) && (auxbuzzer<4))){
   auxbuzzer++;
   BUZZER=~BUZZER;
}

if((alarmCAR==0) || (auxbuzzer>=4)){
   auxbuzzer=0;
}

if(cont==2){
   cont=0;
   counter=get_timer0();   //Read counter TMR0
   set_timer0(0);          //reset  timer0
   //counter*=(100/2);     //Convert to RPM
                           //there are to pulses for round
   counter*=50;      //simplify -- to pulses for round
   refresca=1;
}
}

//////////////////////////////////////////////
///////////***** MAIN PROGRAM *****///////////
//////////////////////////////////////////////
void main()
{
   setup_adc(ADC_OFF);
   setup_adc_ports(no_analogs);
   setup_comparator(NC_NC_NC_NC);
   setup_counters( T0_EXT_L_TO_H | T0_DIV_1, T0_8_BIT );
   setup_oscillator(OSC_INTRC|OSC_4MHZ);
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
   setup_vref( VREF_HIGH );
   setup_wdt(WDT_OFF);   
     
   enable_interrupts(int_timer1);   
   enable_interrupts(int_rda);
   
   enable_interrupts(global);
   
   set_timer1(t1r);
   set_timer0(0);   

   set_tris_a(CONFIGA);
   set_tris_c(CONFIGC);
   
   output_a(0);
   output_c(0);       
 
   for(delay=0;delay<MS100;delay++);
   
   lcd_init();
   lcd_clear();
   
   while(true){
   
   if(refresca==1){
      refresca=0;   
      lcd_erase_line(1);
      lcd_gotoxy(1,1);
      printf(lcd_putc,"  %6lu rpm",counter);
      enable_interrupts(global);
      if(counter<3500)
      {
         alarmRPM=1;
      }
      else
         {
            alarmRPM=0;
            BUZZER=0;
         }
         
      if(STOLVA==0){
         alarmCAR=1;         
         lcd_gotoxy(1,2);
         printf(lcd_putc,"  NIVEL MINIMO  "); 
         enable_interrupts(global);
      }
      else {         
            alarmCAR=0;
            lcd_erase_line(2);
            lcd_gotoxy(1,2);
            proba=strtof(hectarees,9);
            printf(lcd_putc, "Hect: %9.3f" ,proba);
            enable_interrupts(global);
         }
      }   
   }
}


Thanks for your comments and tips. Wink
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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