Skocz do zawartości
Zaloguj się, aby obserwować  
starcu

[STM32][C] Problem z komunikacją I2C

Pomocna odpowiedź

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.

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Napisz odpowiedź...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

Zaloguj się, aby obserwować  

×
×
  • Utwórz nowe...