飞道的博客

STM32+MPU6050设计便携式Mini桌面时钟(自动调整时间显示方向)

159人阅读  评论(0)

一、环境介绍

MCU:  STM32F103C8T6

姿态传感器:  MPU6050

OLED显示屏:  0.96寸SPI接口OLED

温度传感器: DS18B20

编译软件: keil5 

二、功能介绍

完整项目源码下载地址: https://download.csdn.net/download/xiaolong1126626497/18657534

时钟可以根据MPU6050测量的姿态自动调整显示画面方向,也就是倒着拿、横着拿、反着拿都可以让时间显示是正对着自己的,时间支持自己调整,支持串口校准。可以按键切换页面查看环境温度显示。

支持串口时间校准: 

 

三、核心代码

3.1 main.c


  
  1. #include "stm32f10x.h"
  2. #include "beep.h"
  3. #include "delay.h"
  4. #include "led.h"
  5. #include "key.h"
  6. #include "sys.h"
  7. #include "usart.h"
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include "exti.h"
  11. #include "timer.h"
  12. #include "rtc.h"
  13. #include "wdg.h"
  14. #include "ds18b20.h"
  15. #include "oled.h"
  16. #include "fontdata.h"
  17. #include "adc.h"
  18. #include "FunctionConfig.h"
  19. #include "mpu6050.h"
  20. #include "inv_mpu.h"
  21. #include "inv_mpu_dmp_motion_driver.h"
  22. /*
  23. 函数功能: 绘制时钟表盘框架
  24. */
  25. void DrawTimeFrame(void)
  26. {
  27. u8 i;
  28. OLED_Circle( 32, 32, 31); //画外圆
  29. OLED_Circle( 32, 32, 1); //画中心圆
  30. //画刻度
  31. for(i= 0;i< 60;i++)
  32. {
  33. if(i% 5== 0)OLED_DrawAngleLine( 32, 32, 6*i, 31, 3, 1);
  34. }
  35. OLED_RefreshGRAM(); //刷新数据到OLED屏幕
  36. }
  37. /*
  38. 函数功能: 更新时间框架显示,在RTC中断里调用
  39. */
  40. char TimeBuff[ 20];
  41. void Update_FrameShow(void)
  42. {
  43. /*1. 绘制秒针、分针、时针*/
  44. OLED_DrawAngleLine2( 32, 32,rtc_clock.sec* 6 -6 -90, 27, 0); //清除之前的秒针
  45. OLED_DrawAngleLine2( 32, 32,rtc_clock.sec* 6 -90, 27, 1); //画秒针
  46. OLED_DrawAngleLine2( 32, 32,rtc_clock.min* 6 -6 -90, 24, 0);
  47. OLED_DrawAngleLine2( 32, 32,rtc_clock.min* 6 -90, 24, 1);
  48. OLED_DrawAngleLine2( 32, 32,rtc_clock.hour* 30 -6 -90, 21, 0);
  49. OLED_DrawAngleLine2( 32, 32,rtc_clock.hour* 30 -90, 21, 1);
  50. //绘制电子钟时间
  51. sprintf(TimeBuff, "%d",rtc_clock.year);
  52. OLED_ShowString( 65, 16* 0, 16,TimeBuff); //年份字符串
  53. OLED_ShowChineseFont( 66+ 32, 16* 0, 16, 4); //显示年
  54. sprintf(TimeBuff, "%d/%d",rtc_clock.mon,rtc_clock.day);
  55. OLED_ShowString( 75, 16* 1, 16,TimeBuff); //月
  56. if(rtc_clock.sec== 0)OLED_ShowString( 65, 16* 2, 16, " "); //清除多余的数据
  57. sprintf(TimeBuff, "%d:%d:%d",rtc_clock.hour,rtc_clock.min,rtc_clock.sec);
  58. OLED_ShowString( 65, 16* 2, 16,TimeBuff); //秒
  59. //显示星期
  60. OLED_ShowChineseFont( 70, 16* 3, 16, 5); //星
  61. OLED_ShowChineseFont( 70+ 16, 16* 3, 16, 6); //期
  62. OLED_ShowChineseFont( 70+ 32, 16* 3, 16,rtc_clock.week+ 7); //具体的值
  63. }
  64. u8 DS18B20_TEMP_Info[ 10]; //DS18B20温度信息
  65. /*
  66. 函数功能: DS18B20温度显示页面
  67. */
  68. void DS18B20_ShowPageTable(short DS18B20_temp)
  69. {
  70. char DS18B20_buff[ 10]; //存放温度信息
  71. unsigned short DS18B20_intT= 0,DS18B20_decT= 0; //温度值的整数和小数部分
  72. DS18B20_intT = DS18B20_temp >> 4; //分离出温度值整数部分
  73. DS18B20_decT = DS18B20_temp & 0xF; //分离出温度值小数部分
  74. sprintf(( char*)DS18B20_TEMP_Info, "%d.%d",DS18B20_intT,DS18B20_decT); //保存DS18B20温度信息,发送给上位机
  75. OLED_ShowString( 34, 0, 16, "DS18B20");
  76. if(DS18B20_temp== 0xFF)
  77. {
  78. OLED_ShowString( 0, 30, 16, " "); //清除一行的显示
  79. //显示温度错误信息
  80. OLED_ShowString( 0, 30, 16, "DS18B20 Error!");
  81. }
  82. else
  83. {
  84. sprintf(DS18B20_buff, "%sC ",DS18B20_TEMP_Info);
  85. //显示温度
  86. OLED_ShowString( 40, 30, 16,DS18B20_buff);
  87. }
  88. }
  89. int main(void)
  90. {
  91. u8 stat;
  92. u8 key_val;
  93. u32 TimeCnt= 0;
  94. u16 temp_data; //温度数据
  95. short aacx,aacy,aacz; //加速度传感器原始数据
  96. short gyrox,gyroy,gyroz; //陀螺仪原始数据
  97. short temp;
  98. float pitch,roll,yaw; //欧拉角
  99. u8 page_cnt= 0; //显示的页面
  100. u8 display_state1= 0;
  101. u8 display_state2= 0;
  102. BEEP_Init(); //初始化蜂鸣器
  103. LED_Init(); //初始化LED
  104. KEY_Init(); //按键初始化
  105. DS18B20_Init(); //DS18B20
  106. USARTx_Init(USART1, 72, 115200); //串口1的初始化
  107. TIMERx_Init(TIM1, 72, 20000); //辅助串口1接收。20ms为一帧数据。
  108. RTC_Init(); //RTC初始化
  109. OLED_Init( 0xc8, 0xa1); //OLED显示屏初始化--正常显示
  110. //OLED_Init(0xc0,0xa0); //OLED显示屏初始化--翻转显示
  111. while(MPU6050_Init()) //初始化MPU6050
  112. {
  113. printf( "MPU6050陀螺仪初始化失败!\r\n");
  114. DelayMs( 500);
  115. }
  116. // //注意:陀螺仪初始化的时候,必须正常摆放才可以初始化成
  117. // while(mpu_dmp_init())
  118. // {
  119. // printf("MPU6050陀螺仪设置DMP失败!\r\n");
  120. // DelayMs(1000);
  121. // }
  122. OLED_Clear( 0x00); //清屏
  123. DrawTimeFrame(); //画时钟框架
  124. while( 1)
  125. {
  126. key_val=KEY_GetValue();
  127. if(key_val)
  128. {
  129. page_cnt=!page_cnt;
  130. //时钟页面
  131. if(page_cnt== 0)
  132. {
  133. //清屏
  134. OLED_Clear( 0);
  135. DrawTimeFrame(); //画时钟框架
  136. RTC->CRH|= 1<< 0; //开启秒中断
  137. }
  138. else if(page_cnt== 1)
  139. {
  140. //清屏
  141. OLED_Clear( 0);
  142. RTC->CRH&=~( 1<< 0); //关闭秒中断
  143. }
  144. }
  145. if(USART1_RX_STATE)
  146. {
  147. //*20200530154322
  148. //通过串口1校准RTC时间
  149. if(USART1_RX_BUFF[ 0]== '*')
  150. {
  151. rtc_clock.year=(USART1_RX_BUFF[ 1] -48)* 1000+(USART1_RX_BUFF[ 2] -48)* 100+(USART1_RX_BUFF[ 3] -48)* 10+(USART1_RX_BUFF[ 4] -48)* 1;
  152. rtc_clock.mon=(USART1_RX_BUFF[ 5] -48)* 10+(USART1_RX_BUFF[ 6] -48)* 1;
  153. rtc_clock.day=(USART1_RX_BUFF[ 7] -48)* 10+(USART1_RX_BUFF[ 8] -48)* 1;
  154. rtc_clock.hour=(USART1_RX_BUFF[ 9] -48)* 10+(USART1_RX_BUFF[ 10] -48)* 1;
  155. rtc_clock.min=(USART1_RX_BUFF[ 11] -48)* 10+(USART1_RX_BUFF[ 12] -48)* 1;
  156. rtc_clock.sec=(USART1_RX_BUFF[ 13] -48)* 10+(USART1_RX_BUFF[ 14] -48)* 1;
  157. RTC_SetTime(rtc_clock.year,rtc_clock.mon,rtc_clock.day,rtc_clock.hour,rtc_clock.min,rtc_clock.sec);
  158. OLED_Clear( 0); //OLED清屏
  159. DrawTimeFrame(); //画时钟框架
  160. }
  161. USART1_RX_STATE= 0;
  162. USART1_RX_CNT= 0;
  163. }
  164. //时间记录
  165. DelayMs( 10);
  166. TimeCnt++;
  167. if(TimeCnt>= 100) //1000毫秒一次
  168. {
  169. TimeCnt= 0;
  170. LED1=!LED1;
  171. temp_data=DS18B20_ReadTemp();
  172. // printf("temp_data=%d.%d\n",temp_data>>4,temp_data&0xF);
  173. // stat=mpu_dmp_get_data(&pitch,&roll,&yaw);
  174. // temp=MPU6050_Get_Temperature(); //得到温度值
  175. //MPU6050_Get_Gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺仪原始数据
  176. MPU6050_Get_Accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据
  177. //printf("温度数据:%d\r\n",temp);
  178. // printf("陀螺仪原始数据 :x=%d y=%d z=%d\r\n",gyrox,gyroy,gyroz);
  179. printf( "加速度传感器数据:x=%d y=%d z=%d\r\n",aacx,aacy,aacz);
  180. // printf("欧垃角:横滚角=%d 俯仰角=%d 航向角=%d\r\n",(int)(roll*100),(int)(pitch*100),(int)(yaw*10));
  181. //
  182. //正着显示
  183. if(aacz>= 15000)
  184. {
  185. printf( "正着显示\n");
  186. if(display_state1!= 1)
  187. {
  188. display_state2= 0;
  189. display_state1= 1;
  190. OLED_Init( 0xc8, 0xa1); //OLED显示屏初始化--正常显示
  191. }
  192. }
  193. //翻转显示
  194. else if(display_state2!= 1)
  195. {
  196. printf( "反着显示\n");
  197. display_state1= 0;
  198. display_state2= 1;
  199. OLED_Init( 0xc0, 0xa0); //OLED显示屏初始化--翻转显示
  200. }
  201. }
  202. if(page_cnt== 1) //温度显示页面
  203. {
  204. DS18B20_ShowPageTable(temp_data);
  205. }
  206. }
  207. }

3.2 mpu6050.c


  
  1. #include "mpu6050.h"
  2. #include "sys.h"
  3. #include "delay.h"
  4. #include <stdio.h>
  5. /*--------------------------------------------------------------------IIC协议底层模拟时序--------------------------------------------------------------------------------*/
  6. /*
  7. 硬件接线:
  8. 1 VCC 3.3V/5V 电源输入 --->接3.3V
  9. 2 GND 地线 --->接GND
  10. 3 IIC_SDA IIC 通信数据线 -->PB6
  11. 4 IIC_SCL IIC 通信时钟线 -->PB7
  12. 5 MPU_INT 中断输出引脚 ---->未接
  13. 6 MPU_AD0 IIC 从机地址设置引脚-->未接
  14. AD0引脚说明:ID=0X68(悬空/接 GND) ID=0X69(接 VCC)
  15. */
  16. /*
  17. 函数功能:MPU IIC 延时函数
  18. */
  19. void MPU6050_IIC_Delay(void)
  20. {
  21. DelayUs( 2);
  22. }
  23. /*
  24. 函数功能: 初始化IIC
  25. */
  26. void MPU6050_IIC_Init(void)
  27. {
  28. RCC->APB2ENR|= 1<< 3; //先使能外设IO PORTB时钟
  29. GPIOB->CRL&= 0X00FFFFFF; //PB6/7 推挽输出
  30. GPIOB->CRL|= 0X33000000;
  31. GPIOB->ODR|= 3<< 6; //PB6,7 输出高
  32. }
  33. /*
  34. 函数功能: 产生IIC起始信号
  35. */
  36. void MPU6050_IIC_Start(void)
  37. {
  38. MPU6050_SDA_OUT(); //sda线输出
  39. MPU6050_IIC_SDA= 1;
  40. MPU6050_IIC_SCL= 1;
  41. MPU6050_IIC_Delay();
  42. MPU6050_IIC_SDA= 0; //START:when CLK is high,DATA change form high to low
  43. MPU6050_IIC_Delay();
  44. MPU6050_IIC_SCL= 0; //钳住I2C总线,准备发送或接收数据
  45. }
  46. /*
  47. 函数功能: 产生IIC停止信号
  48. */
  49. void MPU6050_IIC_Stop(void)
  50. {
  51. MPU6050_SDA_OUT(); //sda线输出
  52. MPU6050_IIC_SCL= 0;
  53. MPU6050_IIC_SDA= 0; //STOP:when CLK is high DATA change form low to high
  54. MPU6050_IIC_Delay();
  55. MPU6050_IIC_SCL= 1;
  56. MPU6050_IIC_SDA= 1; //发送I2C总线结束信号
  57. MPU6050_IIC_Delay();
  58. }
  59. /*
  60. 函数功能: 等待应答信号到来
  61. 返 回 值:1,接收应答失败
  62. 0,接收应答成功
  63. */
  64. u8 MPU6050_IIC_Wait_Ack(void)
  65. {
  66. u8 ucErrTime= 0;
  67. MPU6050_SDA_IN(); //SDA设置为输入
  68. MPU6050_IIC_SDA= 1;MPU6050_IIC_Delay();
  69. MPU6050_IIC_SCL= 1;MPU6050_IIC_Delay();
  70. while(MPU6050_READ_SDA)
  71. {
  72. ucErrTime++;
  73. if(ucErrTime> 250)
  74. {
  75. MPU6050_IIC_Stop();
  76. return 1;
  77. }
  78. }
  79. MPU6050_IIC_SCL= 0; //时钟输出0
  80. return 0;
  81. }
  82. /*
  83. 函数功能:产生ACK应答
  84. */
  85. void MPU6050_IIC_Ack(void)
  86. {
  87. MPU6050_IIC_SCL= 0;
  88. MPU6050_SDA_OUT();
  89. MPU6050_IIC_SDA= 0;
  90. MPU6050_IIC_Delay();
  91. MPU6050_IIC_SCL= 1;
  92. MPU6050_IIC_Delay();
  93. MPU6050_IIC_SCL= 0;
  94. }
  95. /*
  96. 函数功能:不产生ACK应答
  97. */
  98. void MPU6050_IIC_NAck(void)
  99. {
  100. MPU6050_IIC_SCL= 0;
  101. MPU6050_SDA_OUT();
  102. MPU6050_IIC_SDA= 1;
  103. MPU6050_IIC_Delay();
  104. MPU6050_IIC_SCL= 1;
  105. MPU6050_IIC_Delay();
  106. MPU6050_IIC_SCL= 0;
  107. }
  108. /*
  109. 函数功能:IIC发送一个字节
  110. 返回从机有无应答
  111. 1,有应答
  112. 0,无应答
  113. */
  114. void MPU6050_IIC_Send_Byte(u8 txd)
  115. {
  116. u8 t;
  117. MPU6050_SDA_OUT();
  118. MPU6050_IIC_SCL= 0; //拉低时钟开始数据传输
  119. for(t= 0;t< 8;t++)
  120. {
  121. MPU6050_IIC_SDA=(txd& 0x80)>> 7;
  122. txd<<= 1;
  123. MPU6050_IIC_SCL= 1;
  124. MPU6050_IIC_Delay();
  125. MPU6050_IIC_SCL= 0;
  126. MPU6050_IIC_Delay();
  127. }
  128. }
  129. /*
  130. 函数功能:读1个字节,ack=1时,发送ACK,ack=0,发送nACK
  131. */
  132. u8 MPU6050_IIC_Read_Byte(unsigned char ack)
  133. {
  134. unsigned char i,receive= 0;
  135. MPU6050_SDA_IN(); //SDA设置为输入
  136. for(i= 0;i< 8;i++ )
  137. {
  138. MPU6050_IIC_SCL= 0;
  139. MPU6050_IIC_Delay();
  140. MPU6050_IIC_SCL= 1;
  141. receive<<= 1;
  142. if(MPU6050_READ_SDA)receive++;
  143. MPU6050_IIC_Delay();
  144. }
  145. if(!ack)
  146. MPU6050_IIC_NAck(); //发送nACK
  147. else
  148. MPU6050_IIC_Ack(); //发送ACK
  149. return receive;
  150. }
  151. /*--------------------------------------------------------------------MPU6050底层驱动代码--------------------------------------------------------------------------------*/
  152. /*
  153. 函数功能:初始化MPU6050
  154. 返 回 值:0,成功
  155. 其他,错误代码
  156. */
  157. u8 MPU6050_Init(void)
  158. {
  159. u8 res;
  160. MPU6050_IIC_Init(); //初始化IIC总线
  161. MPU6050_Write_Byte(MPU_PWR_MGMT1_REG, 0X80); //复位MPU6050
  162. DelayMs( 100);
  163. MPU6050_Write_Byte(MPU_PWR_MGMT1_REG, 0X00); //唤醒MPU6050
  164. MPU6050_Set_Gyro_Fsr( 3); //陀螺仪传感器,±2000dps
  165. MPU6050_Set_Accel_Fsr( 0); //加速度传感器,±2g
  166. MPU6050_Set_Rate( 50); //设置采样率50Hz
  167. MPU6050_Write_Byte(MPU_INT_EN_REG, 0X00); //关闭所有中断
  168. MPU6050_Write_Byte(MPU_USER_CTRL_REG, 0X00); //I2C主模式关闭
  169. MPU6050_Write_Byte(MPU_FIFO_EN_REG, 0X00); //关闭FIFO
  170. MPU6050_Write_Byte(MPU_INTBP_CFG_REG, 0X80); //INT引脚低电平有效
  171. res=MPU6050_Read_Byte(MPU_DEVICE_ID_REG);
  172. if(res==MPU6050_ADDR) //器件ID正确
  173. {
  174. MPU6050_Write_Byte(MPU_PWR_MGMT1_REG, 0X01); //设置CLKSEL,PLL X轴为参考
  175. MPU6050_Write_Byte(MPU_PWR_MGMT2_REG, 0X00); //加速度与陀螺仪都工作
  176. MPU6050_Set_Rate( 50); //设置采样率为50Hz
  177. } else return 1;
  178. return 0;
  179. }
  180. /*
  181. 设置MPU6050陀螺仪传感器满量程范围
  182. fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
  183. 返回值:0,设置成功
  184. 其他,设置失败
  185. */
  186. u8 MPU6050_Set_Gyro_Fsr(u8 fsr)
  187. {
  188. return MPU6050_Write_Byte(MPU_GYRO_CFG_REG,fsr<< 3); //设置陀螺仪满量程范围
  189. }
  190. /*
  191. 函数功能:设置MPU6050加速度传感器满量程范围
  192. 函数功能:fsr:0,±2g;1,±4g;2,±8g;3,±16g
  193. 返 回 值:0,设置成功
  194. 其他,设置失败
  195. */
  196. u8 MPU6050_Set_Accel_Fsr(u8 fsr)
  197. {
  198. return MPU6050_Write_Byte(MPU_ACCEL_CFG_REG,fsr<< 3); //设置加速度传感器满量程范围
  199. }
  200. /*
  201. 函数功能:设置MPU6050的数字低通滤波器
  202. 函数参数:lpf:数字低通滤波频率(Hz)
  203. 返 回 值:0,设置成功
  204. 其他,设置失败
  205. */
  206. u8 MPU6050_Set_LPF(u16 lpf)
  207. {
  208. u8 data= 0;
  209. if(lpf>= 188)data= 1;
  210. else if(lpf>= 98)data= 2;
  211. else if(lpf>= 42)data= 3;
  212. else if(lpf>= 20)data= 4;
  213. else if(lpf>= 10)data= 5;
  214. else data= 6;
  215. return MPU6050_Write_Byte(MPU_CFG_REG,data); //设置数字低通滤波器
  216. }
  217. /*
  218. 函数功能:设置MPU6050的采样率(假定Fs=1KHz)
  219. 函数参数:rate:4~1000(Hz)
  220. 返 回 值:0,设置成功
  221. 其他,设置失败
  222. */
  223. u8 MPU6050_Set_Rate(u16 rate)
  224. {
  225. u8 data;
  226. if(rate> 1000)rate= 1000;
  227. if(rate< 4)rate= 4;
  228. data= 1000/rate -1;
  229. data=MPU6050_Write_Byte(MPU_SAMPLE_RATE_REG,data); //设置数字低通滤波器
  230. return MPU6050_Set_LPF(rate/ 2); //自动设置LPF为采样率的一半
  231. }
  232. /*
  233. 函数功能:得到温度值
  234. 返 回 值:返回值:温度值(扩大了100倍)
  235. */
  236. short MPU6050_Get_Temperature(void)
  237. {
  238. u8 buf[ 2];
  239. short raw;
  240. float temp;
  241. MPU6050_Read_Len(MPU6050_ADDR,MPU_TEMP_OUTH_REG, 2,buf);
  242. raw=((u16)buf[ 0]<< 8)|buf[ 1];
  243. temp= 36.53+(( double)raw)/ 340;
  244. return temp* 100;;
  245. }
  246. /*
  247. 函数功能:得到陀螺仪值(原始值)
  248. 函数参数:gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
  249. 返 回 值:0,成功,其他,错误代码
  250. */
  251. u8 MPU6050_Get_Gyroscope(short *gx,short *gy,short *gz)
  252. {
  253. u8 buf[ 6],res;
  254. res=MPU6050_Read_Len(MPU6050_ADDR,MPU_GYRO_XOUTH_REG, 6,buf);
  255. if(res== 0)
  256. {
  257. *gx=((u16)buf[ 0]<< 8)|buf[ 1];
  258. *gy=((u16)buf[ 2]<< 8)|buf[ 3];
  259. *gz=((u16)buf[ 4]<< 8)|buf[ 5];
  260. }
  261. return res;;
  262. }
  263. /*
  264. 函数功能:得到加速度值(原始值)
  265. 函数参数:gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
  266. 返 回 值:0,成功,其他,错误代码
  267. */
  268. u8 MPU6050_Get_Accelerometer(short *ax,short *ay,short *az)
  269. {
  270. u8 buf[ 6],res;
  271. res=MPU6050_Read_Len(MPU6050_ADDR,MPU_ACCEL_XOUTH_REG, 6,buf);
  272. if(res== 0)
  273. {
  274. *ax=((u16)buf[ 0]<< 8)|buf[ 1];
  275. *ay=((u16)buf[ 2]<< 8)|buf[ 3];
  276. *az=((u16)buf[ 4]<< 8)|buf[ 5];
  277. }
  278. return res;;
  279. }
  280. /*
  281. 函数功能:IIC连续写
  282. 函数参数:
  283. addr:器件地址
  284. reg:寄存器地址
  285. len:写入长度
  286. buf:数据区
  287. 返 回 值:0,成功,其他,错误代码
  288. */
  289. u8 MPU6050_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
  290. {
  291. u8 i;
  292. MPU6050_IIC_Start();
  293. MPU6050_IIC_Send_Byte((addr<< 1)| 0); //发送器件地址+写命令
  294. if(MPU6050_IIC_Wait_Ack()) //等待应答
  295. {
  296. MPU6050_IIC_Stop();
  297. return 1;
  298. }
  299. MPU6050_IIC_Send_Byte(reg); //写寄存器地址
  300. MPU6050_IIC_Wait_Ack(); //等待应答
  301. for(i= 0;i<len;i++)
  302. {
  303. MPU6050_IIC_Send_Byte(buf[i]); //发送数据
  304. if(MPU6050_IIC_Wait_Ack()) //等待ACK
  305. {
  306. MPU6050_IIC_Stop();
  307. return 1;
  308. }
  309. }
  310. MPU6050_IIC_Stop();
  311. return 0;
  312. }
  313. /*
  314. 函数功能:IIC连续写
  315. 函数参数:
  316. IIC连续读
  317. addr:器件地址
  318. reg:要读取的寄存器地址
  319. len:要读取的长度
  320. buf:读取到的数据存储区
  321. 返 回 值:0,成功,其他,错误代码
  322. */
  323. u8 MPU6050_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
  324. {
  325. MPU6050_IIC_Start();
  326. MPU6050_IIC_Send_Byte((addr<< 1)| 0); //发送器件地址+写命令
  327. if(MPU6050_IIC_Wait_Ack()) //等待应答
  328. {
  329. MPU6050_IIC_Stop();
  330. return 1;
  331. }
  332. MPU6050_IIC_Send_Byte(reg); //写寄存器地址
  333. MPU6050_IIC_Wait_Ack(); //等待应答
  334. MPU6050_IIC_Start();
  335. MPU6050_IIC_Send_Byte((addr<< 1)| 1); //发送器件地址+读命令
  336. MPU6050_IIC_Wait_Ack(); //等待应答
  337. while(len)
  338. {
  339. if(len== 1)*buf=MPU6050_IIC_Read_Byte( 0); //读数据,发送nACK
  340. else *buf=MPU6050_IIC_Read_Byte( 1); //读数据,发送ACK
  341. len--;
  342. buf++;
  343. }
  344. MPU6050_IIC_Stop(); //产生一个停止条件
  345. return 0;
  346. }
  347. /*
  348. 函数功能:IIC写一个字节
  349. 函数参数:
  350. reg:寄存器地址
  351. data:数据
  352. 返 回 值:0,成功,其他,错误代码
  353. */
  354. u8 MPU6050_Write_Byte(u8 reg,u8 data)
  355. {
  356. MPU6050_IIC_Start();
  357. MPU6050_IIC_Send_Byte((MPU6050_ADDR<< 1)| 0); //发送器件地址+写命令
  358. if(MPU6050_IIC_Wait_Ack()) //等待应答
  359. {
  360. MPU6050_IIC_Stop();
  361. return 1;
  362. }
  363. MPU6050_IIC_Send_Byte(reg); //写寄存器地址
  364. MPU6050_IIC_Wait_Ack(); //等待应答
  365. MPU6050_IIC_Send_Byte(data); //发送数据
  366. if(MPU6050_IIC_Wait_Ack()) //等待ACK
  367. {
  368. MPU6050_IIC_Stop();
  369. return 1;
  370. }
  371. MPU6050_IIC_Stop();
  372. return 0;
  373. }
  374. /*
  375. 函数功能:IIC读一个字节
  376. 函数参数:
  377. reg:寄存器地址
  378. data:数据
  379. 返 回 值:返回值:读到的数据
  380. */
  381. u8 MPU6050_Read_Byte(u8 reg)
  382. {
  383. u8 res;
  384. MPU6050_IIC_Start();
  385. MPU6050_IIC_Send_Byte((MPU6050_ADDR<< 1)| 0); //发送器件地址+写命令
  386. MPU6050_IIC_Wait_Ack(); //等待应答
  387. MPU6050_IIC_Send_Byte(reg); //写寄存器地址
  388. MPU6050_IIC_Wait_Ack(); //等待应答
  389. MPU6050_IIC_Start();
  390. MPU6050_IIC_Send_Byte((MPU6050_ADDR<< 1)| 1); //发送器件地址+读命令
  391. MPU6050_IIC_Wait_Ack(); //等待应答
  392. res=MPU6050_IIC_Read_Byte( 0); //读取数据,发送nACK
  393. MPU6050_IIC_Stop(); //产生一个停止条件
  394. return res;
  395. }

3.3 mpu6050.h


  
  1. #ifndef __MPU6050_H
  2. #define __MPU6050_H
  3. #include "stm32f10x.h"
  4. #define MPU_SELF_TESTX_REG 0X0D //自检寄存器X
  5. #define MPU_SELF_TESTY_REG 0X0E //自检寄存器Y
  6. #define MPU_SELF_TESTZ_REG 0X0F //自检寄存器Z
  7. #define MPU_SELF_TESTA_REG 0X10 //自检寄存器A
  8. #define MPU_SAMPLE_RATE_REG 0X19 //采样频率分频器
  9. #define MPU_CFG_REG 0X1A //配置寄存器
  10. #define MPU_GYRO_CFG_REG 0X1B //陀螺仪配置寄存器
  11. #define MPU_ACCEL_CFG_REG 0X1C //加速度计配置寄存器
  12. #define MPU_MOTION_DET_REG 0X1F //运动检测阀值设置寄存器
  13. #define MPU_FIFO_EN_REG 0X23 //FIFO使能寄存器
  14. #define MPU_I2CMST_CTRL_REG 0X24 //IIC主机控制寄存器
  15. #define MPU_I2CSLV0_ADDR_REG 0X25 //IIC从机0器件地址寄存器
  16. #define MPU_I2CSLV0_REG 0X26 //IIC从机0数据地址寄存器
  17. #define MPU_I2CSLV0_CTRL_REG 0X27 //IIC从机0控制寄存器
  18. #define MPU_I2CSLV1_ADDR_REG 0X28 //IIC从机1器件地址寄存器
  19. #define MPU_I2CSLV1_REG 0X29 //IIC从机1数据地址寄存器
  20. #define MPU_I2CSLV1_CTRL_REG 0X2A //IIC从机1控制寄存器
  21. #define MPU_I2CSLV2_ADDR_REG 0X2B //IIC从机2器件地址寄存器
  22. #define MPU_I2CSLV2_REG 0X2C //IIC从机2数据地址寄存器
  23. #define MPU_I2CSLV2_CTRL_REG 0X2D //IIC从机2控制寄存器
  24. #define MPU_I2CSLV3_ADDR_REG 0X2E //IIC从机3器件地址寄存器
  25. #define MPU_I2CSLV3_REG 0X2F //IIC从机3数据地址寄存器
  26. #define MPU_I2CSLV3_CTRL_REG 0X30 //IIC从机3控制寄存器
  27. #define MPU_I2CSLV4_ADDR_REG 0X31 //IIC从机4器件地址寄存器
  28. #define MPU_I2CSLV4_REG 0X32 //IIC从机4数据地址寄存器
  29. #define MPU_I2CSLV4_DO_REG 0X33 //IIC从机4写数据寄存器
  30. #define MPU_I2CSLV4_CTRL_REG 0X34 //IIC从机4控制寄存器
  31. #define MPU_I2CSLV4_DI_REG 0X35 //IIC从机4读数据寄存器
  32. #define MPU_I2CMST_STA_REG 0X36 //IIC主机状态寄存器
  33. #define MPU_INTBP_CFG_REG 0X37 //中断/旁路设置寄存器
  34. #define MPU_INT_EN_REG 0X38 //中断使能寄存器
  35. #define MPU_INT_STA_REG 0X3A //中断状态寄存器
  36. #define MPU_ACCEL_XOUTH_REG 0X3B //加速度值,X轴高8位寄存器
  37. #define MPU_ACCEL_XOUTL_REG 0X3C //加速度值,X轴低8位寄存器
  38. #define MPU_ACCEL_YOUTH_REG 0X3D //加速度值,Y轴高8位寄存器
  39. #define MPU_ACCEL_YOUTL_REG 0X3E //加速度值,Y轴低8位寄存器
  40. #define MPU_ACCEL_ZOUTH_REG 0X3F //加速度值,Z轴高8位寄存器
  41. #define MPU_ACCEL_ZOUTL_REG 0X40 //加速度值,Z轴低8位寄存器
  42. #define MPU_TEMP_OUTH_REG 0X41 //温度值高八位寄存器
  43. #define MPU_TEMP_OUTL_REG 0X42 //温度值低8位寄存器
  44. #define MPU_GYRO_XOUTH_REG 0X43 //陀螺仪值,X轴高8位寄存器
  45. #define MPU_GYRO_XOUTL_REG 0X44 //陀螺仪值,X轴低8位寄存器
  46. #define MPU_GYRO_YOUTH_REG 0X45 //陀螺仪值,Y轴高8位寄存器
  47. #define MPU_GYRO_YOUTL_REG 0X46 //陀螺仪值,Y轴低8位寄存器
  48. #define MPU_GYRO_ZOUTH_REG 0X47 //陀螺仪值,Z轴高8位寄存器
  49. #define MPU_GYRO_ZOUTL_REG 0X48 //陀螺仪值,Z轴低8位寄存器
  50. #define MPU_I2CSLV0_DO_REG 0X63 //IIC从机0数据寄存器
  51. #define MPU_I2CSLV1_DO_REG 0X64 //IIC从机1数据寄存器
  52. #define MPU_I2CSLV2_DO_REG 0X65 //IIC从机2数据寄存器
  53. #define MPU_I2CSLV3_DO_REG 0X66 //IIC从机3数据寄存器
  54. #define MPU_I2CMST_DELAY_REG 0X67 //IIC主机延时管理寄存器
  55. #define MPU_SIGPATH_RST_REG 0X68 //信号通道复位寄存器
  56. #define MPU_MDETECT_CTRL_REG 0X69 //运动检测控制寄存器
  57. #define MPU_USER_CTRL_REG 0X6A //用户控制寄存器
  58. #define MPU_PWR_MGMT1_REG 0X6B //电源管理寄存器1
  59. #define MPU_PWR_MGMT2_REG 0X6C //电源管理寄存器2
  60. #define MPU_FIFO_CNTH_REG 0X72 //FIFO计数寄存器高八位
  61. #define MPU_FIFO_CNTL_REG 0X73 //FIFO计数寄存器低八位
  62. #define MPU_FIFO_RW_REG 0X74 //FIFO读写寄存器
  63. #define MPU_DEVICE_ID_REG 0X75 //器件ID寄存器
  64. //重力加速度值,单位:9.5 m/s2
  65. typedef struct
  66. {
  67. float accX;
  68. float accY;
  69. float accZ;
  70. }accValue_t;
  71. //因为模块AD0默认接GND,所以转为读写地址后,为0XD1和0XD0(如果接VCC,则为0XD3和0XD2) 从AD0接地机地址为:0X68
  72. u8 MPU6050_Init(void); //初始化MPU6050
  73. u8 MPU6050_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf); //IIC连续写
  74. u8 MPU6050_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf); //IIC连续读
  75. u8 MPU6050_Write_Byte(u8 reg,u8 data); //IIC写一个字节
  76. u8 MPU6050_Read_Byte(u8 reg); //IIC读一个字节
  77. u8 MPU6050_Set_Gyro_Fsr(u8 fsr);
  78. u8 MPU6050_Set_Accel_Fsr(u8 fsr);
  79. u8 MPU6050_Set_LPF(u16 lpf);
  80. u8 MPU6050_Set_Rate(u16 rate);
  81. u8 MPU6050_Set_Fifo(u8 sens);
  82. short MPU6050_Get_Temperature(void);
  83. u8 MPU6050_Get_Gyroscope(short *gx,short *gy,short *gz);
  84. u8 MPU6050_Get_Accelerometer(short *ax,short *ay,short *az);
  85. //如果AD0脚(9脚)接地,IIC地址为0X68(不包含最低位).
  86. //如果接V3.3,则IIC地址为0X69(不包含最低位).
  87. #define MPU6050_ADDR 0X68
  88. //IO方向设置
  89. #define MPU6050_SDA_IN() {GPIOB->CRL&=0XF0FFFFFF;GPIOB->CRL|=8<<24;}
  90. #define MPU6050_SDA_OUT() {GPIOB->CRL&=0XF0FFFFFF;GPIOB->CRL|=3<<24;}
  91. //IO操作函数
  92. #define MPU6050_IIC_SCL PBout(7) //SCL
  93. #define MPU6050_IIC_SDA PBout(6) //SDA
  94. #define MPU6050_READ_SDA PBin(6) //输入SDA
  95. //IIC所有操作函数
  96. void MPU6050_IIC_Delay(void); //MPU IIC延时函数
  97. void MPU6050_IIC_Init(void); //初始化IIC的IO口
  98. void MPU6050_IIC_Start(void); //发送IIC开始信号
  99. void MPU6050_IIC_Stop(void); //发送IIC停止信号
  100. void MPU6050_IIC_Send_Byte(u8 txd); //IIC发送一个字节
  101. u8 MPU6050_IIC_Read_Byte(unsigned char ack); //IIC读取一个字节
  102. u8 MPU6050_IIC_Wait_Ack(void); //IIC等待ACK信号
  103. void MPU6050_IIC_Ack(void); //IIC发送ACK信号
  104. void MPU6050_IIC_NAck(void); //IIC不发送ACK信号
  105. #endif

 


转载:https://blog.csdn.net/xiaolong1126626497/article/details/116746945
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场