msp432搭建平衡小车(二)

发布时间:2022-12-20  

前言

上一节掌握了使用pwm驱动电机,接下来介绍如何使用msp432读取mpu6050数据


正文

首先我们得知道mpu6050通信方式,由于mpu6050只能用i2c通信,所以学会使用msp432的i2c,msp432的i2c驱动可以调用driverlib库来使用msp432的硬件i2c,但是i2c库方法复杂使用起来会比较麻烦,


这里我选择偷个懒,用软件方式模拟i2c驱动。


I2C

建立一个my_i2c.h


/*

 * my_i2c.h

 *

 *  Created on: 2021年7月29日

 *      Author: Administrator

 */


#ifndef MY_I2C_H_

#define MY_I2C_H_


#include

#include


#define SDA_IN()  GPIO_setAsInputPin(GPIO_PORT_P6,GPIO_PIN4)

#define SDA_OUT() GPIO_setAsOutputPin(GPIO_PORT_P6,GPIO_PIN4)



#define IIC_SCL_High()  GPIO_setOutputHighOnPin(GPIO_PORT_P6,GPIO_PIN5) //SCL_High

#define IIC_SCL_Low()   GPIO_setOutputLowOnPin(GPIO_PORT_P6,GPIO_PIN5) //SCL_Low

#define IIC_SDA_High()  GPIO_setOutputHighOnPin(GPIO_PORT_P6,GPIO_PIN4) //SDA_High

#define IIC_SDA_Low()   GPIO_setOutputLowOnPin(GPIO_PORT_P6,GPIO_PIN4) //SDA_Low

#define READ_SDA        GPIO_getInputPinValue(GPIO_PORT_P6,GPIO_PIN4)  //输入SDA



void IIC_Init(void);                //初始化IIC的IO口

void IIC_Start(void);               //发送IIC开始信号

void IIC_Stop(void);                //发送IIC停止信号

void IIC_Send_Byte(uint8_t txd);         //IIC发送一个字节

uint8_t IIC_Read_Byte(unsigned char ack);//IIC读取一个字节

uint8_t IIC_Wait_Ack(void);              //IIC等待ACK信号

void IIC_Ack(void);                 //IIC发送ACK信号

void IIC_NAck(void);                //IIC不发送ACK信号




#endif /* MY_I2C_H_ */

    my_i2c.c


/*

 * my_i2c.c

 *

 *  Created on: 2021年7月29日

 *      Author: Administrator

 */


#include


void IIC_Init (void){

    GPIO_setAsOutputPin(GPIO_PORT_P6,GPIO_PIN5 ); //CLK

    GPIO_setAsOutputPin(GPIO_PORT_P6,GPIO_PIN4);//DIN

    IIC_SCL_High();

    IIC_SDA_High();


}


void IIC_Start(void)//SDA 10 SCL 010

{

    SDA_OUT();     //sda线输出

    IIC_SCL_High();

    IIC_SDA_High();

    delay_us(4);

    IIC_SDA_Low();//START:when CLK is high,DATA change form high to low

    delay_us(4);

    IIC_SCL_Low();//钳住I2C总线,准备发送或接收数据

}


void IIC_Stop(void)//SDA 01 SCL 01

{

    SDA_OUT();//sda线输出

    IIC_SCL_Low();//STOP:when CLK is high DATA change form low to high

    IIC_SDA_Low();

    delay_us(4);

    IIC_SCL_High();

    IIC_SDA_High();//发送I2C总线结束信号

    delay_us(4);

}

//等待应答信号到来

//返回值:1,接收应答失败

//        0,接收应答成功

uint8_t IIC_Wait_Ack(void)//

{

    uint8_t cy;

    SDA_IN();      //SDA设置为输入

    IIC_SCL_High();delay_us(10);

    IIC_SDA_High();delay_us(10);

    if(READ_SDA)

    {

        cy=1;

        IIC_SCL_Low();

        return cy;

    }

    else

    {

        cy=0;

    }

    IIC_SCL_Low();//时钟输出0

    return cy;

}

//产生ACK应答

void IIC_Ack(void)

{

    IIC_SCL_Low();

    SDA_OUT();

    IIC_SDA_Low();

    delay_us(2);

    IIC_SCL_High();

    delay_us(2);

    IIC_SCL_Low();

}

//不产生ACK应答

void IIC_NAck(void)

{

    IIC_SCL_Low();

    SDA_OUT();

    IIC_SDA_High();

    delay_us(2);

    IIC_SCL_High();

    delay_us(2);

    IIC_SCL_Low();

}

//IIC发送一个字节

//返回从机有无应答

//1,有应答

//0,无应答

void IIC_Send_Byte(uint8_t txd)

{

    uint8_t t;

    SDA_OUT();

    IIC_SCL_Low();//拉低时钟开始数据传输

    delay_us(2);

    for(t=0;t<8;t++)

    {

        if(txd&0x80)

        {

            IIC_SDA_High();delay_us(2);

        }

        else

        {

            IIC_SDA_Low();delay_us(2);

        }

        txd<<=1;

        IIC_SCL_High();

        delay_us(4);

        IIC_SCL_Low();

        delay_us(2);

    }

        delay_us(2);


}

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK

uint8_t IIC_Read_Byte(unsigned char ack)

{

    unsigned char i,receive=0;

    SDA_IN();//SDA设置为输入

    for(i=0;i<8;i++ )

    {

        IIC_SCL_Low();

        delay_us(2);

        IIC_SCL_High();

        receive<<=1;

        if(READ_SDA)

            receive++;

        delay_us(2);

    }

    if (!ack)

        IIC_NAck();//发送nACK

    else

        IIC_Ack(); //发送ACK

    return receive;


}

好了到这里i2c驱动有了,就可以继续下一步了


MPU6050

mpu6050.h


/*

 * MPU6050.H

 *

 *  Created on: 2021年7月29日

 *      Author: Administrator

 */


#ifndef MPU6050_H_

#define MPU6050_H_


#include

#include

#include

#include

#include

#include

#include


#define MPU6050_ADDR         0x68

#define MPU6050_SMPLRT_DIV   0x19

#define MPU6050_CONFIG       0x1a

#define MPU6050_GYRO_CONFIG  0x1b

#define MPU6050_ACCEL_CONFIG 0x1c

#define MPU6050_WHO_AM_I     0x75

#define MPU6050_PWR_MGMT_1   0x6b

#define MPU6050_PWR_MGMT_2   0x6c

#define MPU_ACCEL_XOUTH_REG  0x3b

#define MPU_GYRO_XOUTH_REG   0x43

#define MPU6050_TEMP_H       0x41

#define MPU6050_TEMP_L       0x42

#define MPU_DEVICE_ID_REG    0x75

typedef uint8_t u8;

typedef uint16_t u16;


#define PI 3.1415926535897932384626433832795


extern int16_t rawAccX, rawAccY, rawAccZ,rawGyroX, rawGyroY, rawGyroZ;

extern float gyroXoffset, gyroYoffset, gyroZoffset;

extern float temp, accX, accY, accZ, gyroX, gyroY, gyroZ;

extern float angleGyroX, angleGyroY, angleGyroZ,angleAccX, angleAccY, angleAccZ;

extern float angleX, angleY, angleZ;

extern uint32_t timer;

extern float accCoef;

extern float gyroCoef;


u8 MPU_Init(void);

void calcGyroOffsets(void);

void mpu_update(void);

u8 MPU_Set_Gyro_Fsr(u8 fsr);

u8 MPU_Set_Accel_Fsr(u8 fsr);

u8 MPU_Set_LPF(u16 lpf);

u8 MPU_Set_Rate(u16 rate);

short MPU_Get_Temperature();

u8 MPU_Get_Gyroscope(int16_t *gx,int16_t *gy,int16_t *gz);

u8 MPU_Get_Accelerometer(int16_t *ax,int16_t *ay,int16_t *az);

u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf);

u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf);

u8 MPU_Write_Byte(u8 reg,u8 data);

u8 MPU_Read_Byte(u8 reg);


#endif /* MPU6050_H_ */

mpu6050.c


/*

 * MPU6050.C

 *

 *  Created on: 2021年7月29日

 *      Author: Administrator

 */


#include


int16_t rawAccX, rawAccY, rawAccZ,rawGyroX, rawGyroY, rawGyroZ;

float gyroXoffset, gyroYoffset, gyroZoffset;

float temp, accX, accY, accZ, gyroX, gyroY, gyroZ;

float angleGyroX, angleGyroY, angleGyroZ,angleAccX, angleAccY, angleAccZ;

float angleX, angleY, angleZ;

float gyroCoef,accCoef;

uint32_t timer,preInterval;

float interval;


u8 MPU_Init(void)

{

    accCoef = 0.02;

    gyroCoef = 0.98;


    IIC_Init();

    MPU_Write_Byte(MPU6050_SMPLRT_DIV, 0x00);

    MPU_Write_Byte(MPU6050_CONFIG, 0x00);

    MPU_Write_Byte(MPU6050_GYRO_CONFIG, 0x08);

    MPU_Write_Byte(MPU6050_ACCEL_CONFIG, 0x00);

    MPU_Write_Byte(MPU6050_PWR_MGMT_1,0X01);

    mpu_update();

    angleGyroX = 0;

    angleGyroY = 0;

    preInterval = timer;

    return 0;

}


void calcGyroOffsets(void){

    float x = 0, y = 0, z = 0;

    int16_t rx, ry, rz;

    int i;

    for(i =0; i < 1000; i++){

    MPU_Get_Gyroscope(&rx,&ry,&rz);

    x += ((float)rx) / 65.5;

    y += ((float)ry) / 65.5;

    z += ((float)rz) / 65.5;

    }

    gyroXoffset = x / 1000;

    gyroYoffset = y / 1000;

    gyroZoffset = z / 1000;

}

void mpu_update(void){

    MPU_Get_Accelerometer(&rawAccX, &rawAccY, &rawAccZ);

    temp = MPU_Get_Temperature();

    MPU_Get_Gyroscope(&rawGyroX,&rawGyroY,&rawGyroZ);


    accX = ((float)rawAccX) / 16384.0;

    accY = ((float)rawAccY) / 16384.0;

    accZ = ((float)rawAccZ) / 16384.0;


    angleAccX = atan2(accY, accZ + abs(accX)) * 360 / 2.0 / PI;

    angleAccY = atan2(accX, accZ + abs(accY)) * 360 / -2.0 / PI;


    gyroX = ((float)rawGyroX) / 65.5;

    gyroY = ((float)rawGyroY) / 65.5;

    gyroZ = ((float)rawGyroZ) / 65.5;


    gyroX -= gyroXoffset;

    gyroY -= gyroYoffset;

    gyroZ -= gyroZoffset;


    angleGyroX += gyroX * interval;

    angleGyroY += gyroY * interval;

    angleGyroZ += gyroZ * interval;


    interval = (timer - preInterval) * 0.001;


    angleX = (gyroCoef * (angleX + gyroX * interval)) + (accCoef * angleAccX);

    angleY = (gyroCoef * (angleY + gyroY * interval)) + (accCoef * angleAccY);

    angleZ = angleGyroZ;

    preInterval = timer ;


}

//设置MPU6050陀螺仪传感器满量程范围

//fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps

//返回值:0,设置成功

//    其他,设置失败

u8 MPU_Set_Gyro_Fsr(u8 fsr)

{

    return MPU_Write_Byte(MPU6050_GYRO_CONFIG,fsr<<3);//设置陀螺仪满量程范围

}

//设置MPU6050加速度传感器满量程范围

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    警惕:电动平衡车电池95%不达标 你还敢骑吗?;因造型新颖、代步方便等特点,近年来电动平衡车成为不少现代人士的代步工具。然而这一新生事物却遭到多方质疑。 今年8月,因为存在车速过快、刹车......
    感知系统、控制算法及车体机械装置共同协调控制车体的平衡,仅靠人体重心的改变便可以实现车辆的启动、加速、减速、停止等功能。两轮自平衡车主要是绿色环保。电动车使用电池作为动力能源,并可以反复充电使用,大大......
    封测工厂,年产能百亿颗保障品质应用范围• 电动自行车、三轮车、平衡车、滑板车• 空调风机、压缩机,冰箱、洗衣机• 工业风机、水泵、角磨机• 电动工具、园林工具• 筋膜枪、按摩椅• 落地扇、吊扇、PC......
    作用越激进,kP调小会让调节作用更保守。要是你正在制作一个平衡车,有了P的作用,你会发现,平衡车在平衡角度附近来回“狂抖”,比较难稳住。平衡车项目:STM32平衡小车。 如果已经到了这一步——恭喜你!离成......
     tester for fabrics测定织物“耐磨性能”(486页)的仪器。属织物平磨仪中的一种。主要由运动平台、支架等组成。利用电动机传动产生直线往复式运动。在运动平台上以一定张力安装织物试样。将支......
    /1542的符合性证书。 九号公司是自2024年2月18日(EU) 2023/1542法规正式实施以来,首批通过TÜV莱茵符合性认证的企业之一。上述型号LMT电池广泛应用于九号公司智能电动滑板车、平衡车......
    控制问题转化为三步:输入X、Y角度—控制器计算—输出A、B、C电机转速的控制模型。 # 控制器设计 # 首先考虑参考平衡车控制,球上自平衡机器人本质上依然是一个一阶倒立摆问题 这里......
    小车之家的运动学方程: 自平衡控制问题转化为三步:输入X、Y角度—控制器计算—输出A、B、C电机转速的控制模型。 控制器设计 首先考虑参考平衡车控制,球上自平衡......
    电机的转子动平衡检测要点分析;我们都知道,电机的转子不平衡是造成电机故障的主要原因,要想保证电机的正常运行,必须对转子进行动平衡检测。那么,转子动平衡检测要怎么做呢? 转子动平衡检测是指利用平衡原理对转子进行不平衡......
    团队开发的核心产品是锂电池管理芯片(以下简称“BMS芯片”)。 据悉,目前,华泰半导体在低中高端的BMS芯片上都有所布局。其中,“10串”、“14串”的BMS芯片已经进入纳恩博九号平衡车、小米吸尘器、美的吸尘器等终端,并已......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>