|
|
View previous topic :: View next topic |
Author |
Message |
aroman
Joined: 06 Oct 2003 Posts: 12
|
How to implement HW UART Rx timeout |
Posted: Mon Aug 16, 2004 12:51 pm |
|
|
Hello all,
I am using the hardware USART of a PIC16F876 in asynchronous mode, 2400 bps, 8 data bits, 1 stop bit and no parity. The Rx pin of the PIC16F876 (pin C7) is directly connected to the output pin of a RF receiver. I am using the receiver of the USART by "polling" (not by interrupt) and I can receive the incoming characters based on the getc() function. Here is the code from my receiving function and its related code:
Code: |
#include <16F876.h>
#use delay(clock=76800)
#fuses LP,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
#use rs232(baud=2400, parity = N, xmit = PIN_C6,rcv=PIN_C7,bits=8,errors)
#byte rxstatus = 0x18 //Direccion del registro donde se controla la recepcion de la UART
char recibe_caracter(){ //este procedimiento recibe un caracter por el RS232
char caracter_recibido = 0; //son los diferentes caracteres recibidos por el RS232 del Rx provenientes
//del sensor
int i = 2; //es la posición en el vector char1[i]
char char1[12];//vector que va almacenando los diferentes caracteres recibidos por el RS232 provenientes
//del sensor
short ya_capturo_char_OK = FALSE;//bandera que indica si ya capturó el dato correctamente
do {
caracter_recibido=getch(); // Espera a recibir un caracter por el puerto serial.
if ((rxstatus == 0x90)&&(caracter_recibido!=0x00)){//Si rxstatus es 90h significa que
//el caracter recibido no tiene
//error de overrun ni de framing
//El caracter 00h es un caracter de
//sincronización pues su forma de
//no es "confundible" con ningún
//otro
char1[i]=caracter_recibido;//Almacena el i-esimo caracter "no cero" recibido en char1 en la posicion i
if (char1[i-1]==char1[i]) {//si el caracter que acaba de recibir es igual al anterior que habia almacenado
if (char1[i-2]==char1[i]) {//y si ademas tambien es igual al que transanterior que recibio
ya_capturo_char_OK = TRUE;//ya hay 3 seguidos iguales, por lo que considera el caracter recibido como
//valido
}//del if char1[i-2]==char1[i]
}//del if char1[i-1]==char1[i]
i++;
}//del if ((rxstatus == 0x90)&&(caracter_recibido!=0x00))
}
while (!ya_capturo_char_OK);//del while
return (char1[i-1]);//retorna el caracter anterior, pero tambien pudo ser el transanterior o el actual (los 3 son
//iguales)
}//del recibe_caracter
void main() { //aquí inicia el programa principal
char dir_sensor_c=0; //son los caracteres que se reciben por el RX del RS232 con la
//dirección del sensor
disable_interrupts(global); //se deshabilitan las interrupciones pues la recepción se hace
//por "polling" y no por interrupción
dir_sensor_c=recibe_caracter(); //Espera a recibir la direccion del sensor para verificar si
//la transmisión fue exitosa
write_eeprom (1, dir_sensor_c);
}//fin del main
|
I only have to invoke my receiving function in my main() function whenever I expect to receive a character. As you can see, I only consider valid those characters that do not have neither overrun nor framing errors, and those characters that are "non-0x00" (I am using the character "0x00" as a "preamble" or "synchronization" character, so before transmitting any "valid" data, I always transmit at least one "0x00" character).
Now, I need to implement a "timeout" function for the incoming characters, so that if after waiting a certain amount of time I do not detect any incoming (valid) characters, I need to exit from the receiving function and do something else in my main() function. I think that the main problem that I have to implement it is related to my hardware: the RF receiver that I am using (a MICRF002 from Micrel, which works at 315 MHz and uses ASK/OOK demodulation) has an output waveform that is 0 V when there is no RF signal in the air, with some "raises" to a positive voltage, but for a very little period of time (compared with the 2400 bps, which is the speed at which the valid characters are sent). These "raises" are not considered valid received data, because even tough the result of the getc() function is a "0x00" as data, it has overrun and/or framing errors, so in my receiving function I don't consider these as valid data (only when there are no overrun and framing errors). I know that in normal conditions, the Rx pin of the PIC should be +5V when there is no incoming signal, just the opposite that happens with the RF receiver that I have.
I tried to implement the "timeout" function using the kbhit() function, but it did not work because it is always TRUE (due to the output waveform of the RF receiver), even if there is no RF signal in the air. I also tried to do it by using the RCIF flag directly from the PIC registry, but it was always TRUE also (for the same reason). I already checked some messages from these same Forum (like one with the name "Can't get rs232 to time out" from "Simon Thompson", that's where I get the idea of using the kbhit() function), but it did not work. Does please anyone have an idea of how to implement the timeout function given the output waveform of the RF receiver (preferably without modifying too much my code, and using the receiver of the USART by polling)? I don't have too much experience programming PICs yet.
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Aug 16, 2004 2:42 pm |
|
|
Quote: | I know that in normal conditions, the Rx pin of the PIC should be
+5V when there is no incoming signal, just the opposite that happens
with the RF receiver that I have. |
To fix this, put an inverter between the PIC and the RF transmitter.
Also, on the receive side, put an inverter between the output of
the Micrel Receiver and the PIC.
Then, a start bit will be a Logic '1' level when it comes out of the
Micrel receiver. It will be inverted by the inverter chip (that you
will add) before it goes to the PIC. So the PIC will get a Logic '0'
as the start bit, which is what it needs. If the RF input is not
present, the Micrel receiver will put out a '0', and the inverter
will make it into a '1', and this will cause the USART in the PIC
to be in an idle state. It won't start receiving a character when
no real character has been sent.
I'm assuming that you control the circuits for both the transmit side
and the receive side. Otherwise, this idea won't work. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Aug 16, 2004 2:57 pm |
|
|
The device doesn't use the transmit of the UART only the receive. Since you are polling, you could use a software UART and use the invert if the signal needs to be inverted. I believe there is a signal present when there is data. |
|
|
Ttelmah Guest
|
|
Posted: Mon Aug 16, 2004 3:07 pm |
|
|
For the timeout, do a search on the forum. Neutone, published a tidy routine, which uses a timer interrupt to implement a timeout, while waiting for received characters.
Best Wishes |
|
|
|
|
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
|