一、环境介绍
mcu: stm32f103c8t6
姿态传感器: mpu6050
oled显示屏: 0.96寸spi接口oled
温度传感器: ds18b20
编译软件: keil5
二、功能介绍 时钟可以根据mpu6050测量的姿态自动调整显示画面方向,也就是倒着拿、横着拿、反着拿都可以让时间显示是正对着自己的,时间支持自己调整,支持串口校准。可以按键切换页面查看环境温度显示。
支持串口时间校准:
三、核心代码
3.1 main.c#include stm32f10x.h#include beep.h#include delay.h#include led.h#include key.h#include sys.h#include usart.h#include #include #include exti.h#include timer.h#include rtc.h#include wdg.h#include ds18b20.h#include oled.h#include fontdata.h#include adc.h#include functionconfig.h#include mpu6050.h#include inv_mpu.h#include inv_mpu_dmp_motion_driver.h /*函数功能: 绘制时钟表盘框架*/void drawtimeframe(void){ u8 i; oled_circle(32,32,31);//画外圆 oled_circle(32,32,1); //画中心圆 //画刻度 for(i=0;i> 4; //分离出温度值整数部分 ds18b20_dect = ds18b20_temp & 0xf; //分离出温度值小数部分 sprintf((char*)ds18b20_temp_info,%d.%d,ds18b20_intt,ds18b20_dect); //保存ds18b20温度信息,发送给上位机 oled_showstring(34,0,16,ds18b20); if(ds18b20_temp==0xff) { oled_showstring(0,30,16, ); //清除一行的显示 //显示温度错误信息 oled_showstring(0,30,16,ds18b20 error!); } else { sprintf(ds18b20_buff,%sc ,ds18b20_temp_info); //显示温度 oled_showstring(40,30,16,ds18b20_buff); }}int main(void){ u8 stat; u8 key_val; u32 timecnt=0; u16 temp_data; //温度数据 short aacx,aacy,aacz; //加速度传感器原始数据 short gyrox,gyroy,gyroz; //陀螺仪原始数据 short temp; float pitch,roll,yaw; //欧拉角 u8 page_cnt=0; //显示的页面 u8 display_state1=0; u8 display_state2=0; beep_init(); //初始化蜂鸣器 led_init(); //初始化led key_init(); //按键初始化 ds18b20_init(); //ds18b20 usartx_init(usart1,72,115200);//串口1的初始化 timerx_init(tim1,72,20000); //辅助串口1接收。20ms为一帧数据。 rtc_init(); //rtc初始化 oled_init(0xc8,0xa1); //oled显示屏初始化--正常显示 //oled_init(0xc0,0xa0); //oled显示屏初始化--翻转显示 while(mpu6050_init()) //初始化mpu6050 { printf(mpu6050陀螺仪初始化失败!\r\n); delayms(500); } // //注意:陀螺仪初始化的时候,必须正常摆放才可以初始化成// while(mpu_dmp_init())// {// printf(mpu6050陀螺仪设置dmp失败!\r\n);// delayms(1000);// } oled_clear(0x00); //清屏 drawtimeframe(); //画时钟框架 while(1) { key_val=key_getvalue(); if(key_val) { page_cnt=!page_cnt; //时钟页面 if(page_cnt==0) { //清屏 oled_clear(0); drawtimeframe(); //画时钟框架 rtc->crh|=1
4,temp_data&0xf); // stat=mpu_dmp_get_data(&pitch,&roll,&yaw);// temp=mpu6050_get_temperature(); //得到温度值 //mpu6050_get_gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺仪原始数据 mpu6050_get_accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据 //printf(温度数据:%d\r\n,temp); // printf(陀螺仪原始数据 :x=%d y=%d z=%d\r\n,gyrox,gyroy,gyroz); printf(加速度传感器数据:x=%d y=%d z=%d\r\n,aacx,aacy,aacz);// printf(欧垃角:横滚角=%d 俯仰角=%d 航向角=%d\r\n,(int)(roll*100),(int)(pitch*100),(int)(yaw*10));// //正着显示 if(aacz>=15000) { printf(正着显示\n); if(display_state1!=1) { display_state2=0; display_state1=1; oled_init(0xc8,0xa1); //oled显示屏初始化--正常显示 } } //翻转显示 else if(display_state2!=1) { printf(反着显示\n); display_state1=0; display_state2=1; oled_init(0xc0,0xa0); //oled显示屏初始化--翻转显示 } } if(page_cnt==1) //温度显示页面 { ds18b20_showpagetable(temp_data); } } } 3.2 mpu6050.c#include mpu6050.h#include sys.h#include delay.h#include /*--------------------------------------------------------------------iic协议底层模拟时序--------------------------------------------------------------------------------*//*硬件接线:1 vcc 3.3v/5v 电源输入 --->接3.3v2 gnd 地线 --->接gnd3 iic_sda iic 通信数据线 -->pb64 iic_scl iic 通信时钟线 -->pb75 mpu_int 中断输出引脚 ---->未接6 mpu_ad0 iic 从机地址设置引脚-->未接 ad0引脚说明:id=0x68(悬空/接 gnd) id=0x69(接 vcc)*//*函数功能:mpu iic 延时函数*/void mpu6050_iic_delay(void){ delayus(2);}/*函数功能: 初始化iic*/void mpu6050_iic_init(void){ rcc->apb2enr|=1crl|=0x33000000; gpiob->odr|=37; txd<<=1; mpu6050_iic_scl=1; mpu6050_iic_delay(); mpu6050_iic_scl=0; mpu6050_iic_delay(); } }/*函数功能:读1个字节,ack=1时,发送ack,ack=0,发送nack */ u8 mpu6050_iic_read_byte(unsigned char ack){ unsigned char i,receive=0; mpu6050_sda_in();//sda设置为输入 for(i=0;i<8;i++ ) { mpu6050_iic_scl=0; mpu6050_iic_delay(); mpu6050_iic_scl=1; receive<<=1; if(mpu6050_read_sda)receive++; mpu6050_iic_delay(); } if(!ack) mpu6050_iic_nack();//发送nack else mpu6050_iic_ack(); //发送ack return receive;}/*--------------------------------------------------------------------mpu6050底层驱动代码--------------------------------------------------------------------------------*//*函数功能:初始化mpu6050返 回 值:0,成功 其他,错误代码*/u8 mpu6050_init(void){ u8 res; mpu6050_iic_init();//初始化iic总线 mpu6050_write_byte(mpu_pwr_mgmt1_reg,0x80); //复位mpu6050 delayms(100); mpu6050_write_byte(mpu_pwr_mgmt1_reg,0x00); //唤醒mpu6050 mpu6050_set_gyro_fsr(3); //陀螺仪传感器,±2000dps mpu6050_set_accel_fsr(0); //加速度传感器,±2g mpu6050_set_rate(50); //设置采样率50hz mpu6050_write_byte(mpu_int_en_reg,0x00); //关闭所有中断 mpu6050_write_byte(mpu_user_ctrl_reg,0x00); //i2c主模式关闭 mpu6050_write_byte(mpu_fifo_en_reg,0x00); //关闭fifo mpu6050_write_byte(mpu_intbp_cfg_reg,0x80); //int引脚低电平有效 res=mpu6050_read_byte(mpu_device_id_reg); if(res==mpu6050_addr)//器件id正确 { mpu6050_write_byte(mpu_pwr_mgmt1_reg,0x01); //设置clksel,pll x轴为参考 mpu6050_write_byte(mpu_pwr_mgmt2_reg,0x00); //加速度与陀螺仪都工作 mpu6050_set_rate(50); //设置采样率为50hz }else return 1; return 0;}/*设置mpu6050陀螺仪传感器满量程范围fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps返回值:0,设置成功 其他,设置失败 */u8 mpu6050_set_gyro_fsr(u8 fsr){ return mpu6050_write_byte(mpu_gyro_cfg_reg,fsr<<3);//设置陀螺仪满量程范围 }/*函数功能:设置mpu6050加速度传感器满量程范围函数功能:fsr:0,±2g;1,±4g;2,±8g;3,±16g返 回 值:0,设置成功 其他,设置失败 */u8 mpu6050_set_accel_fsr(u8 fsr){ return mpu6050_write_byte(mpu_accel_cfg_reg,fsr=98)data=2; else if(lpf>=42)data=3; else if(lpf>=20)data=4; else if(lpf>=10)data=5; else data=6; return mpu6050_write_byte(mpu_cfg_reg,data);//设置数字低通滤波器 }/*函数功能:设置mpu6050的采样率(假定fs=1khz)函数参数:rate:4~1000(hz)返 回 值:0,设置成功 其他,设置失败 */u8 mpu6050_set_rate(u16 rate){ u8 data; if(rate>1000)rate=1000; if(rate<4)rate=4; data=1000/rate-1; data=mpu6050_write_byte(mpu_sample_rate_reg,data); //设置数字低通滤波器 return mpu6050_set_lpf(rate/2); //自动设置lpf为采样率的一半}/*函数功能:得到温度值返 回 值:返回值:温度值(扩大了100倍)*/short mpu6050_get_temperature(void){ u8 buf[2]; short raw; float temp; mpu6050_read_len(mpu6050_addr,mpu_temp_outh_reg,2,buf); raw=((u16)buf[0]<<8)|buf[1]; temp=36.53+((double)raw)/340; return temp*100;;}/*函数功能:得到陀螺仪值(原始值)函数参数:gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)返 回 值:0,成功,其他,错误代码*/u8 mpu6050_get_gyroscope(short *gx,short *gy,short *gz){ u8 buf[6],res; res=mpu6050_read_len(mpu6050_addr,mpu_gyro_xouth_reg,6,buf); if(res==0) { *gx=((u16)buf[0]<<8)|buf[1]; *gy=((u16)buf[2]<<8)|buf[3]; *gz=((u16)buf[4]<<8)|buf[5]; } return res;;}/*函数功能:得到加速度值(原始值)函数参数:gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)返 回 值:0,成功,其他,错误代码*/u8 mpu6050_get_accelerometer(short *ax,short *ay,short *az){ u8 buf[6],res; res=mpu6050_read_len(mpu6050_addr,mpu_accel_xouth_reg,6,buf); if(res==0) { *ax=((u16)buf[0]<<8)|buf[1]; *ay=((u16)buf[2]<<8)|buf[3]; *az=((u16)buf[4]<<8)|buf[5]; } return res;;}/*函数功能:iic连续写函数参数: addr:器件地址 reg:寄存器地址 len:写入长度 buf:数据区返 回 值:0,成功,其他,错误代码*/u8 mpu6050_write_len(u8 addr,u8 reg,u8 len,u8 *buf){ u8 i; mpu6050_iic_start(); mpu6050_iic_send_byte((addrcrl&=0xf0ffffff;gpiob->crl|=8crl|=3<<24;}//io操作函数 #define mpu6050_iic_scl pbout(7) //scl#define mpu6050_iic_sda pbout(6) //sda #define mpu6050_read_sda pbin(6) //输入sda //iic所有操作函数void mpu6050_iic_delay(void); //mpu iic延时函数void mpu6050_iic_init(void); //初始化iic的io口 void mpu6050_iic_start(void); //发送iic开始信号void mpu6050_iic_stop(void); //发送iic停止信号void mpu6050_iic_send_byte(u8 txd); //iic发送一个字节u8 mpu6050_iic_read_byte(unsigned char ack);//iic读取一个字节u8 mpu6050_iic_wait_ack(void); //iic等待ack信号void mpu6050_iic_ack(void); //iic发送ack信号void mpu6050_iic_nack(void); //iic不发送ack信号 #endif 完整项目源码下载地址: https://download.csdn.net/download/xiaolong1126626497/18657534
四输入音源自动选择器,Audio source selector
5V稳压电源中滤波电容的选取
百度视觉团队在全球最大规模目标检测竞赛,中国团队从全球450多支参赛队伍中脱颖而出
液态金属基可拉伸封装材料的出色性能
中电器材喜获美信中国区代理权,本土分销更添优势
STM32 + MPU6050设计便携式Mini桌面时钟
沃尔沃汽车和吉利汽车的合并计划已暂时搁置
基于嵌入式Linux系统的3G/4G路由器设计
什么样的电源技术和迭代速度才能始终独步于市场?ADI电源专家为你详析
2022广州太阳能光伏产业博览会
东芝正洽谈向联华电子出售两座8英寸晶圆厂
内外需求平衡 海信激光电视前瞻性布局抢占客厅C位
什么是数据通信的传输损耗
MaxWiz编程器更新支持极海半导体APM32F415/417系列
内径百分表校准步骤_内径百分表怎么用_内径百分表的使用方法
智慧工地展厅颠覆了传统宣传片的静态汇报模式
中国制造2025的目标又进一步,支持金额突破百亿元大关
日本家用美容仪哪个品牌好?拒绝烂脸与败家!
微软HoloLens即将登陆日本市场 航空业已提前体验
工程师教你如何设计出优秀LED驱动