Hello mr's, 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.
I think we need to know more about the variables you are using. For example what type is 'int1', 'bkbhit', 'bgetc' and 'returns'?
Should barcode_buffer[2] really have zero in it? It would work as a string terminator.
Should you 'disable_interrupts(INT_RDA), whatever that is , without re-enabling it again somewhere?
I think we need to know more about the variables you are using. For example what type is 'int1', 'bkbhit', 'bgetc' and 'returns'?
Should barcode_buffer[2] really have zero in it? It would work as a string terminator.
Should you 'disable_interrupts(INT_RDA), whatever that is , without re-enabling it again somewhere?
Hi Brian;
int1 is a 1 bit variable, short int, in CCS
bkbhit is a function that takes the characters from the INT_RDA serial interrupt and sends to the while, the bkbhit function along with what occurs while is a buffer (variables in a circle).
returns is a name I put, it returns (actually sends) YES or NO characters to the software on a PC.
I'll edit the code and put more information, I understood that only a piece would help those who could help me!
[TABLE][TR][TD]#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 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_RDAvoid serial_isr(){
restartRS232();// It's unnecessarily hereint 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 displayif(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 enablesif(!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;}[/TD][TD][/TD][/TR][/TABLE]
--- Updated ---
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.
--- Updated ---
would the transmit register be locking the receive register?
hello Klaus, I just put a piece of code so it doesn't get too long, I'm a programming apprentice, but I've already made a code that works perfectly on a pic16f876, and I'm using 66% of this pic.
With the exception of this situation, it does not reactivate INT_RDA (serial interruption). See that I edited the code, and improved it, but still there are the main commands.
in void restartRS232()
you must also read the UART RX register (=> empty buffer) to clear the error
Frame error or Overrun error are blocking status if not cleared.
In addition to showing the faulty code, you should say what it is supposed to do.
There are many instructions spread inline which surely could be enclosed into specific functions.
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.
Friends, I managed to find where the error was, after 1 week suffering from it.
This is very good to learn
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.