宇岚 发表于 2025-5-8 11:14

基于APM32E030的智能手表方案(上)

本帖最后由 宇岚 于 2025-5-14 19:21 编辑

#申请原创# #技术资源#

# **一、简介**

随着科技持续进步,人们对于健康的要求越来越高,智能可穿戴手表应运而生;本项目旨在使用常见不同模块实现简易的智能手表框架,主控选型上采用极海半导体推出的工业级基础拓展型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定位、计时功能以及步数感应功能;

!(data/attachment/forum/202505/08/102807lzhhg22ja9qwzgq2.png "image.png")

# **三、模块实现**

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

## **温度传感器**

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

### 模块工作原理

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

!(data/attachment/forum/202505/08/103913xunceoi23mxebuno.png "image.png")

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

!(data/attachment/forum/202505/08/102100up9ivjipvgezi3im.png "image.png")

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

!(data/attachment/forum/202505/08/102151cw7ztwtfu7tji7i0.png "image.png")

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

!(data/attachment/forum/202505/08/103347xiifhk7ehue33tup.png "image.png")

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

!(data/attachment/forum/202505/08/103631xjqxyc2hxekjksuc.png "image.png")

### 硬件设计

!(data/attachment/forum/202505/07/162522aefmabtvtirft7d3.jpg "DS18B20.jpg")

引脚描述:

| **引脚名称** | **描述**             |
| ------------------ | -------------------------- |
| **VCC**      | **供给电压**5V       |
| **GND**      | **地线**             |
| **I/O**      | **通信引脚,接PA12** |

### **程序设计**

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

```apache
u8 DS18B20_Init(void)
{
    GPIO_Config_TGPIO_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,读取数据;

```apache
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,**可以看到**,模块会通过串口不断打印****数据;**

!(data/attachment/forum/202505/08/093130exjdnd5jankyc5gk.png "image.png")

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

| 缩写标识符 | 含义                   |
| ---------- | ---------------------- |
| BD         | BDS,北斗二代卫星系统|
| GP         | GPS                  |
| GL         | GLONASS                |
| GA         | Galileo                |
| GN         | GNSS,全球卫星导航系统 |

需要关注其中的**“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

### 硬件设计

实物图如下

!(data/attachment/forum/202505/07/171923ps1tsx7bxs1fji7x.jpg "GPS 1.jpg")

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

| **引脚名称** | **描述**               |
| ------------------ | ---------------------------- |
| **VCC**      | **电源(3.3V-5V)**    |
| **GND**      | **地线**               |
| **TXD**      | **发送引脚,接PA9**    |
| **RXD**      | **接收引脚,接PA10**   |
| **PPS**      | **时钟脉冲引脚,PA11** |

### 软件设计

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

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

```apache
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模块接收信息并解析

```apache
void GetsGpsBuffer()
{
        char *subString;
        char *subStringNext;
        char i = 0;
        char usefullBuffer;
        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 == 'A')
                                                Save_Data.isUsefull = true;
                                        else if (usefullBuffer == 'V')
                                                Save_Data.isUsefull = false;
                                }
                                else
                                {
                                        errorLog(2); // 解析错误
                                }
                        }
                }
        }
}
```

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

```apache
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.本问所设计参考文章有:

https://blog.csdn.net/qq_44016222/article/details/141892460?ops_request_misc=%257B%2522request%255Fid%2522%253A%252200602cae32b01e8caf708299723effe6%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=00602cae32b01e8caf708299723effe6&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-2-141892460-null-null.142^v102^pc_search_result_base6&utm_term=max30102%E5%BF%83%E7%8E%87%E8%A1%80%E6%B0%A7%E4%BC%A0%E6%84%9F%E5%99%A8&spm=1018.2226.3001.4187    -----MAX30102心率血氧传感器(IIC协议 STM32)-CSDN博客

https://blog.csdn.net/qq_44016222/article/details/141891589?ops_request_misc=%257B%2522request%255Fid%2522%253A%25225a1bfb03841971f12cfefecb83cbb8c1%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=5a1bfb03841971f12cfefecb83cbb8c1&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-141891589-null-null.142^v102^pc_search_result_base6&utm_term=ADXL345&spm=1018.2226.3001.4187

```
-----【STM32外设系列】GPS定位模块(ATGM336H)-CSDN博
```

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

MrChen93 发表于 2025-5-21 11:40

穿戴设备对功耗要求蛮高的,这个功耗表现咋样?

幻影书记 发表于 2025-5-9 19:03

APM32E030系列都推出了。
这个要替代掉F030系列吗?直接Pk某品牌的G0系列吗?

wang1979 发表于 2025-5-9 15:42

不错的分享,APM32的单片机

宇岚 发表于 2025-5-9 10:04

dffzh 发表于 2025-5-8 16:43
这款MCU的低功耗模式有几种?低功耗电流大概是多少uA?

APM32E030低功耗模式有SLEEP、STOP和STANDBY三种低功耗模式;
在常温、3.3V条件下SLEEP模式功耗低至3mA,STOP模式下低至12uA,STANDBY模式下低至1.12uA

zjk103 发表于 2025-5-9 09:31

这种血氧的监测准确么?

xionghaoyun 发表于 2025-5-9 09:10

兄弟 贴上源码啊

dffzh 发表于 2025-5-8 16:43

这款MCU的低功耗模式有几种?低功耗电流大概是多少uA?

银河漫步 发表于 2025-5-8 15:53

E030系列采用55nm的工艺,其低功耗表现应该更好,对体积受限的电池应用案例应该更适合。
页: [1]
查看完整版本: 基于APM32E030的智能手表方案(上)