View previous topic :: View next topic |
Author |
Message |
niuton
Joined: 28 Jun 2009 Posts: 4
|
(running) 18F problem receiving data rs232 (USART locked) |
Posted: Sun Jun 28, 2009 4:41 pm |
|
|
Hello everybody, I'm a new component in this forum. I need help with comunication PIC -> PC, receipt from a 18F4520 PIC and a PC via RS232. I am programming with CCS C, everything works well in a time 10sec - 1min RDA interruption but then no fire. Still sending data PIC -> PC, but on the contrary ignores the data it receives. It's as if USART locked using the reception. I have simulated Proteus and passes it and then test and then the PIC and it happens as in the simulation.
Code: |
#include <18F4520.h>
#device ADC = 10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=19200, parity=N, xmit=PIN_C6, rcv=PIN_C7)
#int_rda
void rda_isr() {
if(kbhit()){
codigo_buffer[indice_rs232] = getc();
indice_rs232 = indice_rs232 + 1;
if (codigo_buffer[0]=='$' && codigo_buffer[9]=='#'){
indice_rs232 = 0; /
duty_PWM1 = make16(codigo_buffer[1], codigo_buffer[2]);
set_pwm1_duty(duty_PWM1); //Actualizo el PWM
}
}
}
} |
I do not know what is happening or how to solve. I tried to activate interrupts but still the same.
A greeting and thanks.
Last edited by niuton on Mon Jun 29, 2009 4:03 pm; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 28, 2009 4:59 pm |
|
|
You didn't post a complete test program. Are you disabling INT_RDA
interrupts in your program ? If so, it's possible that the UART could
get an overrun error. This would lock up the UART. Add the ERRORS
parameter to the #use rs232() statement to automatically clear an
overrun error. Example:
Quote: |
#use rs232(baud=19200, parity=N, xmit=PIN_C6, rcv=PIN_C7, ERRORS) |
|
|
|
Guest
|
|
Posted: Sun Jun 28, 2009 5:25 pm |
|
|
Hi,
A couple of things. You can get rid of the kbhit() statement inside your ISR. It's redundant - if the ISR fires, by definition you have a character waiting in the Rx buffer. Also, get rid of everything inside the ISR that is not related to receiving characters and putting them in your receive buffer. Instead, set a Rx_Valid flag (for example) and do all your Make and PWM funtions in Main. This is much better programming style, although I don't believe either is the culprit in your current problem....
Frank |
|
|
niuton
Joined: 28 Jun 2009 Posts: 4
|
|
Posted: Sun Jun 28, 2009 5:38 pm |
|
|
Thanks for replying so quickly (PCM_programer and FRANK),
Frank: You're right, I have to change the contents of the RDA and put it in the main.
PCM_programer: I did not disable the interruption RDA.
I have made a VB program that sends data every 50ms to the PIC.
I tried to include the "ERRORS" and somewhat improved but still failing by losing many packages. Do you know any solution?
Code: |
#include <18F4520.h>
#device ADC = 10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=19200, parity=N, xmit=PIN_C6, rcv=PIN_C7)
#define ALL_OUT 0
#define ALL_IN 0xff
#define numero 10
int8 t_Vref = 0, Vref_flag = 0;
int16 tension_V, tension_F;
unsigned int16 duty_PWM1 = 0;
#define MAX_PWM 1000
#define MIN_PWM 0
int1 comenzar=0;
int1 hay_comando=0;
int16 muestreo = 0x0BDC;
int8 codigo_buffer[numero],indice_rs232=0;
void read_Vel(void)
{
delay_us(10);
SET_ADC_CHANNEL(2); //MOTOR "R"
delay_us(10);
tension_F = READ_ADC();
}
#int_rda
void rda_isr() {
if(kbhit()){
codigo_buffer[indice_rs232] = getc();
indice_rs232 = indice_rs232 + 1;
if (comenzar == 1 && codigo_buffer[0]=='$' && codigo_buffer[9]=='#'){
indice_rs232 = 0;
if (codigo_buffer[1] != 0x46){
duty_PWM1 = make16(codigo_buffer[1], codigo_buffer[2]);
set_pwm1_duty(duty_PWM1);
}else
comenzar = 0;
codigo_buffer[0]=0;
codigo_buffer[9]=0;
}
}
}
#int_TIMER3
void timer3_isr(void){
set_timer3(muestreo);
read_Vel();
putc('$');
putc(tension_F>>8);
putc(tension_F&0x00FF);
putc('#');
}
//////////////////////////////////////////
//////////////////////////////////////////
void main() {
delay_ms(333);
disable_interrupts(global);
set_tris_d(0x00);//ALL_OUT);
set_tris_b(0x00);//ALL_OUT);
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_DIV_32);
setup_timer_3(T3_INTERNAL|T3_DIV_BY_4);
setup_ccp1 (CCP_PWM);
setup_ccp2 (CCP_PWM);
setup_timer_2(T2_DIV_BY_1, 250, 1);
set_pwm2_duty(duty_PWM1);
set_pwm1_duty(duty_PWM1);
enable_interrupts(int_rda);
port_b_pullups(true);
delay_ms(300);
output_high(PIN_B7);
enable_interrupts(global);
set_timer3(0x0BDC);
While(TRUE){
enable_interrupts(INT_TIMER3);
}
}
|
Last edited by niuton on Sun Jun 28, 2009 6:05 pm; edited 2 times in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 28, 2009 6:04 pm |
|
|
Quote: | #int_TIMER3
void timer3_isr(void){
set_timer3(muestreo);
read_Vel();
putc('$');
putc(tension_F>>8);
putc(tension_F&0x00FF);
putc('#');
} |
These four characters will take a minimum of 3 character period (0.5 ms
each) to send. During that time, the #int_rda interrupt can't be
handled. The UART receiver will get an overrun error, and it will lock up. |
|
|
niuton
Joined: 28 Jun 2009 Posts: 4
|
|
Posted: Sun Jun 28, 2009 6:14 pm |
|
|
PCM programmer You're right, I simulated proteus and note that activates the overflow flag "OERR" that the two FIFO is full.
OERR is activated that when I'm sending four data and receive data from the PC to jump RDA interrupt.
I send the data every 50ms PC-> PIC and 19200baud can transmit and receive 120byte every 50ms according to the calculations.
How can I fix it?
Thank you very much again. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 28, 2009 6:27 pm |
|
|
Don't send the 4 characters from within the #int_timer3 routine. Instead,
set a global flag in the #int_timer3 routine. Continuously test this flag
in your while() loop in main(). If the flag is set, then clear it, and send
the 4 characters from code that is inside the while() loop in main(). |
|
|
niuton
Joined: 28 Jun 2009 Posts: 4
|
|
Posted: Mon Jun 29, 2009 4:02 pm |
|
|
Thank you very much for the help, and running the program.
I saw that the command putc ( 'a') needs 0.5ms to send the character for RS232. Is there another command or routine that takes less time?
thank |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jun 29, 2009 4:19 pm |
|
|
You could use an INT_TBE interrupt routine with a buffer. Then the only
delay presented to the PIC is the interrupt service time. This is probably
about 15 us, with a 20 MHz clock.
See the following example file:
Quote: | c:\Program Files\picc\Examples\Ex_stisr.c |
|
|
|
|