STM32F3 Discovery liest Werte vom Sensor mit I2C

Ich muss Werte vom integrierten LSM303DLHC-Sensor (über I2C verbunden) lesen und über UART senden. UART-Teil funktioniert, aber PuTTy zeigt: "S▒▒" bei jedem Neustart ... Kann mir jemand sagen, was falsch ist? Ich weiß, dass der I2C-Teil nicht perfekt ist, aber er sollte etwas zurückgeben, oder?

PS. Ich möchte ihre Bibliothek nicht benutzen - ich werde auf diese Weise mehr lernen :)

#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;
}

Das Problem mit UART liegt also darin, dass ich Hex-Werte sende, die als ASCII-Zeichen angezeigt werden. Ich erhalte also Werte, die zum Beispiel meine X-Achsen-Beschleunigungsdaten in zwei Bits (High und Low) im Zweierkomplement sein sollten. Aber wie konvertiert man das in einen Dezimalwert und sendet es über UART?

Das Problem mit UART liegt also darin, dass ich Hex-Werte sende, die als ASCII-Zeichen angezeigt werden. Ich erhalte also Werte, die zum Beispiel meine X-Achsen-Beschleunigungsdaten in zwei Bits (High und Low) im Zweierkomplement sein sollten. Aber wie konvertiert man das in einen Dezimalwert und sendet es über UART?

Antworten (1)

Problem gelöst. Hier ist ein korrigierter Teil des Codes:

    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);

Und korrekte Adresse des Beschleunigungsmessers: I2C1->CR2 |= (0x19 << 1);