CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug Reports on this forum. Send them to support@ccsinfo.com

USB with 18F2550
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
temtronic



Joined: 01 Jul 2010
Posts: 6806
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed May 08, 2019 6:37 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed May 08, 2019 6:57 am     Reply with quote

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: 14611

View user's profile Send private message

PostPosted: Wed May 08, 2019 8:23 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed May 08, 2019 8:59 am     Reply with quote

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: 14611

View user's profile Send private message

PostPosted: Wed May 08, 2019 9:57 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed May 08, 2019 10:03 am     Reply with quote

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: 14611

View user's profile Send private message

PostPosted: Wed May 08, 2019 12:38 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu May 09, 2019 3:02 am     Reply with quote

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: 14611

View user's profile Send private message

PostPosted: Thu May 09, 2019 4:10 am     Reply with quote

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: 14611

View user's profile Send private message

PostPosted: Thu May 09, 2019 4:13 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu May 09, 2019 4:23 am     Reply with quote

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: 14611

View user's profile Send private message

PostPosted: Thu May 09, 2019 4:40 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu May 09, 2019 4:41 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu May 09, 2019 4:46 am     Reply with quote

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: 14611

View user's profile Send private message

PostPosted: Thu May 09, 2019 7:42 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
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