View previous topic :: View next topic |
Author |
Message |
starfire151
Joined: 01 Apr 2007 Posts: 195
|
PIC24FJ128GB202 COM port |
Posted: Wed Nov 09, 2016 12:53 pm |
|
|
I've created a minimal testbed using a PIC24FJ128GB202 to check multiple com port activity. I have a heartbeat LED connected to pin A4 which is toggled every second.
In my first version, I simply echo the uppercase character seen on COM1 (TXD on pin 3, RXD on pin B2).
I initialized everything then enabled the interrupts for TIMER1 and RDA.
1. I'm not seeing my heartbeat pin toggle at all. This is the same code for initializing and starting the timer that I have working correctly with a PIC24FV32KA301.
2. I'm seeing a 3-character delay before seeing any characters echoed to COM1. The first character seems to be corrupt (invalid character) and then the correct data is seen. In explaining, if I enter 1 2 3 4 5 6 7 8, I see a y character with an umlaut (..) above it then 1 2 3 4 5. When I first power up, I have a message printed to the com port and it prints out completely and correctly.
My simple code is as follows:
Code: |
#include <24FJ128GB202.h>
#device adc=12
#device icd=2
#FUSES NOWDT
#FUSES NOPROTECT
#FUSES NOIOL1WAY
#FUSES NOCKSNOFSM
#fuses OSCIO // oscillator pins used as general purpose I/O
#fuses NOJTAG // JTAG interface disabled
#define CLK_FREQ 32000000
#use delay(internal=CLK_FREQ)
#bit LOCK=getenv("BIT:LOCK")
#pin_select U1TX=PIN_B3
#pin_select U1RX=PIN_B2
#use rs232(baud=38400, parity=N, UART1, bits=8, stream=COM1)
#define PA_DEF 0b1111111111111111
#define PA_TRIS 0b1111111111100001
#define PB_DEF 0b1111111111111111
#define PB_TRIS 0b0110010010000111
#define HEARTBEAT PIN_A4 // 1-second heartbeat toggle
#use fast_io(a)
#use fast_io(b)
int1 s1Flag; // TRUE:COM1 character seen
char s1Char; // COM1 character
int8 intCount; // interrupt counter
#INT_TIMER1 // 10 times per second
void ClockISR(void)
{
intCount--;
if(intCount == 0)
{
intCount = 10; // reinit timer ints per msec cntr
output_toggle(HEARTBEAT);
}
}
#INT_RDA
void Com1ISR(void)
{
s1Char = toupper(fgetc(COM1));
s1Flag = TRUE;
}
void main()
{
setup_adc(ADC_OFF);
set_tris_a(PA_TRIS);
set_tris_b(PB_TRIS);
output_a(PA_DEF);
output_b(PB_DEF);
setup_timer1(TMR_INTERNAL | TMR_DIV_BY_256, 6250); // 32MHz 0.1 sec ISR
setup_timer2(TMR_32_BIT | TMR_INTERNAL | TMR_DIV_BY_1);
delay_ms(10);
intCount = 10;
s1Flag = FALSE;
fprintf(COM1, "PIC24FJ128GB202 Testbed\r\n");
delay_ms(100);
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_TIMER1);
clear_interrupt(INT_RDA);
enable_interrupts(INT_RDA);
enable_interrupts(INTR_GLOBAL);
while(TRUE)
{
if(s1Flag) // COM1
{
// fprintf(COM1, "%c\r\n", s1Char);
fputc(s1Char, COM1);
s1Flag = FALSE;
}
}
}
|
Does anyone have an idea of what's happening? I suspect the delay is due to the com buffer but how do I flush it or force characters to the com port without being delayed in the buffer? I have no idea why the timer interrupt isn't working. The com port interrupt is working so the global must be working.
Any help would be appreciated. Thanks. |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Wed Nov 09, 2016 12:55 pm |
|
|
Sorry, I forgot to include the specific...
PCWHD V5.064
Windows 10 desktop
Thanks, again. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Nov 09, 2016 12:59 pm |
|
|
For the initial garbage character, try the following:
1. Put a 100 ms delay at the very beginning of main().
If that doesn't work, then:
2. Add a 10K pullup resistor on the Rx pin. |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Wed Nov 09, 2016 2:02 pm |
|
|
I tried the 100ms delay at the beginning of main(). There didn't appear to be any change. I also tried the 10K pullup to 3.3VDC on the receive pin but there was no change there, either.
I also tried a 10ms delay prior to the fputc() call. No help.
It appears the outgoing characters just sit in the output buffer until it fills and then the characters are sent out (FIFO). I'm not sure how to clear out the first character in the buffer.
Any idea on the TIMER1 problem?
Thanks for looking at this. |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Wed Nov 09, 2016 2:12 pm |
|
|
I found the problem with the heartbeat pin. I changed the heartbeat to pin A3 and it works fine. There must be some restriction on output usage for pin A4? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9240 Location: Greensville,Ontario
|
|
Posted: Wed Nov 09, 2016 2:15 pm |
|
|
hmm.. are you sure it's a PIC problem and NOT a Windows10 problem ?
Maybe have an LED toggle for every character sent to PC ?
This would confirm it was sent and the PC is 'slow' to repond.
Jay |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Wed Nov 09, 2016 3:00 pm |
|
|
starfire151 wrote: | I found the problem with the heartbeat pin. I changed the heartbeat to pin A3 and it works fine. There must be some restriction on output usage for pin A4? |
Isn't A4 part of the Secondary Oscillator circuit (SOSCI or SOSCO)? If so, you need to set a FUSE to enable it as I/O, just like the primary oscillator circuit. |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Wed Nov 09, 2016 3:40 pm |
|
|
jeremiah:
I have the #fuses oscio called out in the beginning of the program. I didn't see a specific fuse associated with the secondary oscillator for io other than sosc, which I assumed was setting the sosc as an oscillator and not IO.
temtronic:
I don't think this is a Windows problem. The same development system is used for code for PIC24FV32KA301 and PIC24EP256GP202 processors with no problems with the com port interface. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Nov 09, 2016 5:13 pm |
|
|
Look for the SOSC_DIG fuse. That sets it for normal i/o. |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Thu Nov 10, 2016 5:30 am |
|
|
I tried the adding the lines:
#fuses SOSC_DIG // secondary oscillator pins as IO (for pin A4 output)
#define HEARTBEAT PIN_A4 // 1-second heartbeat toggle
The output line A4 is still not toggling. When I moved it back to A3, it toggles OK.
I still have the problem of the serial output data being buffered and the first character being corrupted, also. This is a more serious issue, since I intended to use this chip with the multiple simultaneous serial ports. I wanted to eventually have hardware serial interrupts associated with COM1 (TX on pin B3, RX on pin B2), COM2 (unused TX on pin B11, RX on pin B10), and COM3 (unused TX on pin A1, RX on pin A0). I wanted to echo the characters from either COM2 or COM3 onto COM1 in a passive monitor mode. |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Thu Nov 10, 2016 7:09 am |
|
|
some additional information...
I connected a logic analyzer (with an integrated serial port interpreter) to the transmit line and looked for the serial data sent when a character was input. The logic analyzer triggered immediately when I entered the "1" key but it showed an output of 0x00. I entered the "2" key and it showed 0x00 on the output. I entered "3" and it showed 0xff on the output (the y with an umlaut), I entered "4" and it showed "1" on the output. I entered "5" and it showed "2". Every entry was delayed by 3 bytes... |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Thu Nov 10, 2016 7:54 am |
|
|
There is a 4 level receive buffer and a 4 level transmit buffer. You are having a problem with one of them. Make sure both are empty before you begin. |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Thu Nov 10, 2016 9:07 am |
|
|
I tried to find a way to check the output buffer status...
I added the line I = tx_buffer_bytes(COM1); before the line for the fputc(s1Char, COM1); but I get a compiler error:
Error 112 "test1.c" Line 78(1,1): Function used but not defined: ...tx_buffer_bytes 667 SCR=1208
How would I check for how many characters are in the output buffer? Better yet, how can I flush the buffer prior to sending a character and ensure any new characters go out immediately? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Thu Nov 10, 2016 9:40 am |
|
|
Divide and conquer. Try to isolate where the problem may lie.
- I see no problem with your RDA interrupt BUT to ensure that things are doing what you intend, in your main loop, in the if (S1Flag) {}, add output_toggle(HEARTBEAT) [and disable the heartbeat in your ClockISR().]
Then test by typing characters on your laptop and confirm that each character corresponds to the heartbeat LED toggling state. If it works as expected, reset the PIC and repeat several times to confirm that it wasn't a fluke and that it does what it's supposed to do every time the PIC is reset. If all this is confirmed, character reception can be ruled out as a problem
If it doesn't, I have a suspicion that your PIC may have an issue with the generation of the RDA interrupt and that there's an issue with the generation of that interrupt until the buffer fills completely. There may be a listing in that processor's errata along these lines.
Assuming the RDA functions as it should and you can confirm that the processor sees each character as it arrives (via the heartbeat toggling every time you send a character), your attention must then turn to the transmission of characters. The best way to confirm this is to simply place a character to transmit in the UART's output buffer (register) directly, and then trigger the transmission manually. Here you need to read the datasheet. For some of the 16 bit processors, the data sheet is very sparse but there will be a device family spec (very detailed). They/it will list exactly how to manually send a character via the UART. You should implement this to confirm that the CCS code doesn't have a bug. Again, there may be an errata that relates to the problem you're seeing. |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Thu Nov 10, 2016 10:22 am |
|
|
According to the errata for this chip, it states the UART1 and UART2 modules may assert the receive interrupt flag early.
I changed the code to not use interrupts at all. I just look for a kbhit() and do a fgetc(COM1) if seen and echo it to the COM1 port. It works. I do still get the y with an umlaut character (0xff) first, though.
I do get the first signon message (fprintf("PIC24FJ128GB202 Testbed\r\n");) three times when it resets, also, after programming. A reset after that has the 0xff character first then one signon message.
With the defective hardware receive interrupt of this part, and no workaround listed, it appears this part will be unsuitable for my eventual application.
Does anyone have an idea of what would a good PIC24 part to use with 4 operational hardware receive interrupts? |
|
|
|