3. 开发环境搭建:Keil/IAR环境配置、STM32CubeMX初始化、串口驱动配置

说实话,做双模定位开发,环境搭建这一步看着简单,但坑不少。我见过太多人卡在编译不过、串口打印乱码这种基础问题上。今天咱们就把这事彻底捋清楚。

3.1 开发工具选型:Keil还是IAR?

我个人习惯用Keil,因为STM32的生态太成熟了。但IAR的编译优化确实更狠,代码能小个10%左右。怎么选?

对比项 Keil MDK IAR EWARM
上手难度 低,教程多 中,需要适应
编译效率 中等 高,代码密度好
调试体验 好,JLink无缝 好,但License贵
双模定位库兼容 直接支持 需注意浮点ABI

我建议:如果你刚入门,用Keil。项目量产阶段,可以考虑IAR。嗯,这里要注意——不管选哪个,浮点运算单元(FPU)必须开启。GPS解算里大量浮点运算,不开FPU,性能直接腰斩。

3.2 STM32CubeMX初始化:别偷懒,一步步来

STM32CubeMX这个工具,说白了就是帮你省掉写底层配置的时间。但很多人点两下就生成代码,结果串口波特率不对、时钟配错,定位数据全乱套。

我一般按这个顺序操作:

  1. 选芯片:比如STM32F103C8T6,注意后缀,RAM和Flash大小不同
  2. 配时钟:外部晶振8MHz,PLL倍频到72MHz。别用内部RC,温度漂移太厉害
  3. 使能串口:USART1用于调试打印,USART2接GPS/北斗模块
  4. 配中断:串口接收中断必须开,不然你收不到NMEA数据
  5. 生成代码:选MDK或IAR工程,记得勾选“初始化所有外设”

关键点:GPS模块通常用9600或115200波特率。我建议统一用115200,数据量大时不容易丢包。但注意——有些老模块只支持9600,得看手册。

3.3 串口驱动配置:从打印到接收

串口驱动是双模定位的“咽喉”。数据进不来,后面全是白搭。我分两步讲:

3.3.1 调试串口(打印用)

这个最简单,重定向printf到串口就行。Keil里加一行:

// 在usart.c里添加
int fputc(int ch, FILE *f) {
    while(!(USART1->SR & USART_SR_TXE));
    USART1->DR = (uint8_t)ch;
    return ch;
}

然后你就可以用printf打印“Hello GNSS”了。我曾经遇到打印乱码,查了半天发现是HAL库的波特率配置和实际晶振不匹配。嗯,这里要注意——检查CubeMX里的HSE_VALUE是否和你板子一致

3.3.2 数据接收串口(接GPS/北斗模块)

这个要复杂些。GPS模块每秒输出一串NMEA语句,比如$GPGGA、$GPRMC。你得用中断或DMA收,不能轮询。

我常用的中断接收框架:

// 定义接收缓冲区
#define RX_BUF_SIZE 256
uint8_t rx_buf[RX_BUF_SIZE];
uint16_t rx_index = 0;

// 中断回调
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if(huart->Instance == USART2) {
        // 收到一个字节,存入缓冲区
        rx_buf[rx_index++] = rx_byte;
        if(rx_index >= RX_BUF_SIZE) rx_index = 0;
        
        // 检查是否收到完整NMEA语句(以'\n'结尾)
        if(rx_byte == '\n') {
            // 置标志位,主循环解析
            nmea_ready = 1;
        }
        // 继续接收下一个字节
        HAL_UART_Receive_IT(&huart2, &rx_byte, 1);
    }
}

避坑指南:我曾经在中断里直接做NMEA解析,结果导致中断服务时间过长,系统卡死。正确做法是——中断里只收数据、置标志位,解析放到主循环里做。

3.4 时钟配置:别让GPS模块“饿死”

GPS模块需要稳定的时钟信号。如果STM32的时钟抖动太大,模块的捕获灵敏度会下降。我建议:

  • 使用外部有源晶振,精度优于±10ppm
  • 如果板子空间有限,至少用无源晶振加匹配电容
  • 别用内部RC振荡器——温度一变,频率就飘

为什么这么强调时钟?因为GPS信号本身就很弱(-130dBm左右),接收机需要精确的本地时钟来跟踪卫星。时钟不准,相当于你拿着不准的表去约人,永远对不上点。

3.5 验证环境:打印一句“Hello GNSS”

配置完所有东西,先别急着接GPS模块。写个简单测试:

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_USART1_UART_Init();  // 调试串口
    MX_USART2_UART_Init();  // GPS串口
    
    printf("Hello GNSS! System ready.\r\n");
    
    while(1) {
        // 稍后在这里解析NMEA数据
    }
}

如果串口助手能收到“Hello GNSS!”,说明环境通了。如果收不到,检查:

  • 波特率是否匹配(115200)
  • TX/RX是否接反(我犯过这个低级错误)
  • GND是否共地

警告:GPS模块的串口电平通常是3.3V,STM32F103也是3.3V,可以直接连。但如果你用5V的STM32(比如F407),必须加电平转换,否则会烧模块。

3.6 本章知识体系

下面这张图总结了开发环境搭建的核心逻辑:

开发环境搭建核心流程 工具选型 Keil / IAR STM32CubeMX 时钟 / 串口 / 中断 生成代码 MDK / IAR工程 调试串口 printf重定向 波特率匹配 GPS接收串口 中断接收 NMEA缓冲 时钟配置 外部晶振 FPU开启 验证:Hello GNSS!

环境搭建是双模定位开发的第一步,也是后续所有工作的基础。我建议你花半天时间,把每一步都亲手跑通。别急着调定位算法——串口数据收不到,后面全是纸上谈兵。


公众号:蓝海资料掘金营,微信deep3321