工具/软件:Code Composer Studio
大家好、
我尝试从 MPU6050模块读取传感器值、但有时代码会挂起(强制我对 Tiva 进行下电上电、重置是徒劳的)或读取错误的值(看起来是一致的、但不是它应该是什么)。
我已经尝试使用 Arduino、传感器与 Uno 完美配合。 我还使用3V3将传感器与 ATmega328P 连接到试验电路板上、以查看是否是导致问题的电压、但它也可以在那里工作。 因此使用3V3时没有问题。
由于 sensorlib 没有很好地解释如何从 MPU6050读取(在这里不是尝试意义上的意思、但存在一些问题、包括文件、修改 μ I²C 代码以使用 I2CM 等)、我决定使用 μ I²C 作为"传统方式"、手动从寄存器读取/写入。
以下是我的代码:
#include
#include
#include "inc/hw_i2c.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/interrupt.h"
#include "driverlib.rom.driverlib"
#define "driverlib_rom.ide"#define "driverlib_rom.ide"#define "driverlib_rom.ide"#define "driverlib_rom.ide"#define #include "driverlib_rom.ide"#define #include "driverlib.ide"#define "driverlib_ine.h"#include "driverlib_ine.h
0x68
volatile Int32_t g_ACXH;
volatile Int32_t g_ACXL;
volatile Int32_t g_ACX;
volatile Int32_t g_ACYH;
volatile Int32_t g_ACYL;
volatile int32_t g_acy;
volatile int32_t g_acZH;
volatile int32_t g_acZL;
volatile int32_t g_acz;
volatile int32_t g_TempH;
volatile int32_t g_temp;
volatile int32_t g_Temp;
volatile int32_t g_temperature = 0;
volatile int32_t g_g_gxH;
volatile int32_t g_g_gcxl;
volatile int32_t g_g_gcyH
;
volatile int32_t g_gcyL;
volatile int32_t g_gcyy;
volatile int32_t g_gczh;
volatile int32_t g_gczL;
volatile int32_t g_g_gcz;
//init UART 控制台波特115200
内联 void InitConsole (void)
{
//
//启用用于 UART0引脚的 GPIO 端口 A。
// TODO:将其更改为您正在使用的 GPIO 端口。
//
MAP_SysCtlPeripheralDisable (SYSCTL_Periph_GPIOA);
MAP_SysCtlPeripheralReset (SYSCTL_Periph_GPIOA);
MAP_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
while (!map_SysCtlPeripheralReady (SYSCTL_Periph_GPIOA));
//
//为端口 A0和 A1上的 UART0功能配置引脚复用。
//如果您的器件不支持引脚复用、则无需执行此步骤。
// TODO:更改此选项以选择您正在使用的端口/引脚。
//
MAP_GPIOPinConfigure (GPIO_PA0_U0RX);
MAP_GPIOPinConfigure (GPIO_PA1_U0TX);
//
//启用 UART0以便我们可以配置时钟。
//
MAP_SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
//
//使用内部16MHz 振荡器作为 UART 时钟源。
//
MAP_UARTClockSourceSet (UART0_BASE、UART_CLOCK_PIOSC);
//
//为这些引脚选择替代(UART)功能。
// TODO:更改此选项以选择您正在使用的端口/引脚。
//
MAP_GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
//
//初始化控制台 I/O 的 UART
//
UARTStdioConfig (0、115200、16000000);
}
//main 程序
int main (void)
{
//将系统时钟设置为80MHz
MAP_SysCtlClockSet (SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHz|SYSCTL_OSC_MAIN);
//初始化 UART
InitConsole();
//清除屏幕
UARTprintf ("\033[2J");
//将光标移动到位置0,0
UARTprintf ("\033[0;0H");
//初始化 I2C0和 GPIOB
MAP_SysCtlPeripheralDisable (SYSCTL_Periph_I2C0);
MAP_SysCtlPeripheralDisable (SYSCTL_Periph_GPIOB);
MAP_SysCtlPeripheralReset (SYSCTL_Periph_I2C0);
MAP_SysCtlPeripheralReset (SYSCTL_Periph_GPIOB);
MAP_SysCtlPeripheralEnable (SYSCTL_Periph_I2C0);
MAP_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
while (!map_SysCtlPeripheralReady (SYSCTL_Periph_I2C0)||!map_SysCtlPeripheralReady (SYSCTL_Periph_GPIOB));
//将 PB2配置为 SCL 和 PB3 SDA
MAP_GPIOPinConfigure (GPIO_PB2_I2C0SCL);
MAP_GPIOPinConfigure (GPIO_PB3_I2C0SDA);
MAP_GPIOPinTypeI2CSCL (GPIO_PORTB_BASE、GPIO_PIN_2);
MAP_GPIOPinTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_3);
///init I2C 主设备、100kbps (如果为真、则为400kbps)
MAP_I2CMasterInitExpClk (I2C0_BASE、MAP_SysCtlClockGet ()、TRUE);
//设置从器件地址,主器件正在从从器件读取(如果为 false 则写入)
MAP_I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_ADDRESS、FALSE);
//初始化 MPU
I2CMasterDataPut (I2C0_BASE、0x6B);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);
while (I2CMasterBusy (I2C0_BASE));
I2CMasterDataPut (I2C0_BASE、0x00);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_FINISH);
while (I2CMasterBusy (I2C0_BASE));
for (;;)
{
//请求从寄存器0x3B 读取
I2CMasterDataPut (I2C0_BASE、0x3B);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_SEND);
while (I2CMasterBusy (I2C0_BASE));
//主器件正在从从器件读取数据
MAP_I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_ADDRESS、TRUE);
//开始读取寄存器
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_start);
while (I2CMasterBusy (I2C0_BASE));
//移动“较高”位
G_ACXH = MAP_I2CMasterDataGet (I2C0_BASE)<< 8;
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_CONT);
while (I2CMasterBusy (I2C0_BASE));
G_ACXL = MAP_I2CMasterDataGet (I2C0_BASE);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_CONT);
while (I2CMasterBusy (I2C0_BASE));
G_ACYH = MAP_I2CMasterDataGet (I2C0_BASE)<< 8;
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_CONT);
while (I2CMasterBusy (I2C0_BASE));
G_ACYL = MAP_I2CMasterDataGet (I2C0_BASE);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_CONT);
while (I2CMasterBusy (I2C0_BASE));
G_ACZH = MAP_I2CMasterDataGet (I2C0_BASE)<< 8;
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_CONT);
while (I2CMasterBusy (I2C0_BASE));
G_ACZL = MAP_I2CMasterDataGet (I2C0_BASE);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_CONT);
while (I2CMasterBusy (I2C0_BASE));
G_TempH = MAP_I2CMasterDataGet (I2C0_BASE)<< 8;
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_CONT);
while (I2CMasterBusy (I2C0_BASE));
G_Templ = MAP_I2CMasterDataGet (I2C0_BASE);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_CONT);
while (I2CMasterBusy (I2C0_BASE));
G_GCXH = MAP_I2CMasterDataGet (I2C0_BASE)<< 8;
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_CONT);
while (I2CMasterBusy (I2C0_BASE));
G_GCXL = MAP_I2CMasterDataGet (I2C0_BASE);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_CONT);
while (I2CMasterBusy (I2C0_BASE));
G_GCYH = MAP_I2CMasterDataGet (I2C0_BASE)<< 8;
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_CONT);
while (I2CMasterBusy (I2C0_BASE));
G_GCYL = MAP_I2CMasterDataGet (I2C0_BASE);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_CONT);
while (I2CMasterBusy (I2C0_BASE));
G_GCZH = MAP_I2CMasterDataGet (I2C0_BASE)<< 8;
//完成对寄存器的读取
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_Receive_finish);
while (I2CMasterBusy (I2C0_BASE));
G_GCZL = MAP_I2CMasterDataGet (I2C0_BASE);
//将两个8位变量加入一个16位
G_ACx = g_ACXH | g_ACXL;
G_ACY = g_ACYH | g_ACYL;
G_ACZ = g_ACZH | g_ACZL;
G_Temp = g_TempH | g_Templ;
G_GCx = g_GCXH | g_GCXL;
G_GCY = g_GCYH | g_GCYL;
G_GCZ = g_GCZH | g_GCZL;
//主设备正在写入从设备
MAP_I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_ADDRESS、FALSE);
//转换为温度
g_temperature =(g_Temp/340.00f)+36.53f;
UARTprintf ("ACX:\t%d\n"、g_ACX);
UARTprintf ("ACY:\t%d\n"、g_ACY);
UARTprintf ("ACZ:\t%d\n"、g_ACZ);
UARTprintf ("温度:\t%d\n"、g_temperature);
UARTprintf ("GCX:\t%d\n"、g_GCX);
UARTprintf ("GCY:\t%d\n"、g_GCY);
UARTprintf ("GCZ:\t%d\n"、g_GCZ);
//将光标移动到位置0,0
UARTprintf ("\033[0;0H");
MAP_SysCtlDelay (MAP_SysCtlClockGet ()/3*0.01);
}
}
我在 MPU6050上进行读数所执行的步骤:
- 已初始化 GPIO、μ I²C 和 UART
- 已初始化 μ I²C 主机写入模式400kbps
- 已初始化 MPU、向寄存器0x6B 写入0x00
- 向地址0x3B 发送写入请求
- 将 μ I²C 更改为读取模式
- 读取寄存器并将内容放置到变量中
- 合并了变量、使16bitvariable = 8bitvariable_H << 8 | 8bitvariable_L
- 根据 MPU 寄存器映射第30页显示的公式计算温度
- 打印了变量
- 将 μ I²C 更改为写入、向地址0x3B 发送写入请求并再次执行所有读数
减少了挂起的东西:改变了我读取变量的方式。 我在 I2CMasterDataGet ()调用中没有在代码中的后面移动"H"寄存器上剩余的8位、而是直接移动了它。 它只是在我不在环路中插入延迟时偶尔挂起。
Arduino 输出:
Tiva 上的输出:
导致这种奇怪行为的原因是什么?
