Academic Question Converting Data

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

Can somebody help me??
I've been trying to do a step by step programming, including functions at each step. 

Now i'm with a problem... I'm using virtual terminal on Proteus, and everything was Ok till now. On this step i have to send a counting each second in decimal, hexadecimal and binary. I had used itoa function and it was Ok, but i need to do the conversion manually, so i increment a variable each second (by ISR_Timer1) and then i take the variable value and call functions to convert it, then i call another function (SendString) to send the converted data. My problem (now, maybe i get more on future :( ) is: I had converted the data to binary (and i think it's ok, please correct me if i'm wrong) and now i have to place it on a char array and pass the array. What am i doing wrong??? When i simulate, the data appears on the array but it's not sent.
 

#define	F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include "bit_tools.h"
#include <stdlib.h>

#define USART_BAUDRATE 250000		// Define usart baud rate
#define MYUBRRN	((F_CPU/(USART_BAUDRATE<<4))-1) //define UBRR(usart baud rate register) as UBRRN=11 has i had calculated

///////////////////
//GLOBAL VARIABLES/
///////////////////

uint8_t b;

// prototipes

void initUsart (uint16_t MY_UBBR);
void sendChar (uint8_t data);
void sendString ( char *data);
void configTimer1();
void write_dec(uint8_t b);
void write_hex(uint8_t b);
void write_bin(uint8_t b);

//////////////////////////////////
//Function :  Config the timer
////////////////////////////////////
void configTimer1()
{

	TCCR1B	|=	(1<<WGM12); // CTC Mode

	TIMSK1	=	(1<<OCIE1A); // Enable Timer 1 Interrupt

	OCR1A	=	31249; // Load Value calculated to have 1 second / Prescaler = 256 @ 8Mhz

	TCCR1B	|=	(1<<CS12);   // Set Prescaler @ 256

}




//////////////////////////////////
//Function :  Config the usart baudrate
////////////////////////////////////
void initUsart(uint16_t MY_UBBR) // NOTE: THE ARGUMENTS CANNOT BE EQUAL TO MACROS!!!!
{
	//cli(); 								 //Disable Global Interrupts to config USART
	UBRR0H	=	(unsigned char )(MY_UBBR>>8);//LOAD UPPER-8 BITS OF UBRR VALUE in register High
	UBRR0L	=	(unsigned char )MY_UBBR;	//LOAD LOWER-8 BITS OF UBRR VALUE IN REGISTER LOW
	
	UCSR0B	=	(1<<TXEN0) | (1<<RXEN0);	//ENABLE TX, RX AND DATA REGISTER EMPTY ENABLE INTERRUPT USART REGISTER 0 TO TRANSMIT AND RECEIVE DATA
	UCSR0C  = (1<<UCSZ01)|(1<<UCSZ00);	    //SETTING THE NUMBER OF DATA BITS (8)
	
}



//////////////////////////////////
//Function :  send char to the usart
////////////////////////////////////

void sendChar(uint8_t data)
{
	while ( ( UCSR0A & (1<<UDRE0))==0 );		// DO NOTHING UNTIL UDR BECOME READY TO RECEIVE DATA
	
	UDR0	=	data;							//RECEIVING DATA FROM THE VARIABLE TO UDR0 AND SEND VIA USART TX
}



////////////////////////////////////
//Function :  write string to the usart
////////////////////////////////////

void sendString(char *data)
{
	int len, i;

	len = strlen(data);			//STORE THE ARRAY SIZE IN VARIABLE (LEN)
	for (i=0; i<len; i++)
	{						// FOR CYCLE FROM BEGINNING OF CHAR ARRAY TILL THE END (LEN VALUE)
		if(data[i]=='\0')		//CHECK EMPTY DATA INSIDE CHAR ARRAY
		{
		return;
		}
		else
		{
			sendChar(*(data+i));	//CALL FUNCTION AND SEND CHAR IN THAT POSITION
		}
	}

}
	
uint8_t read_char(void)
{
char buffer[50]={0};	//STARTING EMPTY ARRAY ={0}
int i=0;

	for(i=0;i<49;i++)	//RUNNING ARRAY POSITIONS
	{	
		while ( !(UCSR0A & (1<<RXC0)) );	//WAIT TILL BUFFER BE READY TO RECEIVE DATA
			buffer[i]	=	UDR0;			// READ STRING VIA RX, CHAR BY CHAR
			
			if (buffer[i]=='\b')			//CHECK BACKSPACE KEY
				
				buffer[i]='\b';				//ERASE LAST VALUE
							
			if(buffer[i]=='\r')				//CHECK ENTER KEY
			{	
				sendString("\rO nome inserido foi :\r");	//CALL FUNCTION AND SEND STRING VIA TX
				sendString(buffer);							//CALL FUNTION AND SEND THE "buffer" DATA 
				return;										
			}
			
				sendChar(buffer[i]);						//PRINT CHAR BY CHAR "REAL TIME" AS IT'S PRESSED ON KEYBOARD
	}					
			sendString("\rcaracteres a mais\r");			// PRINT STRING IF OVERCOME 49 ARRAY POSITIONS
			sendString(buffer);								//PRINT ALL THE DATA IN THE "buffer" THAT HAS BEEN INSERTED (THE 50 CHARS)
}
///////////////////////////////////////
//FUNCTION : Convert to Int to Decimal
///////////////////////////////////////

void write_dec(uint8_t b)
{
char number[10];
	
		itoa(b,number,10);
		sendString(number);
} 

///////////////////////////////////
//Function: Convert to Int to Hex
///////////////////////////////////

void write_hex(uint8_t b)
{
char number[10];
		
		itoa(b,number,16);
		sendString(number);	
}

///////////////////////////////////
//Function: Convert to Int to Hex
///////////////////////////////////

void write_bin(uint8_t b)
{
char a,number[8]={0};
int num=b,i;
	for(i=0;i<8;i++)
		{
		while(num!=0)
			{	
			number[i]=	num % 2;
			num	=	num / 2;	
			}
		}
	for (i=8;i>0;i--)
		{
			a=number[i];
			sendString(a);
		}		
	
	
		//itoa(b,number,2);
		//sendString(number);
}

///////////////////////////////////
//Interrupt Call
///////////////////////////////////
	
ISR(TIMER1_COMPA_vect)
{
	b++;
	sendString("\r\n");
	write_dec(b);
	sendString(" ");
	write_hex(b);
	sendString(" ");
	write_bin(b);
	sendString(" ");
	PORTB ^=(1<<PINB0);//Toggle PINB0
}
	
////////////////////////////////////
//Function :  main cycle
////////////////////////////////////
 
int main(void)
{

char nome[] ="Nelson Macieira";


	DDRB	|=	(1<<PINB0);		// DEFINE PINB0 AS OUTPUT
	CLKPR	=	(1<<CLKPCE);	// PREPARING PRESCALER TO EDITION
	CLKPR	=	(0);			// EDITING PRESCALER TO 0, F_CPU=8000000/1
	configTimer1();
	
	initUsart(MYUBRRN); 
	sei(); //Enable all activated interruptions
	while(1)
	{
		sendString("\r\n");
		sendString(nome);
		sendString("\r\n");
		sendString("Insira um nome\r\n");
		read_char();
	}
	
}

Thanks for helping me :)

Regards, Nelson

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
for(i=0;i<8;i++)
		{
		while(num!=0)
			{	
			number[i]=	num % 2;
			num	=	num / 2;	
			}
		}

This makes no sense. Why do you have the while loop in there? Also, you are putting numbers (0 or 1) into the elements of "number", but what you need is characters representing those numbers. You also need to leave room in "number" for the terminating NUL character.

for (i=8;i>0;i--)
		{
			a=number[i];
			sendString(a);
		}		

This makes no sense. sendString takes a string, but you are sending it individual characters. Also

Regards,
Steve A.

The Board helps those that help themselves.

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

I had used itoa function and it was Ok, but i need to do the conversion manually, so i increment a variable each second (by ISR_Timer1) and then i take the variable value and call functions to convert it, then i call another function (SendString) to send the converted data.

Tell more about this "need" to do the conversion "manually". The "call functions to convert it" can just be calls to itoa() with the proper base, can't it?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:

I had used itoa function and it was Ok, but i need to do the conversion manually, so i increment a variable each second (by ISR_Timer1) and then i take the variable value and call functions to convert it, then i call another function (SendString) to send the converted data.

Tell more about this "need" to do the conversion "manually". The "call functions to convert it" can just be calls to itoa() with the proper base, can't it?

 

No, the objective is not to use itoa.

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

Koshchi wrote:

for(i=0;i<8;i++)
		{
		while(num!=0)
			{	
			number[i]=	num % 2;
			num	=	num / 2;	
			}
		}

This makes no sense. Why do you have the while loop in there? Also, you are putting numbers (0 or 1) into the elements of "number", but what you need is characters representing those numbers. You also need to leave room in "number" for the terminating NUL character.

for (i=8;i>0;i--)
		{
			a=number[i];
			sendString(a);
		}		

This makes no sense. sendString takes a string, but you are sending it individual characters. Also

 

After talking a while, now i know it is not use the sendString. But i was thinking on it because it calls sendchar function. I thought that i had to use them.
The while loop stays there because i had made mods to my first program, trying to get it work, but... i left it there... Now i can see it's no use.

Also, you are putting numbers (0 or 1) into the elements of "number", but what you need is characters representing those numbers. You also need to leave room in "number" for the terminating NUL character.

Yes, i need the characters '0'or '1' inside the array right? Then i can send the array. (i've done it before, and when debugging i can see the array filled with the corrected values('0' and '1'), but no printing on terminal.

At the first time i have it with space for null, but i had changed it to see what was happening... And stills the same...

 

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

"I learn so much more from re-inventing the wheel."  Truly academic exercise--i.e., homework?

 

I'd be tempted, if a homework exercise, to re-invent itoa() with the radix parameter, with heavy use of % modulus.  Then the result is added to '0' character, and if over 9 then add 8 (to handle radix > 10).  An exercise for the student is to set limits on allowable radix values.

 

Use the straight-forward (but not optimal) repeated-subtraction method.  As that generally uses a powers table, I'd make it in the fly.

 

Much depends on the allowed range of the input number.  What is your max "seconds" counts?  If e.g. a whole hour then you need 12 binary digits, right?  For a whole day, you need 17.  Better make that output buffer big enough.

 

In the real world I make all my conversion routines right-justified as most often the values are placed on LCD displays.  That introduces a wrinkle as the conversion routine needs to know the output width, or a post-processing step is needed to shift the itoa()-type result string.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

After talking a while, now i know it is not use the sendString.

sendChar takes a single character. sendString takes a pointer to an array of characters. You can not freely interchange those two things. If you really want to send one character at a time, then use sendChar, not sendString. But there is nothing wrong with using sendString, you just have to send it a string (properly terminated), not individual characters.

Regards,
Steve A.

The Board helps those that help themselves.

Last Edited: Tue. Mar 3, 2015 - 09:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:

After talking a while, now i know it is not use the sendString.

sendChar takes a single character. sendString takes a pointer to an array of characters. You can not freely interchange those two things. If you really want to send one character at a time, then use sendChar, not sendString. But there is nothing wrong with using sendString, you just have to send it a string (properly terminated), not individual characters.

 

Oh... I think i understand what you are saying... Because i can't pass an argument being a char when i'm passing it to sendstring function as it will receive a pointer, so the minimum that i can pass is an array of char's with the minimum 2 bits. Like one will be the '0' or '1' and the other will be '\0', because the function will be waiting for it. In other words the minimum string allowed (one char and one null) like ('1','\0').

I don't know if you understand what i'm trying to say but i think i understood you and i can see the error i've done.

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

theusch wrote:

"I learn so much more from re-inventing the wheel."  Truly academic exercise--i.e., homework?

 

I'd be tempted, if a homework exercise, to re-invent itoa() with the radix parameter, with heavy use of % modulus.  Then the result is added to '0' character, and if over 9 then add 8 (to handle radix > 10).  An exercise for the student is to set limits on allowable radix values.

 

Use the straight-forward (but not optimal) repeated-subtraction method.  As that generally uses a powers table, I'd make it in the fly.

 

Much depends on the allowed range of the input number.  What is your max "seconds" counts?  If e.g. a whole hour then you need 12 binary digits, right?  For a whole day, you need 17.  Better make that output buffer big enough.

 

In the real world I make all my conversion routines right-justified as most often the values are placed on LCD displays.  That introduces a wrinkle as the conversion routine needs to know the output width, or a post-processing step is needed to shift the itoa()-type result string.

 

 

 

it's not re-inventing the wheel, i understand what you feel, but this is just to begin to understand a little bit more how it works, and it's for training. Learning the basics first.
And if i can do something like itoa(), or i.e a printf i can save a few kb avoiding the use of stdlib i.e and using just exactly what i need. Today is very simple, tomorrow will probably get bigger. I think (maybe i'm wrong) that if i get used to save memory will be better in a future project. I know that i don't know nothing yet, but my wish is to learn more and more. The time is the big problem :(
Anyway, thanks all for your replys

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

And if i can do something like itoa(), or i.e a printf i can save a few kb avoiding the use of stdlib i.e and using just exactly what i need.

Wrong.  If you like, I can dig out threads where this topic (binary to ASCII) was thrashed out in great detail.

 

I don't think you give library writers enough credit.  itoa() implementations are probably about 100 words, give-or-take.  I'll wager your "functions" won't be smaller.

 

Yes, printf() is generally bigger.  But it needs to process many more options than the relatively degenerate "%d". 

 

And also, yes indeed many of us have our own flavours, especially for decimal display,.  As I mentioned, I usually want right-justified and leading-zero-suppressed.

 

Binary is kind of a degenerate case, as well, and can be done in a single pass over the bits.  There was just a thread on that--what use is it in the real world?  For a value of any width, the re-counting of zeroes to grasp the value is onerous.

 

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.