AnsweredAssumed Answered

STM32F4 USART receiving float number

Question asked by rabah.mohamed on Oct 5, 2016
Latest reply on Oct 14, 2016 by Clive One
I am trying to read data from my IMU6050 and displaying it using USART.
I can successfully read integer values, but since i need to convert the data to float to display actual sensor reading, i keep receiving random characters.
BTW i am using sprintf funtion to convert float into array.
u can find my code below.
#include "stm32f4xx.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_i2c.h"
#include "misc.h"
#include "stdlib.h"
#include "math.h"
 
 
void Delay(__IO uint32_t nCount)
{
  while(nCount--)
  {
  }
}
 
//the function “I2C_Write1Byte” to send one byte of data into the slave to a given address is presented next.
//The function receives three arguments for defining the address of the slave (‘SlaveAddr’),
//selecting the register within the slave (‘addr’) and the data to be sent to this register (‘byte1’);
void I2C_Write1Byte(u8 SlaveAddr, char addr, char byte1)
{
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));  //WAIT IF I2C1 IS BUSY
    I2C_GenerateSTART(I2C1, ENABLE);    //GENERATE START
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //WAIT FOR EV5
    I2C_Send7bitAddress(I2C1, (SlaveAddr << 1), I2C_Direction_Transmitter); //SEND SLAVE ADDRESS
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));   //WAIT FOR EV6
    I2C_SendData(I2C1, addr);   //ADDRESS WITHIN SLAVE
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));  //WAIT FOR EV8
    I2C_SendData(I2C1, byte1);  //SEND DATA TO SLAVE
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));   //WAIT FOR EV8_2
    I2C_GenerateSTOP(I2C1, ENABLE); //GENERATE STOP
}
 
//and the function “I2C_Read1Byte” to read one byte of data from slave is presented next.
//The function receives two arguments for defining the address of the slave (‘SlaveAddr’), and selecting the register within the slave (‘addr’);
char I2C_Read1Byte(char SlaveAddr, char addr)
{
    //FORST 6 LINES FOR SENDING ADDRESS WITHIN SLAVE
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));  //WAIT IF I2C1 IS BUSY
    I2C_GenerateSTART(I2C1, ENABLE);    //GENERATES START
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //WAIT FOR EV5
    I2C_Send7bitAddress(I2C1, (SlaveAddr << 1), I2C_Direction_Transmitter); //SEND DEVICE ADDRESS BUT WE ARE WRITING
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));   //WAIT FOR EV6
    I2C_SendData(I2C1, addr);   //addr WITHIN DEVICE
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));    //WAIT FOR EV8_2
 
    //UPCOMING LINES FOR READING DATA FROM DR "DATA REGISTER"
    I2C_GenerateSTART(I2C1, ENABLE);    //GENERATE START
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //WAIT FOR EV5
    I2C_Send7bitAddress(I2C1, (SlaveAddr << 1), I2C_Direction_Receiver);    //SEND DEVICE ADDRESS BUT WE ARE READING
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));  //WAIT FOR EV6
 
    /* If more than one byte is to be read from the slave, then the last part of the function following line 13 should be replaced by the listing below.
     *
     * I2C_AcknowledgeConfig(I2C1, ENABLE); // acknowledge 1st byte
     * while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) ); // wait EV7
     * char byte1 = I2C_ReceiveData(I2C1); // retrieve byte
     * I2C_AcknowledgeConfig(I2C1, DISABLE); // do not acknowledge 2nd byte
     * while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) );
     * char byte2 = I2C_ReceiveData(I2C1);// retrieve byte
     * I2C_GenerateSTOP(I2C1, ENABLE); // generate STOP
     * return ((byte2 << 8) + byte1);
     *
     */
    I2C_AcknowledgeConfig(I2C1, DISABLE);   //DO NOT ACK
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));  //WAIT FOR EV7
    char byte1 = I2C_ReceiveData(I2C1); //RETRIEVE BYTE
    I2C_GenerateSTOP(I2C1, ENABLE); //GENERATE STOP
    return (byte1);
}
 
uint16_t I2C_Read2Byte(char SlaveAddr, char addr)
{
    //FORST 6 LINES FOR SENDING ADDRESS WITHIN SLAVE
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));  //WAIT IF I2C1 IS BUSY
    I2C_GenerateSTART(I2C1, ENABLE);    //GENERATES START
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //WAIT FOR EV5
    I2C_Send7bitAddress(I2C1, (SlaveAddr << 1), I2C_Direction_Transmitter); //SEND DEVICE ADDRESS BUT WE ARE WRITING
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));   //WAIT FOR EV6
    I2C_SendData(I2C1, addr);   //addr WITHIN DEVICE
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));    //WAIT FOR EV8_2
 
    //UPCOMING LINES FOR READING DATA FROM DR "DATA REGISTER"
    I2C_GenerateSTART(I2C1, ENABLE);    //GENERATE START
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //WAIT FOR EV5
    I2C_Send7bitAddress(I2C1, (SlaveAddr << 1), I2C_Direction_Receiver);    //SEND DEVICE ADDRESS BUT WE ARE READING
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));  //WAIT FOR EV6
 
    I2C_AcknowledgeConfig(I2C1, ENABLE); // acknowledge 1st byte
    while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) ); // wait EV7
    char byte1 = I2C_ReceiveData(I2C1); // retrieve byte
    I2C_AcknowledgeConfig(I2C1, DISABLE); // do not acknowledge 2nd byte
    while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) );
    char byte2 = I2C_ReceiveData(I2C1);// retrieve byte
    I2C_GenerateSTOP(I2C1, ENABLE); // generate STOP
    return ((byte2 << 8) | byte1);
}
 
 
void setup_Pheriph()
{
    GPIO_InitTypeDef GPIO_InitStruct;
    USART_InitTypeDef USART_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;
    I2C_InitTypeDef I2C_InitStruct;
 
    //ENABLE PERIPH CLOCK FOR USART2
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    //ENABLE GPIOA CLOCK
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    //ENABLE GPIOD CLOCK
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
    //ENABLE GPIOB CLOCK
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    //ENABLE I2C1 CLOCK
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
 
    //SETUP GPIOA PINS FOR USART Tx AND Rx
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;   //SINCE WE HAVE USED ALTERNATIVE FUNCTION WE SHOULD ASIGN IT DOWN
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;   //PULL UP RESISTORS
    GPIO_Init(GPIOA, &GPIO_InitStruct);
 
    //SETTING UP AF FOR UARTS2
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);   //WE SET PIN2 AND 3 AS AF FOR UART2
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
 
    //SETUP GPIOD PINS FOR BLINKING LED
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_12 |GPIO_Pin_14|GPIO_Pin_15;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_Init(GPIOD, &GPIO_InitStruct);
 
    //SETUP GPIO FOR I2C SCL AND SDL
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //SDA, SCL DEF
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
    GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    //SETTING UP AF FOR I2C
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
 
    //SETUP USART CONFIG
    USART_InitStruct.USART_BaudRate = 9600;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;    //WE SETUP USART FOR Rx AND Tx
    USART_Init(USART2, &USART_InitStruct);
 
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);  //SETUP INTERRUPT REQUEST FOR USART FOR ONLY RECEIVE
 
    //SETTING UP INTERRUPT REQUEST NVIC
    NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;  //CHANNEL IS THE INTERRUPT NAME I WANT TO CONFIGURE
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;    //ENABLE USART GLOBALLY
    NVIC_Init(&NVIC_InitStruct);
 
    //ENABLE USART2 PERIPHERAL
    USART_Cmd(USART2, ENABLE);
 
    //SETTING UP I2C CONFIG
    I2C_InitStruct.I2C_ClockSpeed = 100000;
    I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_16_9;
    I2C_InitStruct.I2C_OwnAddress1 = 0; //GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
    I2C_InitStruct.I2C_Ack = I2C_Ack_Disable;   //
    I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init(I2C1, &I2C_InitStruct);
    I2C_Cmd(I2C1, ENABLE);
}
 
void USART_putch(USART_TypeDef* USARTx, uint8_t ch)
{
    USART_SendData(USARTx,ch);
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
}
 
void USART_puts(USART_TypeDef* USARTx, uint8_t str[])
{
    while(*str)     USART_putch(USARTx, *str++);
}
void USART_PutNumber(USART_TypeDef* USARTx, uint32_t x)
{
  char value[20]; //a temp array to hold results of conversion
  int i = 0; //loop index
 
  do
  {
    value[i++] = (char)(x % 10) + '0'; //convert integer to character
    x /= 10;
  } while(x);
 
  while(i) //send data
  {
      USART_putch(USARTx, value[--i]);
 
  }
  USART_puts(USARTx, " \r\n");
}
 
void USART_Float(USART_TypeDef *USARTx, float x)
{
    char str[80];
    sprintf(str, "%.02f", x);
    USART_putch(USARTx, str);
}
 
uint16_t USART_receive_char(USART_TypeDef *USARTx)
{
    //WAIT UNTIL CHAR IS RECEIVED
    while(!USART_GetFlagStatus(USARTx, USART_FLAG_RXNE));
    //READ RECEIVED CHAR
    return USART_ReceiveData(USARTx);
}
 
 
int main(void)
{
 
    setup_Pheriph();
 
    USART_puts(USART2, "Welcome Mohamed!\r\n");
 
 
 
 
 
    //USART_PutNumber(USART2, 2313);
 
    I2C_Write1Byte(0x68, 0x6B, 0);
    I2C_Write1Byte(0x68, 0x1C, 0);
 
 
 
    while(1)
    {
        // a test to read accelerometer x axis
        uint16_t byte = (I2C_Read1Byte(0x68, 0x3B)<<8)|(I2C_Read1Byte(0x68, 0x3C));
        (float)byte = byte/16384.0;
        USART_Float(USART2, byte);
        Delay(16800000);
 
    }
}
 
 
 
 
 
uint16_t rec_char;
 
void USART2_IRQHandler()
{
 
    rec_char = USART_receive_char(USART2);
    if(rec_char == 'o')
        GPIO_WriteBit(GPIOD, GPIO_Pin_13, Bit_SET);
    if(rec_char == 'g')
        GPIO_WriteBit(GPIOD, GPIO_Pin_12, Bit_SET);
    if(rec_char == 'r')
        GPIO_WriteBit(GPIOD, GPIO_Pin_14, Bit_SET);
    if(rec_char == 'b')
        GPIO_WriteBit(GPIOD, GPIO_Pin_15, Bit_SET);
    if(rec_char == 'x')
        GPIO_WriteBit(GPIOD, GPIO_Pin_13 |GPIO_Pin_12 |GPIO_Pin_14|GPIO_Pin_15, Bit_RESET);
 
}

Outcomes