发新帖本帖赏金 50.00元(功能说明)我要提问
返回列表
打印
[APM32E0]

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

[复制链接]
1652|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
宇岚|  楼主 | 2025-5-8 11:14 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式

[i=s] 本帖最后由 宇岚 于 2025-5-14 19:21 编辑 [/i]<br /> <br />

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

一、简介

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

image.png

三、模块实现

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

温度传感器

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

模块工作原理

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

image.png

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

image.png

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

image.png

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

image.png

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

image.png

硬件设计

DS18B20.jpg

引脚描述:

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

程序设计

第一步,模块初始化,初始化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,可以看到,模块会通过串口不断打印**数据;**

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

硬件设计

实物图如下

GPS1.jpg

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

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

软件设计

第一步,初始化模块,初始化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.本问所设计参考文章有:

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.由于篇幅原因,该项目分为上下两章详细描述;

使用特权

评论回复

打赏榜单

21小跑堂 打赏了 50.00 元 2025-05-20
理由:恭喜通过原创审核!期待您更多的原创作品~~

评论
21小跑堂 2025-5-20 17:59 回复TA
基于APM32E030R8T6为主控的智能手表方案,作者着重介绍了项目的整体框架以及温度传感器和GPS定位定位模块的使用。期待后续作品。 
8
MrChen93| | 2025-5-21 11:40 | 只看该作者
穿戴设备对功耗要求蛮高的,这个功耗表现咋样?

使用特权

评论回复
7
幻影书记| | 2025-5-9 19:03 | 只看该作者
APM32E030系列都推出了。
这个要替代掉F030系列吗?直接Pk某品牌的G0系列吗?

使用特权

评论回复
6
wang1979| | 2025-5-9 15:42 | 只看该作者
不错的分享,APM32的单片机

使用特权

评论回复
5
宇岚|  楼主 | 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 | 只看该作者
这种血氧的监测准确么?

使用特权

评论回复
评论
宇岚 2025-5-9 15:53 回复TA
因为成本原因,这个模块测量血氧精度不够准确 
板凳
xionghaoyun| | 2025-5-9 09:10 | 只看该作者
兄弟 贴上源码啊

使用特权

评论回复
评论
宇岚 2025-5-9 09:24 回复TA
好的 
沙发
dffzh| | 2025-5-8 16:43 | 只看该作者
这款MCU的低功耗模式有几种?低功耗电流大概是多少uA?

使用特权

评论回复
楼主
银河漫步| | 2025-5-8 15:53 | 只看该作者
E030系列采用55nm的工艺,其低功耗表现应该更好,对体积受限的电池应用案例应该更适合。

使用特权

评论回复
发新帖 本帖赏金 50.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

6

帖子

2

粉丝