This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/LAUNCHXL-F28069M: How to increase math accuracy

Part Number: LAUNCHXL-F28069M
Other Parts Discussed in Thread: CONTROLSUITE, SFRA

Tool/software: Code Composer Studio

Hello all,

I have written a program which communicates with a pc interface via sci. Sci sends my launchxl some chars and I need to convert those into integer/float etc.

Just math.h is included.

I have some problems with these calculations. The subroutine below is being called by a for loop for every sci character I get. I know it is not the best char to number converter algorithm but anyway. :)

int whatcomesnext=0;
Uint16 bytecounter=0;


Uint16 sdataA[8];
Uint16 rdataA[8];

Uint32 result=0;
float32 value;
float32 divider;
float32 division;

void stringToNumeric()
{
    if (SciaRegs.SCIRXEMU == 48)
                {
                    whatcomesnext=0;
                }
                else if (SciaRegs.SCIRXEMU == 49)
                {
                    whatcomesnext=1;
                }
                else if (SciaRegs.SCIRXEMU == 50)
                {
                    whatcomesnext=2;
                }
                else if (SciaRegs.SCIRXEMU == 51)
                {
                    whatcomesnext=3;
                }
                else if (SciaRegs.SCIRXEMU == 52)
                {
                    whatcomesnext=4;
                }
                else if (SciaRegs.SCIRXEMU == 53)
                {
                    whatcomesnext=5;
                }
                else if (SciaRegs.SCIRXEMU == 54)
                {
                    whatcomesnext=6;
                }
                else if (SciaRegs.SCIRXEMU == 55)
                {
                    whatcomesnext=7;
                }
                else if (SciaRegs.SCIRXEMU == 56)
                {
                    whatcomesnext=8;
                }
                else if (SciaRegs.SCIRXEMU == 57)
                {
                    whatcomesnext=9;
                }
                else if (SciaRegs.SCIRXEMU == 44 || SciaRegs.SCIRXEMU == 46)
                {
                    whatcomesnext=",";
                }
                else    {
                            whatcomesnext=0;
                        }


    if(SciaRegs.SCIRXEMU>10 && SciaRegs.SCIRXEMU!=32 && SciaRegs.SCIRXEMU!=13 && SciaRegs.SCIRXEMU!=44 && SciaRegs.SCIRXEMU!=46 && bytecounter <=7)
                {
                    bytecounter=bytecounter+1;
                    if(bytecounter>=1)
                    {
                        rdataA[bytecounter]=whatcomesnext;
                    }

                }
                else if (SciaRegs.SCIRXEMU!=44 && SciaRegs.SCIRXEMU!=46)
                {
                    bytecounter=0;
                    result = 0;
                    division = 0;
                }

                    if (bytecounter==1)
                    {
                        if (whatcomesnext >=0 && whatcomesnext<=9)
                        {
                            value = whatcomesnext*10000000;
                            result = value+result;
                        }
                        if (SciaRegs.SCIRXEMU==44 && SciaRegs.SCIRXEMU==46)
                                            {
                                                divider =100000000;
                                            }

                    }
                    else if (bytecounter==2)
                    {
                        if (whatcomesnext >=0 && whatcomesnext<=9)
                        {
                            value = whatcomesnext*1000000;
                            result = value+result;
                        }
                        if (SciaRegs.SCIRXEMU==44 && SciaRegs.SCIRXEMU==46)
                                            {
                                                divider =10000000;
                                            }

                    }
                    else if (bytecounter==3)
                    {
                        if (whatcomesnext >=0 && whatcomesnext<=9)
                        {
                            value = whatcomesnext*100000;
                            result = value+result;
                        }
                        if (SciaRegs.SCIRXEMU==44 && SciaRegs.SCIRXEMU==46)
                                            {
                                                divider =1000000;
                                            }

                    }
                    else if (bytecounter==4)
                    {
                        if (whatcomesnext >=0 && whatcomesnext<=9)
                        {
                            float32 value1 = whatcomesnext*100;
                            value=value1*100;
                            result = value+result;
                        }
                        if (SciaRegs.SCIRXEMU==44 && SciaRegs.SCIRXEMU==46)
                                            {
                                                divider =100000;
                                            }

                    }
                    else if (bytecounter==5)
                    {
                        if (whatcomesnext >=0 && whatcomesnext<=9)
                        {
                            value = whatcomesnext*1000;
                            result = value+result;
                        }
                        if (SciaRegs.SCIRXEMU!=44 && SciaRegs.SCIRXEMU!=46)
                                            {
                                                divider =10000;
                                            }

                    }
                    else if (bytecounter==6)
                    {
                        if (whatcomesnext >=0 && whatcomesnext<=9)
                        {
                            value = whatcomesnext*100;
                            result = value+result;
                        }
                        if (SciaRegs.SCIRXEMU==44 && SciaRegs.SCIRXEMU==46)
                                            {
                                                divider =1000;
                                            }

                    }

                    else if (bytecounter==7)
                    {
                        if (whatcomesnext >=0 && whatcomesnext<=9)
                        {
                            value = whatcomesnext*10;
                            result = value+result;
                        }
                        if (SciaRegs.SCIRXEMU==44 && SciaRegs.SCIRXEMU==46)
                                            {
                                                divider =100;
                                            }

                    }
                    else if (bytecounter==8)
                    {
                        if (whatcomesnext >=0 && whatcomesnext<=9)
                        {
                            value = whatcomesnext;
                            result = value+result;
                        }
                        if (SciaRegs.SCIRXEMU==44 && SciaRegs.SCIRXEMU==46)
                                            {
                                                divider =10;
                                            }

                    }
}

"value" is always correct but "result" is not. When I send 11111111 or 22222222, it is ok. Result is correct. But for 33333333, result becomes 33333334. For 99999999, result = 100000000.

So I need a correct result and according to my result, I will divide and get another value. (33,25 or 77,358 etc. Some float parameter values)

I think math.h is not enough. I have read CLA and IQmath but could not use them properly. What do you suggest to improve the calculation accuracy?

  • 3333333"4" :) 4 how?

  • Uint16 sdataA[8];
    Uint16 rdataA[8];
    
    Uint32 result=0;
    float32 floatResult;
    Uint32 value;
    Uint32 divider;
    float32 division;

    Converting to Uint32 solved my problem. But now I have this :

    floatResult = result;
                                        division = floatResult/divider; // invokes FS$$DIV

    I need to convert Uint32 to float32. 

    But result and floatResult becomes different. Any suggestion?

  • John,

    I think you are approaching the problem at hand in quite a difficult manner, if you really just want to transmitt float data, the SCI does not care if those are bits have float or fixed data , you really do not need to do what you are are doing..

    For example i can point you to routines where we communicate to the PC, and have float data..

    C:\ti\controlSUITE\libs\app_libs\SFRA\v1_10_00_00\GUI

    Unfortunately , I do not have documentation for it and you will need to spend some time to understand the code. However the point i want to make is that comms protocol do not care if it's float or fixed data for them they are bits and you don;t necessarily have to tramsit things as char's and interpret them ... you will be much more efficient designing the packet such that you can accomodate 32 bits data and then use a decode based on your packet whether it's float or fixed.

    Now to answer your specific questions:

    Float representation is 32 bit on C2000 MCU, so some of the rouding errors you are seeing are expected for such large numbers..

    I am not surprised by the floating point result that you are getting... you will have to switch to 64 bit floating point, but then as well conversion from int to float is not guranteed to be exact... though then error might be further down in the decimal point...

    here is a good one for you to refer

    www.ti.com/.../spraan9a.pdf
  • Hey Manish,

    You are the writer of that SFRA example. I am a big fan of you now! :D

    //============================================================================
    //============================================================================
    //
    // FILE:	SciCommsGui.c
    //
    // TITLE:	GP Comms kernel as an interface to external GUI
    // 
    // Version: 22 April 2009 - Release 1.2 - Internal Release (BRL)
    //============================================================================
    //============================================================================
    #include <stdint.h>
    #ifdef F28x_DEVICE
    #include "F28x_Project.h"
    #else
    #include "DSP28x_Project.h"
    #endif
    
    #define	PktSize				6
    #define	CmdNumber			16
    #define	MAX_CMD_NUM			8
    
    
    // Function prototypes for Command RECEIVE State machine
    // ------------------------------------------------------------
    void GetCmdByte(void);
    void EchoCmdByte(void);
    void GetSizeByte(void);
    void EchoSizeByte(void);
    void GetDataByte(void);
    void EchoDataByte(void);
    void PackWord(void);
    void PackArray(void);
    void CmdInterpreter(void);
    
    // Function prototypes for Command Interpreter and dispatcher
    // ------------------------------------------------------------
    void LifePulseTsk(void);		// 0
    void TextSet(void);				// 1
    void ButtonSet(void);			// 2
    void SliderSet(void);			// 3
    void VariableGet(void);			// 4
    void ArrayGet(void);			// 5
    void DataGet(void);				// 6
    void DataSet32(void);			// 7
    void SpareTsk08(void);			// 8
    
    void SendData(void);
    
    // Variable declarations
    void (*RcvTaskPointer)(void); 			// State pointer for Command Packet Receive
    void (*CmdDispatcher[CmdNumber])(void);	// Array of pointers to Function (i.e. tasks)
    
    extern int16_t *varSetTxtList[];
    extern int16_t *varSetBtnList[];
    extern int16_t *varSetSldrList[];
    extern int16_t *varGetList[];
    extern int16_t *arrayGetList[];
    extern int16_t *dataGetList[];
    extern uint32_t *dataSetList[];
    
    extern int16_t CommsOKflg, SerialCommsTimer;
    
    uint16_t	LowByteFlag, SendTaskPtr;
    uint16_t	RxChar, RxWord;
    uint16_t	CmdPacket[PktSize];
    uint16_t	TaskDoneFlag, NumWords, wordsLeftToGet;
    
    uint16_t dataOut16;
    int32_t dataOut32;
    
    int16_t *memDataPtr16;
    int32_t *memDataPtr32;
    
    int16_t  RcvTskPtrShdw;	// for debug
    
    int16_t 	delayer;
    
    int16_t	MemGetPtr;
    uint32_t	MemGetAddress;
    int16_t	MemGetAmount;
    
    int16_t   MemSetPtr;
    uint32_t  MemSetValue;
    
    uint32_t Temp;
    
    
    void SCIA_Init(long SCI_VBUS_CLOCKRATE, long SCI_BAUDRATE)
    {    
    // Note: Assumes Clocks to SCIA are turned on in InitSysCtrl()
    // Note: Assumes GPIO pins for SCIA are configured to Primary function    
    
    	int16_t j = 0;
    
     	SciaRegs.SCICCR.all =0x0007;   // 1 stop bit,  No loopback 
                                       // No parity,8 char bits,
                                       // async mode, idle-line protocol
    	SciaRegs.SCICTL1.all =0x0003;  // enable TX, RX, internal SCICLK, 
                                       // Disable RX ERR, SLEEP, TXWAKE
    	SciaRegs.SCICTL2.all =0x0003; 
    	SciaRegs.SCICTL2.bit.TXINTENA =0;
    	SciaRegs.SCICTL2.bit.RXBKINTENA =0;
        SciaRegs.SCIHBAUD    =0x0000;
    
    	SciaRegs.SCILBAUD = (SCI_VBUS_CLOCKRATE/(8*SCI_BAUDRATE))-1;//0x0020;			// 20h = 57.6Kbaud @ LSPCLK = 60/4 MHz
    
    	SciaRegs.SCICTL1.all =0x0023;		// Relinquish SCI from Reset 
    
        //SciaRegs.SCIFFTX.all=0xE040;		// ENable FIFO enhancement
        SciaRegs.SCIFFTX.all=0x8040;		// DISable FIFO enhancement
        SciaRegs.SCIFFRX.all=0x204f;
        SciaRegs.SCIFFCT.all=0x0;
        SciaRegs.SCIPRI.bit.SOFT=0x0;
        SciaRegs.SCIPRI.bit.FREE=0x1;
    
    	RcvTaskPointer = &GetCmdByte;			// Initialize the CmdPacket Rcv Handler state machine ptr
    	RcvTskPtrShdw = 1;						// DEBUG
    	SendTaskPtr = 0;						// Init to 1st state
    	LowByteFlag = 1;						// Start with LSB during Byte-to-Word packing
    
    	dataOut16 = 0;
    	dataOut32 = 0;
    
    	*memDataPtr16 = 0;
    	*memDataPtr32 = 0;
    
    	RcvTskPtrShdw = 0;	// for debug
    
    	delayer = 0;
    
    	MemGetPtr = 0;
    	MemGetAddress = 0x00000000;
    	MemGetAmount = 0;
    
    	MemSetPtr = 0;
    	MemSetValue = 0x00000000;
    
    	// clear Command Packet
    	for (j=0; j<PktSize; j++)
    	{
    		CmdPacket[j] = 0x0;
    	}
    
    	j=0;
    	
    // init all dispatch Tasks                   
     	CmdDispatcher[0] = LifePulseTsk;             
     	CmdDispatcher[1] = TextSet;                  
     	CmdDispatcher[2] = ButtonSet;                
     	CmdDispatcher[3] = SliderSet;                
     	CmdDispatcher[4] = VariableGet;              
     	CmdDispatcher[5] = ArrayGet;                 
     	CmdDispatcher[6] = DataGet;                  
     	CmdDispatcher[7] = DataSet32;
     	CmdDispatcher[8] = SpareTsk08;               
                                                                     
    }
    
    //===========================================================
    // Host Command RECEIVE and DISPATCH State Machine
    //===========================================================
    
    //======== SM Entry Point =================
    void SerialHostComms()
    {		
    	(*RcvTaskPointer)();	// Call routine pointed to by state pointer
    }
    //=========================================
    
    void GetCmdByte(void) // Task 1
    {
    	if (SciaRegs.SCIRXST.bit.RXRDY == 1)	// check if a char has been received
    	{
    		RxChar = SciaRegs.SCIRXBUF.all;
    		RcvTaskPointer = &EchoCmdByte;		// point to next state
    		SerialCommsTimer = 0;
    		//RcvTskPtrShdw = 2;				// DEBUG
    		EchoCmdByte();
    	}                                                                      
    
    	else if (SciaRegs.SCIRXST.bit.BRKDT == 1 || SerialCommsTimer > 2500) //~2 s timeout
    	{	
    	// If break detected or serialport times out, reset SCI
    		//--- Needed by some serialports when code is run with an emulator  
     		SciaRegs.SCICCR.all =0x0007;   		// 1 stop bit,  No loopback             
      	                                 		// No parity,8 char bits,           
      	                                  		// async mode, idle-line protocol   
     		SciaRegs.SCICTL1.all =0x0003;  		// enable TX, RX, internal SCICLK,      
      	                                  		// Disable RX ERR, SLEEP, TXWAKE    
     		SciaRegs.SCICTL2.all =0x0000;                                                                                
                                                                                  
     		SciaRegs.SCICTL1.all =0x0023;		// Relinquish SCI from Reset        
    
    		asm(" RPT#8 || NOP");
    		//---
    
    		SendTaskPtr = 0;					// Init to 1st state	
    		SerialCommsTimer = 0;
    								                                      
    		CommsOKflg = 0;
    		RcvTaskPointer = &GetCmdByte;		// go back and wait for new CMD                       
    	}
    }
    
    void EchoCmdByte(void) // Task 2
    {
        if(SciaRegs.SCICTL2.bit.TXRDY == 1)		// is TXBUF empty ?, i.e. TXRDY = 1
        {
        	SciaRegs.SCITXBUF=RxChar;			// if yes, echo back the received char
        	CmdPacket[0] = RxChar;
    		RcvTaskPointer = &GetSizeByte;
    		//RcvTskPtrShdw = 3;					// DEBUG
    		//RcvTaskPointer = &GetCmdByte;		// Un-comment for simple echo test
    		SerialCommsTimer = 0;						// Reset Time-out timer
    	}
    
    }
    
    void GetSizeByte(void) // Task 3
    {
    	if (SciaRegs.SCIRXST.bit.RXRDY == 1)	// check if a char has been received
    	{
    		RxChar = SciaRegs.SCIRXBUF.all;
    
    		RcvTaskPointer = &EchoSizeByte;		// point to next state
    		//RcvTskPtrShdw = 4;					// DEBUG
    		EchoSizeByte();
    	}
    
    	else if (SerialCommsTimer > 1000)		// 1000*1mS = 1.0 sec timeout
    	{
    		CommsOKflg = 0;
    		RcvTaskPointer = &GetCmdByte;		// Abort, go back wait for new CMD
    		SerialCommsTimer = 0;
    	}
    }
    
    void EchoSizeByte(void) // Task 4
    {
        if(SciaRegs.SCICTL2.bit.TXRDY == 1)		// is TXBUF empty ?, i.e. TXRDY = 1
        {
        	SciaRegs.SCITXBUF=RxChar;			// if yes, echo back the received char
        	CmdPacket[1] = RxChar;
    		RcvTaskPointer = &GetDataByte;
    		//RcvTskPtrShdw = 5;				// DEBUG
    		//RcvTaskPointer = &GetCmdByte;		// Un-comment for Test
    		SerialCommsTimer = 0;				// Reset Time-out timer
        }
    }
    
    void GetDataByte(void) // Task 5
    {
    	if (SciaRegs.SCIRXST.bit.RXRDY == 1)	// check if a char has been received
    	{
    		RxChar = SciaRegs.SCIRXBUF.all;
    		RcvTaskPointer = &EchoDataByte;		// point to next state
    		//RcvTskPtrShdw = 6;				// DEBUG
    		EchoDataByte();				
    	}
    
    	else if (SerialCommsTimer > 500)		// 1000*1mS = 1 sec timeout
    	{
    		CommsOKflg = 0;
    		RcvTaskPointer = &GetCmdByte;		// Abort, go back wait for new CMD
    		SerialCommsTimer = 0;
    	}
    	
    }
    
    void EchoDataByte(void) // Task 6
    {
        if(SciaRegs.SCICTL2.bit.TXRDY == 1)		// is TXBUF empty ?, i.e. TXRDY = 1
        {
        	SciaRegs.SCITXBUF=RxChar;			// if yes, echo back the received char
    		RcvTaskPointer = &PackWord;
    		//RcvTskPtrShdw = 7;				// DEBUG
        }
    }
    
    void PackWord(void) // expects LSB first then MSB // Task 7
    {
    	if(LowByteFlag == 1)
    	{ 
    		RxWord = RxChar;
    		LowByteFlag = 0;
    		RcvTaskPointer = &GetDataByte;
    		//RcvTskPtrShdw = 5;				// DEBUG
    		GetDataByte();
    	}
    	else
    	{
    		RxWord = RxWord | (RxChar<<8);
    		LowByteFlag = 1;
    		CmdPacket[2] = RxWord;				// store data in packet
    		RcvTaskPointer = &CmdInterpreter;
    		//RcvTskPtrShdw = 8;				// DEBUG
    		TaskDoneFlag = 0; 					// indicate new task underway	
    	}
    }
    
    void CmdInterpreter(void) // Task 8
    {
    	if (TaskDoneFlag == 0)
    	{
    	 	(*CmdDispatcher[ CmdPacket[0] ] )();  	// dispatch Task					
    	}
    
    	// Incase Task never finishes 
    	if (SerialCommsTimer > 2500)			// 2500*1mS = 2.5 sec timeout
    	{
    		CommsOKflg = 0;
    		RcvTaskPointer = &GetCmdByte;		// Abort, go back wait for new CMD
    		SerialCommsTimer = 0;
    	}
    	if (TaskDoneFlag == 1)
    	{
    		RcvTaskPointer = &GetCmdByte;
    	 	//RcvTskPtrShdw = 1;   				// DEBUG
    	}
    }
    
    //===========================================================
    // Slave Tasks commanded by Host
    //===========================================================
    void LifePulseTsk(void) 	// CmdPacket[0] = 0
    {
    	if (CmdPacket[2]==0x0000 && CmdPacket[1]==0x00)  //LED2-ON
    	{
    		#if DSP2802x_DEVICE   
    		GpioDataRegs.GPASET.bit.GPIO12=1;		
    		#else
    		GpioDataRegs.GPASET.bit.GPIO31=1;
    		#endif
    	}
    	if (CmdPacket[2]==0x0001 && CmdPacket[1]==0x00)   //LED2-OFF
    	{
    		#if DSP2802x_DEVICE
    		GpioDataRegs.GPACLEAR.bit.GPIO12=1;
    		#else
    		GpioDataRegs.GPACLEAR.bit.GPIO31=1;
    		#endif		
    	}
    	if (CmdPacket[2]==0x0002 && CmdPacket[1]==0x00)  //LED2-Toggle
    	{
    		#if DSP2802x_DEVICE
    		GpioDataRegs.GPATOGGLE.bit.GPIO12=1;
    		#else
    		GpioDataRegs.GPATOGGLE.bit.GPIO31=1;
    		#endif
    	}
    
    	CommsOKflg = 1;
    	SerialCommsTimer = 0;
    	TaskDoneFlag = 1;
    }
    //-----------------------------------------------------------
    void TextSet(void) // CmdPacket[0] = 1
    {	
    	*varSetTxtList[CmdPacket[1]] = CmdPacket[2];
    
    	TaskDoneFlag = 1; // indicate Task execution is complete
    }
    //-----------------------------------------------------------
    void ButtonSet(void) 	// CmdPacket[0] = 2
    {
    	*varSetBtnList[CmdPacket[1]] = CmdPacket[2];
    
    	TaskDoneFlag = 1; // indicate Task execution is complete
    }
    //-----------------------------------------------------------
    void SliderSet(void) 	// CmdPacket[0] = 3
    {
    	*varSetSldrList[CmdPacket[1]] = CmdPacket[2];
    
    	TaskDoneFlag = 1; // indicate Task execution is complete
    }
    //-----------------------------------------------------------
    void VariableGet(void)		// CmdPacket[0] = 4
    {
    	SendData();
    }
    //-----------------------------------------------------------
    //Send a Uint16 array one element at a time
    void ArrayGet(void)			// CmdPacket[0] = 5
    {
    	SendData();	
    }
    //-----------------------------------------------------------
    void DataGet(void)			// CmdPacket[0] = 6
    {
    	switch(MemGetPtr)
    	{
    		case 0:
    			MemGetAddress = CmdPacket[2];
    			MemGetPtr = 1;
    
    			wordsLeftToGet = 1;
    			SendTaskPtr = 1;
    			TaskDoneFlag = 1;
    			break;
    
    		case 1:
    			Temp = CmdPacket[2];
    			MemGetAddress = MemGetAddress + (Temp<<16);
    			memDataPtr16 = (int16_t*)MemGetAddress;
    			dataOut16 = *memDataPtr16;
    			SendData();		
    
    			if(TaskDoneFlag == 1)
    			{
    				MemGetPtr = 0;
    			}
    			break;
    		}
    
    	//TaskDoneFlag = 1; 	// indicate Task execution is complete
    }
    //-----------------------------------------------------------
    void DataSet32(void)		// CmdPacket[0] = 7 [Edited to get 32-bit set text and set label working]
    {
    	switch(MemSetPtr)
    	{
    		case 0:
    			MemSetValue = CmdPacket[2];
    			MemSetPtr = 1;
    
    			TaskDoneFlag = 1;
    			break;
    
    		case 1:
    			Temp = CmdPacket[2];
    			MemSetValue = MemSetValue + (Temp<<16);
    
    			*dataSetList[CmdPacket[1]] = MemSetValue;
    
    			MemSetPtr = 0;
    			TaskDoneFlag = 1;
    			break;
    	}
    
    }
    //-----------------------------------------------------------
    void SpareTsk08(void)		// CmdPacket[0] = 8
    {
    	TaskDoneFlag = 1; 		// indicate Task execution is complete
    }
    //-----------------------------------------------------------
    
    void SendData(void)
    {
    	if(CmdPacket[0] == 0x04 || CmdPacket[0] == 0x06){
    		switch(SendTaskPtr)
    		{
    		case 0:  //initialization
    
    			memDataPtr16 = (int16_t *) varGetList[CmdPacket[1]];
    			dataOut16 = *memDataPtr16;
    			wordsLeftToGet = CmdPacket[2];
    				//Note that case 0 rolls into case 1 (no break)
    
    		case 1:  //send LSB
    			if(wordsLeftToGet > 0)
    			{
    				if (SciaRegs.SCICTL2.bit.TXRDY == 1)
    				{
    					SciaRegs.SCITXBUF = dataOut16 & 0x000000FF;
    					SendTaskPtr = 2;
    				}
    				else
    				{
    					TaskDoneFlag = TaskDoneFlag;
    					break;
    				}
    			}
    			else
    			{
    				SendTaskPtr = 0;
    				TaskDoneFlag = 1;
    				break;
    			}
    
    		case 2: //send MSB
    			if (SciaRegs.SCICTL2.bit.TXRDY == 1)
    			{
    				SciaRegs.SCITXBUF = (dataOut16>>8 & 0x000000FF);
    
    				memDataPtr16 = memDataPtr16 + 1;
    				dataOut16 = *memDataPtr16;
    				wordsLeftToGet = wordsLeftToGet - 1;
    				SendTaskPtr = 1;
    			}
    			break;
    		}
    	}
    	else
    	{
    		switch(SendTaskPtr)
    		{
    		case 0:  //initialization
    		memDataPtr32 = (int32 *) arrayGetList[CmdPacket[1]];
    		dataOut32 = *memDataPtr32;
    		wordsLeftToGet = CmdPacket[2];
    		//Note that case 0 rolls into case 1 (no break)
    		case 1:  //send LSB
    			if(wordsLeftToGet > 0)
    			{
    				if (SciaRegs.SCICTL2.bit.TXRDY == 1)
    				{
    					SciaRegs.SCITXBUF = (dataOut32 & 0x000000FF);
    					SendTaskPtr = 2;
    				}
    				else
    				{
    					TaskDoneFlag = TaskDoneFlag;
    					break;
    				}
    			}
    			else
    			{
    				SendTaskPtr = 0;
    				TaskDoneFlag = 1;
    				break;
    			}
    
    		case 2:
    			if (SciaRegs.SCICTL2.bit.TXRDY == 1)
    			{
    				SciaRegs.SCITXBUF = (dataOut32>>8 & 0x000000FF);
    				SendTaskPtr = 3;
    			}
    			else
    			{
    				TaskDoneFlag = TaskDoneFlag;
    				break;
    			}
    		case 3:
    			if(SciaRegs.SCICTL2.bit.TXRDY == 1)
    			{
    				SciaRegs.SCITXBUF = (dataOut32>>16 & 0x000000FF);
    				SendTaskPtr = 4;
    			}
    			else
    			{
    				TaskDoneFlag = TaskDoneFlag;
    				break;
    			}
    		case 4:	//send MSB
    			if(SciaRegs.SCICTL2.bit.TXRDY == 1)
    			{
    				SciaRegs.SCITXBUF = (dataOut32>>24 & 0x000000FF);
    
    				memDataPtr32 = memDataPtr32 + 1;
    				dataOut32 = *memDataPtr32;
    				wordsLeftToGet = wordsLeftToGet - 1;
    				SendTaskPtr = 1;
    			}
    			break;
    		}
    	}
    
    }
    

    SciCommsGui_32bit.c file seems perfectly capable for sci communication but I am not that capable to understand easily, so I have some questions.

    Everything was ok until "RxChar = SciaRegs.SCIRXBUF.all;" :)

    Now, I will move some of those codes relevant to receive values, below;

    void GetDataByte(void) // Task 5
    {
    	if (SciaRegs.SCIRXST.bit.RXRDY == 1)	// check if a char has been received
    	{
    		RxChar = SciaRegs.SCIRXBUF.all;
    		RcvTaskPointer = &EchoDataByte;		// point to next state
    		//RcvTskPtrShdw = 6;				// DEBUG
    		EchoDataByte();				
    	}
    
    	else if (SerialCommsTimer > 500)		// 1000*1mS = 1 sec timeout
    	{
    		CommsOKflg = 0;
    		RcvTaskPointer = &GetCmdByte;		// Abort, go back wait for new CMD
    		SerialCommsTimer = 0;
    	}
    	
    }
    

    void PackWord(void) // expects LSB first then MSB // Task 7
    {
    	if(LowByteFlag == 1)
    	{ 
    		RxWord = RxChar;
    		LowByteFlag = 0;
    		RcvTaskPointer = &GetDataByte;
    		//RcvTskPtrShdw = 5;				// DEBUG
    		GetDataByte();
    	}
    	else
    	{
    		RxWord = RxWord | (RxChar<<8);
    		LowByteFlag = 1;
    		CmdPacket[2] = RxWord;				// store data in packet
    		RcvTaskPointer = &CmdInterpreter;
    		//RcvTskPtrShdw = 8;				// DEBUG
    		TaskDoneFlag = 0; 					// indicate new task underway	
    	}
    }
    

    void CmdInterpreter(void) // Task 8
    {
    	if (TaskDoneFlag == 0)
    	{
    	 	(*CmdDispatcher[ CmdPacket[0] ] )();  	// dispatch Task					
    	}
    
    	// Incase Task never finishes 
    	if (SerialCommsTimer > 2500)			// 2500*1mS = 2.5 sec timeout
    	{
    		CommsOKflg = 0;
    		RcvTaskPointer = &GetCmdByte;		// Abort, go back wait for new CMD
    		SerialCommsTimer = 0;
    	}
    	if (TaskDoneFlag == 1)
    	{
    		RcvTaskPointer = &GetCmdByte;
    	 	//RcvTskPtrShdw = 1;   				// DEBUG
    	}
    }
    

    void DataGet(void)			// CmdPacket[0] = 6
    {
    	switch(MemGetPtr)
    	{
    		case 0:
    			MemGetAddress = CmdPacket[2];
    			MemGetPtr = 1;
    
    			wordsLeftToGet = 1;
    			SendTaskPtr = 1;
    			TaskDoneFlag = 1;
    			break;
    
    		case 1:
    			Temp = CmdPacket[2];
    			MemGetAddress = MemGetAddress + (Temp<<16);
    			memDataPtr16 = (int16_t*)MemGetAddress;
    			dataOut16 = *memDataPtr16;
    			SendData();		
    
    			if(TaskDoneFlag == 1)
    			{
    				MemGetPtr = 0;
    			}
    			break;
    		}

    So, I will start from the beginning.

    PC send my sci RXBUF ASCII characters (8 bit, 255 max) like 49, 50, 51,... (decimal 1,2,3...)

    Should I convert these to hex first, keep an address pointer for my float 32 or float 64 buffer, increase the pointer address for every received character and for example if that is 6 bytes total, define an 64 bit float value and use that?

    Or those codes above are already doing these for me? As I understand, I must definitely use pointers, right?

    Sorry again, there are too many variables inside "SciCommsGui_32bit" that makes me confused. :)

    Thanks for your help.

  • By the way, when I test "atof" function for some float values, it also is not accurate.

    converter = atof ("1.2");         // (converter shows : 1.19999993)

  • John , I had been out this entire month for personla and business related travel so trying to touch back on this topic.

    1. The inaccuracy you are refering to with atof will also be expected, in floating point there is no exact representation. Some rounding errors are expected and always present.

    2. For the SCI comms part, i will try to explain as below

    The code works with the following variables..

    //GUI support variables
    // sets a limit on the amount of external GUI controls - increase as necessary
    //16 textbox controlled variables
    volatile int16_t *varSetTxtList[16];
    //16 button controlled variables
    volatile int16_t *varSetBtnList[16];
    //16 slider controlled variables
    volatile int16_t *varSetSldrList[16];
    //16 variables sendable to GUI
    volatile int16_t *varGetList[16];
    //16 arrays sendable to GUI
    volatile int32_t *arrayGetList[16];
    //16 32-bit textbox or label controlled variables
    volatile uint32_t *dataSetList[16];

    We designed it to work with a host GUI, which can accomodate tex boxes, sliders, list ad arrays.

    As you want to use this for the float data you are typically concerned by
    //16 arrays sendable to GUI
    volatile int32_t *arrayGetList[16];
    //16 32-bit textbox or label controlled variables
    volatile uint32_t *dataSetList[16];


    Now as part of the serial host timer, we always call SerialHostComms()

    which executes the function pointed to by RcvTaskPointer () which can point to

    GetCmdByte
    EchoCmdByte;
    GetSizeByte
    EchoSizeByte
    GetDataByte
    EchoDataByte
    PackWord
    CmdInterpreter

    The very first routine the SCI comms goes into is GetCmdByte

    if a command from the host, PC is recieved this is where the code will go. Once it recieves this cmd, the MCU echos's the command back on the SCI channel. By going to EcoCmdByte. The command is stored in RxChar.

    This command is used to distinguish if we are exchanging a "list variable", "slider variable", or "array".

    As per the protocol we have defined for this, the next RxChar will include the Size of the "data", which will be 2 for 16 bit numbers and 4 for 32 bit numbers like float.

    Per the protocol, we wait for this data size to be transmitted from the host, and then received by the MCU. The MCU then echo's back that data size.

    Once the request to transmitt a 32 bit float is interpreted we get to

    where we send out 8 bits at a time of the 32 bit number to the HOST PC, where it can be re-constructed as bits first ..


    switch(SendTaskPtr)
    {
    case 0: //initialization
    memDataPtr32 = (int32_t *) arrayGetList[CmdPacket[1]];
    dataOut32 = *memDataPtr32;
    wordsLeftToGet = CmdPacket[2];
    //Note that case 0 rolls into case 1 (no break)
    case 1: //send LSB
    if(wordsLeftToGet > 0)
    {
    if (SCI_isTransmitterBusy(SCIA_BASE)==0)
    {
    SCI_writeCharBlockingNonFIFO(SCIA_BASE, dataOut32 & 0x000000FF);
    SendTaskPtr = 2;
    }
    }
    else
    {
    SendTaskPtr = 0;
    TaskDoneFlag = 1;
    break;
    }

    case 2:
    if (SCI_isTransmitterBusy(SCIA_BASE)==0)
    {
    SCI_writeCharBlockingNonFIFO(SCIA_BASE, dataOut32>>8 & 0x000000FF);
    SendTaskPtr = 3;
    }

    case 3:
    if(SCI_isTransmitterBusy(SCIA_BASE)==0)
    {
    SCI_writeCharBlockingNonFIFO(SCIA_BASE, dataOut32>>16 & 0x000000FF);
    SendTaskPtr = 4;
    }

    case 4: //send MSB
    if(SCI_isTransmitterBusy(SCIA_BASE)==0)
    {
    SCI_writeCharBlockingNonFIFO(SCIA_BASE, dataOut32>>24 & 0x000000FF);

    memDataPtr32 = memDataPtr32 + 1;
    dataOut32 = *memDataPtr32;
    wordsLeftToGet = wordsLeftToGet - 1;
    SendTaskPtr = 1;
    }
    break;



    Yes you will have to use pointers for all of this..