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

[Solved] Send string from terminal to pic18f4550 usb cdc

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
aftar mukhriz



Joined: 03 Nov 2020
Posts: 11
Location: Johor, Malaysia

View user's profile Send private message

[Solved] Send string from terminal to pic18f4550 usb cdc
PostPosted: Tue Nov 03, 2020 10:45 pm     Reply with quote

Hello everyone,

I have a question related to usb cdc. Can I send string, instead of char from terminal ( Tera Term ) to pic18f4550? Let say, if I want to send "HELLO" to the pic, so it can control led toggle at pin d3, is it possible while using usb cdc? Can anyone show the example of it? Thank you for your time.


Code:
#include <18F4550.h> //if your version of the compiler doesn't support the 4553, you can put the 4550 in your code, which is almost exactly the same.
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN
#use delay(clock=48M) //because of tricky fuses a 20Mhz oscillator will make the PIC run at 48Mhz
#define USB_CON_SENSE_PIN PIN_B2
#include <stdlib.h>
#define __USB_PIC_PERIF__ 1
// Includes all USB code and interrupts, as well as the CDC API
#include <usb_cdc.h>
int1 usb_cdc_oldconnected=FALSE;
#define CR         0x0d      // ASCII Value for a Carriage Return


//!void usb_debug_task(void) {
//!   int8 new_connected;
//!   int8 new_enumerated;
//!   new_connected=usb_attached();
//!   new_enumerated=usb_enumerated();
   
//!   if (new_enumerated)
//!      output_high(pin_d2);     
//!   else
//!      output_low(pin_d2);   
//!}




void main(void)
{
   setup_adc_ports(NO_ANALOGS);
   setup_comparator(NC_NC_NC_NC);
   usb_init_cs();
   usb_cdc_init();
   
   while (true)
   {
      if (usb_attached())
      {
         usb_task();   
         if (usb_enumerated())
         {
            if (usb_cdc_carrier.dte_present)
            {
               if (usb_cdc_oldconnected==FALSE)
               {
                  printf(usb_cdc_putc,"Hello World\n\r");
                  usb_cdc_oldconnected=TRUE;
               }
               if (usb_cdc_kbhit())
               {
                  //use usb_cdc_getc here to read the character and do what
                  //you want
                  usb_cdc_putc(toupper(usb_cdc_getc())); //usb_cdc_putc(toupper(usb_cdc_getc()));
                  //as a demo, return the character converted to upper case
                 
                  if (usb_cdc_getc()=="HELLO") //(usb_cdc_getc()==CR)
                  {
                     output_toggle(pin_d2);
                  }
               }
         
          }
         }
      }
      else
      {
         usb_cdc_oldconnected=FALSE;
         usb_cdc_init(); //clear buffers if disconnected
      }
   }
}


_________________
Learning process never ends


Last edited by aftar mukhriz on Wed Nov 18, 2020 9:13 pm; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Wed Nov 04, 2020 12:55 am     Reply with quote

Yes. However you have to understand that getc, only returns a character.

A string is an array of characters. Look in input.c at how get_string receives
characters building them into a 'string', by waiting for the line feed, and then
adding a null terminator.

so:
Code:

//basic routine to get a string from USB
void usb_get_string(char* s, unsigned int8 max) {
   unsigned int8 len;
   char c;

   max-=2; //space for terminator
   len=0;
   do {
     c=usb_cdc_getc();
     if(c==8) {  // Backspace
        if(len>0) {
          len--; //just move location backwards
        }
     } else if ((c>=' ')&&(c<='~'))
       if(len<=max) {
         s[len++]=toupper(c); //store character in upper case
       }
   } while(c!=13); //wait for line feed
   s[len]=0; //store a null terminator
}

//Now this will sit waiting for the input till a line feed is seen. You might
//want to add a timeout.

//Your code would need a string buffer, large enough to contain the string.
   char buffer[16];
   //You then wait for a string with:

  if (usb_cdc_kbhit())
  {
      usb_get_string(buffer, 16);
      if (strncmp("HELLO", buffer, 5)==0)
      {
          //you have received something starting with "HELLO"

      }
   }
aftar mukhriz



Joined: 03 Nov 2020
Posts: 11
Location: Johor, Malaysia

View user's profile Send private message

PostPosted: Wed Nov 04, 2020 10:54 pm     Reply with quote

Thank you for your reply, Ttelmah. However, I tried to replicate your method as shown below:

Code:

#include <18F4550.h> //if your version of the compiler doesn't support the 4553, you can put the 4550 in your code, which is almost exactly the same.
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN
#use delay(clock=48M) //because of tricky fuses a 20Mhz oscillator will make the PIC run at 48Mhz
#define USB_CON_SENSE_PIN PIN_B2
#include <stdlib.h>
#define __USB_PIC_PERIF__ 1
// Includes all USB code and interrupts, as well as the CDC API
#include <usb_cdc.h>
int1 usb_cdc_oldconnected=FALSE;
//!#define CR         0x0d      // ASCII Value for a Carriage Return

//!void usb_debug_task(void) {
//!   int8 new_connected;
//!   int8 new_enumerated;
//!   new_connected=usb_attached();
//!   new_enumerated=usb_enumerated();
   
//!   if (new_enumerated)
//!      output_high(pin_d2);     
//!   else
//!      output_low(pin_d2);   
//!}

//basic routine to get a string from USB
void usb_get_string(char* s, unsigned int8 max) {
   unsigned int8 len;
   char c;
   max-=2; //space for terminator
   len=0;
   do {
     c=usb_cdc_getc();
     if(c==8) {  // Backspace
        if(len>0) {
          len--; //just move location backwards
        }
     } else if ((c>=' ')&&(c<='~'))
       if(len<=max) {
         s[len++]=toupper(c); //store character in upper case
       }
   } while(c!=13); //wait for line feed
   s[len]=0; //store a null terminator
}

void main(void)
{
   setup_adc_ports(NO_ANALOGS);
   setup_comparator(NC_NC_NC_NC);
   usb_init_cs();
   usb_cdc_init();
   
   while (true)
   {
      if (usb_attached())
      {
         usb_task();   
         if (usb_enumerated())
         {
            if (usb_cdc_carrier.dte_present)
            {
               if (usb_cdc_oldconnected==FALSE)
               {
                  printf(usb_cdc_putc,"Hello World\n\r");
                  usb_cdc_oldconnected=TRUE;
               }
               //Your code would need a string buffer, large enough to contain the string.
               char buffer[16];
//!               const char *cptr={"HELLO"};    //const char cstring[6]={"HELLO"};
               //You then wait for a string with:
           
              if (usb_cdc_kbhit())
              {
                  usb_get_string(buffer, 16);
                  if (strncmp("HELLO", buffer, 5)==0)     //(strncmp("HELLO", buffer, 5)==0)     (strncmp(cptr, buffer, 5)==0)
                  {
                      //you have received something starting with "HELLO"
                      output_toggle(pin_d3);
                  }
               }
          }
         }
      }
      else
      {
         usb_cdc_oldconnected=FALSE;
         usb_cdc_init(); //clear buffers if disconnected
      }
   }
}



But then, it shows error Attempt to create a pointer to a constant. Then, I tried to tweak the code a bit by adding these line.
Code:

 char buffer[16];
               const char *cptr={"HELLO"};    //const char cstring[6]={"HELLO"};
               //You then wait for a string with:
           
              if (usb_cdc_kbhit())
              {
                  usb_get_string(buffer, 16);
                  if (strncmp(cptr, buffer, 5)==0)      //(strncmp("HELLO", buffer, 5)==0)     (strncmp(cptr, buffer, 5)==0)
                  {
                      //you have received something starting with "HELLO"
                      output_toggle(pin_d3);
                  }
               }

This code can be compiled, but when I tried to send string from TeraTerm, no string displays. Can someone point me to right direction on the issue of my code? Thank you for your time.
_________________
Learning process never ends
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 05, 2020 1:03 am     Reply with quote

aftar mukhriz wrote:

But then, it shows error Attempt to create a pointer to a constant.


To fix this, add the line shown in bold, in this position:
Quote:

#include <18F4550.h>
#device PASS_STRINGS=IN_RAM
aftar mukhriz



Joined: 03 Nov 2020
Posts: 11
Location: Johor, Malaysia

View user's profile Send private message

PostPosted: Thu Nov 05, 2020 2:11 am     Reply with quote

Thank you, PCM Programmer. I have added those lines and it works perfectly. I think you have mentioned it in this forum, right? http://www.ccsinfo.com/forum/viewtopic.php?t=34302&start=5
I have a question. For the buffer, 16 means 15 character + 1 string nullifier, am I correct? So, the limit for one time string transfer is 15 characters, right?
Code:
char buffer[16];

I have read about USB CDC limit is 64 bytes. So, for one string transfer, the maximum string is 63 + 1 string nullifier? Thank you for your time.
_________________
Learning process never ends
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Thu Nov 05, 2020 2:23 am     Reply with quote

Apologies about 'pass strings', I meant to say this was needed to use a
constant as I showed, but forgot to do so....

No things are sent by USB 'packet by packet'. So if you send a thousand
character string, it will be broken up into packets, but received just as
if it was a single entity. Obviously your receiving PIC will need a buffer
large enough to receive what is sent, but you can happily receive strings
much longer than the USB buffer size. It'll just take multiple transactions.

I made the buffer 16 characters, since your example was showing a three
character and a six character string (HELLO, and OK), and this was a
sensible size to handle both, and any likely longer commands. However
within the limitations of your PIC's memory (and remember that if a
buffer is larger than 256 characters, the index variables 'max' and 'len',
will need to be int16's), you can make the buffer any size you want.
aftar mukhriz



Joined: 03 Nov 2020
Posts: 11
Location: Johor, Malaysia

View user's profile Send private message

PostPosted: Thu Nov 05, 2020 3:39 am     Reply with quote

Quote:
However
within the limitations of your PIC's memory (and remember that if a
buffer is larger than 256 characters, the index variables 'max' and 'len',
will need to be int16's), you can make the buffer any size you want.


Thank you for the info, Ttelmah. So, since I declared 'max' and 'len' using int8, therefore the max characters is 256 since it is in 8-bit int. If I declared using int16, max characters for the buffer is 65536. Is my understanding correct?

Anyhow, another question popped out of my head. If we are using strncmp function, is 5 means first 5 bytes to compare between HELLO and buffer? And it is not included string nullify, right? String nullify functions to send the string only, is it?
Code:
if (strncmp("HELLO", buffer, 5)==0)      //(strncmp("HELLO", buffer, 5)==0)     (strncmp(cptr, buffer, 5)==0)
                  {
                      //you have received something starting with "HELLO"
                      output_toggle(pin_d3);
                  }


Sorry for so many questions, but really appreciate if someone can clear my doubt. Regards.
_________________
Learning process never ends
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Thu Nov 05, 2020 5:07 am     Reply with quote

It will find the null, if it comes before the count of 5. The definition for
strncmp is:

Quote:

it continues with the following pairs until the characters differ, until a terminating null-character is reached, or until num characters match
in both strings, whichever happens first.
aftar mukhriz



Joined: 03 Nov 2020
Posts: 11
Location: Johor, Malaysia

View user's profile Send private message

PostPosted: Sat Nov 07, 2020 7:47 pm     Reply with quote

Noted. Thank you for your explanation, Ttelmah.
_________________
Learning process never ends
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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