- /* Set PB multi-function pins for UART0 RXD=PB.12 and TXD=PB.13 */
- SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk)) |
- (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);
接下来才是完美的地方
新唐提供的读取MPU6050原始数据的操作函数都是基于两个函数:
一个用于从芯片某个内存地址读取存储的数值,返回该数值;
另外一个是,往芯片某个内存地址写入一个数值
写入芯片某个内存地址一个8位数值,函数原型如下,原来的函数内容一大堆有库函数有寄存器,乱乱的。
void MPU6050_I2C_SingleWrite(uint8_t index, uint8_t data)
{
……
}
uint8_t MPU6050_I2C_SingleRead(uint8_t index)
{
……
}
我比对了官方的库函数列表发现了两个可以完美的一行解决。
实现如下
- void MPU6050_I2C_SingleWrite(uint8_t index, uint8_t data)
- {
- I2C_WriteByteOneReg(MPU6050_I2C_PORT, MPU6050_I2C_SLA, index,data);
- }
- uint8_t MPU6050_I2C_SingleRead(uint8_t index)
- {
- return I2C_ReadByteOneReg(MPU6050_I2C_PORT, MPU6050_I2C_SLA, index);
- }
MPU6050_I2C_PORT 为使用的哪个I2C端口,这里是I2C0MPU6050_I2C_SLA 为从机的地址
index代表的是从机内部寄存器地址
data 代表要写入的数值
所以我使用以上两个函数进行映射,并通过宏指定了另外两个没有的参数MPU6050_I2C_PORT 和 MPU6050_I2C_SLA 。
两个库函数的参数说明如下
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] Specify a byte register address and write a byte to Slave
- *
- * @param[in] i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[in] u8DataAddr Specify a address (1 byte) of data write to
- * @param[in] data A byte data to write it to Slave
- *
- * @retval 0 Write data success
- * @retval 1 Write data fail, or bus occurs error events
- *
- * [url=home.php?mod=space&uid=1543424]@Details[/url] The function is used for I2C Master specify a address that data write to in Slave.
- *
- */
- uint8_t I2C_WriteByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t data)
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] Specify a byte register address and read a byte from Slave
- *
- * @param[in] i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[in] u8DataAddr Specify a address(1 byte) of data read from
- *
- * [url=home.php?mod=space&uid=266161]@return[/url] Read a byte data from Slave
- *
- * [url=home.php?mod=space&uid=1543424]@Details[/url] The function is used for I2C Master specify a byte address that a data byte read from Slave.
- *
- *
- */
- uint8_t I2C_ReadByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr)
怎么样,是不是顿时简单了,不用为了底层的移植头大了吧,比用IO模拟也好用太多了是吧。
完整代码如下
main.c
- #include <stdio.h>
- #include "NuMicro.h"
- #include "MPU6050.h"
- #define TEST_LENGTH 256
- /*---------------------------------------------------------------------------------------------------------*/
- /* Global variables */
- /*---------------------------------------------------------------------------------------------------------*/
- volatile uint8_t g_u8DeviceAddr;
- void SYS_Init(void)
- {
- /*---------------------------------------------------------------------------------------------------------*/
- /* Init System Clock */
- /*---------------------------------------------------------------------------------------------------------*/
- /* Unlock protected registers */
- SYS_UnlockReg();
- /* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
- PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);
- /* Enable HIRC clock (Internal RC 48 MHz) */
- CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);
- /* Wait for HIRC clock ready */
- CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
- /* Set core clock as 96MHz from PLL */
- CLK_SetCoreClock(FREQ_96MHZ);
- /* Set PCLK0/PCLK1 to HCLK/2 */
- CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2);
- /* Enable UART0 clock */
- CLK_EnableModuleClock(UART0_MODULE);
- /* Switch UART0 clock source to HIRC */
- CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));
- /* Enable I2C0 clock */
- CLK_EnableModuleClock(I2C0_MODULE);
- /* Update System Core Clock */
- /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock and cyclesPerUs automatically. */
- SystemCoreClockUpdate();
- /*---------------------------------------------------------------------------------------------------------*/
- /* Init I/O Multi-function */
- /*---------------------------------------------------------------------------------------------------------*/
- /* Set PB multi-function pins for UART0 RXD=PB.12 and TXD=PB.13 */
- SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk)) |
- (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);
- /* Set I2C0 multi-function pins */
- SYS->GPC_MFPL = (SYS->GPC_MFPL & ~(SYS_GPC_MFPL_PC0MFP_Msk | SYS_GPC_MFPL_PC1MFP_Msk)) |
- (SYS_GPC_MFPL_PC0MFP_I2C0_SDA | SYS_GPC_MFPL_PC1MFP_I2C0_SCL);
- /* Lock protected registers */
- SYS_LockReg();
- }
- void I2C0_Init(void)
- {
- /* Open I2C module and set bus clock */
- I2C_Open(I2C0, 50000);
- }
- int main()
- {
-
- int16_t accX, accY, accZ;
- int16_t gyroX, gyroY, gyroZ;
- int16_t TEMP;
- float temp;
- SYS_Init();
- /* Init UART0 to 115200-8n1 for print message */
- UART_Open(UART0, 115200);
- /*
- This sample code sets I2C bus clock to 100kHz. Then, Master accesses Slave with Byte Write
- and Byte Read operations, and check if the read data is equal to the programmed data.
- */
- printf("+--------------------------------------------------------+\n");
- printf("| I2C Driver MPU6050 |\n");
- printf("| |\n");
- printf("| I2C Master (I2C0) <---> I2C Slave |\n");
- printf("| |\n");
- printf("+--------------------------------------------------------+\n");
- printf("\n");
- printf("Configure I2C0 as Master\n");
- printf("The I/O connection to I2C0\n");
- printf("I2C0_SDA(PC.0), I2C0_SCL(PC.1)\n");
- /* Init I2C0 */
- I2C0_Init();
- Init_MPU6050();
- while(1)
- {
- accX = Read_MPU6050_AccX();
- accY = Read_MPU6050_AccY();
- accZ = Read_MPU6050_AccZ();
- gyroX= Read_MPU6050_GyroX();
- gyroY= Read_MPU6050_GyroY();
- gyroZ= Read_MPU6050_GyroZ();
- TEMP= Read_MPU6050_Temp();
- temp=(((float)TEMP/340.0f)+36.53f);
-
- printf("Acc=%x,%x,%x, Gyro=%x,%x,%x\n", accX, accY, accZ, gyroX, gyroY, gyroZ);
- printf("TEMP=%.2f\n",temp);
- CLK_SysTickDelay(2000000);
- }
- }
MPU6050.h
MPU6050.c
- //
- // MPU6050 Driver: 3-axis Gyroscope + 3-axis accelerometer + temperature
- //
- // Interface: I2C
- // pin1: Vcc to Vcc (+5V)
- // pin2: Gnd to Gnd
- // pin3: SCL to I2C1_SCL/PC10
- // pin4: SDA to I2C1_SDA/PC11
- // pin5: XDA -- N.C.
- // pin6: XCL -- N.C.
- // pin7: AD0 -- N.C.
- // pin8: INT -- N.C.
- #include <stdio.h>
- #include <stdint.h>
- #include <NuMicro.h>
- #include "MPU6050.h"
- void MPU6050_I2C_SingleWrite(uint8_t index, uint8_t data)
- {
- I2C_WriteByteOneReg(MPU6050_I2C_PORT, MPU6050_I2C_SLA, index,data);
- }
- uint8_t MPU6050_I2C_SingleRead(uint8_t index)
- {
- return I2C_ReadByteOneReg(MPU6050_I2C_PORT, MPU6050_I2C_SLA, index);
- }
- void Init_MPU6050(void)
- {
- I2C_SetSlaveAddr(MPU6050_I2C_PORT, 0, MPU6050_I2C_SLA, I2C_GCMODE_DISABLE);
- MPU6050_I2C_SingleWrite(MPU6050_PWR_MGMT_1, 0x01); // CLL_SEL=0: internal 8MHz, TEMP_DIS=0, SLEEP=0
- MPU6050_I2C_SingleWrite(MPU6050_SMPLRT_DIV, 0x01); // Gyro output sample rate = Gyro Output Rate/(1+SMPLRT_DIV)
- MPU6050_I2C_SingleWrite(MPU6050_CONFIG, 0x01); // set TEMP_OUT_L, DLPF=2 (Fs=1KHz)
- MPU6050_I2C_SingleWrite(MPU6050_GYRO_CONFIG, 0x18); // bit[4:3] 0=+-250d/s,1=+-500d/s,2=+-1000d/s,3=+-2000d/s
- MPU6050_I2C_SingleWrite(MPU6050_ACCEL_CONFIG, 0x00);// bit[4:3] 0=+-2g,1=+-4g,2=+-8g,3=+-16g, ACC_HPF=On (5Hz)
- }
- uint16_t Read_MPU6050_AccX(void)
- {
- uint8_t LoByte, HiByte;
- LoByte = MPU6050_I2C_SingleRead(MPU6050_ACCEL_XOUT_L); // read Accelerometer X_Low value
- HiByte = MPU6050_I2C_SingleRead(MPU6050_ACCEL_XOUT_H); // read Accelerometer X_High value
- return((HiByte<<8) | LoByte);
- }
- uint16_t Read_MPU6050_AccY(void)
- {
- uint8_t LoByte, HiByte;
- LoByte = MPU6050_I2C_SingleRead(MPU6050_ACCEL_YOUT_L); // read Accelerometer X_Low value
- HiByte = MPU6050_I2C_SingleRead(MPU6050_ACCEL_YOUT_H); // read Accelerometer X_High value
- return ((HiByte<<8) | LoByte);
- }
- uint16_t Read_MPU6050_AccZ(void)
- {
- uint8_t LoByte, HiByte;
- LoByte = MPU6050_I2C_SingleRead(MPU6050_ACCEL_ZOUT_L); // read Accelerometer X_Low value
- HiByte = MPU6050_I2C_SingleRead(MPU6050_ACCEL_ZOUT_H); // read Accelerometer X_High value
- return ((HiByte<<8) | LoByte);
- }
- uint16_t Read_MPU6050_GyroX(void)
- {
- uint8_t LoByte, HiByte;
- LoByte = MPU6050_I2C_SingleRead(MPU6050_GYRO_XOUT_L); // read Accelerometer X_Low value
- HiByte = MPU6050_I2C_SingleRead(MPU6050_GYRO_XOUT_H); // read Accelerometer X_High value
- return ((HiByte<<8) | LoByte);
- }
- uint16_t Read_MPU6050_GyroY(void)
- {
- uint8_t LoByte, HiByte;
- LoByte = MPU6050_I2C_SingleRead(MPU6050_GYRO_YOUT_L); // read Accelerometer X_Low value
- HiByte = MPU6050_I2C_SingleRead(MPU6050_GYRO_YOUT_H); // read Accelerometer X_High value
- return ((HiByte<<8) | LoByte);
- }
- uint16_t Read_MPU6050_GyroZ(void)
- {
- uint8_t LoByte, HiByte;
- LoByte = MPU6050_I2C_SingleRead(MPU6050_GYRO_ZOUT_L); // read Accelerometer X_Low value
- HiByte = MPU6050_I2C_SingleRead(MPU6050_GYRO_ZOUT_H); // read Accelerometer X_High value
- return ((HiByte<<8) | LoByte);
- }
- uint16_t Read_MPU6050_Temp(void)
- {
- uint8_t LoByte, HiByte;
- LoByte = MPU6050_I2C_SingleRead(MPU6050_TEMP_OUT_L); // read Accelerometer X_Low value
- HiByte = MPU6050_I2C_SingleRead(MPU6050_TEMP_OUT_H); // read Accelerometer X_High value
- return ((HiByte<<8) | LoByte);
- }
串口打印输出示例
- +--------------------------------------------------------+
- | I2C Driver Sample Code for Single Byte Read/Write Test |
- | Needs to work with I2C_Slave sample code |
- | |
- | I2C Master (I2C0) <---> I2C Slave(I2C0) |
- | !! This sample code requires two borads to test !! |
- +--------------------------------------------------------+
- Configure I2C0 as Master
- The I/O connection to I2C0
- I2C0_SDA(PC.0), I2C0_SCL(PC.1)
- Acc=ffffce08,10cc,ffffe56a, Gyro=fffffde5,fffffe2b,4ce
- TEMP=21.94
- Acc=ffffcace,f38,ffffe7f8, Gyro=ffffff01,ffffff17,202
- TEMP=21.92
- Acc=ffffc8a2,e22,ffffe588, Gyro=ffffffb2,ffffff66,177
这里温度进行了转换成摄氏度,保留两位小数
其他加速度3个分量与陀螺仪3个分量均采用16进制打印原始数据观察