基于极海APM32E030的智能手表设计(上):健康监测与GPS定位功能实现

发布于:2025-08-06 ⋅ 阅读:(15) ⋅ 点赞:(0)

一、简介


随着科技持续进步,人们对于健康的要求越来越高,智能可穿戴手表应运而生;本项目旨在使用常见不同模块实现简易的智能手表框架,主控选型上采用极海半导体推出的工业级基础拓展型MCU:APM32E030R8T6,这款MCU集成搭载 Arm® Cortex®-M0 + 内核,工作主频 72MHz,采用 12 寸 55nm 先进工艺,具有内置 64KB Flash、8KB SRAM、2 个 I2C、2 个 USART、2个 位高精度 ADC 等丰富资源,符合本次项目要求;

二、系统框图


本项目使用APM32E030R8T6作为主控,使用到的模块有:DS18B20、MAX30102、ATGM336H以及ADXL345等,可实现温度、血压、血氧的测量、GPS定位、计时功能以及步数感应功能;
 

三、模块实现


下面将从模块原理、硬件设计和程序设计三部分详细介绍各个模块的实现思路:

温度传感器


温度获取功能使用的是DS18B20,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点.

模块工作原理


DS18B20作为单线半双工通信,共有6种信号类型:复位脉冲、应答脉冲、写0、写1、读0和读1;

复位脉冲:主机输出低电平保持至少480us,然后释放总线,电平拉高保持15~60us;

应答信号:DS18B20拉低电平保持60~240us;

写时序:写"0" 输出低电平60us,释放总线延迟2us; 写"1" 输出低电平2us,释放总线延迟60us;

读时序:输出电平延时2us,转输入模式延时12us,读取总线电平(15us以内),延时50us;

硬件设计


引脚描述:

程序设计


第一步,模块初始化,初始化PA12引脚,配置其为上拉推挽模式;
 

u8 DS18B20_Init(void)
{
    GPIO_Config_T  GPIO_InitStructure;

    RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);  //使能PORTA口时钟 

    GPIO_InitStructure.pin = GPIO_Pin_12;               //PORTA12 推挽输出
    GPIO_InitStructure.mode = GPIO_Mode_Out_PP;         //配置为输出 
    GPIO_InitStructure.speed = GPIO_Speed_50MHz;
    GPIO_Config(GPIOA, &GPIO_InitStructure);

    GPIO_SetBits(GPIOA,GPIO_PIN_12);    //输出12

    DS18B20_Rst();
}

第二步,复位模块,先拉低PA12引脚5ms,再拉高PA12引脚保持5ms;

第三步,发送指令0xCC,跳过ROM是,再发送指令0x44,开启转换,最后发送0xBE,读取数据;
 

short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
    short tem;
    DS18B20_Start ();                   // ds1820 start convert
    delay_ms(5);                    //延迟5ms
    DS18B20_Rst();                      //ds18b20 复位
    delay_ms(5);                    //延迟5ms
    DS18B20_Check();     
    DS18B20_Write_Byte(0xcc);           // 发送0xCC
    DS18B20_Write_Byte(0x44);           // 发送0x44
    DS18B20_Write_Byte(0xbe);           // 发送0xBE     
    TL=DS18B20_Read_Byte();             // LSB   
    TH=DS18B20_Read_Byte();             // MSB  

    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;//温度为负  
    }else temp=1;//温度为正       
    tem=TH; //获得高八位
    tem<<=8;  
    tem+=TL;//获得底八位
    tem=(float)tem*0.625;//转换   
    if(temp)return tem; //返回温度值
    else return -tem;  
}

第四步,读取两个字节 TH 和 TL ;

第五步,根据DS18B20的温度运算法则进行数据处理;

至此,DS18B20模块读取温度功能实现;


GPS定位模块

ATGM336H是一种高性能的GPS模块,可以在较低功耗下提供高精度、高可靠性的位置信息服务。它采用了SiRFstarIII技术,并支持多种导航卫星系统,包括GPS、GLONASS、Galileo、QZSS和SBAS。ATGM336H可以快速获取卫星信号,提供高达10Hz的位置刷新速率,并能在较弱的GPS信号环境下保持高精度。

模块工作原理


我们将模块的TX和RX通过串口通信串口助手,ATGM336H利用串口发送定位信息给主控芯片,串口波特率为9600,可以看到,模块会通过串口不断打印数据
 

其中信息头的第一个是消息ID,通过查阅芯片手册,简单的含义如下:

需要关注其中的“GNRMC”这条信息,将这条信息解析:
 

$GNRMC,015135.000,A,4159.65553,N,12136.79345,E,0.52,0.00,191123,,,A*7F
  • 消息ID —— \$GNRMC
  • 定位点的UTC时间 —— 015135.000
  • 定位状态 —— A:定位;V:导航(我们进行定位时,如果该位为A表示数据有效,该位为V表示数据无效)
  • 纬度 —— 4159.65553
  • 纬度方向 —— N
  • 经度 —— 12136.79345
  • 经度方向 —— E

硬件设计


实物图如下

引脚定义以及接线如下表所示

软件设计


第一步,初始化模块,初始化USART1模块的两个引脚PA9和PA10,配置串口波特率为9600;

第二步,等待ATGM336H信号连接成功,当连接成功时,PPS引脚会拉低再拉高;

void ATGM336_Baisc_Init(void)  //模块信号引脚初始化  
{
      GPIO_Config_T GPIO_InitStructure;     //定义一个设置GPIO功能的变量
      RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);   //使能GPIOA时钟

      uart1_Init(9600);  //串口初始化
      GPIO_InitStructure.pin = GPIO_Pin_11;              //准备设置PA11
      GPIO_InitStructure.speed = GPIO_Speed_50MHz;      //IO速率50M
      GPIO_InitStructure.mode = GPIO_Mode_IPD;              //下拉输入
      GPIO_Config(GPIOA, &GPIO_InitStructure);                 //设置PA11
}

void ATGM336_Init(void)
{
    int i; 
    uart1_Init(9600);  //USART1初始化
        bool Point_flag;
        while(!GPIO_ReadInputBit(GPIOA,GPIO_Pin_11))  //等待PPS引脚拉低
    {
            if(Point_flag == 0){  //显示函数
            for(i=0;i<11;i++)
        {
                for(i=0;i<11;i++)OLED_ShowChar(0+(i*4),7,' ',1,0);delay_ms(10);
                Point_flag = 1;
        }
        }
        else
        {     //显示函数
            for(i=0;i<11;i++){OLED_ShowChar(0+(i*4),7,' ',1,0);}
            Point_flag = 0;
            delay_ms(10);
        }
        if(setc == 0)
            break;////如果拉低,跳出循环
    }
            if(GPIO_ReadInputBit(GPIOA,GPIO_Pin_11))//改变标志位
                GPS_state   = 1;
            for(i=0;i<9;i++){OLED_ShowChar(0+(i*4),7,' ',1,0);}
}

第三步,USART模块接收信息并解析
 

void GetsGpsBuffer()
{
    char *subString;
    char *subStringNext;
    char i = 0;
    char usefullBuffer[2];
    if (Save_Data.isGetData)
    {
        Save_Data.isGetData = false;
        //截取数据帧前六部分                              |对地航速 对地航向  日期
        //$GNRMC,112536.000,A,2322.75023,N,11326.28605,E,|  0.00,   0.00,  100722,,,A*78
        for (i = 0; i <= 6; i++)
        {
            if (i == 0)
            {
                if ((subString = strstr(Save_Data.GPS_Buffer, ",")) == NULL)
                    errorLog(1); // 解析错误
            }
            else
            {
                subString++;
                if ((subStringNext = strstr(subString, ",")) != NULL)
                {
                    switch (i)
                    {
                                        // 获取UTC时间
                    case 1:memcpy(Save_Data.UTCTime, subString, subStringNext - subString);break; 
                                        // 获取UTC时间
                    case 2:memcpy(usefullBuffer, subString, subStringNext - subString);break; 
                                        // 获取纬度信息
                    case 3:memcpy(Save_Data.latitude, subString, subStringNext - subString);break; 
                                        // 获取N/S
                    case 4:memcpy(Save_Data.N_S, subString, subStringNext - subString);break;
                                        // 获取经度信息
                    case 5:memcpy(Save_Data.longitude, subString, subStringNext - subString);break; 
                                        // 获取E/W
                    case 6:memcpy(Save_Data.E_W, subString, subStringNext - subString);break; 
                    default:break;
                    }
                    subString = subStringNext;
                    Save_Data.isParseData = true;
                    if (usefullBuffer[0] == 'A')
                        Save_Data.isUsefull = true;
                    else if (usefullBuffer[0] == 'V')
                        Save_Data.isUsefull = false;
                }
                else
                {
                    errorLog(2); // 解析错误
                }
            }
        }
    }
}

第四步,数据转换,获取的信息里,单位是**“度-分”,需要将其转换为常用单位“度”;
 

void Data_Transfor (void)
{
    float latitude_temp1,latitude_temp2_min,latitude = 0, ;    // 存储纬度信息
    float longitude_temp1,longitude_temp2_min,longitude = 0;   // 存储经度信息

    latitude = strtod(receDataFrame.latitude,NULL);             // 字符串转换成浮点数
    longitude = strtod(receDataFrame.longitude,NULL);           // 字符串转换成浮点数

    // 纬度信息处理
    latitude_temp1 = (uint16_t)latitude/100;                         //提取度-分中度的不分
    latitude_temp2_min = (latitude%100 )/60                 //提取度-分中,分的部分并将其转为度
    latitude = (float)latitude_temp1 + latitude_temp2_min;

    // 经度信息处理
    // 五位经度信息
    longitude_temp1 = (uint16_t)longitude/100;                           //提取度-分中度的不分
    longitude_temp2_min = (longitude%100 )/60               //提取度-分中,分的部分并将其转为度
    latitude = (float)longitude_temp1 + longitude_temp2_min;
}

至此,GPS模块功能实现完成

四、文献出处


1. 本片所涉及软件代码基于APM32E030官方SDK库,可在官网直接下载使用;

https://www.geehy.com/design/document

2. 本问所设计参考文章有:

MAX30102心率血氧传感器(IIC协议 STM32)-CSDN博客

GPS定位模块(ATGM336H)-CSDN博


3. 由于篇幅原因,该项目分为上下两章详细描述;


网站公告

今日签到

点亮在社区的每一天
去签到