概述: STM32L073工作于低功耗模式,定时间断唤醒通过UART串口与GPS模块通信获取高精度GPS时钟作为母钟(时间基准),通过近距离无线模块CC110L并发送给若干个分布在不同位置的子钟,实现子母钟之间的快速通信和时间统一校准。 硬件: 母钟部分 STM32L073 NUCLEO NEO-6M-0-001串口GPS模块 CC110L无线模块 子钟部分 MSP430F2553+CC110L无线模块 硬件连接与工作原理: STM32L073板为NEO-6M GPS模块提供3.3V工作电压,串口1以中断方式与NEO-6M GPS模块进行通讯,波特率为9600。串口2分别将收到的数据和解析后的数据发给PC端的串口助手。SPI2驱动CC110L发送UTC时间信息。 (硬件连接截图) (GPS串口信息截图) (GPS解析信息截图) 软件处理: 母钟: 定义串口1接收缓冲区,初始化串口1与串口2,初始化定时器,初始化CC110L模块,并进入低功耗模式等待。串口1接收触发中断,收到一帧GPS数据后,调用数据解析子函数检测信息字头,提取经纬度和UTC时间信息,并将时间信息发送到CC110L模块。 GPS数据解析过程:(参考正点原子的GPS模块驱动程序) 由于NEO-6M每隔一秒以9600的波特率发出一帧GPS数据,所以在解析NMEA数据之前,通过判断接收连续2个字符之间的时间差不大于10ms来决定是不是一次连续的数据。如果2个字符接收间隔超过10ms,则认为不是1次连续数据,也就是超过10ms没有接收到任何数据,则表示此次接收完毕。10ms 定时由定时器来完成。 if(USART_GetITStatus(USART1, USART_IT_RXNE)!= RESET) { res =USART_ReceiveData(USART1); if(USART1_RX_STA<USART1_MAX_RECV_LEN) { TIM_SetCounter(TIM4,0); if(USART1_RX_STA==0)TIM4_Set(1); USART1_RX_BUF[USART1_RX_STA++]=res; }else { USART1_RX_STA|=1<<15; } } NMEA数据解析和提取函数: //gpsx:nmea信息结构体 //buf:接收到的GPS数据缓冲区首地址 voidNMEA_GPRMC_Analysis(nmea_msg *gpsx,u8 *buf) { u8 *p1,dx; u8 posx; u32 temp; float rs; p1=(u8*)strstr((const char*)buf,"GPRMC");//"$GPRMC",经常有&和GPRMC分开的情况,故只判断GPRMC. posx=NMEA_Comma_Pos(p1,1); //得到UTC时间 if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx)/NMEA_Pow(10,dx); //得到UTC时间,去掉ms gpsx->utc.hour=temp/10000; gpsx->utc.min=(temp/100)%100; gpsx->utc.sec=temp%100; } posx=NMEA_Comma_Pos(p1,3); //得到纬度 if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); gpsx->latitude=temp/NMEA_Pow(10,dx+2); //得到° rs=temp%NMEA_Pow(10,dx+2); //得到' gpsx->latitude=gpsx->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为° } posx=NMEA_Comma_Pos(p1,4); //南纬还是北纬 if(posx!=0XFF)gpsx->nshemi=*(p1+posx); posx=NMEA_Comma_Pos(p1,5); //得到经度 if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); gpsx->longitude=temp/NMEA_Pow(10,dx+2); //得到° rs=temp%NMEA_Pow(10,dx+2); //得到' gpsx->longitude=gpsx->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为° } posx=NMEA_Comma_Pos(p1,6); //东经还是西经 if(posx!=0XFF)gpsx->ewhemi=*(p1+posx); posx=NMEA_Comma_Pos(p1,9); //得到UTC日期 if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); //得到UTC日期 gpsx->utc.date=temp/10000; gpsx->utc.month=(temp/100)%100; gpsx->utc.year=2000+temp%100; } } 其中,NMEA_Comma_Pos函数用于从buf里面得到第cx个逗号所在的位置,由此分离经纬度和UTC时间信息。 //返回值:0~0XFE,代表逗号所在位置的偏移. // 0XFF,代表不存在第cx个逗号 u8NMEA_Comma_Pos(u8 *buf,u8 cx) { u8 *p=buf; while(cx) { if(*buf=='*'||*buf<''||*buf>'z')return 0XFF;//遇到'*'或者非法字符,则不存在第cx个逗号 if(*buf==',')cx--; buf++; } return buf-p; } 匆匆发帖,更多的程序代码、硬件连接截图和详细的数据结果稍后会补充上传。 |
基于STM32L051使用CubeMX生成工程文件ST系列芯片通用经验分享
基于STM32L051开始添加需要的代码经验分享
STM32L051测试I2C协议设备的添加经验分享
基于STM32L051测试Flash和EEPROM的读写
基于STM32L051串口测试与Enocean模块通讯问题
基于STM32L0的EEPROM读写经验分享
基于STM32L0 ADC使用HAL库关于校准问题经验分享
【工程师笔记】汇总处
【经验之谈】基于STM32L053芯片使用STM32CUBE软件开发低功耗设备的经验分享
在 STM32L0 和 STM32L4 系列微控制器中使用 LPUART 使功耗最小