基于stm32跑步路径记录

author author     2022-12-05     169

关键词:

基于STM32跑步路径记录

  随着科技不断进步,电子化设备不断进入涌入我们的日常生活。生活水平的提高,各项健身运动应运而生,然后,健身运动不能盲目进行,科学的健身方式才能有效的提升我们自身的身体素质。

      现如今各自手环手表的出现, 通过智能手环,用户可以记录日常生活中的锻炼、睡眠、部分还有饮食等实时数据,并将这些数据与手机、平等同步,起到通过数据指导健康生活的作用。

        智能手环作为可穿戴设备,其功能还是比较强大的,其开发涉及智能手环MCU数据指令到蓝牙IC的传输、蓝牙到APP的数据通信协议、APP到手机内部的通信调试逻辑实现、APP数据到云端服务器的数据库算法设计等一系列的开发。支持多种运动监控模式,可以实时监控身体的各项性能指标。

       我国智能手环产品真正大范围进入消费市场是在2012年以后,一方面是这一时期步入4G时代以后手机智能化趋势加快,与手机一样具备数据分享的智能手环的出现给智能手环的研究和应用打开了另一个世界。另一方面是更多实用性功能快速出现,手环不仅仅是用来记录身体特征的单纯工具,同时也可以满足通话、移动支付、人体识别、智能提醒功能以及分享功能,极大的扩宽了手环的应用人群。佩戴智能手环带来健康、科技、自信有品位的良好感受,成为了高科技产品的典型之一。

基于STM32跑步路径记录_GPS

  基于STM32的跑步路记录主要用于记录用户在日常身体锻炼中,可设置跑步路径,跑步路线规划,在50~80m前提醒拐弯,蜂鸣器报警提示;记录跑步路径,显示当前位置,通过按键设置跑步距离。

1.模块选型

2.1 主控MCU:STM32F103C8最小系统板

  STM32最小系统板:STM32系统板

基于STM32跑步路径记录_运动记录_02

2.2 OLED显示屏:0.96寸SPI/IIC接口

  显示屏幕:OLED屏幕

基于STM32跑步路径记录_运动记录_03

2.3 GPS定位模块

GPS定位:GPS模块 北斗模块 双模定位 ATGM336H

基于STM32跑步路径记录_GPS_04

  1. 支持北斗/GPS/GLONASS卫星系统
  2. 支持3.3V-5V供电,可以方便接入3.3V或者5V单片机系统3、板载可充电电子,可加速热启动搜星过程
  3. 默认波特率9600,波特率可设置
  4. TTL电平UART接口,用户连接单片机的串口TTL电平或者USB-TTL模块测试。
  5. 带有SMA和 IPEX两种天线接口,方便选择自己需要的外置天线。
  6. 带有PPS授时输出引脚,方便做时钟同步等应用。

基于STM32跑步路径记录_运动记录_05

基于STM32跑步路径记录_STM32_06

2.4 蜂鸣器

  蜂鸣器:有源蜂鸣器

基于STM32跑步路径记录_GPS_07

3.电路设计

基于STM32跑步路径记录_运动记录_08

4.实物展示

基于STM32跑步路径记录_运动记录_09

基于STM32跑步路径记录_运动记录_10

4.软件设计

4.1 GPS定位信息获取

  ATGM336H采用串口协议,直接接上电源,在空旷的地方只要接收到卫星信号即可返回卫星定位数据。

基于STM32跑步路径记录_运动记录_11

/*
函数功能:分析BDGSV信息
函数参数:GPS_DecodeInfo:nmea信息结构体
buf:接收到的GPS数据缓冲区首地址
*/
void GPS_BDGSV_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf)

u8 *p,*p1,dx;
u8 len,i,j,slx=0;
u8 posx;
p=buf;
p1=(u8*)strstr((const char *)p,"$BDGSV");
if(!p1)return; //没有查找成功
len=p1[7]-0; //得到BDGSV的条数
posx=GPS_GetCommaOffset(p1,3); //得到可见北斗卫星总数
if(posx!=0XFF)GPS_DecodeInfo->beidou_svnum=GPS_StrtoNum(p1+posx,&dx);
for(i=0; i<len; i++)

p1=(u8*)strstr((const char *)p,"$BDGSV");
if(!p1)return; //没有查找成功
for(j=0; j<4; j++)

posx=GPS_GetCommaOffset(p1,4+j*4);
if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_num=GPS_StrtoNum(p1+posx,&dx); //得到卫星编号
else break;
posx=GPS_GetCommaOffset(p1,5+j*4);
if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_eledeg=GPS_StrtoNum(p1+posx,&dx);//得到卫星仰角
else break;
posx=GPS_GetCommaOffset(p1,6+j*4);
if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_azideg=GPS_StrtoNum(p1+posx,&dx);//得到卫星方位角
else break;
posx=GPS_GetCommaOffset(p1,7+j*4);
if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_sn=GPS_StrtoNum(p1+posx,&dx); //得到卫星信噪比
else break;
slx++;

p=p1+1;//切换到下一个BDGSV信息

4.2 卫星数量获取

/*
函数功能:分析GNGGA信息
函数参数:
GPS_DecodeInfo:nmea信息结构体
buf:接收到的GPS数据缓冲区首地址
*/
void GPS_GNGGA_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf)

u8 *p1,dx;
u8 posx;
p1=(u8*)strstr((const char *)buf,"$GNGGA");
if(!p1)return; //没有查找成功
posx=GPS_GetCommaOffset(p1,6); //得到GPS状态
if(posx!=0XFF)GPS_DecodeInfo->gpssta=GPS_StrtoNum(p1+posx,&dx);
posx=GPS_GetCommaOffset(p1,7); //得到用于定位的卫星数
if(posx!=0XFF)GPS_DecodeInfo->posslnum=GPS_StrtoNum(p1+posx,&dx);
posx=GPS_GetCommaOffset(p1,9); //得到海拔高度
if(posx!=0XFF)GPS_DecodeInfo->altitude=GPS_StrtoNum(p1+posx,&dx);

4.3 移动速度获取

/*
函数功能:分析GNVTG信息
函数参数:GPS_DecodeInfo:nmea信息结构体
buf:接收到的GPS数据缓冲区首地址
*/

void GPS_GNVTG_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf)

u8 *p1,dx;
u8 posx;
p1=(u8*)strstr((const char *)buf,"$GNVTG");
if(!p1)return; //没有查找成功
posx=GPS_GetCommaOffset(p1,7); //得到地面速率
if(posx!=0XFF)

GPS_DecodeInfo->speed=GPS_StrtoNum(p1+posx,&dx);
if(dx<3)GPS_DecodeInfo->speed*=GPS_GetPow(10,3-dx); //确保扩大1000倍

4.4 主函数

int main()

u8 key;
char buff[100];
u32 E_data=0,E_data2=0,N_data=0,N_data2=0;
LEDInit();
KEYInit();
Beep_Init();
USARTx_Init(USART1,115200);
USARTx_Init(USART2,9600);//串口3初始化(接收GPS数据)
TIMx_Init(TIM2,72,20000);//定时20ms,用定时器2辅助usart1接收
TIMx_Init(TIM3,72,20000);
USARTx_Sendstr(USART1,"串口1初始化成功\\r\\n");
OLED_Init();//OLED初始化
u8 x=5;
u8 y=16;
u8 stat=0xff;
u8 stat2=0;
u16 time=0;
u16 distance=400;
AA:
while(1)

/*距离选择*/
OLED_ClearGram();
OLED_Display_Font(32,0,16,2);
OLED_Display_Font(32+16,0,16,3);
OLED_Display_Font(32+16*2,0,16,4);
OLED_Display_Font(32+16*3,0,16,5);
OLED_Display_str(24,16,16,(u8 *)"400 M");
OLED_Display_str(24,16*2,16,(u8 *)"1000 M");
OLED_Display_str(24,16*3,16,(u8 *)"2000 M");
OLED_Display_str(128-30,y,16,(u8 *)"<--");
key=GetKeyVual(1);
if(key==1)//距离选择

if(y<48)y+=16;
else y=16;
OLED_RefreshGram();//更新数据到屏幕

else if(key==2)//确认

BEEP=1;
if(y==16)distance=400;
else if(y==32)distance=1000;
else if(y==48)distance=2000;
OLED_RefreshGram();//更新数据到屏幕
DelayMs(50);
BEEP=0;
DelayMs(200);
break;

DelayMs(1);
time++;
if(time>=50)

time=0;
OLED_RefreshGram();//更新数据到屏幕
LED1=!LED1;


y=60;
while(1)

if(usart2_flag)//获取GPS数据

usart2_rx_buff[usart2_cnt]=\\0;
//printf("%s\\r\\n",usart2_rx_buff);
usart2_flag=0;
usart2_cnt=0;
GPS_GNGGA_InfoGet(&GPS_DecodeInfo,usart2_rx_buff);//获取卫星数量
GPS_GNVTG_InfoGet(&GPS_DecodeInfo,usart2_rx_buff);//获取移动速度
GPS_GNRMC_InfoGet(&GPS_DecodeInfo,usart2_rx_buff);//获取经纬度
printf("卫星数量: %d\\r\\n",GPS_DecodeInfo.posslnum);
E_data=GPS_DecodeInfo.longitude;
N_data=GPS_DecodeInfo.latitude;
printf("经度:%c,%d \\r\\n",GPS_DecodeInfo.ewhemi,E_data);
printf("纬度:%c,%d\\r\\n",GPS_DecodeInfo.nshemi,N_data);
printf("移动速度:%.1f. km/h\\r\\n",GPS_DecodeInfo.speed/1000.0);

if(GPS_DecodeInfo.posslnum>=3 && stat2==0)//卫星数量超过3颗开始定位

printf("stat2==%d\\n",stat2);
BEEP=1;
DelayMs(1000);
BEEP=0;
stat2=1;


key=GetKeyVual(1);
if(key==1 && stat2==1)//开始

LED1=!LED1;
stat=0;
x=5;
y=60;

else if(key==2)//退出

LED3=LED2=1;
LED1=!LED1;
stat=0xff;
stat2=0;
y=16;
goto AA;//重新选择距离

OLED_ClearGram();
OLED_Display_Font(15,35,16,2);
OLED_Display_Font(15+16,35,16,3);
snprintf(buff,sizeof(buff),":%d M",distance);
OLED_Display_str(15+16*2,35,16,(u8 *)buff);
OLED_Display_Font(15,15,16,0);
OLED_Display_Font(15+16,15,16,1);
//snprintf(buff,sizeof(buff),":%.fkm/h",GPS_DecodeInfo.speed/1000.0);
snprintf(buff,sizeof(buff),":%.fkm/h",GPS_DecodeInfo.speed/1000.0);
OLED_Display_str(15+16*2,15,16,(u8 *)buff);
OLED_DrawRectangle(5, 5, 124, 60);
OLED_DrawRectangle(4, 4, 125, 61);
gui_circle(x, y,1,3,1);
if(stat==0)

if(N_data-N_data2>=4)

x+=2;
N_data2=N_data;


else if(stat==1)

if(N_data-N_data2>=2 || N_data2-N_data>=2)

N_data2=N_data;
y--;


else if(stat==2)

if(N_data2-N_data>=3)

N_data2=N_data;
x-=2;


else if(stat==3)

if(N_data-N_data2>=3 || N_data2-N_data>=3)

N_data2=N_data;
y+=2;


if(x>=124 && y==60)

x=124;
stat=1;

else if(y==5 && x>=124)

x=124;
stat=2;

else if(x<=5 && y==5)

x=5;
stat=3;

else if(x==5 && y>=60 && (stat==3 || stat==4))

BEEP=1;
DelayMs(100);
BEEP=0;
stat=4;
LED1=LED2=1;
LED3=!LED3;
y=60;
x=5;


if(time>=20)

time=0;
if(stat==0xff)

LED3=LED2=1;
LED1=!LED1;

else if(stat<=3)

LED1=LED3=1;
LED2=!LED2;


DelayMs(1);
time++;
OLED_RefreshGram();//更新数据到屏幕

5.注意事项

  由于采用的是STM32F103实现本功能,该CPU主频仅有72MHZ,SRAM和flash均比较小,所以此示例并未调用地图接口实现,而是通过直接判断经纬度来决定当前位置。因此实现功能方式类似于公交报站实现方式,所有路径需要提交采集路线,进行路径保存。

基于stm32单片机项目设计目录-加油吧√

★♥基于STM32单片机项目设计目录√♥※目录★♥基于STM32单片机项目设计目录√♥※1、基于STM32的音乐喷泉2、STM32的智能浇水补光系统3、基于STM32的手机通过wifi控LED灯4、基于STM32的电子打铃器5、基于STM32的智能手环6、基于STM32... 查看详情

基于stm32单片机项目设计目录-加油吧√

★♥基于STM32单片机项目设计目录√♥※目录★♥基于STM32单片机项目设计目录√♥※1、基于STM32的音乐喷泉2、STM32的智能浇水补光系统3、基于STM32的手机通过wifi控LED灯4、基于STM32的电子打铃器5、基于STM32的智能手环6、基于STM32... 查看详情

基于stm32f4开发的智能台灯(代码片段)

基于STM32F4开发的智能台灯写这篇博客的目的有2个,首先是记录一下学习STM32大半年来的第一个自己动手开发的项目,整理一下开发过程和思路;其次也是希望可以和更多的同行交流开发经验,有什么问题可以多多... 查看详情

基于stm32f103入门1——点亮led灯(代码片段)

今天学习了STM32固件库点灯程序点灯也可以玩过很多好玩的东西,在这里做一下总结。STM32点灯程序合集1:新建固件库工程文件1.1找到一个固件库模板1.2:打开KEIL5新建工程1.3:添加相关文件1.4:手动添加其他... 查看详情

基于stm32的多功能心电信号监测系统设计

...、运动姿态以及体温生理信息,本文设计实现了一种基于STM32系列MCU的多功能心电信号监测系统,系统包含心电信号采集模块、体表温度采集模块、运动信息测量模块、无线数据传输模块、系统控制模块。实现对人体心电... 查看详情

stm32使用freertos过程记录

STM32使用FreeRTOS过程记录 查看详情

基于stm32f103——矩阵按键+串口打印(代码片段)

STM32F103-矩阵按键+串口打印基本介绍代码matrix_key.cmatrix_key.hmain.c项目演示基本介绍最近做了一个门禁卡小玩意,用到了4X4矩阵按键,在这里也单独的记录一下。矩阵按键图思路:矩阵按键读取键值写法多样,有一行... 查看详情

stm32学习笔记二基于stm32f103c8t6和stm32cubemx实现uart串口通信数据收发(代码片段)

系列文章目录一、基于STM32F103C8T6最小系统板和STM32CubeMX实现LED灯循环闪烁二、基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发三、实战小例程基于STM32F103C8T6最小系统板和STM32CubeMX驱动WS2812B光立方四、基于STM32F103C8T6最小系统板... 查看详情

stm32学习笔记一基于stm32f103c8t6最小系统板和stm32cubemx实现板载led灯循环闪烁(代码片段)

系列文章目录一、基于STM32F103C8T6最小系统板和STM32CubeMX实现LED灯循环闪烁二、基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发三、实战小例程基于STM32F103C8T6最小系统板和STM32CubeMX驱动WS2812B光立方四、基于STM32F103C8T6最小系统板... 查看详情

1基于stm32的音乐喷泉√♥(代码片段)

1、基于STM32的音乐喷泉文章目录1、基于STM32的音乐喷泉Introduction引言1、系统概述1.1、设计任务1.2、设计要求2、方案设计2.1、芯片选择方案2.2、系统概述:2.3、系统总体设计思路2.4、各功能模块程序实现原理分析2.4.1.水泵驱... 查看详情

1基于stm32的音乐喷泉√♥(代码片段)

1、基于STM32的音乐喷泉文章目录1、基于STM32的音乐喷泉Introduction引言1、系统概述1.1、设计任务1.2、设计要求2、方案设计2.1、芯片选择方案2.2、系统概述:2.3、系统总体设计思路2.4、各功能模块程序实现原理分析2.4.1.水泵驱... 查看详情

stm32f103vet6基于stm32cubemx利用exti外部中断测量pwm频率(代码片段)

STM32F103VET6基于STM32CubeMX利用EXTI外部中断测量PWM频率📌相关篇《STM32G070RBT6基于STM32CubeMX配置定时器PWM功能案例》📍《STM32F103VET6基于STM32CubeMX创建EXTI外部中断工程》🌼本篇利用上面两篇示例综合,利用STM32F103VET6引... 查看详情

11基于stm32的智能药盒

11、基于STM32的智能药盒引言1系统概述1.1设计任务1.2设计要求2方案设计与论证2.1芯片选择方案2.2系统概述:2.3设计要求:2.4系统总体设计思路2.5各功能模块程序实现原理分析2.5.1显示模块:2.5.2按键模块:2.5.3语音模块:2.5.4时钟... 查看详情

stm32cubemx安装与使用

STM32CubeMX安装与使用1.1JRE安装​STM32CubeMX软件是基于JAVA环境运行的,所以需要安装JRE(JavaRuntimeEnvironment)才能使用。首先在官网上下载安装包https://www.java.com/en/download/manual.jsp然后点击进入安装界面,根据个人选择... 查看详情

19基于stm32的电子打铃器

19、基于STM32的电子打铃器引言1系统概述1.1设计任务1.2设计要求2方案设计与论证2.1芯片选择方案2.2系统概述:2.3设计要求:2.4系统总体设计思路2.5各功能模块程序实现原理分析3STM32性能介绍及硬件设计3.1STM32单片机性能介绍3.2电... 查看详情

19基于stm32的电子打铃器

19、基于STM32的电子打铃器引言1系统概述1.1设计任务1.2设计要求2方案设计与论证2.1芯片选择方案2.2系统概述:2.3设计要求:2.4系统总体设计思路2.5各功能模块程序实现原理分析3STM32性能介绍及硬件设计3.1STM32单片机性能介绍3.2电... 查看详情

12基于stm32的电子密码器

**12、基于STM32的电子密码器引言一、系统概述1.1设计任务1.2设计要求二、系统方案论证2.1芯片选择方案2.2系统概述2.3系统总体设计思路2.4各功能模块程序实现原理分析三、STM32性能介绍和硬件设计3.1STM32单片机性能介绍3.2电子密... 查看详情

10基于stm32的汽车倒车防撞雷达

基于STM32的汽车倒车防撞雷达引言1系统概述1.1设计任务1.2设计要求2方案设计与论证2.1芯片选择方案2.2系统概述2.3设计要求:2.4系统总体设计思路2.5各功能模块程序实现原理分析2.5.1电源电路设计2.5.2主控制电路2.5.3超声波电路3STM3... 查看详情