2017-09-15 11:41 PM
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 homeSendPacket(cmd1,5);
SendPacket(cmd2,4);}// I2C setup for pressure sensorvoid 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-uart2017-09-18 03:11 AM
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?
2017-09-21 10:00 AM
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.
2018-12-19 12:22 PM
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