STM32F3 Descubriendo valores de lectura desde el sensor utilizando I2C

2

Necesito leer los valores del sensor LSM303DLHC (conectado a través de I2C) a bordo y enviarlos a través de UART. La parte de UART está funcionando 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, ¿no?

PS. 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 porque estoy enviando valores hexadecimales que se muestran como caracteres ASCII. Así que estoy recibiendo valores que deberían ser, por ejemplo, mis datos de aceleración del eje X en dos bits (Alto y Bajo) en el complemento de dos. ¿Pero cómo convertir eso a valor decimal y enviarlo a través de UART?

    
pregunta Ekci

1 respuesta

1

Problema resuelto. Aquí se corrige parte 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);

    
respondido por el Ekci

Lea otras preguntas en las etiquetas