STM32F3 Descubrimiento de valores de lectura del sensor usando I2C

Necesito leer los valores del sensor LSM303DLHC integrado (conectado a través de I2C) y enviarlos a través de UART. La parte UART funciona pero PuTTy muestra: "S▒▒" cada reinicio... ¿Alguien puede decirme qué está mal? Sé que la parte I2C no es perfecta, pero debería devolver algo, ¿verdad?

PD. No quiero usar su biblioteca. Aprenderé más de esta manera :)

#include "stm32f30x.h"

void SysTick_Handler(void);
void TimingDelay_Decrement(void);
void Delay(__IO uint32_t nTime);

static __IO uint32_t TimingDelay;
int b=0;

void UART_init (void);
void UART_SendChar (char data);
void USART_SendString (uint8_t * str);
int UART_read (void);

void i2c_conf();
void i2c_write_byte(uint8_t addr, uint8_t data);
uint8_t i2c_read_byte(uint8_t addr);

char read;
char data_from_i2c;

uint8_t CRA_REG_M = 0x00;
uint8_t MR_REG_M = 0x02;
uint8_t CRB_REG_M = 0x01;
uint8_t scldel;
uint8_t sdadel;

int main(void)
{
    SysTick_Config(SystemCoreClock / 1000);                         // Delay(1) = 1 ms with */1000

    UART_init();
    i2c_conf();

    /* ustaw zakres pomiarowy */
    i2c_write_byte(CRB_REG_M, 0x80);
    /* wlacz termometr i ustaw czestotliwosc odswiezania */
    i2c_write_byte(CRA_REG_M, 0x90);
    i2c_write_byte(MR_REG_M, 0x00);

    UART_SendChar('S'); 

    data_from_i2c = i2c_read_byte(0x03);
    UART_SendChar(data_from_i2c); 
    data_from_i2c = i2c_read_byte(0x04);
    UART_SendChar(data_from_i2c);

    while(1)
    {
//      uint8_t String[]="Hello world!";
//      USART_SendString (String);
//      Delay(1000);

        read=UART_read();
        UART_SendChar(read);
        read=0;

    }
}

void SysTick_Handler(void)
{
  TimingDelay_Decrement();
}

void Delay(__IO uint32_t nTime)
{
  TimingDelay = nTime;

  while(TimingDelay != 0);
}

void TimingDelay_Decrement(void)
{
  if (TimingDelay != 0x00)
  { 
    TimingDelay--;
  }
}

void UART_init (void) {
    RCC -> AHBENR  |=  (1UL << 19);                                     // Enable GPIOC clock
    GPIOC -> MODER |= (2 << 2*10) | (2 << 2*11);                // PC10 PC11 as AF mode
    GPIOC -> AFR[1] |= (7 << 8);                                                // PC10 as AF7 - USART3_TX
    GPIOC -> AFR[1] |= (7 << 12);                                               // PC11 as AF7 - USART3_RX

    RCC->APB1ENR  |=  (1UL << 18);                                      // Enable USART3 clock
    USART3 -> BRR = 3750; //Baudrate based on 24MHz clock 
    USART3 -> CR1 |= (USART_CR1_RE | USART_CR1_TE); 
    USART3 -> CR1 |= USART_CR1_UE;
}

void UART_SendChar (char data) {
    while( ( USART3 -> ISR & USART_ISR_TXE) == 0 ); 
    USART3 -> TDR = data;
}

void USART_SendString (uint8_t * str) {
    while(*str != 0) {
        UART_SendChar(*str); 
        str++;
    }
    UART_SendChar(10); 
    UART_SendChar(13); 
}

int UART_read (void)
{
    while ( (USART3->ISR & USART_ISR_RXNE) == 0); 
    return USART3-> RDR & USART_RDR_RDR;
}

void i2c_conf() {
    /* ustaw altenatywne funkcje GPIO */
    RCC -> AHBENR |= RCC_AHBENR_GPIOBEN;
    GPIOB -> OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR6 | ~GPIO_OSPEEDER_OSPEEDR7;
    GPIOB -> MODER |= GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1;
    GPIOB -> OTYPER |= GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7;
    GPIOB -> AFR[0] |= (4 << 24) | (4 << 28);

    /* zegar z APB1 - 72 MHz */
    //RCC->CFGR3 |= RCC_CFGR3_I2C1SW;
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN ;

    /* skonfiguruj I2C1 */
    I2C1->CR1 |= I2C_CR1_ANFOFF;
    scldel = 4;
    sdadel = 5;
    I2C1->TIMINGR = 0xF0001317 | ((scldel & 0x0F) << 20) | ((sdadel & 0x0F) << 16);
    I2C1->CR2 |= (0x1E << 1);
    I2C1->CR1 |= I2C_CR1_PE;
}

void i2c_write_byte(uint8_t addr, uint8_t data) {
    I2C1->CR2 &= ~(I2C_CR2_RD_WRN);
    I2C1->CR2 |= I2C_CR2_START |  (2 << 16);
    while(I2C1->CR2 & I2C_CR2_START);
    I2C1->TXDR = addr;
    while (!(I2C1->ISR & I2C_ISR_TXE));

    I2C1->TXDR = data;
    while (!(I2C1->ISR & I2C_ISR_TXE));
    I2C1->CR2 |= I2C_CR2_STOP;
    while(I2C1->CR2 & I2C_CR2_STOP);
}

uint8_t i2c_read_byte(uint8_t addr) {
    uint8_t data = 0;

    I2C1->CR2 &= ~(I2C_CR2_RD_WRN);
    I2C1->CR2 &= ~(0xff << 16);
    I2C1->CR2 |= I2C_CR2_START | (1 << 16);
    while(I2C1->CR2 & I2C_CR2_START);

    I2C1->TXDR = addr;
    while (!(I2C1->ISR & I2C_ISR_TXE));

    I2C1->CR2 |= I2C_CR2_RD_WRN;
    I2C1->CR2 |= I2C_CR2_START | (1 << 16);
    while(I2C1->CR2 & I2C_CR2_START);
    while (!(I2C1->ISR & I2C_ISR_RXNE));
    data = I2C1->RXDR;
    I2C1->CR2 |= I2C_CR2_STOP;
    while(I2C1->CR2 & I2C_CR2_STOP);
    return data;
}

Entonces, el problema con UART es que estoy enviando valores hexadecimales que se muestran como caracteres ASCII. Así que recibo valores que deberían ser, por ejemplo, mis datos de aceleración del eje X en dos bits (alto y bajo) en complemento a dos. Pero, ¿cómo convertir eso a valor decimal y enviarlo a través de UART?

Entonces, el problema con UART es que estoy enviando valores hexadecimales que se muestran como caracteres ASCII. Así que recibo valores que deberían ser, por ejemplo, mis datos de aceleración del eje X en dos bits (alto y bajo) en complemento a dos. Pero, ¿cómo convertir eso a valor decimal y enviarlo a través de UART?

Respuestas (1)

Problema resuelto. Aquí hay una parte corregida del código:

    i2c_write_byte(0x20, 0x37);  //CTRL_REG1_A = 00110111b

    test = i2c_read_byte(0x28);
    test2 = i2c_read_byte(0x29);
    X = (int16_t)(test | test2 << 8);

    test = i2c_read_byte(0x2A);
    test2 = i2c_read_byte(0x2B);
    Y = (int16_t)(test | test2 << 8);

    test = i2c_read_byte(0x2C);
    test2 = i2c_read_byte(0x2D);
    Z = (int16_t)(test | test2 << 8);

    AccYangle = (float) atan2(Y, Z) * 180/M_PI;
    AccXangle = (float) atan2(-X, sqrt(Y*Y + Z*Z)) * 180/M_PI;

    sprintf(buffer, "X = %f", AccXangle);
    USART_SendString(buffer);
    sprintf(buffer, "Y = %f", AccYangle);
    USART_SendString(buffer);

Y la dirección correcta del Acelerómetro: I2C1->CR2 |= (0x19 << 1);