基于STM32单片机步数测量系统
1.1设计要求
1.设计所需设备
1.3 设计原理
1.4核心代码
1.5结果展示
1.6资源链接
1.7硬件电路图
1.1设计要求
基于设计STM32步数测量系统要求数据传输到云和OLED屏幕显示。
1.设计所需设备
STM32F407 MPU6050,ESP8266,OLED
1.3设计原理
电子计步器需要正确MPU6050陀螺仪的数据处理需要一个性能良好的微处理器作为主芯片。需要人机交互OLED屏幕,按钮切换用户界面和ESP8266—01S WIFI将模块数据传输到云然后手机APP显示。
MPU6050简介 MPU6050 是 InvenSense 该公司推出了世界上第一家集成公司 6 与多组件方相比,轴运动处理组件 本案消除了陀螺仪与加速器组合时轴间差的问题,减少了安装空间。 MPU6050 内部整合了 3 轴陀螺仪和 3 轴加速度传感器,含有第二个 IIC 接口,可用 连接外部磁力传感器,并使用自己的数字运动处理器(DMP: Digital Motion Processor)硬件 加速发动机,通过主 IIC 将完整的接口输出到应用端 9 轴融合计算数据。
计步原理 人体在行走过程中,必须伴随着手臂的摆动,手臂的摆动会导致加速度的变化,加速度的变化会导致MPU通过对6050传感器数据的变化MPU6050加速度数据寄存器,偏向角数据寄存器读取数据,进一步过滤和处理数据后可获得步数 系统软件总体设计 第二章和第三章讲述了一些总体方案和电路设计,重点关注硬件电路,包括其选择和电路连接。软件和硬件在嵌入式开发中同样重要,所以本章关注软件的设计。本设计的软件主要涉及OLED的初始化,MPU6050的初始化,ESP8266WIFI模块和系统的初始化。 巴发云简介 由于物联网设备的特殊性,为了确保数据在低带宽、不可靠的网络中传输有效数据,云协议的设计原则是简化,不添加可有可无的功能,努力保持云平台的轻量级特性,因此,结合当前的设计趋势,构思了一套新的平台产品交互语言。巴发云是为轻量级物联网开发的云平台,支持发布订阅模式、遗嘱机制和支持TCP长链接,实现全平台兼容。云平台支持TCP心跳长链接,MQTT3.1和MQTT3.1.1协议,支持HTTP API目前还支持天猫精灵、小爱同学、微信小程序控制。 创建主题后,云将自动分配密钥
1.3核心代码
main.c
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "oled.h" #include "oled_myiic.h" #include "myiic.h" #include "inv_mpu.h" #include "inv_mpu_dmp_motion_driver.h" #include "mpu6050.h" #include <string.h> #include "esp8266.h" #include "timer.h" typedef enum {
no=0,yes=!no}bool;//定义一个bool类型 extern bool key_flag; bool key_flag=no; float weight=60,weight_index=0.8214;//假设体重为60kG,运动指数
void OLED1_showchinese(void);//第一页显示函数
void OLED_2showchinese(void);//第二页显示
int main(void)
{
u8 key_number;//获取按键值
unsigned long walk_count ,walk_time;//步行步数,步行时间。
delay_init(168);
LED_Init();
usart3_init(115200); //初始化串口1波特率为115200
IIC_Init(); //MPU6050的IIC初始化
IIC_Init1(); //OLED的IIC初始化
OLED_Init(); //OLED初始化
MPU_Init(); //初始化MPU6050
mpu_dmp_init(); //初始化6050的DMP库
OLED_init_showchinese();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
TIM3_Int_Init(60000-1,8400-1); //定时器时钟84M,分频系数8400,所以84M/8400=10Khz的计数频率,计数400000次为40000ms
ESP8266_Set_ok(USART3,"AT+RST");
delay_ms(1000);
ESP8266_Set_ok(USART3,"AT+CWMODE=3");
delay_ms(1000);
ESP8266_Set_ok(USART3,"AT+CWJAP=\""Ssid"\",\""PassWord"\"");
delay_ms(1000);
connect_bemfa();//连接巴发云
while(1)
{
key_number=KEY_Scan(1);//读取按键返回值
if(key_number==1)//切换页面函数
{
key_flag=!key_flag;
OLED_CLS();
}
if(key_flag==no)
{
OLED1_showchinese();//第一页显示函数
//connect_fasong(char_step,char_sporttime,char_caloreis,"50" );//传输
LED2=!LED2;
}
else
{
OLED_2showchinese();
dmp_get_pedometer_step_count(&walk_count);
dmp_get_pedometer_walk_time(&walk_time);
sprintf(char_step,"%lu",walk_count );//unsigend long 型变为无符号整型
sprintf(char_caloreis,"%.2f",walk_count*30*weight*weight_index/100000);//计算消耗的能量
OLED_P8x16Str(56,0,char_step );//显示计步步数
OLED_P8x16Str(48,2,char_caloreis );//显示消耗能量
sprintf(char_sporttime,"%lu",walk_time/1000 );
OLED_P8x16Str(70,4,char_sporttime);//显示运动时间
OLED_P8x16Str(84,6,"50"); //显示目标步
delay_ms(10);
if(jishi==2)
connect_fasong(char_step,char_sporttime,char_caloreis,"50" );//传输
}
}
}
ESP8266.c
#include <stdio.h> #include "esp8266.h" #include "string.h" #include "sys.h" unsigned char Receive_shuju[150]; unsigned char Okword=0; char char_step[4],char_caloreis[6],char_sporttime[4]; void usart3_init(u32 bound) { NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; USART_DeInit(USART3); //复位串口3 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //使能GPIOB时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//使能USART3时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_10; //GPIOB11和GPIOB10初始化 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化GPIOB11,和GPIOB10 GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_USART3); //GPIOB11复用为USART3 GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_USART3); //GPIOB10复用为USART3 USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART3, &USART_InitStructure); //初始化串口3 USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断 USART_Cmd(USART3, ENABLE); //使能串口 NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02 ;//抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 } //发送字节 void USART_SendByte(USART_TypeDef* USARTx, uint16_t Data) { USART_SendData(USARTx,Data); while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); } /******************************************************************** 名称:WIFI模块设置函数 作用: 启动模块,以便可以实现无线接入和控制,并等待OK回复 ********************************************************************/ void ESP8266_Set_ok(USART_TypeDef* USARTx, char *str) { uint16_t i = 0; do{ USART_SendByte(USARTx, *(str + i)); i++; }while(*(str + i) !='\0'); delay_us(5); USART_SendByte( USART3,'\r'); delay_us(5); USART_SendByte( USART3,'\n'); while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); while(!Okword); Okword=0; } 没有等待OK void ESP8266_Set(USART_TypeDef* USARTx, char *str) { uint16_t i = 0; do{ USART_SendByte(USARTx, *(str + i)); i++; }while(*(str + i) !='\0'); delay_us(5); USART_SendByte( USART3,'\r'); delay_us(5); USART_SendByte( USART3,'\n'); while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); } /******************************************************************** 名称:WIFI模块设置函数 作用: 启动模块,没有回车换行 ********************************************************************/ void ESP8266_Set_Only(USART_TypeDef* USARTx, char *str) { uint16_t i = 0; do{ USART_SendByte(USARTx, *(str + i)); i++; }while(*(str + i) !='\0'); while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET); } void USART3_IRQHandler() { static int im=0; //当 RDR
移位寄存器的内容已传输到 USART_DR 寄存器时,该位由硬件置 1 if (USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET)//获取中断标志位,为1 { Receive_shuju[im] = USART_ReceiveData( USART3 ); im++; USART_ClearITPendingBit(USART3,USART_IT_RXNE); //清除中断标志位 if((Receive_shuju[im-2]=='O')&&(Receive_shuju[im-1]=='K'))//接收到OK之后 Okword为1 { im=0; Okword=1; } } if( im>140) im=0; } /******************************************************************** 名称:心跳函数 作用:发送心跳。如果一分钟不发送心跳,服务器就会认为设备掉线,故建议30s发送一次心跳 在中断1中调用,和发送数据函数,留一个就行,发送数据也相当于心跳 ********************************************************************/ void Ping(void) { ESP8266_Set(USART3,"cmd=0&msg=ping"); //发送心跳 } void connect_topic(void) { //发送订阅指令,原格式为:cmd=1&uid=***UID***&topic=***Topic*** ESP8266_Set_Only(USART3,"cmd=1&uid="); ESP8266_Set_Only(USART3,Uid); ESP8266_Set_Only(USART3,"&topic="); //************ 需要修改以下部分 ************ ESP8266_Set_Only(USART3,Topic); delay_us(5); USART_SendByte(USART3,'\r');//回车 delay_us(5); USART_SendByte(USART3,'\n'); //换行 } void connect_bemfa(void) { ESP8266_Set(USART3,"AT+CIPMODE=1"); //开启透明传输模式 delay_ms(1000); ESP8266_Set(USART3,"AT+CIPSTART=\"TCP\",\"bemfa.com\",8344"); // 连接服务器和端口 delay_ms(1000); ESP8266_Set(USART3,"AT+CIPSEND"); //进入透传模式,下面发的都会无条件传输 delay_ms(1000); connect_topic(); //连接订阅主题 } void connect_fasong(char data1[],char data2[],char data3[],char data4[] ) { //发送订阅指令,原格式为:cmd=1&uid=***UID***&topic=***Topic*** ESP8266_Set_Only(USART3,"cmd=2&uid="); ESP8266_Set_Only(USART3,Uid); ESP8266_Set_Only(USART3,"&topic="); ESP8266_Set_Only(USART3,Topic); ESP8266_Set_Only(USART3,"&msg="); ESP8266_Set_Only(USART3,"#"); ESP8266_Set_Only(USART3,data1); ESP8266_Set_Only(USART3,"#"); ESP8266_Set_Only(USART3,data2); ESP8266_Set_Only(USART3,"#"); ESP8266_Set_Only(USART3,data3); ESP8266_Set_Only(USART3,"#"); ESP8266_Set_Only(USART3,data4); ESP8266_Set_Only(USART3,"#"); delay_us(5); USART_SendByte(USART3,'\r');//回车 delay_us(5); USART_SendByte(USART3,'\n'); //换行 }
ESP8266.h
#ifndef _ESP8266_H
#define _ESP8266_H
#include "delay.h"
#include "sys.h"
#define Ssid "mawei" //WIFI名称,,修改为自己路由器的WIFI名称,好像不支持中文
#define PassWord "12345678" //WIFI密码,修改为自己路由器的
#define Uid "bfcf65510b5a4895a30b449eaaeb4b34" //巴法云UID密钥,控制台获取
#define Topic "MPU6050" //巴法云控制台创建,名称自定义,app订阅主题要和这个推送主题一致
extern unsigned char Receive_shuju[150];
extern unsigned char Okword;
extern char char_step[4],char_caloreis[6],char_sporttime[4];//步数,卡路里,运动时间
void usart3_init(u32 bound);
void POST(char data1[] ,char data2[],char data3[],char data4[]);//POST数据函数
void ESP8266_Set_ok(USART_TypeDef* USARTx, char *str);
void USART_SendByte(USART_TypeDef* USARTx, uint16_t Data);
void ESP8266_Set_Only(USART_TypeDef* USARTx, char *str);
void ESP8266_Set(USART_TypeDef* USARTx, char *str);
void Ping(void);
void connect_topic(void);
void connect_bemfa(void);
void connect_fasong(char data1[],char data2[],char data3[],char data4[] );
#endif
1.4结果展示
1.5资源链接
链接:https://pan.baidu.com/s/1-gpK4esXYDvpuTZc0HVPeQ 提取码:a520