diff --git a/Hardware/esp32s/esp32s.c b/Hardware/esp32s/esp32s.c new file mode 100644 index 0000000..72fccba --- /dev/null +++ b/Hardware/esp32s/esp32s.c @@ -0,0 +1,54 @@ +/** + * @file esp32s.c + * @author Myth + * @version 0.1 + * @date 2021.10.16 + * @brief ESP32-S 库 + */ + +#include "uart.h" + +#include "esp32s.h" + +/** + * @brief 初始化 ESP32-S,请在 UART_Init 后调用 + */ +void ESP32S_Init(void) +{ +} + +/** + * @brief 向 ESP32-S 发送数据。数据放到发送缓冲区后立即返回,由中断服务程序在后台完成发送 + * @param pdata: 待发送的数据缓冲区 + * @param len : 数据长度 + */ +void ESP32S_Send(uint8_t *pdata, uint8_t len) +{ + UART_SendBuff(ESP32S_COM, pdata, len); +} + +/** + * @brief 从 ESP32-S 接收一字节 + * @param pbyte: 存放接收字节位置的指针 + * @retval 0 表示无数据,1 表示读取到有效字节 + */ +uint8_t ESP32S_ReceiveByte(uint8_t *pbyte) +{ + return UART_GetChar(ESP32S_COM, pbyte); +} + +/** + * @brief 清空 ESP32-S 接收缓冲区 + */ +void ESP32S_ClearRx(void) +{ + UART_ClearRxFIFO(ESP32S_COM); +} + +/** + * @brief 清空 ESP32-S 发送缓冲区 + */ +void ESP32S_ClearTx(void) +{ + UART_ClearTxFIFO(ESP32S_COM); +} diff --git a/Hardware/esp32s/esp32s.h b/Hardware/esp32s/esp32s.h new file mode 100644 index 0000000..59c78f2 --- /dev/null +++ b/Hardware/esp32s/esp32s.h @@ -0,0 +1,26 @@ +/** + * @file esp32s.h + * @author Myth + * @version 0.1 + * @date 2021.10.16 + * @brief ESP32-S 库 + */ + +#ifndef _ESP32S_H +#define _ESP32S_H + +#include "sys.h" + +#define ESP32S_COM COM2 + +void ESP32S_Init(void); + +void ESP32S_Send(uint8_t *pdata, uint8_t len); + +uint8_t ESP32S_ReceiveByte(uint8_t *pbyte); + +void ESP32S_ClearRx(void); + +void ESP32S_ClearTx(void); + +#endif diff --git a/Libraries/SX1278 b/Libraries/SX1278 index a7a4236..d57a2a8 160000 --- a/Libraries/SX1278 +++ b/Libraries/SX1278 @@ -1 +1 @@ -Subproject commit a7a42360525ea26f45b459f37c06580706f030b6 +Subproject commit d57a2a85dfd2d34f91483ad0ad6ede816c7c2e84 diff --git a/Project/MasterNode.uvprojx b/Project/MasterNode.uvprojx index ef70e95..8aa537e 100644 --- a/Project/MasterNode.uvprojx +++ b/Project/MasterNode.uvprojx @@ -339,7 +339,7 @@ USE_HAL_DRIVER, STM32F103x6 - ..\Core;..\Libraries\HAL_Lib\Inc;..\Libraries\SoftSPI_HAL_Lib;..\Libraries\SX1278\driver;..\User\Main;..\System\sys;..\System\systick;..\System\uart;..\Hardware\led;..\Hardware\lora + ..\Core;..\Libraries\HAL_Lib\Inc;..\Libraries\SoftSPI_HAL_Lib;..\Libraries\SX1278\driver;..\User\Main;..\System\sys;..\System\systick;..\System\uart;..\Hardware\led;..\Hardware\lora;..\Hardware\esp32s @@ -698,6 +698,11 @@ 1 ..\Hardware\lora\lora.c + + esp32s.c + 1 + ..\Hardware\esp32s\esp32s.c + diff --git a/System/uart/uart.c b/System/uart/uart.c index d385a42..8b42a96 100644 --- a/System/uart/uart.c +++ b/System/uart/uart.c @@ -10,7 +10,6 @@ #include "stdio.h" -#include "sys.h" #include "systick.h" #include "uart.h" diff --git a/System/uart/uart.h b/System/uart/uart.h index b01aa7e..bc594c6 100644 --- a/System/uart/uart.h +++ b/System/uart/uart.h @@ -15,6 +15,8 @@ #ifndef __UART_H #define __UART_H +#include "sys.h" + //注释此处语句可禁用特定串口 #define UART1_FIFO_EN 1 #define UART2_FIFO_EN 1 @@ -35,8 +37,8 @@ typedef enum #if UART2_FIFO_EN == 1 #define UART2_BAUD 115200 -#define UART2_TX_BUF_SIZE 1 * 64 -#define UART2_RX_BUF_SIZE 1 * 64 +#define UART2_TX_BUF_SIZE 1 * 512 +#define UART2_RX_BUF_SIZE 1 * 512 #endif //回调函数定义 diff --git a/User/Main/main.c b/User/Main/main.c index bc3c9cf..fa03fcf 100644 --- a/User/Main/main.c +++ b/User/Main/main.c @@ -1,24 +1,39 @@ /** * @file main.c * @author Myth - * @version 0.8 - * @date 2021.10.15 + * @version 1.0 + * @date 2021.10.17 * @brief 工程主函数文件 * @details 初始化及主循环 * @note 此版本实现功能: - * 串口回显,回显时 PC13 上的 LED 闪烁 - * LoRa 模块发送 hello, world + * 网关(本机)通过 LoRa 模块轮流向其它 4 个节点请求数据,节点将数据返回给主节点 + * 收到有效数据后,网关通过 ESP32-S 的串口透传模式,将数据发送给 TCP 服务器 + * + * 基本流程: + * 发送采集指令 -> 在等待过程中将上一次采集的数据发送 -> 收到本次采集的数据 + * -> 若上一次采集的数据仍未发送成功则重试 -> 发送下一次采集指令 + * * JTAG 已禁用,请使用 SWD 调试 */ +#include "stdio.h" + #include "sys.h" #include "systick.h" #include "uart.h" #include "led.h" #include "lora.h" +#include "esp32s.h" -void Echo(uint8_t byte); +typedef struct +{ + uint8_t seq; + float humi; + float temp; + float light; + uint8_t end; +} DataPack; //数据包定义,由于平台相同,网关和节点通讯无需考虑对齐问题 int main(void) { @@ -31,35 +46,99 @@ int main(void) SysTick_Init(); //初始化 SysTick 和软件定时器 UART_Init(); //初始化串口 - LED_Init(); //初始化 LED - LoRa_Init(); //初始化 LoRa 模块 + LED_Init(); //初始化 LED + LoRa_Init(); //初始化 LoRa 模块 + ESP32S_Init(); //初始化 ESP32-S 模块 - UART_BindReceiveHandle(COM1, Echo); //绑定 COM1 串口接收中断至 Echo 函数 + uint8_t current_seq = '2'; //起始时向 2 号子节点查询 + uint8_t control_bytes[3] = {'#', '2', '@'}; //查询数据序列,子节点校验此序列判断自己是否为接收方 - uint8_t str[] = "hello, world"; + DataPack pack; //接收到的数据包 + uint8_t size; //数据包大小,用以校验数据包是否正确 + + int32_t time; //时间,控制时序 + + uint8_t send_buff[50]; //通过 ESP32-S 上行数据缓冲区 + uint8_t send_len; //上行数据长度 + uint8_t receive_byte; // TCP 回传的字节 + uint8_t send_times = 0; // TCP 发送次数 + uint8_t is_first_run = 1; //是否为初次运行,此时不存在上一个包 while (1) { //程序主循环 - if (LoRa_Send(str, 13) == 0) //发送 + if (LoRa_Send(control_bytes, 3) == 0) //发送查询数据指令 { Error_Handler(__FILE__, __LINE__); //错误处理 } - LED1_Toggle; + Delay_ms(100); //延时确保发送结束 - Delay_ms(500); + //正确的方式是读取 DIO0 上的发送空中断。由于实验板 DIO0 无法接线,无法判断数据是否发送完毕,因此采用延时 + + time = SysTick_GetRunTime(); //获取当前时间 + ESP32S_ClearRx(); //清接收 FIFO + ESP32S_ClearTx(); //清发送 FIFO + while (SysTick_CheckRunTime(time) < 1000) // 1000ms 时间用以等待子节点返回数据 + { + //在等待 LoRa 模块回传数据的同时,发送上一次收到的包。200ms 发送一次,无阻塞,检测是否有正确返回 + if (!is_first_run && SysTick_CheckRunTime(time) >= send_times * 200) + { + ESP32S_Send(send_buff, send_len); //通过 ESP32-S 发向 TCP 服务器 + send_times++; + + if (ESP32S_ReceiveByte(&receive_byte) && (receive_byte == 'O' || receive_byte == 'K')) + send_times = 255; //标记为 255,表示已正确返回。TCP 服务器应对符合格式的数据返回 OK + + //注意:TCP 服务端实现 + //即使收到测量错误或重复的数据,只要符合 & 格式也应返回 OK + //网关侧并未对数据作合理性判断,如果 TCP 服务端不对不合理数据返回 OK,网关端会认为是网络问题而不断重传 + } + + size = LoRa_Receive(&pack); //由于 DIO0 无法使用,此函数不阻塞,需判断是否接收成功 + if (size < 1) // size = 0,一般为无数据到达 + { + continue; + } + else if (size != sizeof(DataPack) || pack.seq != current_seq || pack.end != '@') //判断数据包是否正确,是否来自要查询的节点 + { + printf("Wrong Data, Size: %d\n", size); + continue; + } + + LED1_Toggle; //收到有效数据,LED1 翻转 + + //通过 COM1 向电脑发送数据 + printf("Get data:\n"); + printf("%c&%.1f&%.1f&%.1f&\n", pack.seq, pack.humi, pack.temp, pack.light); + + if (!is_first_run && send_times != 255) //上一个包未正确返回,先将上一个包发送完成,防止丢包 + { + while (1) + { + ESP32S_Send(send_buff, send_len); //通过 ESP32-S 发向 TCP 服务器 + if (ESP32S_ReceiveByte(&receive_byte) && (receive_byte == 'O' || receive_byte == 'K')) //检测是否有回传数据证明发送成功 + break; + + Delay_ms(200); //防止发送过快 + } + } + + //生成下一个包,这个包在下次查询时发送 + send_len = sprintf(send_buff, "%c&%.1f&%.1f&%.1f&", pack.seq, pack.humi, pack.temp, pack.light) + 1; //上行数据 + is_first_run = 0; + send_times = 0; + + break; + } + + //向下一个节点查询,节点范围为 2 ~ 5 共 4 个节点 + current_seq++; + if (current_seq > '5') //一轮查询完成 + current_seq = '2'; + + control_bytes[1] = current_seq; } return 1; } - -/** - * @brief 串口回显函数 - * @param byte: 本次中断接收到的字节 - */ -void Echo(uint8_t byte) -{ - LED1_Slow_Toggle; - UART_SendChar(COM1, byte); -}