历史上的今天
返回首页

历史上的今天

今天是:2025年10月14日(星期二)

正在发生

2022年10月14日 | STM32+MPU6050设计便携式Mini桌面时钟(自动调整时间显示方向)

2022-10-14 来源:csdn

一、环境介绍

MCU:  STM32F103C8T6


姿态传感器:  MPU6050


OLED显示屏:  0.96寸SPI接口OLED


温度传感器: DS18B20


编译软件: keil5 


二、功能介绍

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


时钟可以根据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<60;i++)

{

if(i%5==0)OLED_DrawAngleLine(32,32,6*i,31,3,1);

}

OLED_RefreshGRAM();  //刷新数据到OLED屏幕

}

 

/*

函数功能: 更新时间框架显示,在RTC中断里调用

*/

char TimeBuff[20];

void Update_FrameShow(void)

{

/*1. 绘制秒针、分针、时针*/

OLED_DrawAngleLine2(32,32,rtc_clock.sec*6-6-90,27,0);//清除之前的秒针

OLED_DrawAngleLine2(32,32,rtc_clock.sec*6-90,27,1); //画秒针

OLED_DrawAngleLine2(32,32,rtc_clock.min*6-6-90,24,0);

OLED_DrawAngleLine2(32,32,rtc_clock.min*6-90,24,1);

OLED_DrawAngleLine2(32,32,rtc_clock.hour*30-6-90,21,0);

OLED_DrawAngleLine2(32,32,rtc_clock.hour*30-90,21,1);

//绘制电子钟时间

sprintf(TimeBuff,"%d",rtc_clock.year);

OLED_ShowString(65,16*0,16,TimeBuff);  //年份字符串

OLED_ShowChineseFont(66+32,16*0,16,4); //显示年

sprintf(TimeBuff,"%d/%d",rtc_clock.mon,rtc_clock.day);

OLED_ShowString(75,16*1,16,TimeBuff); //月

if(rtc_clock.sec==0)OLED_ShowString(65,16*2,16,"        "); //清除多余的数据

sprintf(TimeBuff,"%d:%d:%d",rtc_clock.hour,rtc_clock.min,rtc_clock.sec);

OLED_ShowString(65,16*2,16,TimeBuff); //秒

//显示星期

OLED_ShowChineseFont(70,16*3,16,5); //星

OLED_ShowChineseFont(70+16,16*3,16,6); //期

OLED_ShowChineseFont(70+32,16*3,16,rtc_clock.week+7); //具体的值

}

 

 

u8 DS18B20_TEMP_Info[10];   //DS18B20温度信息

 

/*

函数功能: DS18B20温度显示页面

*/

void DS18B20_ShowPageTable(short DS18B20_temp)

{

    char DS18B20_buff[10]; //存放温度信息

    unsigned short DS18B20_intT=0,DS18B20_decT=0;   //温度值的整数和小数部分

    DS18B20_intT = DS18B20_temp >> 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陀螺仪初始化失败!rn");

            DelayMs(500);

    }

    

//    //注意:陀螺仪初始化的时候,必须正常摆放才可以初始化成

//    while(mpu_dmp_init())

//    {

//            printf("MPU6050陀螺仪设置DMP失败!rn");

//            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<<0; //开启秒中断

            }

            else if(page_cnt==1)

            {

                 //清屏

                OLED_Clear(0);

                RTC->CRH&=~(1<<0); //关闭秒中断

            }

        }

        

        if(USART1_RX_STATE)

        {

            //*20200530154322

            //通过串口1校准RTC时间

            if(USART1_RX_BUFF[0]=='*')

            {

                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;

                rtc_clock.mon=(USART1_RX_BUFF[5]-48)*10+(USART1_RX_BUFF[6]-48)*1;

                rtc_clock.day=(USART1_RX_BUFF[7]-48)*10+(USART1_RX_BUFF[8]-48)*1;

                rtc_clock.hour=(USART1_RX_BUFF[9]-48)*10+(USART1_RX_BUFF[10]-48)*1;

                rtc_clock.min=(USART1_RX_BUFF[11]-48)*10+(USART1_RX_BUFF[12]-48)*1;

                rtc_clock.sec=(USART1_RX_BUFF[13]-48)*10+(USART1_RX_BUFF[14]-48)*1;

                RTC_SetTime(rtc_clock.year,rtc_clock.mon,rtc_clock.day,rtc_clock.hour,rtc_clock.min,rtc_clock.sec);

                

                OLED_Clear(0); //OLED清屏

                DrawTimeFrame();//画时钟框架

            }

            USART1_RX_STATE=0;

            USART1_RX_CNT=0;

        }

        

        //时间记录

        DelayMs(10);

        TimeCnt++;

        if(TimeCnt>=100) //1000毫秒一次

        {

             TimeCnt=0;

             LED1=!LED1;

            

             temp_data=DS18B20_ReadTemp();

            // printf("temp_data=%d.%dn",temp_data>>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("温度数据:%drn",temp);

           // printf("陀螺仪原始数据  :x=%d y=%d z=%drn",gyrox,gyroy,gyroz);

            printf("加速度传感器数据:x=%d y=%d z=%drn",aacx,aacy,aacz);

//            printf("欧垃角:横滚角=%d 俯仰角=%d 航向角=%drn",(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显示屏初始化--正常显示 

                }

            }

            //翻转显示

推荐阅读

史海拾趣

Anderson Power公司的发展小趣事

Anderson Power是一家专注于电源连接器和配件制造的公司,以下是该公司发展的相关故事:

  1. 公司成立与初期阶段:Anderson Power成立于1953年,总部位于美国马萨诸塞州斯特林。最初,公司主要从事电源连接器的制造和销售。公司的创始人是William E. Anderson,他在创立公司之初便致力于提供高质量、可靠的连接器产品,满足不断增长的市场需求。

  2. 技术创新与产品发展:随着市场的需求不断增长,Anderson Power不断进行技术创新和产品开发,推出了一系列新型的电源连接器和配件产品。公司在连接器设计和制造方面拥有丰富的经验和专业知识,能够根据客户的需求定制各种类型的连接器产品。

  3. 客户合作与市场拓展:Anderson Power与全球各个行业的客户建立了长期稳定的合作关系。公司的客户群涵盖了汽车、航空航天、工业、能源等多个领域。通过与客户的紧密合作,Anderson Power不断拓展市场份额,提升品牌知名度,成为电源连接器领域的领先供应商之一。

  4. 全球布局与生产基地:为了更好地服务全球客户,Anderson Power在全球建立了多个生产基地和销售办事处。除了在美国的总部外,公司还在欧洲、亚洲等地区设立了生产工厂和销售办事处,以满足不同地区客户的需求。这些生产基地拥有先进的设备和技术,能够为客户提供高质量的连接器产品。

  5. 持续发展与未来展望:作为一家专注于电源连接器的公司,Anderson Power将继续致力于技术创新和产品发展。公司将不断推出适应市场需求的新产品,提升生产效率和产品质量,以满足客户不断变化的需求。同时,Anderson Power也将继续关注行业的发展趋势和技术变革,不断调整战略,保持在行业内的竞争优势。

Diconex公司的发展小趣事

随着环保意识的不断提高,电子行业的环保要求也越来越高。Diconex公司积极响应环保号召,将环保理念融入生产全过程。公司采用环保材料和工艺进行生产,降低生产过程中的污染排放。同时,公司还建立了完善的废弃物处理机制,确保废弃物得到合理处理和资源化利用。这种环保理念的实施不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实基础。

Ferroperm公司的发展小趣事

Ferroperm公司成立于XXXX年,由一群热衷于电磁材料研究的科学家和工程师共同创立。创立之初,公司便致力于电磁材料和相关产品的研发和生产。通过对市场需求的精准把握和对技术创新的持续投入,Ferroperm很快在电磁材料领域取得了初步的成功,并积累了一定的客户基础。

广州奥松公司的发展小趣事

奥松电子拥有一支近200名工程师组成的专职研发团队,并配备了超过7000㎡的研发实验室。实验室中配置了步进式投影光刻机、双面光刻机等先进设备,为公司的产品研发提供了有力的支持。这些设备不仅满足了产品研发、小试以及中试各个阶段的试验条件,也为公司的技术创新提供了坚实的基础。

迈翔科技(COILMX)公司的发展小趣事

迈翔科技(COILMX)的创始人看到了电子行业,特别是电感器市场的巨大潜力。1996年,公司正式成立,初期主要专注于SMD电感的设计、制造和销售。公司从香港起步,逐步在深圳设立工厂,引进先进的生产设备和技术,为未来的发展奠定了坚实的基础。

BREL International Components公司的发展小趣事

品质是BREL International Components公司发展的基石。公司从原材料采购到生产流程控制,再到产品检测,都严格遵循国际质量标准。BREL还建立了完善的品质管理体系,通过定期的质量检查和持续改进,确保每一件产品都达到客户的要求。正是这种对品质的执着追求,让BREL的产品在市场上赢得了良好的口碑,品牌价值不断提升。

问答坊 | AI 解惑

TI芯片选型指南

相信很多工程师都在用TI的产品 本人在此分享一下官网公布的选型指南 希望对面临选型困惑的工程师有帮助 http://focus.ti.com.cn/cn/analog/docs/selectionguides.tsp…

查看全部问答>

【藏书阁】数字信号处理课件

第00章 数字信号处理 绪论 27页 0.5M PDF格式.pdf 第01章 离散时间信号与离散时间系统基础 71页 1.7M PDF格式 .pdf 第02章 Z变换及离散系统分析 43页 1.1M PDF格式.pdf 第03章 离散傅立叶变换 65页 1.4M PDF格式.pdf 第04章 附:关于图象压缩 4 ...…

查看全部问答>

如何在WM5.0上安装sqlite?

如题:如何在WM5.0上安装sqlite?    wce上又该怎么装?…

查看全部问答>

printk奇怪问题,请高手指点!

小弟我在调试网卡驱动的时候写了下面语句:             static   long   long   count   =   0;           stati ...…

查看全部问答>

电路板打样超级便宜

最近发现一个做电路板便宜的地方  www.sz-jlc.com/o   5*5cm以内50元 10*10以内100元 到现在为止最便宜的了 分享一下哈哈…

查看全部问答>

ST10技术资料

有关ST10的技术资料介绍,请参考:http://mcu.st.com/mcu/inchtml.php?fdir=pages&fnam=st10http://mcu.st.com/mcu/modules.php?name=mcu&file=familiesdocs&FAM=17ST10的中文手册书籍(类似ST7一样)不久也会面世了!!…

查看全部问答>

CC3000 wifi模块有木有

soso姐,帮我问一下TI办事处,CC3000什么时候搞一个活动哈,我看了TI 官网的宣传片了,我想要学习一下wifi的实时性能,我看他的DEMO 的是实时性还可以呀…

查看全部问答>

纽扣电池请教

关于纽扣电池,使用万用表测试其两端电阻,发现只有几欧姆的样子,这个是正常的吗?此外,想请教一下,如果我将纽扣电池串接在5V的电压源上放电,当串联电压降低后可以认为其电流都出自纽扣电池内吗?…

查看全部问答>