【为什么单片机串口无法收到GPS模块输出的串口数据?】

【故障现象】

家里的车载电子狗闲置多年了,拆开把GPS模块取出来准备做个户外手持的小东东。这个GPS模块足够简单,就三根线:VCC、GND和LVTTL串口输出。把串口输出信号连到CH340G的USB转接头,PC机能正常接收到NMEA-183格式的卫星电文。但是,连接到单片机的串口RX端,则无法接收到任何数据!

【问题排查】

一开始还以为是软件编写有BUG,但排查后与软件代码无关。用示波器观察GPS模块输出的串口数据引脚: 悬空测量,电平在0V~3V之间变化;连接至单片机或USB转换头,电平则在1V~3V之间变化!从现象来看,应该是GPS模块信号输出的驱动能力不足导致的

【解决方案】

先后尝试了3种方法:

1、输出引脚串1K电阻,试图降低电流——失败。低电平仍然超过1V,单片机接收失败。

2、增加1K上拉电阻,同时串入1N4148二极管,试图加大低电平的灌电流——失败。低电平未改善。

3、单片机I/O引脚属性设置由默认的“准双向口”改为“高阻输入” ,试图降低负载(以单片机STC8G1K08A的P3.0口为例: P3M0 &= ~0x01; P3M1 &= ~0x01 )——成功解决!示波器上串口信号的低电平降为0V,单片机接收正常!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要解析GPS数据,需要了解NMEA协议。NMEA协议是一种标准的GPS数据格式,其中包含了GPS接收机的位置、速度等信息。 在STM32单片机上通过串口接收GPS模块发送的数据,可以按照以下步骤进行解析: 1. 配置串口,使其能够接收GPS模块发送的数据。 2. 通过串口接收数据,并将数据存储到一个缓冲区中。 3. 对缓冲区中的数据进行解析,找到NMEA协议中的位置信息。 4. 将位置信息解析出来,并进行处理。 以下是一个简单的代码示例,可以帮助你实现这一任务: ```c #include "stm32f10x.h" #include <string.h> #define GPS_BUFFER_SIZE 256 #define GPS_MESSAGE_SIZE 64 char gpsBuffer[GPS_BUFFER_SIZE]; int gpsBufferIndex = 0; void USART1_IRQHandler(void) { if (USART1->SR & USART_SR_RXNE) { char c = USART1->DR; if (gpsBufferIndex < GPS_BUFFER_SIZE - 1) { gpsBuffer[gpsBufferIndex++] = c; } } } void parseGPSData(char *data, int size) { char message[GPS_MESSAGE_SIZE]; int messageIndex = 0; int commaCount = 0; float latitude = 0; float longitude = 0; float altitude = 0; for (int i = 0; i < size; i++) { char c = data[i]; if (c == '$') { messageIndex = 0; commaCount = 0; } else if (c == ',' && messageIndex < GPS_MESSAGE_SIZE - 1) { message[messageIndex] = '\0'; messageIndex = 0; commaCount++; if (commaCount == 3 && strcmp(message, "GGA") == 0) { // Found GGA message char *latitudeString = strtok(NULL, ","); char *latitudeDirection = strtok(NULL, ","); char *longitudeString = strtok(NULL, ","); char *longitudeDirection = strtok(NULL, ","); char *altitudeString = strtok(NULL, ","); if (latitudeString != NULL && latitudeDirection != NULL && longitudeString != NULL && longitudeDirection != NULL && altitudeString != NULL) { // Parse latitude float latitudeDegrees = atof(latitudeString) / 100; float latitudeMinutes = latitudeDegrees - (int)latitudeDegrees; latitude = ((int)latitudeDegrees) + latitudeMinutes * 100 / 60; if (*latitudeDirection == 'S') { latitude = -latitude; } // Parse longitude float longitudeDegrees = atof(longitudeString) / 100; float longitudeMinutes = longitudeDegrees - (int)longitudeDegrees; longitude = ((int)longitudeDegrees) + longitudeMinutes * 100 / 60; if (*longitudeDirection == 'W') { longitude = -longitude; } // Parse altitude altitude = atof(altitudeString); } } } else if (c != ',' && messageIndex < GPS_MESSAGE_SIZE - 1) { message[messageIndex++] = c; } } // Do something with the latitude, longitude, and altitude values } int main(void) { // Configure USART1 for GPS module communication RCC->APB2ENR |= RCC_APB2ENR_USART1EN; RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; GPIOA->CRH |= GPIO_CRH_MODE9_1 | GPIO_CRH_CNF9_1; GPIOA->CRH &= ~(GPIO_CRH_MODE9_0 | GPIO_CRH_CNF9_0); USART1->BRR = SystemCoreClock / 9600; USART1->CR1 |= USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE; NVIC_EnableIRQ(USART1_IRQn); while (1) { // Check for new GPS data if (gpsBufferIndex > 0) { // Process GPS data parseGPSData(gpsBuffer, gpsBufferIndex); // Reset GPS buffer gpsBufferIndex = 0; memset(gpsBuffer, 0, sizeof(gpsBuffer)); } } } ``` 在上述代码中,我们使用了USART1串口接收GPS模块发送的数据。在USART1的中断处理函数中,我们将接收到数据存储到缓冲区中。在主函数中,我们不断检查缓冲区是否有新的数据,如果有,则对数据进行解析。解析过程中,我们使用了strtok函数来提取NMEA协议中的位置信息,并进行解析和处理。 需要注意的是,上述代码仅供参考,实际应用中可能需要根据具体的GPS模块和需求进行修改。同时,由于GPS数据量较大,需要注意缓冲区的大小和处理效率。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值