Atmega328p按下按键时获取GPS数据问题求助
问题描述
我正在实现按键触发外部中断时获取GPS数据的功能:硬件采用Quectel L80-M39模块连接Atmega328p的RX引脚,按键接PD3引脚。无外部中断时功能正常,但添加中断后无法获取GPS数据,怀疑代码存在问题,以下是我的代码:
#define F_CPU 8000000UL // Defining the CPU Frequency #include <avr/io.h> // Contains all the I/O Register Macros #include <util/delay.h> // Generates a Blocking Delay #include <avr/interrupt.h> #define USART_BAUDRATE 9600 // Desired Baud Rate #define BAUD_PRESCALER (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) void USART_Init() { // Set Baud Rate UBRR0H = (unsigned char)(BAUD_PRESCALER >> 8); UBRR0L = (unsigned char)BAUD_PRESCALER; // Enable Receiver UCSR0B |= (1 << RXEN0); // Set data frame format: asynchronous mode,no parity, 1 stop bit, 8 bit size UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00); } unsigned char USART_ReceivePolling(void) { while (!(UCSR0A & (1 << RXC0))); return UDR0; } void readgps() { uint8_t lati_value[15]; unsigned char LocalData; int i = 0; LocalData = USART_ReceivePolling(); if (LocalData == '$') { LocalData = USART_ReceivePolling(); if (LocalData == 'G') { LocalData = USART_ReceivePolling(); if (LocalData == 'P') { LocalData = USART_ReceivePolling(); if (LocalData == 'G') { LocalData = USART_ReceivePolling(); if (LocalData == 'G') { LocalData = USART_ReceivePolling(); if (LocalData == 'A') { LocalData = USART_ReceivePolling(); if (LocalData == ',') { LocalData = USART_ReceivePolling(); while (LocalData != ',') { LocalData = USART_ReceivePolling(); } LocalData = USART_ReceivePolling(); while (LocalData != ',') { lati_value[i] = LocalData; ++i; LocalData = USART_ReceivePolling(); } PORTD |= (1 << PD2); _delay_ms(100); } } } } } } } else { PORTD &= ~(1 << PD2); } } int main(void) { EICRA |= (1 << ISC10) | (1 << ISC11); // interrupt on rising edge of INT1 EIMSK |= (1 << INT1); // external interrupt enable on INT1 sei(); while (1) { } } ISR(INT1_vect) { if (PIND & (1 << 3)) { DDRD = 0b01110110; USART_Init(); readgps(); } }
问题排查与修复建议
核心问题点
- 中断内初始化USART:GPS模块持续输出数据,中断触发前USART未初始化,会丢失前期数据;且每次中断才初始化,可能错过当前帧数据,同时浪费资源。
- 引脚配置错误:中断内直接设置
DDRD = 0b01110110,将PD3(按键输入)改为输出,导致后续按键无法触发中断。 - 中断阻塞风险:
readgps()采用阻塞式USART读取,中断服务函数长时间阻塞会导致系统无法响应其他事件,甚至卡死。 - 按键无消抖:机械按键的抖动会导致多次触发中断,干扰正常逻辑。
修改后的参考代码
#define F_CPU 8000000UL #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define USART_BAUDRATE 9600 #define BAUD_PRESCALER (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) volatile uint8_t read_gps_flag = 0; // 读取GPS标志位 void USART_Init() { // 设置波特率 UBRR0H = (unsigned char)(BAUD_PRESCALER >> 8); UBRR0L = (unsigned char)BAUD_PRESCALER; // 使能接收器 UCSR0B |= (1 << RXEN0); // 设置帧格式:异步、无校验、1停止位、8位数据 UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00); } unsigned char USART_ReceivePolling(void) { while (!(UCSR0A & (1 << RXC0))); return UDR0; } void readgps() { uint8_t lati_value[15]; unsigned char LocalData; int i = 0; // 清空接收缓冲区残留数据 while(UCSR0A & (1 << RXC0)) { UDR0; } LocalData = USART_ReceivePolling(); if (LocalData == '$') { LocalData = USART_ReceivePolling(); if (LocalData == 'G') { LocalData = USART_ReceivePolling(); if (LocalData == 'P') { LocalData = USART_ReceivePolling(); if (LocalData == 'G') { LocalData = USART_ReceivePolling(); if (LocalData == 'G') { LocalData = USART_ReceivePolling(); if (LocalData == 'A') { LocalData = USART_ReceivePolling(); if (LocalData == ',') { LocalData = USART_ReceivePolling(); while (LocalData != ',') { LocalData = USART_ReceivePolling(); } LocalData = USART_ReceivePolling(); // 限制数组索引,防止越界 while (LocalData != ',' && i < 14) { lati_value[i] = LocalData; ++i; LocalData = USART_ReceivePolling(); } PORTD |= (1 << PD2); _delay_ms(100); PORTD &= ~(1 << PD2); } } } } } } } else { PORTD &= ~(1 << PD2); } read_gps_flag = 0; // 重置标志位 } int main(void) { // 配置引脚:PD3为输入(开启内部上拉),PD2为输出,PD0(RX)保持输入 DDRD = 0b00000100; PORTD |= (1 << PD3); USART_Init(); // 提前初始化USART // 配置INT1为下降沿触发(适配上拉电阻的按键逻辑) EICRA |= (1 << ISC11); EICRA &= ~(1 << ISC10); EIMSK |= (1 << INT1); // 使能INT1中断 sei(); // 开启全局中断 while (1) { // 主循环处理GPS读取,避免中断阻塞 if(read_gps_flag) { readgps(); } } } ISR(INT1_vect) { // 软件消抖,确认按键真实按下 _delay_ms(10); if (!(PIND & (1 << PD3))) { read_gps_flag = 1; } }
内容的提问来源于stack exchange,提问作者Jane Malibiran
相关产品推荐
相关产品推荐

