Hello,
I have a discovery board with stm32f407vg-t6.There is a mems sensor on it and I am trying to read sensor values via I2C. However, my code is not working. I also upload my code.
I checked my code 4 times and couldn't find any mistake. I even messed up the code a little bit to be sure all the parameters were set correctly.
I connected physically the pins on the board like this below:
PA5->PB6
PA6->GND
PA7->PB7
Please help me to find the problem in this code.
main.c
#include <stdio.h>
#include <stdint.h>
#include "stm32f407xx.h"
#include "mems.h"
int16_t x,y,z;
float xg,yg,zg;
extern uint8_t data_rec[6];
int main(void){
mems_init();
while(1){
mems_read_values(Data_Start_ADDR);
x=((data_rec[1]<<8)| data_rec[0]);
y=((data_rec[3]<<8)| data_rec[2]);
z=((data_rec[5]<<8)| data_rec[4]);
xg = (x * 0.0078);
yg = (y * 0.0078);
zg = (z * 0.0078);
}
}
i2c.c
#include "stm32f407xx.h"
/*PB6 ----> SCL
*PB7 ----> SDA */
void i2c1_init(void){
//Enable GPIO clock
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
//Set SCL pin mode as alternate function
GPIOB->MODER &= ~(1U<<12);
GPIOB->MODER |= 1U<<13;
//Set SDA pin mode as alternate function
GPIOB->MODER &= ~(1U<<14);
GPIOB->MODER |= 1U<<15;
//Select alternate function for SCL pin
GPIOB->AFR[0] &=~(1U<<24);
GPIOB->AFR[0] &=~(1U<<25);
GPIOB->AFR[0] |=(1U<<26);
GPIOB->AFR[0] &=~(1U<<27);
//Select alternate function for SDA pin
GPIOB->AFR[0] &=~(1U<<28);
GPIOB->AFR[0] &=~(1U<<29);
GPIOB->AFR[0] |=(1U<<30);
GPIOB->AFR[0] &=~(1U<<31);
//Configure the SCL pin output type
GPIOB->OTYPER |=(1U<<6);
GPIOB->OTYPER |=(1U<<7);
//Configure the SDA pin output type
//Configure the SCL pin pull-up register
GPIOB->PUPDR |=(1U<<12);
GPIOB->PUPDR &=~(1U<<13);
GPIOB->PUPDR |=(1U<<14);
GPIOB->PUPDR &=~(1U<<15);
//Configure the SDA pin pull-up register
//Enable the clock access to I2C1
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
//Software reset enable
I2C1->CR1 |= I2C_CR1_SWRST;
//Software reset disable
I2C1->CR1 &= ~I2C_CR1_SWRST;
//Configure I2C_CR2 peripheral clock frequency [16MHz]
I2C1->CR2 = (1U<<4);
//Configure I2C_CCR register standard frequency
I2C1->CCR = 80;
//Configure I2C_TRISE
I2C1->TRISE = 17;
//Enable I2C Control Register
I2C1->CR1 |= I2C_CR1_PE;
}
void i2c1_byteRead(char saddr, char maddr, char* data){
volatile int tmp;
while(I2C1->SR2 & I2C_SR2_BUSY){}
I2C1->CR1 |= I2C_CR1_START;
while(!(I2C1->SR1 & I2C_SR1_SB)){}
I2C1->DR = saddr<<1;
while(!(I2C1->SR1 & I2C_SR1_ADDR)){}
/*Clear the ADDR flag*/
tmp = I2C1->SR2; //This comes from the referance manual. When you read SR2 after reading I2C_SR1 clears ADDR flag
I2C1->DR = maddr;
while(!(I2C1->SR1 & I2C_SR1_TXE)){}
I2C1->CR1 |= I2C_CR1_START;
while(!(I2C1->SR1 & I2C_SR1_SB)){}
I2C1->DR = saddr<<1 | 1;
while(!(I2C1->SR1 & I2C_SR1_ADDR)){}
I2C1->CR1 &= ~I2C_CR1_ACK;
tmp = I2C1->SR2;
I2C1->CR1 |= I2C_CR1_STOP;
while(!(I2C1->SR1 & I2C_SR1_RXNE)){}
*data++ = I2C1->DR;
}
void i2c1_burstRead(char saddr,char maddr, int n, char* data){
volatile int tmp;
while(I2C1->SR2 & I2C_SR2_BUSY);
I2C1->CR1 |= I2C_CR1_START;
while(!(I2C1->SR1 & I2C_SR1_SB));
I2C1->DR = saddr <<1;
while(!(I2C1->SR1 & I2C_SR1_ADDR));
tmp = I2C1->SR2; //This comes from the referance manual. When you read SR2 after reading I2C_SR1 clears ADDR flag
while(!(I2C1->SR1 & I2C_SR1_TXE));
I2C1->DR = maddr;
while(!(I2C1->SR1 & I2C_SR1_TXE));
I2C1->CR1 |= I2C_CR1_START;
while(!(I2C1->SR1 & I2C_SR1_SB));
I2C1->DR = saddr <<1|1;
while(!(I2C1->SR1 & I2C_SR1_ADDR));
tmp= I2C1->SR2;
I2C1->CR1|=I2C_CR1_ACK;
while(n>0U){
if(n==1U){
I2C1->CR1 &= ~I2C_CR1_ACK;
I2C1->CR1 |= I2C_CR1_STOP;
while(!(I2C1->SR1 & I2C_SR1_RXNE));
*data++=I2C1->DR;
break;
}
else{
while(!(I2C1->SR1 & I2C_SR1_RXNE));
(*data++) =I2C1->DR;
n--;
}
}
}
void i2c1_burstWrite(char saddr, char maddr, int n, char* data){
volatile int tmp;
while(I2C1->SR2 & I2C_SR2_BUSY){}
I2C1->CR1 |= I2C_CR1_START;
while(!(I2C1->SR1 & I2C_SR1_SB)){}
I2C1->DR = saddr << 1;
while(!(I2C1->SR1 & I2C_SR1_ADDR)){}
tmp = I2C1->SR2;
while(!(I2C1->SR1 & I2C_SR1_TXE)){}
I2C1->DR = maddr;
for(int i = 0; i<n; i++){
while(!(I2C1->SR1 & I2C_SR1_TXE)){}
I2C1->DR = *data++;
}
while(!(I2C1->SR1 & I2C_SR1_BTF)){}
I2C1->CR1 |= I2C_CR1_STOP;
}
mems.c
#include "mems.h"
#include <stdint.h>
char data;
uint8_t data_rec[6];
void mems_read_address(uint8_t reg){
i2c1_byteRead(Who_Am_I_R, reg, &data);
}
void mems_write(uint8_t reg, char value){
char data[1];
data[0] = value;
i2c1_burstWrite(Who_Am_I_R, reg, 1, data);
}
void mems_read_values(uint8_t reg){
i2c1_burstRead(Who_Am_I_R,reg, 6, (char*)data_rec);
}
void mems_init(void){
i2c1_init();
mems_read_address(SAD_R);
mems_write(CTRL_REG1, CTRL1_EIGHT_G);
mems_write(CTRL_REG1,RESET );
mems_write(CTRL_REG1, POWER_CTRL);
}
i2c.h
#ifndef I2C_H_
#define I2C_H_
void i2c1_init(void);
void i2c1_byteRead(char saddr, char maddr, char* data);
void i2c1_burstRead(char saddr,char maddr, int n, char* data);
void i2c1_burstWrite(char saddr, char maddr, int n, char* data);
#endif /* I2C_H_ */
mems.h
#ifndef MEMS_H_
#define MEMS_H_
#include <stdint.h>
#include "i2c.h"
#define Who_Am_I_R 0x0F
#define SAD_R 0x1D
#define CTRL_REG1 0x20
#define Data_Start_ADDR 0x29
#define CTRL1_EIGHT_G 0U<<5
#define POWER_CTRL 1U<<6
#define DATA_RATE 0U<<7
#define RESET 0X0U
void mems_init(void);
void mems_read_values(uint8_t reg);
#endif /* MEMS_H_ */