2021-12-19 10:26 AM
Hi everybody!
I have an STM32F411RE Nucleoboard and an ADXL345-M accelerometer. I have 2 problems.
I attach my code and a picture about register values.
Thank you in advance for your help!
Best regards,
Martin
void I2C_Init(void) {
//I2C_1 SCL: PB8
//I2C_1 SDA: PB9
//Enable clock access to I2C
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
//Enable clock access to GPIOB
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
//Set alternate function mode AF04
GPIOB->MODER &= ~(0x3 <<16);
GPIOB->MODER |= (0x2<<16);
GPIOB->MODER &= ~(0x3 <<18);
GPIOB->MODER |= (0x2<<18);
GPIOB->AFR[1] &= ~(0xF<<0);
GPIOB->AFR[1] |= (0x4<<0);
GPIOB->AFR[1] &= ~(0xF<<4);
GPIOB->AFR[1] |= (0x4<<4);
//Set output open-drain
GPIOB->OTYPER |= GPIO_OTYPER_OT8;
GPIOB->OTYPER |= GPIO_OTYPER_OT9;
//Enable pull up resistor
GPIOB->PUPDR &= ~(0x3 <<16);
GPIOB->PUPDR |= (0x1<<16);
GPIOB->PUPDR &= ~(0x3 <<18);
GPIOB->PUPDR |= (0x1<<18);
//Enable peripheral
I2C1->CR1 |= I2C_CR1_PE;
//Enable acknowledge
I2C1->CR1 |= I2C_CR1_ACK;
//Set clock frequency (16 MHz)
I2C1->CR2 |= (1<<4);
//Set CCR
I2C1->CCR |= (0x50<<0);
//Set TRISE to 16+1
I2C1->TRISE = 17;
}
void I2C_read_1_byte(char slave_addr, char mem_addr, char* data) {
volatile int temp;
//Wait for bus
while(I2C1->SR2 & I2C_SR2_BUSY){}
//Send START
I2C1->CR1 |= I2C_CR1_START;
//Wait for SB
while(!(I2C1->SR1 & I2C_SR1_SB)) {}
//Write slave address to DR | 1
I2C1->DR = slave_addr << 1;
//Wait for ADDR
while(!(I2C1->SR1 & I2C_SR1_ADDR)) {}
//Clear ADDR
temp = I2C1->SR1;
temp = I2C1->SR2;
//Wait for TRxE
while(!(I2C1->SR1 & I2C_SR1_TXE)) {}
//Set register address
I2C1->DR = mem_addr;
//Wait for TRxE and BTF
while(!(I2C1->SR1 & I2C_SR1_TXE)) {}
//Generate restart
I2C1->CR1 |= I2C_CR1_START;
//Wait for SB
while(!(I2C1->SR1 & I2C_SR1_SB)) {}
//Write slave address to DR
I2C1->DR = slave_addr << 1 | 1;
//Wait for ADDR
while(!(I2C1->SR1 & I2C_SR1_ADDR)) {}
//Send NACK
I2C1->CR1 &= ~I2C_CR1_ACK;
//Clear ADDR
temp = I2C1->SR1;
temp = I2C1->SR2;
//Wait for RxNE
while(!(I2C1->SR1 & I2C_SR1_RXNE)) {}
//Send STOP
I2C1->CR1 |= I2C_CR1_STOP;
//Read data
*data = I2C1->DR;
}
int main(void)
{
uint8_t id[0];
I2C_Init();
while(1) {
I2C_read_1_byte(SLAVE_ADDR, DEV_ID, (char*) id);
}
}
Solved! Go to Solution.
2021-12-19 01:41 PM
> uint8_t id[0];
"id" is defined as array of length 0. Probably not going to be able to put anything in there. Technically array of constant length 0 aren't allowed, but GCC didn't throw any warnings for me on it with default settings.
I2C protocol requires you to react to certain events quickly enough such that single stepping in the debugger is likely to cause problems. I would suggest finding another method to debug, perhaps through a UART stream or ITM.
The value that you store in "id" is also never used anywhere, so the compiler is free to optimize that out.
2021-12-19 01:41 PM
> uint8_t id[0];
"id" is defined as array of length 0. Probably not going to be able to put anything in there. Technically array of constant length 0 aren't allowed, but GCC didn't throw any warnings for me on it with default settings.
I2C protocol requires you to react to certain events quickly enough such that single stepping in the debugger is likely to cause problems. I would suggest finding another method to debug, perhaps through a UART stream or ITM.
The value that you store in "id" is also never used anywhere, so the compiler is free to optimize that out.
2021-12-21 07:35 AM
Thank you for the answer!:folded_hands:
Indeed the 0 array length was the problem...This is the case when can't see the forest for the trees.=)
All the best!
Martin