Thread: using a digital compass need to convert ASCII character to int

  1. #1
    Registered User
    Join Date
    Nov 2006
    Posts
    34

    using a digital compass need to convert ASCII character to int

    Hello all,

    I'm using a digital compass for a microcontroller project, that displays the direction the compass is facing on an LCD. I've gotten it working to the point where it displays 0-255 on the LCD thanks to author at EngScope.com!

    However, that 0-255 is represented as ASCII characters. I need to convert those to integer values now. I know I can't use atoi since the character bytes aren't null terminated and aren't constant. Here is the code Thanks!

    Code:
    #include <p24FJ128GA010.h>
    #include <stdio.h>
    
    _CONFIG1(JTAGEN_OFF & GCP_OFF & GWRP_OFF & BKBUG_OFF & ICS_PGx2 & FWDTEN_OFF)
    _CONFIG2(IESO_OFF & FCKSM_CSDCMD & OSCIOFNC_ON &  FNOSC_FRC & POSCMOD_NONE)
    
    void i2c_init(int BRG);
    void i2c_start(void);
    void i2c_restart(void);
    void reset_i2c_bus(void);
    char send_i2c_byte(int data);
    char i2c_read(void);
    char i2c_read_ack(void);
    char I2Cread(char addr, char subaddr);
    unsigned char I2Cpoll(char addr);
    void DelayuSec(unsigned int N);
    
    char testChar ='0';
    
    main()
    {
    	i2c_init(39); //initializes i2c function
    	LCDInit();   // initalizes LCD
    	LCDClear();  //clears LCD
    	while(1)
    	{
    	DelayuSec(15000);  //15kuS delay
    	DelayuSec(15000);  //15kuS delay
    	LCDClear();		   //clear LCD
    	testChar =	I2Cread(0xC0, 1); //reads compass register 1
    								  //amd returns a value of 0-255
    								  
        /*
        //  convert the testChar ASCII value to its equivalent int value
        */
    
    	LCDPut(testChar); //prints a character on LCD screen
    	}
    }	
    
    //function initiates I2C1 module to baud rate BRG
    void i2c_init(int BRG)
    {
    
    int temp;
    
    	I2C1BRG = BRG; // I2CBRG = 39 for 8Mhz OSCI with 100kHz I2C clock
    	I2C1CONbits.I2CEN = 0; // Disable I2C Mode
    	I2C1CONbits.DISSLW = 1; // Disable slew rate control
    	IFS1bits.MI2C1IF = 0; // Clear Interrupt
    	I2C1CONbits.I2CEN = 1; // Enable I2C Mode
    	temp = I2C1RCV; // read buffer to clear buffer full
    	reset_i2c_bus(); // set bus to idle 
    
    }
    
    
    
    unsigned char I2Cpoll(char addr)
    { 
    unsigned char temp = 0;
    
    	i2c_start();
    	temp = send_i2c_byte(addr);
    	reset_i2c_bus();
    
    return temp;
    
    }
    
    
    char I2Cread(char addr, char subaddr)
    {
    
    char temp;
    
    	i2c_start();
    	send_i2c_byte(addr);
    	send_i2c_byte(subaddr);
    	DelayuSec(10);
    
    	i2c_restart();
    	send_i2c_byte(addr | 0x01);
    	temp = i2c_read();
    	
    	reset_i2c_bus();
    	
    return temp;
    }
    
    //function iniates a start condition on bus
    void i2c_start(void)
    {
    
    int x = 0;
    
    	I2C1CONbits.ACKDT = 0; //Reset any previous Ack
    	DelayuSec(10);
    	I2C1CONbits.SEN = 1; //Initiate Start condition
    	Nop();
    
    //the hardware will automatically clear Start Bit
    //wait for automatic clear before proceding
    	while (I2C1CONbits.SEN)
    	{
    		DelayuSec(1); 
    		x++; 
    		if (x > 20) break; 
    	}
    	DelayuSec(2);
    }
    
    
    //function iniates a restart condition on bus
    void i2c_restart(void)
    {
    
    int x = 0;
    
    	I2C1CONbits.RSEN = 1; //Initiate restart condition
    	Nop();
    
    	//the hardware will automatically clear restart bit
    	//wait for automatic clear before proceding
    	while (I2C1CONbits.RSEN)
    	{
    		DelayuSec(1); 
    		x++; 
    	if (x > 20) break; 
    	}
    	DelayuSec(2);
    }
    
    
    //Resets the I2C bus to Idle
    void reset_i2c_bus(void)
    {
    
    int x = 0;
    
    //initiate stop bit
    	I2C1CONbits.PEN = 1;
    
    //wait for hardware clear of stop bit
    	while (I2C1CONbits.PEN)
    	{
    		DelayuSec(1); 
    		x++; 
    	if (x > 20) break; 
    } 
    
    I2C1CONbits.RCEN = 0;
    IFS1bits.MI2C1IF = 0; // Clear Interrupt
    I2C1STATbits.IWCOL = 0;
    I2C1STATbits.BCL = 0;
    DelayuSec(10);
    
    }
    
    
    //basic I2C byte send
    char send_i2c_byte(int data)
    {
    
    int i;
    
    	while (I2C1STATbits.TBF) { }
    	IFS1bits.MI2C1IF = 0; // Clear Interrupt
    	I2C1TRN = data; // load the outgoing data byte
    
    	// wait for transmission
    	for (i=0; i<500; i++)
    	{
    		if (!I2C1STATbits.TRSTAT) break; 
    		DelayuSec(1); 
    	}
    	if (i == 500)
    	{
    return(1); 
    }
    
    // Check for NO_ACK from slave, abort if not found
    if (I2C1STATbits.ACKSTAT == 1)
    {
    reset_i2c_bus(); 
    return(1); 
    
    }
    DelayuSec(2);
    return(0);
    
    }
    
    
    //function reads data, returns the read data, no ack
    char i2c_read(void)
    {
    
    int i = 0;
    char data = 0;
    
    //set I2C module to receive
    	I2C1CONbits.RCEN = 1;
    
    //if no response, break
    	while (!I2C1STATbits.RBF)
    	{
    		i ++; 
    		if (i > 2000) break; 
    	}
    
    //get data from I2CRCV register
    	data = I2C1RCV;
    
    //return data
    return data;
    }
    
    //function reads data, returns the read data, with ack
    char i2c_read_ack(void) //does not reset bus!!!
    {
    
    	int i = 0;
    	char data = 0;
    
    //set I2C module to receive
    	I2C1CONbits.RCEN = 1;
    
    //if no response, break
    	while (!I2C1STATbits.RBF)
    	{
    		i++; 
    		if (i > 2000) break; 
    	}
    
    //get data from I2CRCV register
    data = I2C1RCV;
    
    //set ACK to high
    	I2C1CONbits.ACKEN = 1;
    
    //wait before exiting
    	DelayuSec(10);
    
    //return data
    return data;
    } 
    
    void DelayuSec(unsigned int N)
    {
    
    	unsigned int j;
    	while(N > 0)
    	{
    		for(j=0; j < 10; j++);
    		N--;
    	}
    }

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Lince View Post
    However, that 0-255 is represented as ASCII characters. I need to convert those to integer values now. I know I can't use atoi since the character bytes aren't null terminated and aren't constant.
    By far the easiest way will still be to use atoi. You just need to null terminate the strings (the part in red is nonsensical; either you don't understand or you are using a few words wrong).

    However, from glancing at your code I would say (for sure) that your numbers ARE NOT represented as ASCII characters at all. A single char is used to store a number, which would make a lot of sense since a char byte is a number with 256 possibilities (an unsigned char will be 0-255, a signed char will be -128 to 127).

    If you try something like this somewhere:
    Code:
    char data=oneofyourfunctions();
    int x=data;
    printf("%d",x);
    You will see what I mean.

    Since you might have used signed and unsigned chars interchangeably in the program, however, you might experience some complications.
    Last edited by MK27; 02-21-2009 at 02:42 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Nov 2006
    Posts
    34
    Yes looking back a character is used to store a value from 0-255;

    I added this code in the main and things are closer and i'm seeing the actual numbers

    Code:
    	z = (int)testChar;
    	
    	sprintf(zString, "%d", z);
    	LCDPut(zString[0]);
    	LCDPut(zString[1]);
    	LCDPut(zString[2]);

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Lince View Post
    Yes looking back a character is used to store a value from 0-255;

    I added this code in the main and things are closer and i'm seeing the actual numbers
    Yay -- you are getting the idea. Don't forget what I said about signed and unsigned. An unsigned char with a value of 255 will yield -1 as a signed char:
    Code:
    #include <stdio.h>
    
    int main() {
    	int z;
    	char X=0xff; /* all bits set, so highest possible value */
    	printf("%d %d\n",X,(unsigned char)X);
    	X=144; z=X;
    	printf("%d %d as int: %d\n",X,(unsigned char)X,z);
    	X=0;
    	printf("%d %d\n",X,(unsigned char)X);
    	return 0;
    }
    Output:
    -1 255
    -112 144 as int: -112
    0 0


    If this becomes a problem just use a (cast).
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    Nov 2006
    Posts
    34
    Thanks for the tip, I went back and changed all function returns and parameters to unsigned and multiplied the integer output by 1.411 to get 0-360 degrees output on my LCD.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 05-13-2007, 08:55 AM
  2. Debug Error Really Quick Question
    By GCNDoug in forum C Programming
    Replies: 1
    Last Post: 04-23-2007, 12:05 PM
  3. Game Won't Compile
    By jothesmo in forum C++ Programming
    Replies: 2
    Last Post: 04-01-2006, 04:24 PM
  4. Replies: 2
    Last Post: 03-24-2006, 08:36 PM
  5. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM