我们在做一些项目时有时会需要进行GPS定位,获取自身的经纬度信息,这里使用的是中科微电子的GPS模块ATGM336H,带陶瓷天线。
该模块可以实现GPS定位,返回定位点的UTC时间和经纬度信息。
UTC时间是全世界公用的时间,我们用的北京时间比UTC时间快8个小时。
在使用时必须注意以下几点
ATGM336H使用3.3V或者5V供电,利用串口将GPS信息发送出来,我们简单地介绍一下它的几个引脚
PPS引脚这里没有用到,就不再做介绍了,有兴趣的小伙伴可以自行搜索一下它的用途。
ATGM336H利用串口发送定位信息给主控芯片,串口波特率为9600,我们最开始可以先用USB-TTL连接ATGM336H,到空旷地带观察一下它的输出信息,定位成功时接收到的信息如下
我们可以看到,ATGM336H一次会返回许多信息,其实我们只需要关注其中的“GNRMC”这条信息即可,我们简单看一下这条信息。
$GNRMC,015135.000,A,4159.65553,N,12136.79345,E,0.52,0.00,191123,,,A*7F 需要注意的是,这里的经纬度并不能直接拿来在地图上搜索定位,而是需要进行数据转换之后才可以,关于数据抓换,后续的程序设计会详细介绍。
ATGM336H有三种不同的启动模式,不同模式定位成功所需的时间是不同的,我们这里来简单描述一下这几种启动模式
我们在介绍程序设计之前先介绍一下一些必备的前置知识,关于STM32串口的配置这里就不再详细介绍了,具体可以到博主的STM32俗称笔记专栏串口篇查看。这里着重介绍几个C语言中的函数。
strstr函数原型为
char *strstr( const char *str1, const char *str2 ); 该函数是在字符串str1中查找是否含有字符串str2,如果存在,返回str2在str1中第一次出现的地址(指针);否则返回NULL。使用strstr函数时需要包含头文件<string.h>。
值得注意的是,实际输入变量都是指针,如果我们稍加设计,能得到循环查找分隔符的效果,具体可以看后面在解析接收帧信息时的程序设计,这里只介绍一下它的基本用法。
memset函数的函数原型为
void *memset(void *s, int c, size_t n); memset是一个初始化函数,作用是将某一块内存中的全部设置为指定的值。
memcpy函数的函数原型为
void *memcpy(void*dest, const void *src, size_t n); 该函数的功能是将由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。
strtod函数的函数原型为
double strtod(const char *nptr, char **endptr); strtod函数会检查输入的nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,到出现非数字或字符串结束时(‘\0’)才结束转换,并将结果返回,返回值是一个double型数值。
若endptr不为NULL,则会将遇到不合条件而终止的nptr中的字符指针由endptr传回。参数nptr字符串可包含正负号、小数点或E(e)来表示指数部分。
使用该函数时需要包含头文件。
下面我们来进行程序设计,我们用串口1来接收ATGM336H发送来的信息,用串口2将我们解析处理后的GPS信息发送给上位机。
这里用到了两个串口,我们封装一个串口初始化函数用来初始化串口
/*
*==============================================================================
*函数名称:uart_init
*函数功能:初始化USART
*输入参数:UARTx:串口几;bound:波特率
*返回值:无
*备 注:可以修改成输入初始化哪个USART
*==============================================================================
*/ void uart_init(UART_TypeDef UARTx,u32 bound) { // 相关结构体定义 GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure; switch (UARTx)
{ case 0: // 使能USART1,GPIOA时钟 RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); // USART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA.9 // USART1_RX GPIOA.10初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA.10 // Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; // 抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能 NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器 // USART 初始化设置 USART_InitStructure.USART_BaudRate = bound; // 串口波特率 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(USART1, &USART_InitStructure); // 初始化串口1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启串口接收中断 USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); // 使能空闲中断 USART_Cmd(USART1, ENABLE); // 使能串口1 break; case 1: // 使能USART2,GPIOA时钟 RCC_APB1PeriphClockCmd (RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOA, ENABLE); // USART2_TX GPIOA.2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // PA.2 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA.2 // USART2_RX GPIOA.3初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // PA3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA.3 .......
}
} 完整代码可进群免费领取!!!
嵌入式物联网的学习之路非常漫长,不少人因为学习路线不对或者学习内容不够专业而错失高薪offer。不过别担心,我为大家整理了一份150多G的学习资源,基本上涵盖了嵌入式物联网学习的所有内容。点击下方链接,0元领取学习资源,让你的学习之路更加顺畅!记得点赞、关注、收藏、转发哦!