|
|
View previous topic :: View next topic |
Author |
Message |
aftar mukhriz
Joined: 03 Nov 2020 Posts: 11 Location: Johor, Malaysia
|
[Solved] Send string from terminal to pic18f4550 usb cdc |
Posted: Tue Nov 03, 2020 10:45 pm |
|
|
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: 19539
|
|
Posted: Wed Nov 04, 2020 12:55 am |
|
|
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
|
|
Posted: Wed Nov 04, 2020 10:54 pm |
|
|
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
|
|
Posted: Thu Nov 05, 2020 1:03 am |
|
|
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
|
|
Posted: Thu Nov 05, 2020 2:11 am |
|
|
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?
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: 19539
|
|
Posted: Thu Nov 05, 2020 2:23 am |
|
|
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
|
|
Posted: Thu Nov 05, 2020 3:39 am |
|
|
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: 19539
|
|
Posted: Thu Nov 05, 2020 5:07 am |
|
|
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
|
|
Posted: Sat Nov 07, 2020 7:47 pm |
|
|
Noted. Thank you for your explanation, Ttelmah. _________________ Learning process never ends |
|
|
|
|
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
|