2015-09-06 59 views
1

我使用的IDE是'KeilμVision5'。STM32F4-Discovery Board:在PC屏幕上从连接的传感器打印数据

我拥有一个STM32F429ZIT-Discovery Board(它有一个LCD显示器),我连接了一个Bosch Sensortec BNO055 9-Axis IMU。我希望他们通过I²C彼此通信,因此,我已经作出所需的连接如下:

  • VIN(传感器) - > 5V(愉板)
  • GND(传感器) - > GND(愉 局)
  • SDA(传感器) - > PB7(愉局)
  • SCL(传感器) - > PB6 (愉局)

我下载了BNO055_driver,其中包含文件“bno055_support.c'(它包含有关如何从传感器获取数据的代码示例)。

我觉得这很混乱。我不知道我的项目中需要包含哪些代码行。 我试了一下,并且还包含了一些应该与I²C相关的行。

我必须说我对编程和微控制器一般都很缺乏经验,很清楚。这就像我拼凑在一起的一堆代码,这可能没有任何意义。请多多包涵。在这里你可以看到我试过的代码。

的混乱到目前为止我有:

#include "stm32f4xx.h"     
#include "system_stm32f4xx.h" 
#include "stm32f4xx_i2c.h" 
#include "stm32f4xx_gpio.h" 
#include <stdint.h> 
#include "bno055.h" 
#include "stm32f4xx_rcc.h" 

#define SLAVE_ADDRESS 0x29       // BNO055 Slave Address 

void init_I2C1(void){ 

    GPIO_InitTypeDef GPIO_InitStruct; 
    I2C_InitTypeDef I2C_InitStruct; 

    // enable APB1 peripheral clock for I2C1 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); 
    // enable clock for SCL and SDA pins 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); 

    /* setup SCL and SDA pins 
    * You can connect I2C1 to two different 
    * pairs of pins: 
    * 1. SCL on PB6 and SDA on PB7 
    * 2. SCL on PB8 and SDA on PB9 
    */ 
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // we are going to use PB6 and PB7 
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;   // set pins to alternate function 
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  // set GPIO speed 
    GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;   // set output to open drain --> the line has to be only pulled low, not driven high 
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;   // enable pull up resistors 
    GPIO_Init(GPIOB, &GPIO_InitStruct);     // init GPIOB 

    // Connect I2C1 pins to AF 
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1); // SCL 
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1); // SDA 

    // configure I2C1 
    I2C_InitStruct.I2C_ClockSpeed = 100000;   // 100kHz 
    I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;   // I2C mode 
    I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; // 50% duty cycle --> standard 
    I2C_InitStruct.I2C_OwnAddress1 = 0x00;   // own address, not relevant in master mode 
    I2C_InitStruct.I2C_Ack = I2C_Ack_Disable;  // disable acknowledge when reading (can be changed later on) 
    I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // set address length to 7 bit addresses 
    I2C_Init(I2C1, &I2C_InitStruct);    // init I2C1 

    // enable I2C1 
    I2C_Cmd(I2C1, ENABLE); 
} 

/* This function issues a start condition and 
* transmits the slave address + R/W bit 
* 
* Parameters: 
*  I2Cx --> the I2C peripheral e.g. I2C1 
*  address --> the 7 bit slave address 
*  direction --> the tranmission direction can be: 
*      I2C_Direction_Tranmitter for Master transmitter mode 
*      I2C_Direction_Receiver for Master receiver 
*/ 
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction){ 
    // wait until I2C1 is not busy anymore 
    while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)); 

    // Send I2C1 START condition 
    I2C_GenerateSTART(I2Cx, ENABLE); 

    // wait for I2C1 EV5 --> Slave has acknowledged start condition 
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); 

    // Send slave Address for write 
    I2C_Send7bitAddress(I2Cx, address, direction); 

    /* wait for I2C1 EV6, check if 
    * either Slave has acknowledged Master transmitter or 
    * Master receiver mode, depending on the transmission 
    * direction 
    */ 
    if(direction == I2C_Direction_Transmitter){ 
     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); 
    } 
    else if(direction == I2C_Direction_Receiver){ 
     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); 
    } 
} 

/* This function transmits one byte to the slave device 
* Parameters: 
*  I2Cx --> the I2C peripheral e.g. I2C1 
*  data --> the data byte to be transmitted 
*/ 
void I2C_write(I2C_TypeDef* I2Cx, uint8_t data) 
{ 
    I2C_SendData(I2Cx, data); 
    // wait for I2C1 EV8_2 --> byte has been transmitted 
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); 
} 

/* This function reads one byte from the slave device 
* and acknowledges the byte (requests another byte) 
*/ 
uint8_t I2C_read_ack(I2C_TypeDef* I2Cx){ 
    // enable acknowledge of recieved data 
    I2C_AcknowledgeConfig(I2Cx, ENABLE); 
    // wait until one byte has been received 
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); 
    // read data from I2C data register and return data byte 
    uint8_t data = I2C_ReceiveData(I2Cx); 
    return data; 
} 

/* This function reads one byte from the slave device 
* and doesn't acknowledge the recieved data 
*/ 
uint8_t I2C_read_nack(I2C_TypeDef* I2Cx){ 
    // disabe acknowledge of received data 
    // nack also generates stop condition after last byte received 
    // see reference manual for more info 
    I2C_AcknowledgeConfig(I2Cx, DISABLE); 
    I2C_GenerateSTOP(I2Cx, ENABLE); 
    // wait until one byte has been received 
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); 
    // read data from I2C data register and return data byte 
    uint8_t data = I2C_ReceiveData(I2Cx); 
    return data; 
} 

/* This funtion issues a stop condition and therefore 
* releases the bus 
*/ 
void I2C_stop(I2C_TypeDef* I2Cx){ 
    // Send I2C1 STOP Condition 
    I2C_GenerateSTOP(I2Cx, ENABLE); 
} 

int main(void){ 

    init_I2C1(); // initialize I2C peripheral 

    uint8_t received_data[2]; 

    while(1){ 

     I2C_start(I2C1, SLAVE_ADDRESS<<1, I2C_Direction_Transmitter); // start a transmission in Master transmitter mode 
     I2C_write(I2C1, 0x20); // write one byte to the slave 
     I2C_write(I2C1, 0x03); // write another byte to the slave 
     I2C_stop(I2C1); // stop the transmission 

     I2C_start(I2C1, SLAVE_ADDRESS<<1, I2C_Direction_Receiver); // start a transmission in Master receiver mode 
     received_data[0] = I2C_read_ack(I2C1); // read one byte and request another byte 
     received_data[1] = I2C_read_nack(I2C1); // read one byte and don't request another byte, stop transmission 
    } 
} 

/*----------------------------------------------------------------------------* 
* The following functions are used for reading and writing of 
* sensor data using I2C communication 
*----------------------------------------------------------------------------*/ 
#ifdef BNO055_API 
/* \Brief: The function is used as I2C bus read 
* \Return : Status of the I2C read 
* \param dev_addr : The device address of the sensor 
* \param reg_addr : Address of the first register, will data is going to be read 
* \param reg_data : This data read from the sensor, which is hold in an array 
* \param cnt : The no of byte of data to be read 
*/ 
s8 BNO055_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt); 
/* \Brief: The function is used as SPI bus write 
* \Return : Status of the SPI write 
* \param dev_addr : The device address of the sensor 
* \param reg_addr : Address of the first register, will data is going to be written 
* \param reg_data : It is a value hold in the array, 
*  will be used for write the value into the register 
* \param cnt : The no of byte of data to be write 
*/ 
s8 BNO055_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt); 
/* 
* \Brief: I2C init routine 
*/ 
s8 I2C_routine(void); 
#endif 
/********************End of I2C function declarations***********************/ 
s32 bno055_data_readout_template(void) 
{ 
/*---------------------------------------------------------------------------* 
*********************** START INITIALIZATION ************************ 
*--------------------------------------------------------------------------*/ 
#ifdef BNO055_API 
/* Based on the user need configure I2C interface. 
* It is example code to explain how to use the bno055 API*/ 
    I2C_routine(); 
#endif 
/*--------------------------------------------------------------------------* 
* This function used to assign the value/reference of 
* the following parameters 
* I2C address 
* Bus Write 
* Bus read 
* Chip id 
* Page id 
* Accel revision id 
* Mag revision id 
* Gyro revision id 
* Boot loader revision id 
* Software revision id 
*-------------------------------------------------------------------------*/ 
    comres = bno055_init(&bno055); 

/* For initializing the BNO sensor it is required to the operation mode 
    of the sensor as NORMAL 
    Normal mode can set from the register 
    Page - page0 
    register - 0x3E 
    bit positions - 0 and 1*/ 
    power_mode = POWER_MODE_NORMAL; /* set the power mode as NORMAL*/ 
    comres += bno055_set_power_mode(power_mode); 
/*--------------------------------------------------------------------------* 
************************* END INITIALIZATION ************************* 

/************************* START READ RAW SENSOR DATA****************/ 

/* Using BNO055 sensor we can read the following sensor data and 
    virtual sensor data 
    Sensor data: 
     Accel 
     Mag 
     Gyro 
    Virtual sensor data 
     Euler 
     Quaternion 
     Linear acceleration 
     Gravity sensor */ 
/* For reading sensor raw data it is required to set the 
    operation modes of the sensor 
    operation mode can set from the register 
    page - page0 
    register - 0x3D 
    bit - 0 to 3 
    for sensor data read following operation mode have to set 
    * SENSOR MODE 
     *0x01 - OPERATION_MODE_ACCONLY 
     *0x02 - OPERATION_MODE_MAGONLY 
     *0x03 - OPERATION_MODE_GYRONLY 
     *0x04 - OPERATION_MODE_ACCMAG 
     *0x05 - OPERATION_MODE_ACCGYRO 
     *0x06 - OPERATION_MODE_MAGGYRO 
     *0x07 - OPERATION_MODE_AMG 
     based on the user need configure the operation mode*/ 
    comres += bno055_set_operation_mode(OPERATION_MODE_ACCONLY); 

/******************START READ CONVERTED SENSOR DATA****************/ 

/* API used to read Linear acceleration data output as m/s2 
    float functions also available in the BNO055 API */ 
    comres += bno055_convert_double_linear_accel_x_msq(&d_linear_accel_datax); 
    comres += bno055_convert_double_linear_accel_y_msq(&d_linear_accel_datay); 
    comres += bno055_convert_double_linear_accel_z_msq(&d_linear_accel_dataz); 
    comres += bno055_convert_double_linear_accel_xyz_msq(&d_linear_accel_xyz); 

/*-----------------------------------------------------------------------* 
************************* START DE-INITIALIZATION *********************** 
*-------------------------------------------------------------------------*/ 
/* For de - initializing the BNO sensor it is required to the operation mode 
    of the sensor as SUSPEND 
    Suspend mode can set from the register 
    Page - page0 
    register - 0x3E 
    bit positions - 0 and 1*/ 
    power_mode = POWER_MODE_SUSPEND; /* set the power mode as SUSPEND*/ 
    comres += bno055_set_power_mode(power_mode); 

/*---------------------------------------------------------------------* 
************************* END DE-INITIALIZATION ********************** 
*---------------------------------------------------------------------*/ 
return comres; 
} 

#ifdef BNO055_API 
/*--------------------------------------------------------------------------* 
* The following function is used to map the I2C bus read, write, delay and 
* device address with global structure bno055_t 
*-------------------------------------------------------------------------*/ 
/*-------------------------------------------------------------------------* 
* By using bno055 the following structure parameter can be accessed 
* Bus write function pointer: BNO055_WR_FUNC_PTR 
* Bus read function pointer: BNO055_RD_FUNC_PTR 
* Delay function pointer: delay_msec 
* I2C address: dev_addr 
*--------------------------------------------------------------------------*/ 
s8 I2C_routine(void) { 

    bno055.bus_write = BNO055_I2C_bus_write; 
    bno055.bus_read = BNO055_I2C_bus_read; 
    bno055.delay_msec = BNO055_delay_msek; 
    bno055.dev_addr = BNO055_I2C_ADDR2; 

    return BNO055_ZERO_U8X; 
} 

/************** I2C buffer length******/ 

#define I2C_BUFFER_LEN 8 
#define I2C0 5 
/*-------------------------------------------------------------------* 
* 
* This is a sample code for read and write the data by using I2C 
* Use either I2C based on your need 
* The device address defined in the bno055.h file 
* 
*-----------------------------------------------------------------------*/ 

/* \Brief: The function is used as I2C bus write 
* \Return : Status of the I2C write 
* \param dev_addr : The device address of the sensor 
* \param reg_addr : Address of the first register, will data is going to be written 
* \param reg_data : It is a value hold in the array, 
*  will be used for write the value into the register 
* \param cnt : The no of byte of data to be write 
*/ 
s8 BNO055_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt) 
{ 
    s32 iError = BNO055_ZERO_U8X; 
    u8 array[I2C_BUFFER_LEN]; 
    u8 stringpos = BNO055_ZERO_U8X; 
    array[BNO055_ZERO_U8X;] = reg_addr; 
    for (stringpos = BNO055_ZERO_U8X; stringpos < cnt; stringpos++) { 
     array[stringpos + BNO055_ONE_U8X] = *(reg_data + stringpos); 
    } 
    /* 
    * Please take the below function as your reference for 
    * write the data using I2C communication 
    * "IERROR = I2C_WRITE_STRING(DEV_ADDR, ARRAY, CNT+1)" 
    * add your I2C write function here 
    * iError is an return value of I2C read function 
    * Please select your valid return value 
    * In the driver SUCCESS defined as 0 
    * and FAILURE defined as -1 
    * Note : 
    * This is a full duplex operation, 
    * The first read data is discarded, for that extra write operation 
    * have to be initiated. For that cnt+1 operation done in the I2C write string function 
    * For more information please refer data sheet SPI communication: 
    */ 
    return (s8)iError; 
} 

/* \Brief: The function is used as I2C bus read 
* \Return : Status of the I2C read 
* \param dev_addr : The device address of the sensor 
* \param reg_addr : Address of the first register, will data is going to be read 
* \param reg_data : This data read from the sensor, which is hold in an array 
* \param cnt : The no of byte of data to be read 
*/ 
s8 BNO055_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt) 
{ 
    s32 iError = BNO055_ZERO_U8X; 
    u8 array[I2C_BUFFER_LEN] = {BNO055_ZERO_U8X;}; 
    u8 stringpos = BNO055_ZERO_U8X; 
    array[BNO055_ZERO_U8X;] = reg_addr; 
    /* Please take the below function as your reference 
    * for read the data using I2C communication 
    * add your I2C rad function here. 
    * "IERROR = I2C_WRITE_READ_STRING(DEV_ADDR, ARRAY, ARRAY, 1, CNT)" 
    * iError is an return value of SPI write function 
    * Please select your valid return value 
    * In the driver SUCCESS defined as 0 
    * and FAILURE defined as -1 
    */ 
    for (stringpos = BNO055_ZERO_U8X; stringpos < cnt; stringpos++) { 
     *(reg_data + stringpos) = array[stringpos]; 
    } 
    return (s8)iError; 
} 

#endif 

当然,我收到错误消息,当我试图编译:

main.c(108): error: #268: declaration may not appear after executable statement in block uint8_t data = I2C_ReceiveData(I2Cx);

main.c(124): error: #268: declaration may not appear after executable statement in block uint8_t data = I2C_ReceiveData(I2Cx);

main.c(140): error: #268: declaration may not appear after executable statement in block uint8_t received_data(2);

main.c(140): warning: #550-D: variable "received_data" was set but never used uint8_t received_data(2);

main.c(207): error: #20: identifier "comres" is undefined comres = bno055_init(&bno055);

main.c(207): error: #20: identifier "bno055" is undefined comres = bno055_init(&bno055);

main.c(215): error: #20: identifier "power_mode" is undefined
power_mode = POWER_MODE_NORMAL; /* set the power mode as NORMAL*/

main.c(220): warning: #9-D: nested comment is not allowed
/************************* START READ RAW SENSOR DATA****************/

main.c(255): error: #20: identifier "d_linear_accel_datax" is undefined comres += bno055_convert_double_linear_accel_x_msq(&d_linear_accel_datax);

main.c(256): error: #20: identifier "d_linear_accel_datay" is undefined comres += bno055_convert_double_linear_accel_y_msq(&d_linear_accel_datay);

main.c(257): error: #20: identifier "d_linear_accel_dataz" is undefined comres += bno055_convert_double_linear_accel_z_msq(&d_linear_accel_dataz);

main.c(258): error: #20: identifier "d_linear_accel_xyz" is undefined comres += bno055_convert_double_linear_accel_xyz_msq(&d_linear_accel_xyz);

main.c(375): warning: #1-D: last line of file ends without a newline

endif

的“BNO055传感器”已经BUIT传感器融合算法(将加速度计,磁力计和陀螺仪数据混合成稳定的三轴定向输出)。所以它可以输出我需要的数据。我希望将'X,Y和Z直线加速度数据作为m/s2'并在计算机屏幕上打印出来。我不知道是否甚至可以在我的电脑屏幕上打印数据,因为我通过USB将探索板连接到了我的电脑。如果不可能,那么也许可以将其打印在Discovery Board的内置LCD显示器上。

任何有助于澄清我的关注将大受欢迎。

+0

tl; dr,但:液晶**显示**显示?提供[mcve]。 SO不是咨询网站。你有**特定**问题吗? – Olaf

+0

编译错误通常与应用程序本身的细节有关 - 它们只是编码错误。 –

回答

0

第一个错误是抱怨,该函数调用

init_I2C1(); 

preceeds声明

uint8_t received_data[2]; 

一些编译器允许这样做,其他人(比如你)必须有之前的任何可执行代码声明的所有变量在一个函数中。

第二个错误是相同类型

uint8_t data = I2C_ReceiveData(I2Cx); 

的但更复杂,因为要定义的变量和具有可执行代码的设定其值。您应该分开的两个

uint8_t data; 
// ... more code 
data = I2C_ReceiveData(I2Cx); 

我将无法通过他们全都走了,大多数是不言自明像"nested comments not allowed"

+0

谢谢,这是非常有帮助的,但我仍然无法弄清楚如何正确定义标识符 – mascail

+0

下一个错误类型是'comres'未定义。它总结了一些函数的值,如果它们是状态位,那就很糟糕,因为如果相同的状态位被添加两次,它将移动到下一位。但是'comres'可能会计数(不)成功的呼叫:它没有记录。它由's32返回'bno055_data_readout_template(void)'so's32 comres;'应该被定义,但不是本地的。你将不得不查找被调用的函数来查看它们的返回值是什么意思。我可以建议你一件一件地构建你的项目,而不是试图强迫整个例子工作吗? –

+0

如何查看调用的函数以查看它们的返回值mein?我需要寻找什么以及在哪里? – mascail

0

我打算在未来几周内为此IMU编写一个STM32发现端口。在此之前,我建议从Adafruit提供的Arduino示例开始,并开始用适当的STM32 Discovery I2C调用替换Arduino I2C调用。另一方面,如果您不需要使用Discovery板,并且只需要IMU与一个微控制器一起工作,那么我就推荐使用Arduino。示例项目和库已存在于此处:https://github.com/adafruit/Adafruit_BNO055