[DemoCode下载] 八月新唐+M058SSAN操作MPU6050

[复制链接]
2480|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


  1. #include "M058S.h"                      // Device header
  2. #include "stdio.h"
  3. #include "mpu6050.h"

  4. /*----------------------------------------------------------------------------
  5.         初初化函数
  6. *----------------------------------------------------------------------------*/
  7. extern void SYS_Init(void);
  8. extern void Uart_Init(void);
  9. extern void GPIO_Init(void);
  10. extern void Timer_Init(void);

  11. void wait_us(uint32_t us);
  12. void wait_ms(uint32_t ms);
  13. void wait_s(uint32_t s);
  14. void WorkOut(void);

  15. /*
  16. * [url=home.php?mod=space&uid=247401]@brief[/url] 主函数
  17. * @param 无
  18. * [url=home.php?mod=space&uid=266161]@return[/url] 退出代码
  19. */
  20. int main(void)
  21. {
  22.         SYS_Init();
  23.         GPIO_Init();
  24.         Uart_Init();
  25.         Timer_Init();
  26.         InitMPU6050();
  27.         
  28.         while(1)
  29.         {
  30.                 WorkOut();
  31.                 wait_s(1);
  32.         }
  33. }

  34. /*
  35. * [url=home.php?mod=space&uid=247401]@brief[/url] 工作输出
  36. * @param 无
  37. * [url=home.php?mod=space&uid=266161]@return[/url] 无
  38. */
  39. void WorkOut()
  40. {
  41.         printf("begin");
  42.         
  43.         printf("┌───────────────────────────────────┐");
  44.         printf("│                八月,新唐你好!                                        │");
  45.         printf("│                Hello, 21ic.com !                                        │");
  46.         printf("│                                                                        │");
  47.         printf("│                Read the MPU6050 test using the I2C bus.                 │");
  48.         printf("│                加速度:X=%04d,Y=%04d,Z=%04d                                │",GetAccelValue('x'),GetAccelValue('y'),GetAccelValue('z'));
  49.         printf("│                角速度:X=%04d,Y=%04d,Z=%04d                                │",GetGyroValue('x'),GetGyroValue('y'),GetGyroValue('z'));
  50.         printf("│                                                                        │");
  51.         printf("│                MyID:Ketose                                                │");
  52.         printf("└───────────────────────────────────┘");
  53.         
  54.         uint8_t c = 0x1A;
  55.         UART_Write(UART0,(uint8_t*)&c,1);
  56. }

  57. /*
  58. * [url=home.php?mod=space&uid=247401]@brief[/url] 延时函数
  59. * @param 秒
  60. * [url=home.php?mod=space&uid=266161]@return[/url] 无
  61. */
  62. void wait_s(uint32_t s)
  63. {
  64.         for(int i=s;i>0;i--)
  65.         {
  66.                 wait_ms(1000);
  67.         }
  68. }
  69. /*
  70. * [url=home.php?mod=space&uid=247401]@brief[/url] 延时函数
  71. * @param 毫秒
  72. * [url=home.php?mod=space&uid=266161]@return[/url] 无
  73. */
  74. void wait_ms(uint32_t ms)
  75. {
  76.         for(int i=ms;i>0;i--)
  77.         {
  78.                 wait_us(1000);
  79.         }
  80. }
  81. /*
  82. * [url=home.php?mod=space&uid=247401]@brief[/url] 延时函数
  83. * @param 微秒
  84. * [url=home.php?mod=space&uid=266161]@return[/url] 无
  85. */
  86. void wait_us(uint32_t us)
  87. {
  88.         CLK_SysTickDelay(us);
  89. }

mpu6050.c
  1. #include "MPU6050.h"

  2. extern void wait_ms(uint32_t us);

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

  7. int16_t offsetGyroX = 11;
  8. int16_t offsetGyroY = 38;
  9. int16_t offsetGyroZ = 3;

  10. void i2c_write(uint8_t Register,uint8_t data)
  11. {
  12.         i2c_WriteByte(SlaveAddress,Register,data);
  13. }

  14. uint8_t i2c_read(uint8_t Register)
  15. {
  16.         return i2c_ReadByte(SlaveAddress,Register);
  17. }

  18. #define Single_WriteI2C         i2c_write
  19. #define Single_ReadI2C                i2c_read


  20. //**************************************
  21. //初始化MPU6050
  22. //**************************************
  23. void InitMPU6050()
  24. {
  25.         i2c_init();
  26.         
  27.         Single_WriteI2C(PWR_MGMT_1, 0x80);        //复位MPU6050
  28.         
  29.         wait_ms(10);
  30.         
  31.         Single_WriteI2C(PWR_MGMT_1,0X00);        //唤醒MPU6050
  32.         
  33.         wait_ms(10);

  34.         Single_WriteI2C(SMPLRT_DIV, 0x07);
  35.         
  36.         wait_ms(10);

  37.         Single_WriteI2C(CONFIG, 0x06);
  38.         
  39.         wait_ms(10);

  40.         Single_WriteI2C(GYRO_CONFIG, 0x18);
  41.         
  42.         wait_ms(10);

  43.         Single_WriteI2C(ACCEL_CONFIG, 0x01);
  44.         
  45.         wait_ms(10);
  46. }
  47. //**************************************
  48. //合成数据
  49. //**************************************
  50. int16_t GetMPUOutValue(uint8_t REG_Address)
  51. {
  52.         int16_t result;
  53.         uint8_t H,L;
  54.         H=Single_ReadI2C(REG_Address);
  55.         L=Single_ReadI2C(REG_Address+1);
  56.         result = (H<<8)+L;
  57.         return result;   //合成数据
  58. }

  59. //**************************************
  60. //取某一轴上的加速度数据
  61. //**************************************
  62. int16_t GetAccelValue(char axis)
  63. {
  64.         int16_t result = 0;
  65.         switch(axis)
  66.         {
  67.                 case 'x':
  68.                 case 'X':
  69.                 {
  70.                         result = GetMPUOutValue(ACCEL_XOUT_H) - offsetAccelX;
  71.                 }
  72.                 break;
  73.                 case 'y':
  74.                 case 'Y':
  75.                 {
  76.                         result = GetMPUOutValue(ACCEL_YOUT_H) - offsetAccelY;
  77.                 }
  78.                 break;
  79.                 case 'z':
  80.                 case 'Z':
  81.                 {
  82.                         result = GetMPUOutValue(ACCEL_ZOUT_H) - offsetAccelZ;
  83.                 }
  84.                 break;
  85.         }
  86.         return result;
  87. }

  88. //**************************************
  89. //取某一轴上的角速度数据
  90. //**************************************
  91. int16_t GetGyroValue(char axis)
  92. {
  93.         int16_t result = 0;
  94.         switch(axis)
  95.         {
  96.                 case 'x':
  97.                 case 'X':
  98.                 {
  99.                         result = GetMPUOutValue(GYRO_XOUT_H) - offsetGyroX;
  100.                 }
  101.                 break;
  102.                 case 'y':
  103.                 case 'Y':
  104.                 {
  105.                         result = GetMPUOutValue(GYRO_YOUT_H) - offsetGyroY;
  106.                 }
  107.                 break;
  108.                 case 'z':
  109.                 case 'Z':
  110.                 {
  111.                         result = GetMPUOutValue(GYRO_ZOUT_H) - offsetGyroZ;
  112.                 }
  113.                 break;
  114.         }
  115.         return result;
  116. }
i2c_api.c
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     i2c_api.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V1.0
  4. * $Revision: 2 $
  5. * $Date: 17/08/03 7:08p $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    M058S SPI hardware abstract layer API implemented.
  7. *
  8. * @note
  9. * Copyright (C) 2017 sunsjw All rights reserved.
  10. *
  11. ******************************************************************************/

  12. #include
  13. #include
  14. #include

  15. extern void wait_us(uint32_t us);

  16. #define I2Cx        I2C0

  17. #define WRITE        0
  18. #define READ        1


  19. //**************************************
  20. //I2C总线初始化
  21. //**************************************
  22. void i2c_init(void)
  23. {
  24.         SYS->P3_MFP |= (SYS_MFP_P34_SDA0|SYS_MFP_P35_SCL0);
  25.         SYS_ResetModule(I2C0_RST);
  26.         I2C_Open(I2Cx,400000);
  27.         I2C0->I2CLK = 124;
  28. }

  29. //**************************************
  30. //向I2C设备写入一个字节数据
  31. //**************************************
  32. void i2c_WriteByte(uint8_t SlaveAddr,uint8_t REG_Address,uint8_t REG_data)
  33. {
  34.         I2C_START(I2Cx);
  35.         I2C_WAIT_READY(I2Cx);

  36.         while(I2C_GetStatus(I2Cx) != 0x08);
  37.         I2C_SetData(I2Cx,(SlaveAddr<<1)+WRITE);
  38.         I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
  39.         I2C_WAIT_READY(I2Cx);
  40.         
  41.         while(I2C_GetStatus(I2Cx) != 0x18);
  42.         I2C_SetData(I2Cx,REG_Address);
  43.         I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
  44.         I2C_WAIT_READY(I2Cx);
  45.         
  46.         while(I2C_GetStatus(I2Cx) != 0x28);
  47.         I2C_SetData(I2Cx,REG_data);
  48.         I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
  49.         I2C_WAIT_READY(I2Cx);
  50.         
  51.         while(I2C_GetStatus(I2Cx) != 0x28);
  52.         I2C_STOP(I2Cx);
  53.         wait_us(100);
  54. }

  55. //**************************************
  56. //从I2C设备读取一个字节数据
  57. //**************************************
  58. uint8_t i2c_ReadByte(uint8_t SlaveAddr,uint8_t REG_Address)
  59. {
  60.         I2C_START(I2Cx);
  61.         I2C_WAIT_READY(I2Cx);
  62.         while(I2C_GetStatus(I2Cx) != 0x08);
  63.         
  64.         I2C_SetData(I2Cx,(SlaveAddr<<1)+WRITE);
  65.         I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
  66.         I2C_WAIT_READY(I2Cx);
  67.         while(I2C_GetStatus(I2Cx) != 0x18);
  68.         
  69.         I2C_SetData(I2Cx,REG_Address);
  70.         I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
  71.         I2C_WAIT_READY(I2Cx);
  72.         while(I2C_GetStatus(I2Cx) != 0x28);
  73.         
  74.         I2C_START(I2Cx);
  75.         I2C_WAIT_READY(I2Cx);
  76.         while(I2C_GetStatus(I2Cx) != 0x10);
  77.         
  78.         I2C_SetData(I2Cx,(SlaveAddr<<1)+READ);
  79.         I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
  80.         I2C_WAIT_READY(I2Cx);
  81.         while(I2C_GetStatus(I2Cx) != 0x40);
  82.         
  83.         I2C_SET_CONTROL_REG(I2Cx,I2C_I2CON_SI);
  84.         I2C_WAIT_READY(I2Cx);
  85.         while(I2C_GetStatus(I2Cx) != 0x58);
  86.         
  87.         uint8_t result = I2C_GetData(I2Cx);
  88.         I2C_STOP(I2Cx);
  89.         return result;
  90. }
  91. //**************************************
  92. //从I2C设备读取指定长度字节数据
  93. //**************************************
  94. int i2c_ReadBytes(int dev_address,int reg_address,char* buffer,int length)
  95. {
  96.         return 0;
  97. }
  98. //**************************************
  99. //向I2C设备写入多字节数据
  100. //**************************************
  101. int i2c_WriteBytes(int dev_address,int reg_address,char* buffer,int length)
  102. {
  103.         return 0;
  104. }
这个项目借鉴了MBed驱动的一些思想,把I2C总线抽象出来,MPU6050的驱动只使用I2C的抽象API,不同的平台只需要实现I2C的抽象API就可以了。最上再传个我自己SuperCom的动画效果图。

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


  

SuperUART.zip

97.83 KB, 下载次数: 36

修一明 发表于 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 | 显示全部楼层
好贴,学习了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

66

主题

3267

帖子

15

粉丝
快速回复 在线客服 返回列表 返回顶部