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

Serial interrupt RX-C7 crashes after sending TX-C6 char PC
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
erpgc82



Joined: 02 May 2020
Posts: 73

View user's profile Send private message Send e-mail

Serial interrupt RX-C7 crashes after sending TX-C6 char PC
PostPosted: Thu Mar 25, 2021 3:42 pm     Reply with quote

Hello friends, I'm having a problem here and I'm not able to solve it, I don't know what happens, if it is some bit of some transmission register that I must clear, if it is the serial interrupt that I need to clear clear_interrupts (INT_RDA) ;.
I put delay_ms (1) as a test, after sending the character.
I've done clear_interrupts (INT_RDA); after re-enabling the serial interrupt.
Anyway, I've done everything and nothing works.

Here is just a piece of the code.

Today I can get the string that arrives at the RX (hardware) I do what I have to do with it and send it to the PC via TX (hardware) and it works perfectly.

The response variable, if it is 1 (TRUE) when the PIC reads sensors / input pins, it must send a certain character to the PC, only when doing this the serial interrupt #INT_RDA stops working.

If the response variable is 0 (FALSE), that is, never send characters to the PC, the serial interrupt works perfectly. Note¹: it always stops when a certain number of characters arrives, and then right after a certain function that takes about 5 seconds to occur, the serial interruption is reactivated and this works PERFECTLY.

I'm not getting to know why it hangs / stops after sending a character to the PC. Note¹: Whenever I send a character to the computer, the serial interrupt is activated (at least it was supposed to be) because until then the PIC had not read anything from it and so it was not deactivated.




Code:


#include <16F876a.h>
#case                     
#use delay(clock=10000000) 
 
#fuses HS,NOWDT, PUT, BROWNOUT, NOLVP
#use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8, stop=1, ERRORS)
 
int1 returns=1;
char X='X';
char Y='Y';

#INT_RDA
void serial_isr()
{
    restartRS232();  // It's unnecessarily here
    int t; 
   
    buffer[next_in]=getc();
    t=next_in;
    next_in=(next_in+1)%BUFFER_SIZE; 
    if(next_in==next_out) next_in=t;   
}
 
BYTE bgetc()
{
    BYTE c;
    while(!bkbhit);
    c=buffer[next_out];
    next_out=(next_out+1)%BUFFER_SIZE;
    return(c);
}

void main()
{
    enable_interrupts(GLOBAL);
    enable_interrupts(INT_RDA);
     
     while(TRUE)
    {
            if(bkbhit)
           {
            c=bgetc();
            if(c=='0')
            {
                key_card=TRUE;
                clean_keyboard();
                output_high(BEEP);
                delay_ms(40);
                output_low(BEEP);
                barcode_buffer[0]=c;       
                barcode_buffer[1]=bgetc(); 
                barcode_buffer[2]=bgetc(); 
                barcode_buffer[3]=bgetc(); 
                barcode_buffer[2]=0;       
                printf("%c%c%c%c%c%cC\n\r",barcode_buffer[0],barcode_buffer[1],barcode_buffer[2],barcode_buffer[3]);
                d_int_rda=FALSE;
                disable_interrupts(INT_RDA);
                read_code();
            }
             /*******************************************************************************************/
             if((returns)&&(!input(SENSOR_OUT))) printf("%c\r\n",X);
             if((returns)&&(!input(SENSOR_IN)))    printf("%c\r\n",Y);             
        }
    }
}
[/code]
_________________
Gradually you will go far with persistence, will and determination!
erpgc82



Joined: 02 May 2020
Posts: 73

View user's profile Send private message Send e-mail

I edited the code better
PostPosted: Thu Mar 25, 2021 8:10 pm     Reply with quote

Observation. the time_td variable is reported as true (1) within the read_code () function as this function only displays the code on the LCD display and returns to the while, then makes contact and then returns to the standard message, and automatically enabling the enable_interrupts function (INT_RDA);

I also tried before rehabilitating using the function
clear_interrupts (INT_RDA); but it's no use, the problem is sending a simple character "printf (" X ");" and the interruption doesn't work again.


Code:

#include <16F876a.h>
#case
#use delay(clock=10000000)

#fuses HS,NOWDT, PUT, BROWNOUT, NOLVP
#use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8, stop=1, ERRORS)

#include "display_8bits16f876.c"

#define BUFFER_SIZE 32
#define BEEP        PIN_A2
#define SENSOR_IN   PIN_A3
#define SENSOR_OUT  PIN_A4
#define bkbhit      (next_in!=next_out)
BYTE  next_in                 = 0;
BYTE  next_out                = 0;
BYTE  buffer                    [BUFFER_SIZE];
int8  barcode_buffer            [10];

int1  returns     = 1; // short int returns=TRUE; // Checks whether to send characters to the PC software
int1  time_Td     = 0; // Checks whether to enter the time count
int1  d_int_rda   = 0; // checks if the serial interrupt is disabled
int1  msg_default = 0; // checks whether to display the standard message on the LCD
int8  code        = 0;
char X='X';
char Y='Y';

void restartRS232();
void msg_Default();

#INT_RDA
void serial_isr()
{
   restartRS232(); // It's unnecessarily here
   int t;

   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1)%BUFFER_SIZE;
   if(next_in==next_out) next_in=t;
}

BYTE bgetc()
{
   BYTE c;
   while(!bkbhit);
   c=buffer[next_out];
   next_out=(next_out+1)%BUFFER_SIZE;
   return(c);
}

void main()
{
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_RDA);
   setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_256);
   setup_timer_1(T1_DISABLED);
   set_timer0(11);   
   display_ini();

   while(TRUE)
   {
        if(d_int_rda)   // check if it is to re-enable the interruption and if it is true, re-enable
        {
            enable_interrupts(INT_RDA); /* Without considering, that the function enable_interrupts (INT_RDA);
                                         * already starts in main (), but if it is disabled, then re-enable*/                                         
            delay_ms(1);
            d_int_rda=FALSE;
        }
       
        if(!msg_default) msg_Default(); // if you are not displaying the default message, then display
       
        if(time_Td) 
        {
            if(tmr0if)
            {
                tmr0if=0;     
                set_timer0(11); // initializes timer0
                code++;      // increments the variable that will define the time that the code will be displayed on the LCD
            }
        }       
        if(code>=200)
        {
            tmr0if=0;                     
            code=0;
            msg_Default();  // After a XX time displaying the characters on the LCD, it then returns to the standard message       
        }                   /**************************************************
                             * It turns out that, if the situations have not occurred:
                             * if ((returns) && (! input (SENSOR_IN))) printf ("% c \ r \ n", Y);
                             * or
                             * if ((returns) && (! input (SENSOR_OUT))) printf ("% c \ r \ n", X);
                             * the serial interrupt works again, and the characters are received.
                             *
                             * But if you receive an electric pulse on the corresponding pin and the
                             * interruption is disabled, when the "d_int_rda" flag returns to re-enable
                             * the serial interruption, calling the enable_interrupts (INT_RDA)
                             * function, nothing happens, it does not receive any more characters.
                             * Then, making only the flag returns to 0 or FALSE, so as not to receive
                             * any more electrical pulse, then the interruption will work again, being
                             * disabled and re-enabled normally.*/
           
       if(bkbhit)     /* Next to INT_RDA and bgetc () it takes the characters it stores in
                      * a character array. Circular buffer.*/
       {
         c=bgetc();
         if(c=='0')       
         { 
            output_high(BEEP);
            delay_ms(40);
            output_low(BEEP);
            barcode_buffer[0]=c;
            barcode_buffer[1]=bgetc();
            barcode_buffer[2]=bgetc();
            barcode_buffer[3]=bgetc();
            barcode_buffer[2]=0;
            printf("%c%c%c%c%c%cC\n\r",barcode_buffer[0],barcode_buffer[1],barcode_buffer[2],barcode_buffer[3]);
            d_int_rda=FALSE;       /* Disables the standard message, and displays the numbers read on the LCD.
                                    * I did not put the function of displaying the codes read on the LCD here,
                                    * as I thought it was unnecessary not to get too long the code*/
            disable_interrupts(INT_RDA); /* I disable the serial interrupt, so that I don't receive
                                          * another character while doing certain situations or commands.*/
            read_code();            // This function displays the received code on the LCD display, it is 4 characters.         
         }
/*******************************************************************************************/
         if((returns)&&(!input(SENSOR_OUT))) printf("%c\r\n",X);  /* if returns are true, and receive an electrical pulse
                                                                   * on the SENSOR_OUT pin, send an X character to the PC software*/
         if((returns)&&(!input(SENSOR_IN))) printf("%c\r\n",Y);   /* if returns are true, and receive an electrical pulse
                                                                    * on the SENSOR_IN pin, send a Y character to the PC software*/
      } 
   }
}

void restartRS232()           /* Error checking routine, call it at the beginning of the interrupt function: See example below.
                               * But it hasn't solved anything*/
{
   if (OERR || FERR) // RS232 Error Handling 
   {                 // Reset / Clear errors in reception usart
      SPEN = 1;
      CREN = 0;
      delay_us (1);
      CREN = 1;
      delay_us (1);
      return;
   }
}

void msg_Default()
{                   
    if(!msg_default)      msg_default = TRUE;   // checks if the default message is disabled and then enables
    if (!d_int_rda)       d_int_rda = TRUE;     // checks if the serial interrupt is disabled and re-enables
     
    // write these messages and go back to the while
    printf(write_display,"\f>>>>  Test  <<<<");
    printf(write_display,"\n>>    Ready   <<");
    return;
}
[/code]
_________________
Gradually you will go far with persistence, will and determination!


Last edited by erpgc82 on Fri Mar 26, 2021 10:21 am; edited 1 time in total
erpgc82



Joined: 02 May 2020
Posts: 73

View user's profile Send private message Send e-mail

transmit register ???
PostPosted: Thu Mar 25, 2021 8:16 pm     Reply with quote

would the transmit register be locking the receive register?

I'm new to programming, sorry for the ignorance.
_________________
Gradually you will go far with persistence, will and determination!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 25, 2021 10:02 pm     Reply with quote

The code is not compilable by us. It's missing the BUFFER_SIZE #define
statement. It's missing the definition of tmr0if. In main() it uses the
variable 'c', but there's no declaration statement of 'c'. Etc.

Fix all this stuff. Post a program that we can drop into MPLAB and compile.


In the code below, you are using the same name for a function and
a variable. Don't do this.
Quote:
void msg_Default()
{
if(!msg_default) msg_default = TRUE; // checks if the default message is disabled and then enables
if (!d_int_rda) d_int_rda = TRUE; // checks if the serial interrupt is disabled and re-enables

// write these messages and go back to the while
printf(write_display,"\f>>>> Test <<<<");
printf(write_display,"\n>> Ready <<");
return;
}
erpgc82



Joined: 02 May 2020
Posts: 73

View user's profile Send private message Send e-mail

PostPosted: Fri Mar 26, 2021 10:22 am     Reply with quote

PCM programmer wrote:
The code is not compilable by us. It's missing the BUFFER_SIZE #define
statement. It's missing the definition of tmr0if. In main() it uses the
variable 'c', but there's no declaration statement of 'c'. Etc.

Fix all this stuff. Post a program that we can drop into MPLAB and compile.


In the code below, you are using the same name for a function and
a variable. Don't do this.
Quote:
void msg_Default()
{
if(!msg_default) msg_default = TRUE; // checks if the default message is disabled and then enables
if (!d_int_rda) d_int_rda = TRUE; // checks if the serial interrupt is disabled and re-enables

// write these messages and go back to the while
printf(write_display,"\f>>>> Test <<<<");
printf(write_display,"\n>> Ready <<");
return;
}



Hello PCM programmer, consider the last code I posted.

See that I used the directive #case and msg_default is in lowercase and msg_Default () is in uppercase.

I liked the #case directive :-)
_________________
Gradually you will go far with persistence, will and determination!
erpgc82



Joined: 02 May 2020
Posts: 73

View user's profile Send private message Send e-mail

NEVER DISABLE SERIAL INTERRUPTION
PostPosted: Fri Mar 26, 2021 10:25 am     Reply with quote

I've been thinking, and I'm going to do another programming test.

NEVER DISABLE SERIAL INTERRUPTION, use a "flag" and then delete the characters that are in the matrix, if they arrive at a time when INT_RDA would be deactivated.
_________________
Gradually you will go far with persistence, will and determination!
erpgc82



Joined: 02 May 2020
Posts: 73

View user's profile Send private message Send e-mail

reception stops working, even enabled 100% of the time.
PostPosted: Fri Mar 26, 2021 1:57 pm     Reply with quote

I just tested here, and the problem is not even the interruption, now I have NEVER set the serial interruption to be disabled, and even so, when sending any character eg: printf ("x") to the pc / software the interruption stops to work, I really don’t know what’s going on, I’ll put that aside and then come back, because I need to send characters to the pc / software.
_________________
Gradually you will go far with persistence, will and determination!
erpgc82



Joined: 02 May 2020
Posts: 73

View user's profile Send private message Send e-mail

;;
PostPosted: Sat Mar 27, 2021 11:15 am     Reply with quote

Hello, could someone with experience help me?
_________________
Gradually you will go far with persistence, will and determination!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Mar 27, 2021 12:12 pm     Reply with quote

Your claim is that doing a printf("x") disables RDA interrupts or perhaps
disables Global interrupts.

What's your CCS compiler version ?

What happens if you subsitute putc('x') for the printf("x") ?
Does it still fail to receive ?
erpgc82



Joined: 02 May 2020
Posts: 73

View user's profile Send private message Send e-mail

PostPosted: Sat Mar 27, 2021 12:30 pm     Reply with quote

PCM programmer wrote:
Your claim is that doing a printf("x") disables RDA interrupts or perhaps
disables Global interrupts.

What's your CCS compiler version ?

What happens if you subsitute putc('x') for the printf("x") ?
Does it still fail to receive ?



was using printf ()
I started using putc () and the problem also occurs

I'm reading the datasheet and seeing the SPEN CREN FERR OERR SYNC TXIE RCIE TXEN TXIF RCIF GIE PEIE registers I will follow everyone, monitor everyone on the LCD and see what happens before locking and after locking ...

Version 5.076
_________________
Gradually you will go far with persistence, will and determination!
erpgc82



Joined: 02 May 2020
Posts: 73

View user's profile Send private message Send e-mail

PostPosted: Sat Mar 27, 2021 1:09 pm     Reply with quote

PCM programmer wrote:
Your claim is that doing a printf("x") disables RDA interrupts or perhaps
disables Global interrupts.

What's your CCS compiler version ?

What happens if you subsitute putc('x') for the printf("x") ?
Does it still fail to receive ?




I just identified a new situation.

the FERR, BIT 2 bit of the RCSTA is at 0 when everything works correctly, and stays at 1 after sending a single character to the TX of the pc / software.

So this function could solve?
void restartRS232 () // Error checking routine, call it at the beginning of the interrupt function: See example below.


I am also monitoring the TXREG byte and after sending the first character to the pc / software, it has several invalid characters

the restartRS232 () function does not solve the problem when cleaning.

when I press a key that is in PIN_A1 or PIN_A2 the reading of the RX (INT_RDA) returns to work. Make a reading, but when sending one (1) minimum character to the pc, it will stop again ...

But I found that these PIN_A1 and PIN_A2 are just digital ports.




Code:

{
     if (OERR || FERR) // Error Handling RS232
     {// Reset / Clear errors in reception usart
        SPEN = 1;
        CREN = 0;
        delay_us (1);
        CREN = 1;
        delay_us (1);
        Returns;
     }
}

_________________
Gradually you will go far with persistence, will and determination!


Last edited by erpgc82 on Sat Mar 27, 2021 2:21 pm; edited 1 time in total
temtronic



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

View user's profile Send private message

PostPosted: Sat Mar 27, 2021 2:20 pm     Reply with quote

OK, I have to ask...
what device do you have between the PIC and the PC ?

normally I use a TTL to USB module..as modern Pcs do not have true 'RS-232' ports anymore.

I've used the ex-sisr.c code for years, so I KNOW it's reliable.

Jay
erpgc82



Joined: 02 May 2020
Posts: 73

View user's profile Send private message Send e-mail

PostPosted: Sat Mar 27, 2021 2:25 pm     Reply with quote

temtronic wrote:
OK, I have to ask...
what device do you have between the PIC and the PC ?

normally I use a TTL to USB module..as modern Pcs do not have true 'RS-232' ports anymore.

I've used the ex-sisr.c code for years, so I KNOW it's reliable.

Jay


I'm using a usr TCP / T2 network module purchased on aliexpress.

when in doubt I have also used a small ftdi module purchased from digikey.

this is not the problem, i have no problem with communication (external to pic)

what happens is that the PIC stops receiving characters in the serial interruption, after sending something to the pc.

I am researching the recorders for this 16f876, but as I am inexperienced, I may be on the wrong subject.
_________________
Gradually you will go far with persistence, will and determination!
erpgc82



Joined: 02 May 2020
Posts: 73

View user's profile Send private message Send e-mail

resolved
PostPosted: Sat Mar 27, 2021 2:38 pm     Reply with quote

Friends, I managed to find where the error was, after 1 week suffering from it.

This is very good to learn Very Happy

I was doing the directives
#use fast_io (c)

then in main ()
{
set_tris_c (0b00000000); // all pins as output
output_c (0b00000000); // all pins at 0V
}

and just now I thought, the TX and RX pins are from the portC and if that is the problem?

but the use of rom increased considerably in percentage%.

so i commented the lines and the problem disappeared, now i can send characters to the pc (serial monitor) normally, which does not lock the serial interrupt. Very Happy
_________________
Gradually you will go far with persistence, will and determination!
temtronic



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

View user's profile Send private message

PostPosted: Sat Mar 27, 2021 3:14 pm     Reply with quote

Don't bother using 'fast_io' and 'set _tris', let the compiler do it AUTOMATICALLY for you !!!
In over 2 decades of using PICs, I've only needed fast_io/set-tris TWICE. Both were to interface to proprietary, custom serial devices that needed precise timing.

I have no idea why the %increase in ROM, unless you've made changes.

Jay
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