Skocz do zawartości

[STM32][C] Problem z komunikacją I2C


Pomocna odpowiedź

Napisano

Po pojawieniu się kursu programowania stm32 postanowiłem podszkolić się w programowaniu tych mikroprocków i utknąłem na obsłudze i2c. Próbuje odczytać dane z modułu MPU6050, ale nie udaje mi się to. W debugerze zauważyłem, że program zatrzymuje się na pętli while w jednej z funkcji obsługującej i2c. Poniżej zamieszczam kod, w którego komentarzach zaznaczyłem gdzie jest problem.

Plik "mpu6050.h":

/*
* mpu6050.h
*
*  Created on: 13 mar 2016
*      Author: Łukasz
*/

#ifndef MPU6050_H_
#define MPU6050_H_

#include "stm32f10x.h"

#define MPU6050_ADDRESS ((uint16_t)(0x69))
#define MPU6050_RA_WHO_AM_I ((uint16_t)(0x75))

void mpu_set_reg(uint8_t reg){
 I2C_GenerateSTART(I2C1, ENABLE); //start i2c
 while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS); //dziala ok
 I2C_Send7bitAddress(I2C1, MPU6050_ADDRESS, I2C_Direction_Transmitter); 
 while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS); //zatrzymuje sie tutaj, flag1 w I2C_CheckEvent wynosi 1024 zamiast 2
 I2C_SendData(I2C1, 0x80 | reg); //dlazcego tu jest 0x80???
 while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
}

void mpu_write(uint8_t reg, const void* data, int size){
 int i;
 const uint8_t* buffer = (uint8_t*)data;

 mpu_set_reg(reg);
 for (i = 0; i < size; i++) {
 I2C_SendData(I2C1, buffer[i]);
 while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
 }
 I2C_GenerateSTOP(I2C1, ENABLE);
}

void mpu_read(uint8_t reg, void* data, int size){
 int i;
 uint8_t* buffer = (uint8_t*)data;

 mpu_set_reg(reg);

 I2C_GenerateSTART(I2C1, ENABLE);
 while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);

 I2C_AcknowledgeConfig(I2C1, ENABLE);
 I2C_Send7bitAddress(I2C1, MPU6050_ADDRESS, I2C_Direction_Receiver);
 while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS);

 for (i = 0; i < size - 1; i++) {
 while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
     buffer[i] = I2C_ReceiveData(I2C1);
    }
 I2C_AcknowledgeConfig(I2C1, DISABLE);
    I2C_GenerateSTOP(I2C1, ENABLE);
    while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
    buffer[i] = I2C_ReceiveData(I2C1);
}

#endif /* MPU6050_H_ */

Plik "main.c":

/**
 ******************************************************************************
 * @file    main.c
 * @author  Lukasz S.
 * @version V1.0
 * @date    01-December-2013
 * @brief   Default main function.
 ******************************************************************************
*/

#include "stm32f10x.h"
#include "mpu6050.h"
#include "uart.h"
#include <stdio.h>

volatile uint32_t timer_ms = 0;

void SysTick_Handler(){
if (timer_ms) {
timer_ms--;
}
}

void delay_ms(int time){
timer_ms = time*1000;
while (timer_ms) {
 SysTick_Handler();
}
}

int main(void){

 GPIO_InitTypeDef gpio;
 I2C_InitTypeDef i2c;
 USART_InitTypeDef uart;

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

 GPIO_StructInit(&gpio);
 gpio.GPIO_Pin = GPIO_Pin_2;
 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_Init(GPIOA, &gpio);

 gpio.GPIO_Pin = GPIO_Pin_3;
 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
 GPIO_Init(GPIOA, &gpio);

 gpio.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_4;
 gpio.GPIO_Mode=GPIO_Mode_Out_PP;
 GPIO_Init(GPIOA, &gpio);

 USART_StructInit(&uart);
 uart.USART_BaudRate = 115200;
 USART_Init(USART2, &uart);
 USART_Cmd(USART2, ENABLE);

 gpio.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; // SCL, SDA
 gpio.GPIO_Mode = GPIO_Mode_AF_OD;
 gpio.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(GPIOB, &gpio);

 I2C_StructInit(&i2c);
 i2c.I2C_Ack = I2C_Ack_Enable;
 i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
 i2c.I2C_Mode = I2C_Mode_I2C;
 i2c.I2C_OwnAddress1 = 0;
 I2C_Init(I2C1, &i2c);
 I2C_Cmd(I2C1, ENABLE);

 unsigned char who_am=0;

while(1){

	mpu_read(MPU6050_RA_WHO_AM_I, &who_am, sizeof(who_am));

	if(who_am==0x68){
		printf("Znaleziono modul.\n");
	}else{
		printf("Niepoprawna odpowiedz ukladu.\n");
	}

	//printf("Hello world!\r\n");
	GPIO_SetBits(GPIOA, GPIO_Pin_4);
	GPIO_ResetBits(GPIOA, GPIO_Pin_5);
	delay_ms(500);
	GPIO_ResetBits(GPIOA, GPIO_Pin_4);
	GPIO_SetBits(GPIOA, GPIO_Pin_5);
	delay_ms(500);
}
}

Ponadto nie rozumiem dlaczego wykonano or z 0x80 na rejestrze.

[ Dodano: 15-03-2016, 22:36 ]

Udało mi się dojąć poprzez debugger, ze błąd zwracany przez i2c ma kod 0x0400 co oznacza "acknowledge failure", spotkał się ktoś z czymś takim?

[ Dodano: 16-03-2016, 10:41 ]

Ok, wszystko działa, miałem ustawiony adres urządzenia 0x69 zamiast 0x68, a mógłbym przysiąc, że to już wcześniej sprawdzałem.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...