View previous topic :: View next topic |
Author |
Message |
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Wed May 08, 2019 6:37 am |
|
|
Now you know why I gave up with that PIC (well, 4550..big brother). Unless you get the HW correct, it's a nightmare...and of coures the USB driver fills 1/4-1/3 of code space memory.
I've used TTL<>USB modules for years. At $2 each, they really only add $1 to the units, free up memory and they work. I did remove the PWR LED though. Too dang bright for my eyes!
Hopefully you'll get the HW sorted out soon.
Jay |
|
|
RaptorUK
Joined: 30 Apr 2019 Posts: 17
|
|
Posted: Wed May 08, 2019 6:57 am |
|
|
Ttelmah wrote: | I'm confused now. You are talking about some other device?.
You said this unit was powered by the USB.
Is this some other device attached to this part?. |
Yep, I'm talking about the device that is the source of the RS232 comms |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Wed May 08, 2019 8:23 am |
|
|
Your circuit does not show 'RS232'. You have TTL serial, or RS485.
You show the connections to the RS485 buffer as 'open'.
On the TTL, you have the TTL serial line TX line directly from the PIC.
You also don't show how this device is grounded. The two pin connector
for this shows no ground.
If you are using the RS485, this has no termination shown (does have a
little bus biasing though).
If the input to the LVT125 goes low, the PIC will be receiving a continuous
'break'. |
|
|
RaptorUK
Joined: 30 Apr 2019 Posts: 17
|
|
Posted: Wed May 08, 2019 8:59 am |
|
|
Ttelmah wrote: | Your circuit does not show 'RS232'. You have TTL serial, or RS485.
You show the connections to the RS485 buffer as 'open'.
On the TTL, you have the TTL serial line TX line directly from the PIC.
You also don't show how this device is grounded. The two pin connector
for this shows no ground.
If you are using the RS485, this has no termination shown (does have a
little bus biasing though).
If the input to the LVT125 goes low, the PIC will be receiving a continuous
'break'. |
Yes, you are correct, the comms is not RS232 levels but TTL, it's coming direct from a PIC on the device I'm testing. The RS485 is not implemented in this application of the board I posted the schematic for. The TX is not used in this application. The ground is not shown but is there on a spare connector which is connected to ground.
I think I may be making some progress, the additional caps didn't noticeably help. I'm starting to wonder if my transmit buffer is getting full.
EDIT: Added a test for the buffer being full and it seems its not, I'm going to route the comms through a relay tomorrow so I can disable it while my device under test is powering up from battery.
Last edited by RaptorUK on Wed May 08, 2019 9:59 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Wed May 08, 2019 9:57 am |
|
|
Continuous break, means a character is seen every ten bit times.
You have 'errors' in your serial setup, so provided getc is called the
error that could result would be cleared. However if your code does
not 'cope' with receiving these unexpected characters it could give
problems. This is where something like an interrupt driven serial
RX helps. |
|
|
RaptorUK
Joined: 30 Apr 2019 Posts: 17
|
|
Posted: Wed May 08, 2019 10:03 am |
|
|
Ttelmah wrote: | This is where something like an interrupt driven serial
RX helps. |
Code: | #INT_RDA
void RDA_isr(void)
{
if (RX9D == 0) // check the 9th bit, if low the current byte is the
// first byte of the 50
{
LED_ON(RED_LED);
rx_index = 0;
next_tx = false; // RXed data not ready to be TXed via USB yet . . .
RXBuffer[rx_index] = fgetc(RX); // read the received data into the array
}
else
{
++rx_index; // increment location in array for RXed byte
LED_OFF(GREEN_LED);
RXBuffer[rx_index] = fgetc(RX); // write the received data into the array
if (rx_index == 49)
{
next_tx = TRUE; // RXed data ready to be transmitted via USB
rx_index = 0; // reset for next lot of data
}
else
{
if (rx_index == 25) LED_OFF(RED_LED);
}
}
} |
My RX Interrupt seems to be doing what I expect it to, I can see my RED LED flashing when I allow the comms through to the board. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Wed May 08, 2019 12:38 pm |
|
|
Change your #use rs232, to use 16bit fetches for the data from the UART
(manual shows this option), then just getc the int16 and test it's
9th bit.
You current approach has an issue if a second byte is in the UART
when the interrupt fires. It'll get the wrong 9th bit. I think using 16bit
is safer.
However it does sound as if your problem is with the USB only.
Post your 'usb decision' code. The code that decides if there is a connection,
and enumerates etc..
For example, mine on a recent project was:
Code: |
//usb_cdc_oldconnected is a boolean starting 'FALSE'
if (usb_attached())
{
usb_task();
if (usb_enumerated())
{
if (usb_cdc_carrier.dte_present)
{
if (usb_cdc_oldconnected==FALSE)
{ //This is used to send a status message when the USB connects
printf(usb_cdc_putc,"active message here\n\r");
usb_cdc_oldconnected=TRUE;
}
if (usb_cdc_kbhit())
{
//Need to parse USB here
tchar=usb_cdc_getc();
parseusb(tchar);
bit_clear(sys_stat,NO_HOST); //also clear host error
//This is a status bit that flags if the host is not present
timeout=70;
}
}
else
{
usb_cdc_oldconnected=FALSE;
}
}
else
{
usb_cdc_oldconnected=FALSE;
}
}
|
|
|
|
RaptorUK
Joined: 30 Apr 2019 Posts: 17
|
|
Posted: Thu May 09, 2019 3:02 am |
|
|
Ttelmah wrote: | Change your #use rs232, to use 16bit fetches for the data from the UART
(manual shows this option), then just getc the int16 and test it's
9th bit.
You current approach has an issue if a second byte is in the UART
when the interrupt fires. It'll get the wrong 9th bit. I think using 16bit is safer. |
The FIFO has a specific location for the 9th bit so using RX9D should give me the correct 9th bit shouldn't it ?
[quote="Ttelmah"]However it does sound as if your problem is with the USB only.
Post your 'usb decision' code.
I don't have any . . .
I do this before entering my main loop . . .
Code: | usb_init_cs();
usb_task(); |
Then call usb_task() frequently.
I have seen you posting before about this and tried to implement it at one point but it didn't work, I assumed it was due to my version of the compiler being quite old.
Just reading before trying to implement this again . . .
Code: | usb_attached() - Returns TRUE if the device is attached to a ////
//// USB cable. A macro that looks at the defined ////
//// connection sense pin. If this returns TRUE ////
//// it does not mean the PC has connected to it, ////
//// you need to use usb_enumerated() to check this. |
As I'm not using the sense pin this is always going to return FALSE for me isn't it ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Thu May 09, 2019 4:10 am |
|
|
If you look at the CCS 9 bit code, and the Microchip code, they read the
RX9D bit _after_ they read the UART buffer register. My memory is
that the RX9D bit receives the 9th bit when the received character is
transferred out of the FIFO. Not before. This is what worries me here...
Your USB code needs to handle the bus going off-line and the CDC
connection being dropped. Do you just call usb_getc, or use usb_kbhit
first?. kbhit won't return true unless the bus is live, but if you use
getc, without the test for kbhit, then the code will hang inside the getc
routine, if the bus drops, and then usb_task won't be being called, so the
bus won't recover. If you look at the examples, even the most basic one
uses:
Code: |
if (usb_cdc_kbhit())
{
c=usb_cdc_getc();
|
Not doing this with USB causes issues.... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Thu May 09, 2019 4:13 am |
|
|
Yes, can confirm. Microchip say in an application note:
Quote: |
Reading the RCREG will load bits RX9D and FERR with new values.
|
So you need to read the incoming character _before_ doing your test on
the RX9D bit. |
|
|
RaptorUK
Joined: 30 Apr 2019 Posts: 17
|
|
Posted: Thu May 09, 2019 4:23 am |
|
|
Ttelmah wrote: | If you look at the CCS 9 bit code, and the Microchip code, they read the
RX9D bit _after_ they read the UART buffer register. My memory is
that the RX9D bit receives the 9th bit when the received character is
transferred out of the FIFO. Not before. This is what worries me here...
Your USB code needs to handle the bus going off-line and the CDC
connection being dropped. Do you just call usb_getc, or use usb_kbhit
first?. |
I always test usb_kbhit first, for example:
Code: | SetupTimeOut(5); // time out time is count * 87mS
while (!usb_cdc_kbhit() && !TimedOut) // wait for char ready on USB
{
delay_us(500);
usb_task();
}
disable_interrupts(INT_TIMER0);
// Timeout
if(!TimedOut)
{
// disable RX interrupt . . .
disable_interrupts(INT_RDA);
CharFromUSB = usb_cdc_getc(); // get char from USB
LED_ON(RED_LED); |
. . . and use a timeout to ensure I can get out of my endless loop. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Thu May 09, 2019 4:40 am |
|
|
Why do you disable INT_RDA?.
Keep the serial interrupt enabled.
'ERRORS' will allow this to recover if this results in character loss, but why
lose characters if you don't have to?.
Correct handling for 9th bit:
Code: |
#INT_RDA
void RDA_isr(void)
{
byte temp;
temp=fgetc(RX);
if (RX9D == 0) // check the 9th bit, if low the current byte is the
// first byte of the 50
{
LED_ON(RED_LED);
rx_index = 0;
next_tx = false; // RXed data not ready to be TXed via USB yet . . .
}
else
{
++rx_index; // increment location in array for RXed byte
LED_OFF(GREEN_LED);
}
RXBuffer[rx_index] = temp; // write the received data into the array
if (rx_index == 49)
{
next_tx = TRUE; // RXed data ready to be transmitted via USB
rx_index = 0; // reset for next lot of data
}
else
{
if (rx_index == 25)
LED_OFF(RED_LED);
}
}
|
|
|
|
RaptorUK
Joined: 30 Apr 2019 Posts: 17
|
|
Posted: Thu May 09, 2019 4:41 am |
|
|
Ttelmah wrote: | Yes, can confirm. Microchip say in an application note:
Quote: |
Reading the RCREG will load bits RX9D and FERR with new values.
|
So you need to read the incoming character _before_ doing your test on
the RX9D bit. |
I'm not sure I agree, how I read it is that the 8bit data, the 9th bit and the FERR that are all relevant to that data byte are all clocked through together, I think this says it better than I just did . . .
Quote: | The FERR bit and the 9th receive bit are buffered the same way as the receive data. Reading the RCREG will load the RX9D and FERR bits with new values. Therefore, it is essential for the user to read the RCSTA register before reading the next RCREG register, in order not to lose the old(previous) information in the FERR and RX9D bits. |
So this says to read the RX9D (RCSTA register) before the next incoming char (RCREG) |
|
|
RaptorUK
Joined: 30 Apr 2019 Posts: 17
|
|
Posted: Thu May 09, 2019 4:46 am |
|
|
Ttelmah wrote: | Why do you disable INT_RDA?.
|
The serial data is 50 bytes of status info and is sent every 200mS, I don't need to get it all the time, for example when I'm sending EEPROM data over the I2C to the device I'm testing I don't want the RDA interrupt firing off, I'm pretty sure it wouldn't effect the data transfer over the I2C but didn't want to take the risk.
I do the same when I'm reading or writing the RTC on the device I'm testing. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Thu May 09, 2019 7:42 am |
|
|
No it does not.
You are misunderstanding.
It is very clear:
Reading the RCREG will load the RX9D and FERR bits with new values.
It is the act of reading RCREG, that _loads_ the values. At this point if
you want these bits you must then read them before you read the next
received byte.
Think about it. If only one byte has been received (so one byte of data in
the buffer), it can't load RC9D, with the 'next' ninth bit. It loads it with the
received bit when you read the register. |
|
|
|