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

Problems with 16F88 and int_rda

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



Joined: 09 Oct 2003
Posts: 39
Location: LA PLATA, ARGENTINA

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

Problems with 16F88 and int_rda
PostPosted: Wed Jun 23, 2004 6:56 am     Reply with quote

Hi everyone,

Previous data, before telling wich is the problem.

I´m using CCS 3.187
The example EX_STISR.C works ok with 16F88 (it buffers up outgoing serial data). Outgoing data is sent OK, and incoming data is received OK.

The only problem with this example, is that it does not use INT_RDA.

The program I compiled, works OK a 16F628, and it does this:

Waits until INT_RBO is activated, and sends the character "?".
Then waits 200ms, and hopes to receive ANY character.
If it receives one, then blinks an led 3 times.

Well, first time you activate INT_RB0, it works fine, but NEVER AGAIN.
Is there anything wrong in my code, that I can not see ???
I think it´s OK
Well, hope someone could help me.

Here goes the code:

#include <16F88.H>
#device *=16
#fuses XT,NOWDT,NOBROWNOUT,NOPROTECT,PUT,NOLVP,MCLR,NODEBUG
#use delay(clock=7327280)
#use rs232(baud=38400, xmit=PIN_B5,rcv=PIN_B2, ERRORS)

static char Rx[10];
static boolean rda;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// DEFINO FUNCIONES //////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Encendido intermitente del led //
void blink_green(int veces, int duracion)
{ int i;
for (i=0;i<veces;i++)
{
output_bit(PIN_A3,1);
delay_ms(duracion);
output_bit(PIN_A3,0);
delay_ms(duracion);
}
}

// Encendido intermitente del led //
void blink_red(int veces, int duracion)
{ int i;
for (i=0;i<veces;i++)
{
output_bit(PIN_A2,1);
delay_ms(duracion);
output_bit(PIN_A2,0);
delay_ms(duracion);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////// RUTINAS DE INTERRUPCION ///////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#int_ext
void ext_isr()
{
}

#int_rda
void serial_isr()
{
rda=TRUE;
Rx[0]=getc();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// ///////////////////////////////////////////////////
///////////////////////////////////////////////// PROGRAMA PRINCIPAL ///////////////////////////////////////////////////
///////////////////////////////////////////////// ///////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void main()
{

#ZERO_RAM

// Configuro periféricos para bajo consumo //
setup_timer_2(T2_DISABLED,0,2);
setup_ccp1(CCP_OFF);
setup_adc(ADC_OFF);
setup_vref(FALSE);

// Configuro puertos para bajo consumo //
port_b_pullups(TRUE);

// Habilito interrupciones //
ext_int_edge(H_to_L);
enable_interrupts(INT_EXT);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);

// Fin de configuración //
blink_red(3,50);
blink_green(3,50);

// Habilito RS232 //
output_bit(PIN_A1,0);
output_bit(PIN_A0,1);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////// RUTINA QUE DETERMINA LA TAREA QUE DEBE REALIZARSE ////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Loop:
sleep();

///////////////////////////////////////////////////////////
if (input(PIN_B0) == FALSE)
{
do {} While (input(PIN_B0) == FALSE);
delay_ms(200);
putc('?');
delay_ms(200);
}

if (rda==TRUE) blink_green(3,10);
rda = FALSE;
///////////////////////////////////////////////////////////

goto Loop;
}
Ttelmah
Guest







Re: Problems with 16F88 and int_rda
PostPosted: Wed Jun 23, 2004 9:37 am     Reply with quote

Gabriel Caffese wrote:
Hi everyone,

Previous data, before telling wich is the problem.

I´m using CCS 3.187
The example EX_STISR.C works ok with 16F88 (it buffers up outgoing serial data). Outgoing data is sent OK, and incoming data is received OK.

The only problem with this example, is that it does not use INT_RDA.

The program I compiled, works OK a 16F628, and it does this:

Waits until INT_RBO is activated, and sends the character "?".
Then waits 200ms, and hopes to receive ANY character.
If it receives one, then blinks an led 3 times.

Well, first time you activate INT_RB0, it works fine, but NEVER AGAIN.
Is there anything wrong in my code, that I can not see ???
I think it´s OK
Well, hope someone could help me.

Here goes the code:

#include <16F88.H>
#device *=16
#fuses XT,NOWDT,NOBROWNOUT,NOPROTECT,PUT,NOLVP,MCLR,NODEBUG
#use delay(clock=7327280)
#use rs232(baud=38400, xmit=PIN_B5,rcv=PIN_B2, ERRORS)

static char Rx[10];
static boolean rda;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// DEFINO FUNCIONES //////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Encendido intermitente del led //
void blink_green(int veces, int duracion)
{ int i;
for (i=0;i<veces;i++)
{
output_bit(PIN_A3,1);
delay_ms(duracion);
output_bit(PIN_A3,0);
delay_ms(duracion);
}
}

// Encendido intermitente del led //
void blink_red(int veces, int duracion)
{ int i;
for (i=0;i<veces;i++)
{
output_bit(PIN_A2,1);
delay_ms(duracion);
output_bit(PIN_A2,0);
delay_ms(duracion);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////// RUTINAS DE INTERRUPCION ///////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#int_ext
void ext_isr()
{
}

#int_rda
void serial_isr()
{
rda=TRUE;
Rx[0]=getc();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// ///////////////////////////////////////////////////
///////////////////////////////////////////////// PROGRAMA PRINCIPAL ///////////////////////////////////////////////////
///////////////////////////////////////////////// ///////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void main()
{

#ZERO_RAM

// Configuro periféricos para bajo consumo //
setup_timer_2(T2_DISABLED,0,2);
setup_ccp1(CCP_OFF);
setup_adc(ADC_OFF);
setup_vref(FALSE);

// Configuro puertos para bajo consumo //
port_b_pullups(TRUE);

// Habilito interrupciones //
ext_int_edge(H_to_L);
enable_interrupts(INT_EXT);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);

// Fin de configuración //
blink_red(3,50);
blink_green(3,50);

// Habilito RS232 //
output_bit(PIN_A1,0);
output_bit(PIN_A0,1);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////// RUTINA QUE DETERMINA LA TAREA QUE DEBE REALIZARSE ////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Loop:
sleep();

///////////////////////////////////////////////////////////
if (input(PIN_B0) == FALSE)
{
do {} While (input(PIN_B0) == FALSE);
delay_ms(200);
putc('?');
delay_ms(200);
}

if (rda==TRUE) blink_green(3,10);
rda = FALSE;
///////////////////////////////////////////////////////////

goto Loop;
}

What you post here, should not work.
The problem is that the processor clock stops when you enter sleep mode, so the UART, cannot wake the chip up. It _can_ wake the chip if you are running as a USART in synchronous mode (using an external clock), but not when running in async mode as a UART.
One thought, would be to join the incoming serial data line, to the INT interrupt pin. This signal can then be used to wake the chip, and the data will then follow. However even this is dangerous, because the 'start time' of the crystal oscillator will probably be enough to prevent the data being properly received. Unless you need the low power associated with sleep, or can work out a way of waking the chip in advance of the data coming (using a RS232 status line for example), I would not put the chip to sleep for this application.

Best Wishes
Gabriel Caffese



Joined: 09 Oct 2003
Posts: 39
Location: LA PLATA, ARGENTINA

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

PostPosted: Wed Jun 23, 2004 10:21 am     Reply with quote

Ttelmah,

First, thanks for replying.

The process is this way. INT_RB0 (int.ext.) and INT_RDA are enabled.
When an external interrupt is generated, the PIC gets out of sleep mode, then the UART sends a character, to which the PC has to reply to (it certainly does so).
The thing is that first time the PIC receives an external interrupt, everything works fine. But next time you generate an external interrupt, the character is sent to the PC (and the PC replies with another), but 16F88 doesn't seem to detect it, cause the led doesn?t blink at all.

Any clue ?

Gabriel.-
Joan



Joined: 29 May 2004
Posts: 41
Location: Barcelona, Spain

View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger

PostPosted: Wed Jun 23, 2004 4:04 pm     Reply with quote

Gabriel Caffese wrote:
Ttelmah,

First, thanks for replying.

The process is this way. INT_RB0 (int.ext.) and INT_RDA are enabled.
When an external interrupt is generated, the PIC gets out of sleep mode, then the UART sends a character, to wich the PC has to reply to (it certainly does so).
The thing is that first time the PIC receives an external interrupt, everything works fine. But next time you generate an external interrupt, the character is sent to the PC (and the PC replies whith another), but 16F88 doesn´t seem to detect it, cause the led doesn´t blink at all.

Any clue ?

Gabriel.-


Hola:
has probado con rearmar la interrupción dentro de la isr correspondiente ?

( Algo así como INTF=0;)

Saludos Cordiales;
Joan Exclamation
_________________
I Came. I Saw. I Won.
Humberto



Joined: 08 Sep 2003
Posts: 1215
Location: Buenos Aires, La Reina del Plata

View user's profile Send private message

PostPosted: Wed Jun 23, 2004 5:07 pm     Reply with quote

Hi Gabriel,

I will try in this way.

Code:


#int_rda
void serial_isr()
{
  rda=TRUE;
  Rx[0] = 0x00;

  if(kbhit)  // Not to "hang" in getc()
   {
     Rx[0]=getc();
   }
}


while(1)
   { 
     sleep();

     do
        {} while(input(PIN_B0));   // Do nothing while B0 == HIGH
     // The going down Start Bit must trigger the wake-up, break
     // this while and hopfully catch the incoming char, not sure if
     // the rigth one but in your example it doesn´t matter.
     
     delay_ms(10);  // To catch the char in background in your
                            // interrupt routine
         
      if(Rx[0] != 0x00)
        {
          putc('?');
         }
       delay_ms(200);
     

      if (rda)
         {
           blink_green(3,10);
           rda = FALSE;
         }
   }



No time to compile and test, just the idea. HTH

Best regards,

Humberto


PD: Me voy ya a ver el partido de Boca Juniors !!!



.
Joan



Joined: 29 May 2004
Posts: 41
Location: Barcelona, Spain

View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger

PostPosted: Thu Jun 24, 2004 3:42 am     Reply with quote

Hi:
If you have a look at the 16F88/87 Datasheet it says something like ...

Microchip wrote:
5.2 PORTB and the TRISB Register

RB0/INT is an external interrupt input pin and is configured using the INTEDG bit (OPTION<6>).


REGISTER 2-2: OPTION REGISTER (ADDRESS 81h, 181h)

bit 6 INTEDG: Interrupt Edge Select bit

1 = Interrupt on rising edge of RB0/INT pin
0 = Interrupt on falling edge of RB0/INT pin


2.2.2.3 INTCON Register


bit 1 INTF: RB0/INT External Interrupt Flag bit

1 = The RB0/INT external interrupt occurred (must be cleared in software)
0 = The RB0/INT external interrupt did not occur


Best Regadrs;
Joan Idea
_________________
I Came. I Saw. I Won.
Gabriel Caffese



Joined: 09 Oct 2003
Posts: 39
Location: LA PLATA, ARGENTINA

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

PostPosted: Thu Jun 24, 2004 8:43 am     Reply with quote

Humberto y Joan,

Gracias a ambos por responder. Sigo en inglés, para que el resto entienda.
The RB0 ISR, automatically clears that flags when exiting.
Now, I have found the problem -but don´t know how to solve it-

For lowering power consumption to 4uA, I have to turn off every peripheral. RS232 transmision is being done using pairs of IR Led and phototransistor on both sides.
So, I stop "feeding" both IR, and am on 100uA, then, disabling RS232 on 16F88, get those 4uA. The only thing that keeps working (and consuming) is T1, with an 32,768Khz crystal.
Then, when receiving an external interrupt, I turn on RS232 module. TX works OK, but RX does NEVER work again.
It works OK before turning off RS232, but if I disable it, and then re-enable, it will never ever work until reset.

Up to now, have no clues. Any help ??

Gabriel.-
Ttelmah
Guest







PostPosted: Thu Jun 24, 2004 9:52 am     Reply with quote

Gabriel Caffese wrote:
Humberto y Joan,

Gracias a ambos por responder. Sigo en inglés, para que el resto entienda.
The RB0 ISR, automatically clears that flags when exiting.
Now, I have found the problem -but don´t know how to solve it-

For lowering power consumption to 4uA, I have to turn off every peripheral. RS232 transmision is being done using pairs of IR Led and phototransistor on both sides.
So, I stop "feeding" both IR, and am on 100uA, then, disabling RS232 on 16F88, get those 4uA. The only thing that keeps working (and consuming) is T1, with an 32,768Khz crystal.
Then, when receiving an external interrupt, I turn on RS232 module. TX works OK, but RX does NEVER work again.
It works OK before turning off RS232, but if I disable it, and then re-enable, it will never ever work until reset.

Up to now, have no clues. Any help ??

Gabriel.-

How are you 'turning off the RS232'?.
You should only need to toggle bit 7 of RCSTA.
I'd do something like:

#bit SPEN=0x18.7
#bit FERR=0x18.2
#bit OERR=0x18.1

#define serial_off() disable_interrupts(INT_RDA);\
disable_interrupts(INT_TDA);\
SPEN=0

#define serial_on() clear_interrupts(INT_RDA);\
clear_interrupts(INT_TDA);\
SPEN=1;\
FERR=0;\
if (OERR) getchar();\
enable_interrupts(INT_RDA);\
enable_interrupts(INT_TDA)

Remember that if you take control of the port bits to minimise power consumption, you must also set them back to the correct state.
This should be a pretty reliable way of switching the port off/on.

Best Wishes
Gabriel Caffese



Joined: 09 Oct 2003
Posts: 39
Location: LA PLATA, ARGENTINA

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

PostPosted: Thu Jun 24, 2004 9:59 am     Reply with quote

Ttelmah,

I´m going out to work. I will check this tonight and
post what happened. Thank´s for this information.

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