第一次拿到正点原子的ATK-LORA-01模块时,我和大多数嵌入式开发者一样,既兴奋又有点懵。这个火柴盒大小的模块,居然能实现几公里远的无线通信?后来我才明白,这就是LoRa技术的魅力所在。
简单来说,LoRa(Long Range Radio)是一种低功耗广域网络技术。它最大的特点就是通信距离远、功耗低。ATK-LORA-01模块就是基于LoRa技术的一款无线串口透传模块。你可以把它想象成一个"无线版的串口线"——一端发送数据,另一端就能收到,完全不需要考虑复杂的无线通信协议。
这个模块的工作频率是433MHz(国内免许可频段),支持多种传输速率(从0.3kbps到19.2kbps)。传输速率越低,通信距离越远,实测在开阔地带最远能到3公里。模块支持AT指令配置,默认波特率是115200,但可以根据需要调整。
我特别喜欢它的透传模式。在这个模式下,模块对用户完全透明,你只需要像操作普通串口一样收发数据就行,所有无线通信的细节都被模块自动处理了。这对于快速原型开发特别友好。
ATK-LORA-01模块有6个主要引脚:
我使用的是STM32F103开发板,连接方式如下:
这里有个坑要注意:模块的RXD要接MCU的TX,TXD接MCU的RX,千万别接反了。我第一次就接反了,调试了半天才发现问题。
模块通过串口通信,所以首先要初始化USART。我用的是USART3,配置代码如下:
c复制static void LoRa_USART_Config(u32 bound) {
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 使能GPIO和USART时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
// 配置GPIO复用功能
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
// 配置GPIO
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_10;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 配置USART参数
USART_InitStructure.USART_BaudRate = bound;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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);
// 使能USART
USART_Cmd(USART3, ENABLE);
}
这段代码配置了USART3工作在8位数据位、无校验位、1位停止位的模式,波特率通过参数传入。特别注意要配置GPIO的复用功能,否则数据无法正常传输。
ATK-LORA-01模块的所有配置都是通过AT指令完成的。AT指令是一种常见的设备控制协议,格式通常是"AT+指令名=参数"。
几个关键点:
下面是我实际项目中用到的几个关键AT指令:
c复制// 设置工作信道为23,空中速率19.2kbps
LoRa_SendString("AT+WLRATE=23,5\r\n");
SysTick_Delay_Ms(100);
// 设置串口参数:波特率9600,8数据位,无校验,1停止位
LoRa_SendString("AT+UART=3,0\r\n");
SysTick_Delay_Ms(100);
// 设置发射功率为20dBm(最大功率)
LoRa_SendString("AT+TPOWER=3\r\n");
SysTick_Delay_Ms(100);
// 设置为透传模式
LoRa_SendString("AT+TMODE=0\r\n");
SysTick_Delay_Ms(100);
每个指令发送后要留出足够的时间让模块处理。我一般给100ms的延迟,这个时间可以根据实际情况调整。
结合前面的硬件初始化,完整的模块配置函数如下:
c复制void LoRa_Set(void) {
// 初始化GPIO
LoRa_GPIO_Init();
// 初始化串口,默认115200
LoRa_USART_Config(115200);
// 等待模块就绪(AUX引脚变高)
while(LORA_AUX);
// 进入配置模式
LORA_MD0 = 1;
SysTick_Delay_Ms(100);
// 发送配置指令
LoRa_SendString("AT+WLRATE=23,5\r\n");
SysTick_Delay_Ms(100);
LoRa_SendString("AT+UART=3,0\r\n");
SysTick_Delay_Ms(100);
LoRa_SendString("AT+TPOWER=3\r\n");
SysTick_Delay_Ms(100);
LoRa_SendString("AT+TMODE=0\r\n");
SysTick_Delay_Ms(100);
// 退出配置模式
LORA_MD0 = 0;
SysTick_Delay_Ms(100);
// 重新初始化串口为配置后的波特率(9600)
LoRa_USART_Config(9600);
}
这个函数完成了从硬件初始化到参数配置的全过程。特别注意最后要重新初始化串口,因为我们在配置中修改了波特率。
模块配置完成后,数据发送就非常简单了。因为工作在透传模式,直接往串口发送数据就行:
c复制void LoRa_Usart_Send(u8 *data, uint16_t len) {
for(int i=0; i<len; i++) {
USART_SendData(USART3, data[i]);
while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
}
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
}
这个函数可以发送任意长度的数据。我在实际项目中用它来传输传感器数据,效果很稳定。
接收数据需要通过串口中断实现。下面是我的中断处理函数:
c复制uint8_t RxBuffer[256];
uint16_t RxCounter = 0;
void USART3_IRQHandler(void) {
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) {
uint8_t data = USART_ReceiveData(USART3);
// 简单的数据缓存
if(RxCounter < sizeof(RxBuffer)) {
RxBuffer[RxCounter++] = data;
}
// 可以根据需要添加帧头帧尾判断等
}
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
}
对于简单的应用,可以直接在中断里处理数据。如果是复杂协议,建议先缓存数据,然后在主循环中解析。
在调试LoRa模块时,我总结了几个实用技巧:
串口调试助手:在电脑上用串口调试助手直接连接模块,手动发送AT指令测试,确认模块正常工作后再写代码。
LED指示灯:我在开发板上加了一个LED,每次收到数据就让LED翻转,这样能直观看到通信状态。
距离测试:配置完成后,逐步增加两个模块之间的距离,测试通信稳定性。记得在不同的环境中测试(开阔地带、室内、有障碍物等)。
功耗测量:用万用表测量模块在不同模式下的电流,特别是休眠模式下的电流,这对电池供电的应用很重要。
天线方向:LoRa通信对天线方向比较敏感,调试时可以尝试旋转天线找到最佳位置。
遇到问题时,首先检查硬件连接是否正确,然后确认AT指令格式是否正确(特别是\r\n),最后再检查软件逻辑。我遇到的90%的问题都是前两步导致的。