0. 前言
主要参考正点原子 stm32 《第92讲 GPS-NEO-6M全球定位模块讲解》、
使用硬件: GPS-NEO-6M,stm32开发板
配套软件:串口调试助手、U-center
技术文档: 《 ATK-NEO-6M用户手册_V2.0 》、《u-blox6_ReceiverDescriptionProtocolSpec_GPS.G6-SW-10018-C》、《ATK-NEO-6M GPS模块使用说明》
1. NMEA-0183协议
用于输出
该协议采用ASCII码,其串行通信默认参数为:波特率=4800bps,数据位=8bit,开始位=1bit,停止位=1bit,无奇偶校验。、
数据帧格式:
如:$aaccc,ddd,ddd,…,ddd*hh<CR><LF>
1、“$”——帧命令起始位
2、aaccc——地址域,前两位为识别符,后三位为语句名
3、ddd…ddd——数据
4、“*”——校验和前缀
5、hh——校验和(check sum),$与*之间所有字符ASCII码的校验和(各字节做异或运算,得到校验和后,再转换16进制格式的ASCII字符。)
6、<CR><LF>——CR(Carriage Return) + LF(Line Feed)帧结束,回车和换行。
1、“$”——帧命令起始位
2、aaccc——地址域,前两位为识别符,后三位为语句名
3、ddd…ddd——数据
4、“*”——校验和前缀
5、hh——校验和(check sum),$与*之间所有字符ASCII码的校验和(各字节做异或运算,得到校验和后,再转换16进制格式的ASCII字符。)
6、<CR><LF>——CR(Carriage Return) + LF(Line Feed)帧结束,回车和换行。
2. UBX协议
用于配置
UBX码是u-blox公司UBX就是用串口来控制模块的一种协议,钟对于u-blox的系列产品进行的控制精简代码,输出的代码主要是对模块进行软硬件及功能方面的控制,如模块的冷启动,热启动,温启动,启动模式选择,刷新速率,波特率,定位精度,天线检测等等,均可以通过UBX代码来通过MCU使用COM口来对模块来进行控制。
3. 程序设计
核心代码在usart3.c和gps.c中。
3.1 usart3.c
基本思想:通过判断接收连续2个字符之间的时间差不大于10ms,来决定是不是一次连续的数据。如果2个字符接收间隔超过10ms,则认为不是1次连续数据.也就是超过10ms没有接收到任何数据,则表示此次接收完毕。
详细代码如下:
#include "delay.h" #include "usart3.h" #include "stdarg.h" #include "stdio.h" #include "string.h" #include "timer.h"//串口接收缓存区 u8 USART3_RX_BUF[USART3_MAX_RECV_LEN]; //接收缓冲,最大USART3_MAX_RECV_LEN字节. u8 USART3_TX_BUF[USART3_MAX_SEND_LEN]; //发送缓冲,最大USART3_MAX_SEND_LEN字节//通过判断接收连续2个字符之间的时间差不大于10ms来决定是不是一次连续的数据. //如果2个字符接收间隔超过10ms,则认为不是1次连续数据.也就是超过10ms没有接收到 //任何数据,则表示此次接收完毕. //接收到的数据状态 //[15]:0,没有接收到数据;1,接收到了一批数据. //[14:0]:接收到的数据长度 vu16 USART3_RX_STA=0; void USART3_IRQHandler(void) {u8 res; if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)//接收到数据{ res =USART_ReceiveData(USART3); if((USART3_RX_STA&(1<<15))==0)//接收完的一批数据,还没有被处理,则不再接收其他数据{ if(USART3_RX_STA<USART3_MAX_RECV_LEN) //还可以接收数据{TIM_SetCounter(TIM7,0);//计数器清空 //计数器清空if(USART3_RX_STA==0) //使能定时器7的中断 {TIM_Cmd(TIM7,ENABLE);//使能定时器7}USART3_RX_BUF[USART3_RX_STA++]=res; //记录接收到的值 }else {USART3_RX_STA|=1<<15; //强制标记接收完成} }} } //初始化IO 串口3 //pclk1:PCLK1时钟频率(MHz) //bound:波特率 void usart3_init(u32 bound) { NVIC_InitTypeDef NVIC_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // GPIOB时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //串口3时钟使能USART_DeInit(USART3); //复位串口3//USART3_TX PB10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10//USART3_RX PB11GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB11USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式USART_Init(USART3, &USART_InitStructure); //初始化串口 3USART_Cmd(USART3, ENABLE); //使能串口 //使能接收中断USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断 //设置中断优先级NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器TIM7_Int_Init(99,7199); //10ms中断USART3_RX_STA=0; //清零TIM_Cmd(TIM7,DISABLE); //关闭定时器7}//串口3,printf 函数 //确保一次发送数据不超过USART3_MAX_SEND_LEN字节 void u3_printf(char* fmt,...) {
u16 i,j;
va_list ap; va_start(ap,fmt);vsprintf((char*)USART3_TX_BUF,fmt,ap); //vsprintf,把数据按照fmt格式存入USART3_TX_BUF中,ap为数据头的指针va_end(ap);i=strlen((const char*)USART3_TX_BUF); //此次发送数据的长度for(j=0;j<i;j++) //循环发送数据{while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); //检测这一字节信息是否发送完成,发送完成则进行下一字节的发送USART_SendData(USART3,USART3_TX_BUF[j]); } }
分为3个函数:
1. USART3_IRQHandler串口3的中断处理函数
2. usart3_init 初始化函数
3. u3_printf把要发送的数据存入缓冲区,进行发送
3.2 gps.c
主要负责数据解析
子函数分为NMEA信息解析和UBLOX配置发送。