You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F103驱动SIM808做GPS追踪器 发送一次短信后死机问题咨询

故障原因及修复方案

核心问题点

  • 串口接收中断逻辑错误
    USART1中断处理函数中,接收缓存下标i、接收完成标志get_Enter完全没有复位逻辑,每次接收到换行后i会持续累加,很快就会超出str1数组的300字节长度,引发内存越界,导致程序跑飞或者变量值异常。同时get_Enter置1后没有清零,后续的串口接收逻辑完全无法正常触发。
    另外接收用到的全局变量i、ch、get_Enter都没有加volatile修饰,编译器优化后会导致主循环读取到的变量值和实际值不一致。
  • 存在死等逻辑
    主循环中do { p=strstr(str1,"+CMTI:"); } while(p==NULL);是无超时的死等逻辑,一旦模块报文丢失、或者报文被之前的残留数据覆盖,程序会直接卡在此处,不再响应任何操作。
  • strtok修改原缓存
    解析CGNSINF数据时使用的strtok函数会直接修改传入的原字符串内容,会破坏str1中存储的原始返回数据,影响后续逻辑判断。
  • 没有做命令响应判断
    所有AT指令发送后都只靠固定延时等待响应,没有校验模块是否返回OK,一旦模块响应慢、或者返回ERROR,后续逻辑全部错乱。

修复代码示例

1. 调整全局变量定义和中断逻辑

// 全局变量增加volatile修饰,避免编译器优化引发的取值异常
volatile char get_Enter = 0;
volatile uint8_t ch;
volatile int i=0;
char str1[300] = {0}; // 初始化时清空缓存

// 修改串口中断服务函数
void USART1_IRQHandler(void) {
    // 先判断是否为接收中断,避免误触发
    if(USART1->SR & (1<<5)) {
        ch = USART1->DR & 0xFF; 
        if (ch == '\n'){ 
            get_Enter = 1;
            str1[i] = '\0'; // 给字符串补结束符
        }
        else{
            // 增加边界判断,防止数组越界
            if(i < 299) {
                str1[i] = ch;
                i++;
            }
        }
    }
}

2. 调整主循环逻辑

while (1)
{
    if (get_Enter == 1)
    {
        if (flag == 0){
            // 去掉无超时死等逻辑,没有找到报文就等待下一次接收触发
            p = strstr(str1,"+CMTI:");   
            if(p != NULL)
            {
                Delay(1000);
                CMGR();
                Delay(350);
                flag = 1;
            }
            // 每次处理完当前报文后复位接收标志和缓存
            get_Enter = 0;
            i = 0;
            memset(str1, 0, 300);
        }
        if (flag == 1) {
            p = strstr(str1,"+CMGR");
            if (p){
                p = strstr(str1,"loc");
                                
                if (p != NULL)
                {
                    CGNSINF();
                    Delay(300);
                    p = strstr(str1,"+CGNSINF:");
                    if (p)
                    {
                        float a[5];
                        char str2[80];
                        // 用临时缓存拷贝数据,避免strtok修改原缓存
                        char tmp_buf[300];
                        strcpy(tmp_buf, p);
                        const char s[2] = ",";
                        char *token;
                        token = strtok(tmp_buf, s);
                        // 循环变量不要和全局变量i重名
                        for (int j=0;j<5;j++){
                            if(token == NULL) break;
                            a[j] = atof(token);
                            token = strtok(NULL, s);
                        } 
                        sprintf(str2,"https://maps.google.com/?q=%.6f,%.6f",a[3],a[4]);
                        Send_SMS(str2);
                    }
                }
                del_All_SMS();
                flag = 0;
                // 复位接收标志和缓存
                get_Enter = 0;
                i = 0;
                memset(str1, 0, 300);
            }
        }
    }
}

额外优化建议

  • 所有AT指令发送后建议增加10秒超时的OK校验逻辑,一旦校验失败可以自动重发指令,避免逻辑卡死后只能手动复位
  • SIM808发送短信后需要等待+CMGS:OK返回后再执行删除短信操作,不要只靠固定延时
  • 如果GPS首次定位还没完成,CGNSINF返回的经纬度是空值,建议增加定位有效性判断,避免返回无效的地图链接

内容的提问来源于stack exchange,提问作者salar1991

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 13:39:01