[DemoCode下载]

八月新唐+M058SSAN操作MPU6050

[复制链接]
1713|5
手机看帖
扫描二维码
随时随地手机跟帖
Ketose|  楼主 | 2017-8-19 11:00 | 显示全部楼层 |阅读模式
本帖最后由 Ketose 于 2017-8-19 11:19 编辑

二姨家的活动一定要参加。NuTiny-SDK-M0518S 这个板子还是二姨家搞活动送的,基本上属于最小开发板了,板子上自带Nu-Link。趁这次活动,把这个小开发板拿出来又玩一下。先看下M058SSAN的资源
EN_M051D.jpg

M058S为Cortex™-M0 32位微控制器系列,其特点为宽电压工作范围2.5V至.5V与-40℃ ~ 85℃工作温度、内建22.1184 MHz高精度RC晶振(±1%精确度,25℃ 5V)、并内建Data Flash、欠压检测、丰富周边、整合多种多组串行传输接口、高抗干扰能力(8KV ESD/4KV EFT)、支持在线系统更新(ISP)、在线电路更新(ICP)与在线应用程序更新(IAP),提供封装有QFN33、LQFP48与LQFP64。

关键特性 :

• 内核(Core)

- Cortex™-M0 32位微处理器

- 工作频率可达 50 MHz

- 工作电压:2.5V to 5.5V

- 工作温度:-40℃ ~ 85℃

内存(Memory)

- 32 KB应用程序

- 内嵌4 KB SRAM

- 内嵌4 KB Data Flash

- 在线系统更新ISP(In-System Programming)

- 在线电路更新ICP(In-Circuit Programming)

- 在线应用程序更新 IAP(In-Application Programming)

模拟转数字转换器(ADC)

- 提供8通道

- 12位分辨率

- 每秒采样率可达 800kSPS

- 提供误差±1℃温度传感器

脉波宽度调变(PWM)

- 最多4通道PWM输出或互补式PWM输出

通讯接口(Connectivity)

- 一组SPI(可达36 MHz)

- 2组I²C(可达 400 kHz)

- 一组UART

时钟控制(Clock control)

- 外部晶振4 to 24 MHz

- 内置22.1184 MHz高精度RC晶振,常温5V下±1%误差


板子实物图:
IMG_20170818_205837.jpg
主要是M058S通过I2C总线读MPU6050的数据(x,y,z三个坐标轴的加速度数据和角速度数据),然后把它通过串口显示出来,先看下显示效果,为了好看些,加了些修饰。
QQ图片20170817215800.png
因为加入了中文,这个串口显示,时不时的要给我乱码。
如果下图:
QQ截图20170818210535.png
所以干脆自己用C#写了一个...
QQ截图20170818210358.png
下面说下过程,新唐的SDK里BUG很多,大家用的时候要小心哦。首先用新唐的NuTool-ClockConfigure图形化的配工具来生成MCU的时钟系统初始化代码。
步骤1:选择外部晶振,这里是12M
1.png
步骤2:设置PLL时钟频率50MHZ,选择第一项目,其它的也可以。
2.png
步骤3:设置系统时钟
3.png
步骤4:配置使用到的外设的时钟。UART要使用HIRC 22.1184MHZ做为时钟源。其它用到哪个选哪个。
4.png
以后配置完成后,生成时钟初始化代码,命 名这clock_init.c,这个生成的代码就有问题,如下图
err.png
这个函数在最新的M058S的SDK里是没有的,最后我在M0546的SDK里找到相应的代码,把它移植M058S里来,看了参考手器,应该是没有问题,使用过程也没有什么问题。(这个应该是M058S的BUG
接下来使用NuTool-PinConfigure配置外设:使用了UART和I2C0,如图所示
QQ截图20170818214556.png
配置完后生成外设初始化代码。
项目中使用了I2C总线,在使用M058S的SDK的I2C操作的SDK里也有BUG。如下:
e1.png
这个计算公式是错误的,至少我用实验了是不对的。使用这个函数I2C总结是没法工作。(I2C_Open(I2C_T *i2c, uint32_t u32BusClock)这个BUG害人不浅)
参考手册上是这么写的,按这个计算出I2CLK的值才是正确的。
e4.png
还要吐槽下,从新唐官网上下载了最新的Nu-Link_Keil_Driver_V2.02.6629这个也更坑,安装上这个以后Keil里调试时查看外设寄存器全乱了。。。还是看图吧。
e5.png
所有的寄存器都用P0代表了,请问下新唐,我想看P1怎么办?
好下,我发现的BUG就这些了,下面上代码
main.c


#include "M058S.h"                      // Device header
#include "stdio.h"
#include "mpu6050.h"

/*----------------------------------------------------------------------------
        初初化函数
*----------------------------------------------------------------------------*/
extern void SYS_Init(void);
extern void Uart_Init(void);
extern void GPIO_Init(void);
extern void Timer_Init(void);

void wait_us(uint32_t us);
void wait_ms(uint32_t ms);
void wait_s(uint32_t s);
void WorkOut(void);

/*
* [url=home.php?mod=space&uid=247401]@brief[/url] 主函数
* @param 无
* [url=home.php?mod=space&uid=266161]@return[/url] 退出代码
*/
int main(void)
{
        SYS_Init();
        GPIO_Init();
        Uart_Init();
        Timer_Init();
        InitMPU6050();
        
        while(1)
        {
                WorkOut();
                wait_s(1);
        }
}

/*
* [url=home.php?mod=space&uid=247401]@brief[/url] 工作输出
* @param 无
* [url=home.php?mod=space&uid=266161]@return[/url] 无
*/
void WorkOut()
{
        printf("begin");
        
        printf("┌───────────────────────────────────┐");
        printf("│                八月,新唐你好!                                        │");
        printf("│                Hello, 21ic.com !                                        │");
        printf("│                                                                        │");
        printf("│                Read the MPU6050 test using the I2C bus.                 │");
        printf("│                加速度:X=%04d,Y=%04d,Z=%04d                                │",GetAccelValue('x'),GetAccelValue('y'),GetAccelValue('z'));
        printf("│                角速度:X=%04d,Y=%04d,Z=%04d                                │",GetGyroValue('x'),GetGyroValue('y'),GetGyroValue('z'));
        printf("│                                                                        │");
        printf("│                MyID:Ketose                                                │");
        printf("└───────────────────────────────────┘");
        
        uint8_t c = 0x1A;
        UART_Write(UART0,(uint8_t*)&c,1);
}

/*
* [url=home.php?mod=space&uid=247401]@brief[/url] 延时函数
* @param 秒
* [url=home.php?mod=space&uid=266161]@return[/url] 无
*/
void wait_s(uint32_t s)
{
        for(int i=s;i>0;i--)
        {
                wait_ms(1000);
        }
}
/*
* [url=home.php?mod=space&uid=247401]@brief[/url] 延时函数
* @param 毫秒
* [url=home.php?mod=space&uid=266161]@return[/url] 无
*/
void wait_ms(uint32_t ms)
{
        for(int i=ms;i>0;i--)
        {
                wait_us(1000);
        }
}
/*
* [url=home.php?mod=space&uid=247401]@brief[/url] 延时函数
* @param 微秒
* [url=home.php?mod=space&uid=266161]@return[/url] 无
*/
void wait_us(uint32_t us)
{
        CLK_SysTickDelay(us);
}

mpu6050.c
#include "MPU6050.h"

extern void wait_ms(uint32_t us);

//各坐标轴上静止偏差(重力,角速度)
int16_t offsetAccelX = 17;
int16_t offsetAccelY = -70;
int16_t offsetAccelZ = 16474;

int16_t offsetGyroX = 11;
int16_t offsetGyroY = 38;
int16_t offsetGyroZ = 3;

void i2c_write(uint8_t Register,uint8_t data)
{
        i2c_WriteByte(SlaveAddress,Register,data);
}

uint8_t i2c_read(uint8_t Register)
{
        return i2c_ReadByte(SlaveAddress,Register);
}

#define Single_WriteI2C         i2c_write
#define Single_ReadI2C                i2c_read


//**************************************
//初始化MPU6050
//**************************************
void InitMPU6050()
{
        i2c_init();
        
        Single_WriteI2C(PWR_MGMT_1, 0x80);        //复位MPU6050
        
        wait_ms(10);
        
        Single_WriteI2C(PWR_MGMT_1,0X00);        //唤醒MPU6050
        
        wait_ms(10);

        Single_WriteI2C(SMPLRT_DIV, 0x07);
        
        wait_ms(10);

        Single_WriteI2C(CONFIG, 0x06);
        
        wait_ms(10);

        Single_WriteI2C(GYRO_CONFIG, 0x18);
        
        wait_ms(10);

        Single_WriteI2C(ACCEL_CONFIG, 0x01);
        
        wait_ms(10);
}
//**************************************
//合成数据
//**************************************
int16_t GetMPUOutValue(uint8_t REG_Address)
{
        int16_t result;
        uint8_t H,L;
        H=Single_ReadI2C(REG_Address);
        L=Single_ReadI2C(REG_Address+1);
        result = (H<<8)+L;
        return result;   //合成数据
}

//**************************************
//取某一轴上的加速度数据
//**************************************
int16_t GetAccelValue(char axis)
{
        int16_t result = 0;
        switch(axis)
        {
                case 'x':
                case 'X':
                {
                        result = GetMPUOutValue(ACCEL_XOUT_H) - offsetAccelX;
                }
                break;
                case 'y':
                case 'Y':
                {
                        result = GetMPUOutValue(ACCEL_YOUT_H) - offsetAccelY;
                }
                break;
                case 'z':
                case 'Z':
                {
                        result = GetMPUOutValue(ACCEL_ZOUT_H) - offsetAccelZ;
                }
                break;
        }
        return result;
}

//**************************************
//取某一轴上的角速度数据
//**************************************
int16_t GetGyroValue(char axis)
{
        int16_t result = 0;
        switch(axis)
        {
                case 'x':
                case 'X':
                {
                        result = GetMPUOutValue(GYRO_XOUT_H) - offsetGyroX;
                }
                break;
                case 'y':
                case 'Y':
                {
                        result = GetMPUOutValue(GYRO_YOUT_H) - offsetGyroY;
                }
                break;
                case 'z':
                case 'Z':
                {
                        result = GetMPUOutValue(GYRO_ZOUT_H) - offsetGyroZ;
                }
                break;
        }
        return result;
}
i2c_api.c
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     i2c_api.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V1.0
* $Revision: 2 $
* $Date: 17/08/03 7:08p $
* [url=home.php?mod=space&uid=247401]@brief[/url]    M058S SPI hardware abstract layer API implemented.
*
* @note
* Copyright (C) 2017 sunsjw All rights reserved.
*
******************************************************************************/

#include
#include
#include

extern void wait_us(uint32_t us);

#define I2Cx        I2C0

#define WRITE        0
#define READ        1


//**************************************
//I2C总线初始化
//**************************************
void i2c_init(void)
{
        SYS->P3_MFP |= (SYS_MFP_P34_SDA0|SYS_MFP_P35_SCL0);
        SYS_ResetModule(I2C0_RST);
        I2C_Open(I2Cx,400000);
        I2C0->I2CLK = 124;
}

//**************************************
//向I2C设备写入一个字节数据
//**************************************
void i2c_WriteByte(uint8_t SlaveAddr,uint8_t REG_Address,uint8_t REG_data)
{
        I2C_START(I2Cx);
        I2C_WAIT_READY(I2Cx);

        while(I2C_GetStatus(I2Cx) != 0x08);
        I2C_SetData(I2Cx,(SlaveAddr<<1)+WRITE);
        I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
        I2C_WAIT_READY(I2Cx);
        
        while(I2C_GetStatus(I2Cx) != 0x18);
        I2C_SetData(I2Cx,REG_Address);
        I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
        I2C_WAIT_READY(I2Cx);
        
        while(I2C_GetStatus(I2Cx) != 0x28);
        I2C_SetData(I2Cx,REG_data);
        I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
        I2C_WAIT_READY(I2Cx);
        
        while(I2C_GetStatus(I2Cx) != 0x28);
        I2C_STOP(I2Cx);
        wait_us(100);
}

//**************************************
//从I2C设备读取一个字节数据
//**************************************
uint8_t i2c_ReadByte(uint8_t SlaveAddr,uint8_t REG_Address)
{
        I2C_START(I2Cx);
        I2C_WAIT_READY(I2Cx);
        while(I2C_GetStatus(I2Cx) != 0x08);
        
        I2C_SetData(I2Cx,(SlaveAddr<<1)+WRITE);
        I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
        I2C_WAIT_READY(I2Cx);
        while(I2C_GetStatus(I2Cx) != 0x18);
        
        I2C_SetData(I2Cx,REG_Address);
        I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
        I2C_WAIT_READY(I2Cx);
        while(I2C_GetStatus(I2Cx) != 0x28);
        
        I2C_START(I2Cx);
        I2C_WAIT_READY(I2Cx);
        while(I2C_GetStatus(I2Cx) != 0x10);
        
        I2C_SetData(I2Cx,(SlaveAddr<<1)+READ);
        I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
        I2C_WAIT_READY(I2Cx);
        while(I2C_GetStatus(I2Cx) != 0x40);
        
        I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
        I2C_WAIT_READY(I2Cx);
        while(I2C_GetStatus(I2Cx) != 0x58);
        
        uint8_t result = I2C_GetData(I2Cx);
        I2C_STOP(I2Cx);
        return result;
}
//**************************************
//从I2C设备读取指定长度字节数据
//**************************************
int i2c_ReadBytes(int dev_address,int reg_address,char* buffer,int length)
{
        return 0;
}
//**************************************
//向I2C设备写入多字节数据
//**************************************
int i2c_WriteBytes(int dev_address,int reg_address,char* buffer,int length)
{
        return 0;
}
这个项目借鉴了MBed驱动的一些思想,把I2C总线抽象出来,MPU6050的驱动只使用I2C的抽象API,不同的平台只需要实现I2C的抽象API就可以了。最上再传个我自己SuperCom的动画效果图。

有需要的同学可以私聊我。
   


  

SuperUART.zip

97.83 KB

修一明| | 2017-8-19 11:46 | 显示全部楼层
楼主棒棒哒。。。

使用特权

评论回复
zhuomuniao110| | 2017-8-19 21:19 | 显示全部楼层
给力,这套件玩的666666666666

使用特权

评论回复
wanduzi| | 2017-8-19 22:16 | 显示全部楼层
还是用终端打印看的给力。

使用特权

评论回复
huahuagg| | 2017-8-19 22:20 | 显示全部楼层
MBED前段还挺火的,最近没动静了。

使用特权

评论回复
wahahaheihei| | 2023-2-9 11:20 | 显示全部楼层
好贴,学习了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:我最讨厌两种人:一是有种族歧视的; 二是黑人;三是不识数的!

63

主题

3204

帖子

15

粉丝