|
|
View previous topic :: View next topic |
Author |
Message |
aaaaamartin
Joined: 17 Apr 2005 Posts: 39 Location: Germany Stuttgart
|
sw rs232 weird behaviour |
Posted: Tue Jul 10, 2007 10:02 pm |
|
|
Hi,
the code below works fine, however if you bring in both delays, it just recieves garbage.
Toggling "sample_early" makes no difference and
the baudrate is just 1200.
Compiler is PCH 3.235
Hopefully somebody has an explanation for this.
Thanks Martin
Code: |
#include <18F4550.h>
#device adc=10
#fuses HSPLL, PLL5, NOWDT, PUT, NOPROTECT, BROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG, CCP2C1
#use delay(clock=48000000)
#use rs232(stream=term, baud=1200, xmit=PIN_C1, rcv=PIN_c2, disable_ints, errors, sample_early, force_sw)
#priority CCP1
#zero_ram
#bit RE0 = 0x0f84.0
int x;
#INT_CCP1
void CCP1_isr ()
{
char rx;
(x==0) ? (RE0=1) : (RE0=0);
x = ~x;
rx = fgetc (term);
fputc (rx, term);
//delay_ms (10);
}
void main (void)
{
setup_ccp1 (CCP_CAPTURE_FE);
enable_interrupts (INT_CCP1);
enable_interrupts (GLOBAL);
set_tris_c (0b00000100);
set_tris_e (0x00);
x=0;
while (1) {
//delay_ms (10);
}
}
|
|
|
|
Ttelmah Guest
|
|
Posted: Wed Jul 11, 2007 2:42 am |
|
|
With software RS232, there is no buffering. The receive code _must_ start to sample the first bit, within less than half a bit time, of this bit actually arriving at the chip.
As soon as you delay in the interrupt statement, you make it unlikely that this will be true (your interrupt handler already waits longer than is safe, in transmitting the character back...). Worse, if you then add a second delay in the main, this results in interrupts being disabled in this delay in the main (since you now have the same code being use in both locations - a search here for the keyword 'reentrancy', will find thousands of posts about this).
As written, with the delays present, you have a total 'worst case' time, where the code may not be able to interrupt, and receive the next character, of about 28mSec (2*10mSc, plus the time to send the character). Something like 50* the safe value....
Best Wishes |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Jul 11, 2007 2:48 am |
|
|
I see Ttelmah answered when I was typing my reply. I post my response anyway, though some may be already explained.
1200 baud = 120 bytes / second = 1 byte every 8.3ms
With a delay of 20ms it will only take you a short time before you loss synchronization / miss data.
Quote: | the code below works fine, however if you bring in both delays, it just recieves garbage. | When you enabled both delays, did you notice the compiler warning? Quote: | Interrupts disabled during call to prevent re-entrancy: @delay_ms1 |
This warning is issued because the compiler uses the same delay_ms() function for both the main and interrupt. In order to avoid re-entrancy conflicts the compiler will disable the interrupts during execution of the delay() routine. This is not what you want!
The solution is easy, make sure the compiler doesn't use the same delay routines for interrupt and main. The compiler always calls the most recent declared delay function macro, so just insert a second #use delay declaration after the interrupt rountines and before main().
Code: | #fuses ...
#use delay(clock=16000000)
....
interrupt routines
....
#use delay(clock=16000000) // Second #delay declaration for use by main()
void main()
{
} |
|
|
|
aaaaamartin
Joined: 17 Apr 2005 Posts: 39 Location: Germany Stuttgart
|
|
Posted: Wed Jul 11, 2007 12:49 pm |
|
|
Thank_you (Ttelmah && ckielstra);
this solved the problem and made it clear to understand.
I should have looked at the warnings, but by that time it was 5 o'clock in the morning, after a long night coding things.
Regards Martin |
|
|
|
|
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
|