Сэр, я делаю проект I2C с MPU6050, используя плату STM32F4DISCOVERY. Бит ADDR в регистре SR1 сбрасывается в одном выполнении инструкции без чтения регистра SR2. Я получаю значение регистра WHO_AM_I 0X68H в режиме главного приемника I2C. Но он очищается в ходе выполнения 2-й инструкции без чтения регистра I2C_DR, но RXNE установлен.IНе могу понять и исправить. Пожалуйста, помогите мне. Какое решение?
MPUcheck.c
#include "stm32f4xx.h"
#include "i2ccc.h"
#include "MPU65.h"
uint8_t devicecon;
uint8_t mydata;
int main(void)
{
i2c1_init();
devicecon=deviceconnected(MPU6050_ADDRESS);
mydata=i2c1_read(MPU6050_ADDRESS,MPU6050_WHO_AM_I);
}
I2c.c
#include "stm32f4xx.h"
#include "i2ccc.h"
int a,b;
int i2c1_timeout=10;
uint8_t received_data;
uint8_t dat;
void i2c1_init(void)
{
RCC->APB1ENR |= (1<<21);//Enable clock to I2C1
//ENABLE PINS
RCC->AHB1ENR |= (1<<1);//ENABLE CLOCK FOR B PORT
GPIOB->MODER |= ((1<<13)|(1<<15));//PB6for SCL &PB7 for SDA SET TO ALTERNATE FUNCTION MODE
GPIOB->OTYPER |= ((1<<6)|(1<<7));
GPIOB->OSPEEDR |= ((1<<13)|(1<<15));
GPIOB->PUPDR |= ((1<<12)|(1<<14));
GPIOB->AFR[0] |= ((1<<30)|(1<<26));
I2C1->CR2 |= 16;//PERIPHERAL FREQ 16MHZ IN DECIMAL
/*SET I2C MASTERMODE SELECTION IN FM MODE,
SET TO 50 50% DUTY CYCLE*/
I2C1->CCR = 0X800D;//Controls the SCL clock in master mode.
I2C1->TRISE = 0X0005;//Maximum rise time in Fm/Sm mode (Master mode)
I2C1->OAR1=0x40A0;
I2C1->CR1 |= (1<<0);//ENABLE THE PE BIT
}
int16_t i2c1_start(uint8_t address,uint8_t direction,uint8_t ack)
{
/*generate i2c start pulse*/
I2C1->CR1 |= 1<<8;//SET START BIT TO start generation
/* WAIT TILL BUSY BIT CLEARED IN SR2 AND SET THE SB BIT IN SR1*/
while(!(I2C1->SR1 & (1<<0)))
{
if(--i2c1_timeout ==0x00)
{
return 1;
}
}
/*enable ack if we select it*/
if(ack)
{
I2C1->CR1 |= (1<<10);//ENABLE ACK BIT IF SB IS SET
}
if(direction==i2c_transmitter_mode)
{
I2C1->DR = address | 0;//SEND ADDRESS WITH ZERO LAST BIT
while(!(I2C1->SR1 & (1<<7)))
{
if(--i2c1_timeout==00)
{
return 1;
}
}
I2C1->SR2;
return 0;
}
if(direction == i2c_receiver_mode)
{
I2C1->DR=address|1;
while(!(I2C1->SR1 & (1<<6)))
{
if(--i2c1_timeout==0x00)
{
return 1;
}
}
}
I2C1->SR2;
return 0;
}
uint8_t i2c1_stop(void)
{
/*WAIT TILL TRANSMITTER NOT EMPTY MEANS SET THE TXE AND BTF BITS*/
if((I2C1->SR1&1<<7)||(I2C1->SR1&1<<2))
{
/*generate stop*/
I2C1->CR1 |= (1<<9);
}
else
{
return 1;
}
/*RETURN 0,EVERYTHING OK*/
return 0;
}
void i2c1_writedata(uint8_t data)
{
/*wait til i2c is not busy anymore*/
while(!(I2C1->SR1 & (1<<7)))
{
i2c1_timeout--;
}
I2C1->DR=data;
}
uint8_t i2c1_readnack(void)
{
uint8_t data;
/*disable ack for single byte*/
I2C1->CR1 &= (0<<10);
/*GENERATE STOP*/
//I2C1->CR1 |= (1<<9);
/* wait till received*/
while(!(I2C1->SR1 & (1<<6)))
{
if(i2c1_timeout==0x00)
{
i2c1_timeout--;
}
}
data=I2C1->DR;
return data;
}
uint8_t i2c1_read(uint8_t address,uint8_t reg)
{
i2c1_start(address, i2c_transmitter_mode,i2c_ack_disable);
i2c1_writedata(reg);
i2c1_start(address,i2c_receiver_mode,i2c_ack_disable);
received_data=i2c1_readnack();
return received_data;
}
MPU65.C
#include "stm32f4xx.h"
#include "i2ccc.h"
#include "MPU65.h"
uint8_t connected=0;
uint8_t address=MPU6050_ADDRESS ;
uint8_t deviceconnected(uint8_t address)
{
if(!i2c1_start(address,i2c_transmitter_mode ,i2c_ack_enable))
{
connected =1;
}
i2c1_stop();
return connected;
}