cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F0 I2C AND UART SIMULTANEOUSLY

GenuineDeveloper
Associate III
Posted on September 16, 2017 at 08:41

Hi All,

I am trying to interface a digital(I2C) pressure sensor with STM32F051R8T6(STM32F0 Discovery board). I basically want to read data from the sensor and display it on a serial terminal software(USB to TTL converter) using UART(to check the sensor). I tried UART first and was successful to send strings and display the same on terminal software. But, when I added the I2C part I couldn't send even a character through UART. What am I doing wrong here? or are there any other robust methods for this application.

Note:

1) I am using STANDARD PERIPHERAL LIBRARY

2) Pressure sensor address: 0x28

3) I2C on PB6 (SCL) & PB7 (SDA)

4) UART Rx (PA10) & Tx (PA9)

CODE:

//Includes

&sharpinclude <stm32f0xx.h>

&sharpinclude <stm32f0xx_gpio.h>

&sharpinclude <stm32f0xx_i2c.h>

&sharpinclude <stm32f0xx_rcc.h>

&sharpinclude <stm32f0xx_usart.h>

//Declarations

&sharpdefine PS_I2C I2C1

&sharpdefine PS_PORT    GPIOB

&sharpdefine PS_SCL GPIO_Pin_6

&sharpdefine PS_SDA GPIO_Pin_7

&sharpdefine PS_PIN_AF GPIO_AF_1

&sharpdefine PS_ADDR (0x28)

//Private variables

int8_t Data[2] = {0,0};

//Function declaration

void gpio_init(void)

{

    GPIO_InitTypeDef GPIO;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);

    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);

    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);

    GPIO.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;

    GPIO.GPIO_Mode = GPIO_Mode_AF;

    GPIO.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO.GPIO_OType = GPIO_OType_PP;

    GPIO.GPIO_PuPd = GPIO_PuPd_UP;

    GPIO_Init(GPIOA,&GPIO);

}

void usart_init(void)

{

    USART_InitTypeDef USART;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

    USART.USART_BaudRate = 115200;

    USART.USART_WordLength = USART_WordLength_8b;

    USART.USART_StopBits = USART_StopBits_1;

    USART.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

    USART.USART_Parity = USART_Parity_No;

    USART.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART1,&USART);

    //enable USART

    USART_Cmd(USART1,ENABLE);

}

char SendByte(uint8_t c)

{

    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

    USART_SendData(USART1,c);

}

void SendPacket(uint8_t *data, uint16_t length)

{

    uint16_t i;

    i = 0;

    while(i<length)

    {

        SendByte(data[i]);

        i++;

    }

}

void USART_clearscreen(void)

{

  char cmd1[5] = {0x1B, '[', '2', 'J', '\0'}; // Clear screen

  char cmd2[4] = {0x1B, '[', 'f', '\0'}; // Cursor home

  SendPacket(cmd1,5);

  SendPacket(cmd2,4);

}

// I2C setup for pressure sensor

void PSensor_Setup(void)

{

    GPIO_InitTypeDef GPIO;

    I2C_InitTypeDef I2C;

    //Set I2C1 clock to SYSCLK

    RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);

    //enable peripheral clock for I2C1 on APB1

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);

    //enable SDA, SCL and SMBA(if used) GPIO clocks

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB,ENABLE);

    //Peripheral alternate function configuration

    GPIO_PinAFConfig(PS_PORT,PS_SCL,GPIO_AF_1);

    GPIO_PinAFConfig(PS_PORT,PS_SDA,GPIO_AF_1);

    //Configure the GPIO as per I2C requirement

    GPIO.GPIO_Pin = PS_SCL | PS_SDA;

    GPIO.GPIO_Mode = GPIO_Mode_AF;

    GPIO.GPIO_OType = GPIO_OType_OD;

    GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(PS_PORT,&GPIO);

    //I2C configuration

    I2C.I2C_Ack = I2C_Ack_Enable;

    I2C.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

    I2C.I2C_AnalogFilter = I2C_AnalogFilter_Enable;

    I2C.I2C_DigitalFilter = 0;

    I2C.I2C_Mode = I2C_Mode_I2C;

    I2C.I2C_OwnAddress1 = 0;

    I2C.I2C_Timing = 0x00310309;

    I2C_Init(PS_I2C,&I2C);

    //Enable I2C

    I2C_Cmd(PS_I2C,ENABLE);

}

// Function to read from pressure sensor

uint8_t Read_PSensor()

{

    char cNoOfBytes = 0;

    //Check if I2C peripheral isn't busy

    while(I2C_GetFlagStatus(PS_I2C,I2C_FLAG_BUSY) == SET);

    //Start I2C Read transfer for 1 byte, do not end transfer(SoftEnd_Mode)

    I2C_TransferHandling(PS_I2C,PS_ADDR,2,I2C_AutoEnd_Mode,I2C_Generate_Start_Read);

    //Read 2 bytes of data

    for(cNoOfBytes = 0; cNoOfBytes<2; cNoOfBytes++)

    {

        //Wait until RX register is full of data

        while(I2C_GetFlagStatus(PS_I2C,I2C_FLAG_RXNE) == RESET);

        //store in array 'Data' pointer called from main

        Data[cNoOfBytes] = I2C_ReceiveData(PS_I2C);

    }

    //wait for the stop condition to be sent

    while(I2C_GetFlagStatus(PS_I2C,I2C_FLAG_STOPF) == RESET);

    //clear the stop flag for further transfers

    I2C_ClearFlag(PS_I2C,I2C_FLAG_STOPF);

    return 0;

}

int main(void)

{

    gpio_init();

    usart_init();

    PSensor_Setup();

    USART_clearscreen();

    int8_t FirstByte = 0;

    int8_t SecondByte = 0;

    while(1)

    {

        Read_PSensor();

        FirstByte = (Data[0]);

        SecondByte = (Data[1]);

        SendPacket('FirstByte: ',13);

        SendPacket(FirstByte,13);

        SendByte('\n');

        SendPacket('SecondByte: ',13);

        SendPacket(SecondByte,13);

        SendByte('\n');

        for(int i = 0; i<50000; i++);         //delay after one reading

    }

}

#stm32f0 #i2c #uart #i2c-and-uart #i2c-sensor-read #stm32f0-i2c-uart
3 REPLIES 3
Posted on September 18, 2017 at 12:11

Have you stepped through the I2C code in the debugger? Does it talk to the sensor properly? Do you get an error? Have you looked at the signal with an oscilloscope? Do you have external pull up resistors? 

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on September 21, 2017 at 17:00

Yes, I have external pull-up resistors. Yes, I stepped through the code in the debugger, didn't get any error. The variable storing the value received is also not changing, which means it has not established a proper connection with the sensor.

I have tried to do the same with Cube and I have been able to do that successfully. But, I did not get any proper resource to do the same using Standard Peripheral Library, because I feel using Cube will make it easy but might not let me learn in depth. Kindly help.

Lloyd Blackbeard
Associate II

If you stepped through and it worked, move your breakpoints around to isolate the bug. Otherwise, off the top of my head, I see that you've not bitwise or'd the sensor address with 1? Is that intended?

Imho, switching to Cube's low lEvel drivers generates code that you can learn from