【STM32外設系列】GPS定位模塊(ATGM336H)
一、GPS模塊簡介
??我們在做一些項目時有時會需要進行GPS定位,獲取自身的經緯度信息,這里使用的是中科微電子的GPS模塊ATGM336H,帶陶瓷天線。
?該模塊可以實現GPS定位,返回定位點的UTC時間和經緯度信息。
??UTC時間是全世界公用的時間,我們用的北京時間比UTC時間快8個小時。
??在使用時必須注意以下幾點
- 必須在室外空曠地帶才能進行定位;
- 定位是陶瓷天線上的小圓點必須朝上,上方不要有遮擋物;
- 樓間距也可能會影響定位,樓間距較小的地方可能定位失敗;
二、使用方法
2.1 引腳介紹
??ATGM336H使用3.3V或者5V供電,利用串口將GPS信息發送出來,我們簡單地介紹一下它的幾個引腳
引腳 |
功能 |
VCC |
電源正極(3.3V或5V) |
GND |
電源負極 |
TXD |
串口發送 |
RXD |
串口接收 |
??PPS引腳這里沒有用到,就不再做介紹了,有興趣的小伙伴可以自行搜索一下它的用途。
2.2 數據幀介紹
??ATGM336H利用串口發送定位信息給主控芯片,串口波特率為9600,我們最開始可以先用USB-TTL連接ATGM336H,到空曠地帶觀察一下它的輸出信息,定位成功時接收到的信息如下
??我們可以看到,ATGM336H一次會返回許多信息,其實我們只需要關注其中的“GNRMC”這條信息即可,我們簡單看一下這條信息。
$GNRMC,015135.000,A,4159.65553,N,12136.79345,E,0.52,0.00,191123,,,A*7F
- 消息ID —— $GNRMC
- 定位點的UTC時間 —— 015135.000
- 定位狀態 —— A:定位;V:導航(我們進行定位時,如果該位為A表示數據有效,該位為V表示數據無效)
- 緯度 —— 4159.65553
- 緯度方向 —— N
- 經度 —— 12136.79345
- 經度方向 —— E
??需要注意的是,這里的經緯度并不能直接拿來在地圖上搜索定位,而是需要進行數據轉換之后才可以,關于數據抓換,后續的程序設計會詳細介紹。
2.3 關于不同的啟動方式
??ATGM336H有三種不同的啟動模式,不同模式定位成功所需的時間是不同的,我們這里來簡單描述一下這幾種啟動模式
-
冷啟動
冷啟動是指在一個陌生的環境下啟動 GPS 直到 GPS 和周圍衛星聯系并且計算出坐標的啟動過程。比如我們初次使用,電池耗盡導致星歷信息丟失,或者關機狀態下將接收機移動 1000 公里以上距離再啟動都屬于冷啟動,冷啟動大概需要等待1~2分鐘才能定位成功。 -
溫啟動
溫啟動是指距離上次定位時間超過 2 個小時的啟動,搜星定位時間介于冷啟動和熱啟動之間。 -
熱啟動
熱啟動是指在上次關機的地方沒有過多移動啟動 GPS,但距離上次定位時間必須小于 2 個小時。
三、前置知識
??我們在介紹程序設計之前先介紹一下一些必備的前置知識,關于STM32串口的配置這里就不再詳細介紹了,具體可以到博主的STM32俗稱筆記專欄串口篇查看。這里著重介紹幾個C語言中的函數。
3.1 strstr函數
??strstr函數原型為
char *strstr( const char *str1, const char *str2 );
??該函數是在字符串str1中查找是否含有字符串str2,如果存在,返回str2在str1中第一次出現的地址(指針);否則返回NULL。使用strstr函數時需要包含頭文件<string.h>。
??值得注意的是,實際輸入變量都是指針,如果我們稍加設計,能得到循環查找分隔符的效果,具體可以看后面在解析接收幀信息時的程序設計,這里只介紹一下它的基本用法。
3.2 memset函數
??memset函數的函數原型為
void *memset(void *s, int c, size_t n);
??memset是一個初始化函數,作用是將某一塊內存中的全部設置為指定的值。
- s指向要填充的內存塊。
- c是要被設置的值。
- n是要被設置該值的字符數。
- 返回類型是一個指向存儲區s的指針。
3.3 memcpy函數
??memcpy函數的函數原型為
void *memcpy(void*dest, const void *src, size_t n);
??該函數的功能是將由src指向地址為起始地址的連續n個字節的數據復制到以destin指向地址為起始地址的空間內。
3.4 strtod函數
??strtod函數的函數原型為
double strtod(const char *nptr, char **endptr);
??strtod函數會檢查輸入的nptr字符串,跳過前面的空格字符,直到遇上數字或正負符號才開始做轉換,到出現非數字或字符串結束時(‘\0’)才結束轉換,并將結果返回,返回值是一個double型數值。
??若endptr不為NULL,則會將遇到不合條件而終止的nptr中的字符指針由endptr傳回。參數nptr字符串可包含正負號、小數點或E(e)來表示指數部分。
??使用該函數時需要包含頭文件。
四、程序設計
??下面我們來進行程序設計,我們用串口1來接收ATGM336H發送來的信息,用串口2將我們解析處理后的GPS信息發送給上位機。
4.1 串口初始化程序
??這里用到了兩個串口,我們封裝一個串口初始化函數用來初始化串口
/*
*==============================================================================
*函數名稱: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元領取學習資源,讓你的學習之路更加順暢!記得點贊、關注、收藏、轉發哦!
- 贊