diff --git a/TaiChi/radioTaiChi.cpp b/TaiChi/radioTaiChi.cpp new file mode 100644 index 0000000..0eac844 --- /dev/null +++ b/TaiChi/radioTaiChi.cpp @@ -0,0 +1,217 @@ +#include + +#include "radioTaiChi.h" + + +//静态变量 +HandleMessageFunction Radio::hm_func; +NeoHWSerial* Radio::NeoSerialX; + + +Radio::Radio() +{ + NeoSerialX = &RADIO_SERIAL_NUM; + + EnableReceiveInterrupt(); +} + + +//打开串口 +void Radio::BeginTransmit(unsigned long baud_rate) +{ + NeoSerialX->begin(RADIO_BAUD_RATE); +} + + +//发送 +void Radio::Send(char* message, uint8_t send_type, uint8_t send_times) +{ + //强制发送,禁用接收中断,防止发送被打断 + if (send_type == FORCE_SEND) + DisableReceiveInterrupt(); + + //生成完整通信包 + char full_message[FULL_MESSAGE_SIZE]; + uint8_t message_length = strlen(message); + char check_str[CHECK_STR_LENGTH + 1]; + + message_length = message_length < MAX_REAL_MESSAGE_SIZE ? message_length : MAX_REAL_MESSAGE_SIZE; + + itoa(message_length, check_str, 10); + + for (uint8_t i = 0, j = 0, k = 0; i < FULL_MESSAGE_SIZE; i++) + { + if (i < BLANK_CHAR_LENGTH) + { + full_message[i] = BLANK_CHAR; + } + else if (i == BLANK_CHAR_LENGTH) + { + full_message[i] = START_CHAR; + } + else if (j < message_length && j < MAX_REAL_MESSAGE_SIZE) + { + full_message[i] = message[j]; + j++; + } + else if (j == message_length || j == MAX_REAL_MESSAGE_SIZE) + { + full_message[i] = CHECK_CHAR; + j++; + } + else if (k < CHECK_STR_LENGTH) + { + full_message[i] = check_str[k]; + k++; + + if (check_str[k] == '\0') + k = CHECK_STR_LENGTH; + } + else + { + full_message[i] = END_CHAR; + } + } + + //发送完整通信包 + for (uint8_t times = 0; times < send_times; times++) + { + NeoSerialX->print(full_message); + } + + #ifdef RADIO_DEBUG + NeoSerial.print("#RADIO: SEND: "); + full_message[FULL_MESSAGE_SIZE - 1] = '\0'; + NeoSerial.print(full_message); + NeoSerial.print(" TIMES: "); + NeoSerial.println(send_times); + #endif + + if (send_type == FORCE_SEND) + EnableReceiveInterrupt(); +} + + +//设置接收回调函数 +void Radio::SetHandleMessageFunction(HandleMessageFunction hm_func) +{ + Radio::hm_func = hm_func; +} + + +//禁用接收中断 +void Radio::DisableReceiveInterrupt() //禁用接收中断 +{ + NeoSerialX->detachInterrupt(); +} + + +//恢复接收中断 +void Radio::EnableReceiveInterrupt() //恢复接收中断 +{ + NeoSerialX->attachInterrupt(Receive); +} + + +//接收,使用中断触发 +bool Radio::Receive(uint8_t ch, uint8_t status) +{ + static long begin_time = millis(); + static bool is_start_record = false; + static bool is_check_record = false; + static bool is_end_record = false; + static char message[FULL_MESSAGE_SIZE]; + static char check_str[CHECK_STR_LENGTH + 1]; + static uint8_t i = 0, j = 0; + + //若上一次中断已在 100 ms前,可以认为当前是一次新的传输 + if (millis() - begin_time > 100) + { + begin_time = millis(); //更新时间 + + is_start_record = false; + is_check_record = false; + is_end_record = false; + } + else + { + begin_time = millis(); //更新时间 + + switch (ch) + { + case START_CHAR: + { + if (is_end_record == false) + { + is_start_record = true; + is_check_record = false; + + //重置字符串 + for (uint8_t k = 0; k < i; k++) + message[k] = '\0'; + for (uint8_t k = 0; k < j; k++) + check_str[k] = '\0'; + + i = 0; + j = 0; + } + } break; + + case CHECK_CHAR: + { + if (is_end_record == false && is_start_record == true) + { + is_start_record = false; + is_check_record = true; + } + } break; + + case END_CHAR: + { + if (is_end_record == false && is_check_record == true) + { + is_check_record = false; + + if (j <= CHECK_STR_LENGTH) + check_str[j] = '\0'; + + if (atoi(check_str) == strlen(message)) //位数校验成功 + { + is_end_record = true; + + #ifdef RADIO_DEBUG + NeoSerial.print("#RADIO: RECEIVE: "); + NeoSerial.println(message); + #endif + + hm_func(message); + } + else //位数校验失败 + { + #ifdef RADIO_DEBUG + NeoSerial.println("#RADIO: RECEIVE FAIL!"); + #endif + } + } + } break; + + default: + { + if (is_start_record == true) + { + if (i < FULL_MESSAGE_SIZE) + message[i] = ch; + i++; + } + else if (is_check_record == true) + { + if (j <= CHECK_STR_LENGTH) + check_str[j] = ch; + j++; + } + } + } + } + + return false; +} \ No newline at end of file diff --git a/TaiChi/radioTaiChi.h b/TaiChi/radioTaiChi.h new file mode 100644 index 0000000..23e351e --- /dev/null +++ b/TaiChi/radioTaiChi.h @@ -0,0 +1,64 @@ +#ifndef RADIOTAICHI_H +#define RADIOTAICHI_H + + +#include +#include + +//注释以关闭调试功能 +#define RADIO_DEBUG + +//默认与 HC-12 连接串口 +#define RADIO_SERIAL_NUM NeoSerial2 +//与 HC-12 串口通信波特率 +#define RADIO_BAUD_RATE 9600 + +//通信包大小 +#define FULL_MESSAGE_SIZE 50 +//通信包最大有效信息大小 +#define MAX_REAL_MESSAGE_SIZE 41 +//通信包前段空字符填充长度 +#define BLANK_CHAR_LENGTH 4 +//通信包校验段字符串长度 +#define CHECK_STR_LENGTH 2 +//通信包标志字符 +#define BLANK_CHAR '~' +#define START_CHAR '!' +#define CHECK_CHAR '@' +#define END_CHAR '#' +#define SUCCUESS_CHAR '$' +#define FAIL_CHAR '%' + +//发送相关宏 +#define FORCE_SEND 0 //强制发送 +#define NO_FORCE_SEND 1 //非强制发送 + +#define DEFAULT_SEND_TIMES 1 //默认重复发送次数 + + +//回调函数指针 +typedef void (*HandleMessageFunction)(char*); + + +class Radio +{ +public: + Radio(); + + static void BeginTransmit(unsigned long baud_rate = RADIO_BAUD_RATE); //打开串口 + + static void Send(char* message, uint8_t send_type = NO_FORCE_SEND, uint8_t send_times = DEFAULT_SEND_TIMES); //发送 + + static void SetHandleMessageFunction(HandleMessageFunction hm_func); //设置接收回调函数 + static void DisableReceiveInterrupt(); //禁用接收中断 + static void EnableReceiveInterrupt(); //恢复接收中断 +private: + static bool Receive(uint8_t ch, uint8_t status); //接收,使用中断触发 + + static HandleMessageFunction hm_func; //接收回调函数 + + static NeoHWSerial* NeoSerialX; +}; + + +#endif \ No newline at end of file