Converting string to usnigned long for USART speed

Go To Last Post
19 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys

 

I've been trying to implement a method for the user of my bus monitor project to be able to change the speed of the USART.

atoi() works fine, but not above a certain value (38400 +) as such values need to be stored in a long or unsigned long and itoa() falls over at that point.

 

Googling around, I've found that people are recommending strtol(). However, no matter what, I get nothing but 0 as a result.

Can anyone see where I'm going wrong?

 

 

 

int paramsCount = 0;
unsigned char params[10][32] = {{0}};

uint8_t COM_stop_bits = 1;
uint8_t COM_data_bits = 8;
unsigned long COM_baud = 19200;

COM_baud = strtol(*params[1],NULL,10);
COM_data_bits = atoi(params[2]);
COM_stop_bits = atoi(params[3]);

[edit] corrected itoa() to atoi()

This topic has a solution.
Last Edited: Mon. Oct 12, 2015 - 06:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have an ltoa function in that bagotricks?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried "COM_baud = atol(params[1]);", but I get 0 out of that as well.

 

This is the entire function (mostly set up for testing while I iron out the bugs etc):

 

uint8_t COM_stop_bits = 1;
uint8_t COM_data_bits = 8;
unsigned long COM_baud = 19200;

void cmd_COM(void)
{
	if (paramsCount!=4)
	{
		displaytext(SerialStrPtrTable[6]);
		return;
	}

char s[30], *cc;
	/*	always 1 start bit (always 1)
		5,6,7,8 or 9 data bits (default 8)
		no, even or odd parity (always no)
		1 or 2 stop bits (default 1) */
	COM_baud = atol(params[1]);                   

	//COM_baud = strtol(*params[1],NULL,10);

	COM_data_bits = atoi(params[2]);
	COM_stop_bits = atoi(params[3]);
	unsigned long ul = 0;
	int i=0;

	sprintf(s,"[COM_baud=%u]",COM_baud);
	displaytext(s);
	
	
	do 
	{
		ul = SerialSpeedsPtrTable[i];
		//sprintf(s,"[%i]",ul);
		//displaytext(s);
		if ((COM_baud==ul) && (ul!=0)) break;
		i++;
	} while (ul!=0);

	if (ul==0)
	{
		displaytext("Non-valid baud value\n\r");
		return;
	}

	sprintf(s, "Read: %u, %u, %u\n\r", COM_baud, COM_data_bits, COM_stop_bits);

	displaytext(s);
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Given the code

int paramsCount = 0;
unsigned char params[10][32] = {{0}};

uint8_t COM_stop_bits = 1;
uint8_t COM_data_bits = 8;
unsigned long COM_baud = 19200;

COM_baud = strtol(*params[1],NULL,10);
COM_data_bits = atoi(params[2]);
COM_stop_bits = atoi(params[3]);

nowhere are you placing any valuer in params1.

 

Also, since params[1] is an array, you should pass it to strtol like this:

COM_baud = strtol(params[1],NULL,10);

Using a name of an array is equal to a pointer to the array (to be precise, to the first element of the array). Your extra * dereferences the pointer twice.

 

Here's a minimal demo using strtol

 

    unsigned char params[10][32] = {"whatever", "456"};
    unsigned long COM_baud = strtol((const char *)params[1],NULL,10);

 

 

@Bob: OP wants to convert a string to a long (not a long to a string). How would ltoa() help him with that?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sun. Oct 11, 2015 - 03:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sprintf %lu

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry. I just saw itoa and thought that ltoa would eat bigger numbers.

 

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I just saw itoa

I was about to say you need new glasses, Bob. But then I saw that in the test of the OP "itoa" actually is used - while the code has the atoi().

 

So, it's me who need new glasses. (I already knew that..)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Apologies for causing confusion with the itoa() when I meant atoi().

 

params is used to hold the elements of a command string received from the user, with the space character used as a separator

 

So, if the user enters: COM 9600 8 1

Then:

params[0] = "COM"

params[1] = "9600"

params[2] = "8"

params[3] = "1"

 

I've tried using COM_baud = strtol((const char *)params[1],NULL,10); and also COM_baud = strtol(params[1],NULL,10);, but I still get back 0.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

"still get back 0" - how do you know that? sprintf? You should use "%lu" for longs, not "%u".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What I find odd is that :

COM_baud = atoi(params[1]); 

works fine and gives 9600 when params[1]="9600" (although bauds above 19200 break this)

 

However,

COM_baud = atol(params[1]);

gives 0.

I've tried defining COM_baud as a long and unsigned long. Makes no difference.

 

Last Edited: Sun. Oct 11, 2015 - 06:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've tried your suggestion and get 0, but before that I was doing a simple if statement to check if the value was 0 or not.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Something you are not telling us. You need to show the whole program again. Or do something like:
char b[30];
char* s1 = "123456";
unsigned long l = atol(s1);
sprintf(b, "l1=%lu\n", l);
displaytest(b);
sprintf(b, "p1='%s'\n", params[1]);
displaytest(b);
l = atol(params[1]);
sprintf(b, "l2=%lu\n", l);
displaytest(b);

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've inserted your  code at the top of the routine and blocked o0ff any other code with a return statement (so only your code runs).

 

The result:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One thing to note is that the params array is not defined as a pointer (with a *):

 

int paramsCount = 0;
unsigned char params[10][32] = {{0}};

Where-as yours is defined with a * :

char* s1 = "123456";

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This does not make any sense. The only explanation that I can think of is that it the compiler thinks that atol returns an int. Do you include ? (You have to!) Do you get any compilation warnings when you build your program?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Show us a small test program that demonstrates this. Also you never answered:

"still get back 0" - how do you know that? sprintf? You should use "%lu" for longs, not "%u".

While this is on a PC not an AVR the fact is that this shows strtoul() working...

$ cat test4.c 
#include <stdio.h>

char  params[4][10] = {
	"COM",
	"57600",
	"8",
	"1"
};

int main(void) {
	int baud;
	baud = strtoul(params[1], NULL, 10);
	printf("baud = %u\n", baud);
	return 0;
}
$ gcc test4.c -o test4
$ ./test4
baud = 57600

So how does your circumstance differ?

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

It has been a while since I tried compiling anything without -Wall. I see that by default gcc does not even complain about implicit declarations. Well, then it really must be a missing "#include <stdlib.h>". The implicit return types default to int. Since int and long are the same on the PC, everything is still good. But not good on AVR.

Last Edited: Mon. Oct 12, 2015 - 12:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh well spotted - that'll teach me to use simple compiler invocations - I didn't even use a -O option either (not that it probably matters given the speed PCs run at!).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:

It has been a while since I tried compiling anything without -Wall. I see that by default gcc does not even complain about implicit declarations. Well, then it really must be a missing "#include <stdlib.h>". The implicit return types default to int. Since int and long are the same on the PC, everything is still good. But not good on AVR.

Brilliant! That sorted it out. As atoi() worked out of the box I didn't even think of the library being the issue.

 

Thanks again and to all who responded :)