LORA-B1S——串口透传
Lora串口透传例程说明
这个例程实现了串口和lora之间的数据透传。
两块Lora-B1s A和B烧录一样的串口透传固件。A板收到串口的数据以后会通过Lora透传出去,B板Lora收到数据以后会通过串口输出。反过来当B串口收到数据最终也可以通过A板的串口输出。
并且该例程也可以多于两块板子同时工作,这样一个发送,其他的几块都可以收到。
测试时候串口波特率设置为:115200
工作模型如下图所示:
基于LADK工程创建实现步骤
- 拷贝lora-ADK并重新命名为lora-UART
- 在
./user/app
文件夹中新建三个文件uart_lora.c
uart_lora.h
- 把
uart_lora.c
uart_lora.h
添加到MDK工程分组App中 - 在
uart_lora.c
uart_lora.h
中添加应用代码,实现uart透传功能
- 修改main.c 调用uart_lora 接口
- 在stm32g0xx_it.c 中调用串口中断处理函数
- 编译烧录到开发板中
代码分析
app_buffer的关键性
为什么需要一个app_buffer?实际上就是一个缓冲区,因为从串口收过来的数据Lora可能还来不及发送。所以就构成一个生产快,消费慢的情况。
这样设计一个缓冲区就可以很好的解决这个问题,把来不得发送的数据都先缓存起来,在空闲的时候慢慢再发出去。
app_buffer的具体实现就不再详细探讨,有兴趣可以读读我们的源码,可以参考我们另一篇文章《app_buffer的设计》,提供的接口如下:
1 2 3 4 5 6 7 8 9 10 11 |
//用来定义一个app_buffer #define APP_BUFFER_DEF(buffer_obj_name) buffer_obj_t buffer_obj_name; void app_buffer_create(buffer_obj_t* obj, uint8_t *buf,uint16_t buf_len); void app_buffer_flush(buffer_obj_t* obj); uint16_t app_buffer_write_bytes(buffer_obj_t* obj,uint8_t *pdata,uint16_t data_len); uint16_t app_buffer_read_bytes(buffer_obj_t* obj,uint8_t *pdata,uint16_t data_len); uint16_t app_buffer_peek_bytes(buffer_obj_t *obj,uint8_t *pdata,uint16_t data_len); uint16_t app_buffer_write_message(buffer_obj_t* obj,uint8_t *pdata,uint16_t data_len); uint16_t app_buffer_read_message(buffer_obj_t* obj,uint8_t *pdata,uint16_t data_max_len); |
- app_buffer_create:创建一个buffer
- app_buffer_flush:清除buffer内容
- app_buffer_write_bytes:按照bytes写入数据,不可以和buffer_write_message混用
- app_buffer_read_bytes:按照bytes读取数据,不可以和buffer_read_message混用
- app_buffer_write_message:按照message写入数据,这样读取的时候也是直接读出一条message的数据
- app_buffer_read_message:读取一条message的数据
uart_lora的代码实现
lora的发送和接收前面例子已经用的次数比较多,比较熟悉,重点就在于串口数据的接收。
串口可能会同时收到多个byte数据,那总不能一个个byte通过lora往外传,这样的效率太低。所以接收一帧串口数据,就把这一帧的数据统一通过Lora发送出去。
这一帧数据的区分,就用到了stm32G0系列的一个接收超时中断。当连续接收时候把收到的数据先存入数组,然后一旦产生了超时中断。则把数组中的一包数据通过buffer_write_message
写入到buffer。
在主循环里面就不断的调用buffer_read_message
从buffer中取一条message数据,如果取到就从Lora发送出去。
这是串口中断服务函数的代码,用到三个中断:
- 接收溢出出错中断
- 接收完成中断
- 接收超时中断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
void u2l_handler(void) { uint8_t ch=0; if ((__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_RXNE)) && (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE))) { __HAL_UART_CLEAR_FLAG(&huart1,UART_CLEAR_OREF); } if ((__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_RXNE)) && (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE))) { ch= huart1.Instance->RDR; if(rx_counter<UART_RX_BUF_SIZE) { rx_buf[rx_counter++]=ch; } } if ((__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_RTO)) && (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RTOF))) { __HAL_UART_CLEAR_FLAG(&huart1,UART_CLEAR_RTOF); buffer_write_message(&u2l_buf_obj,rx_buf,rx_counter); rx_counter=0; } } |
主逻辑代码就很简单了,被while(1)循环不停调用就可以:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
void u2l_process() { Radio.IrqProcess(); if(lora_sending==false) { tx_counter=buffer_read_message(&u2l_buf_obj,tx_buf,LORA_TX_BUF_SIZE); if(tx_counter>0) { lora_sending=true; Radio.Send(tx_buf,tx_counter); } } } |
在Lora接收完成回调函数里面,可以直接把数据通过串口发送接口函数发出:
1 2 3 4 5 6 7 |
static void lora_rx_done_callback( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); HAL_UART_Transmit(&huart1,payload,size,0xffff); Radio.Rx(5000); } |
LORA-B1S支持
淘宝购买地址:
https://item.taobao.com/item.htm?&id=657480900713
Lora技术支持群:
QQ群:603253865
LORA-B1S专栏
源码下载地址,最新文档都会更新在专栏内,欢迎大家订阅收藏