STM32F4DISCOVERY: получение WHO_AM_I значения регистра MPU6050 - PullRequest
0 голосов
/ 15 октября 2019

Сэр, я делаю проект 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;
}
...