From c7ef237e7e759f86369e5cae52b7afc1ae3f6b48 Mon Sep 17 00:00:00 2001 From: klein1412 <1148878282@qq.com> Date: Thu, 1 Aug 2024 18:16:40 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E7=BB=99=20main.cpp=20=E5=87=86=E5=A4=87?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=B7=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/myBlueTooth/myBlueTooth.cpp | 7 ++++--- PlatformIO_ESP32_oscilloscope/src/main.cpp | 10 +++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp index 9c1e5161..b43b5894 100644 --- a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp +++ b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp @@ -604,7 +604,7 @@ void XHZS_RemoteControlInterruptMode() /************************* XHZS end *************************/ // -/************************* example funtion begin *************************/ +/************************* example begin *************************/ // 开启串口回调函数,需要在蓝牙初始化之前调用 // isEnable = true 开启,false 关闭 // 串口(蓝牙)接收到数据触发回调函数 Uart_onDataReceive() @@ -626,8 +626,9 @@ void test_oscilloscope_send_wave() void test_oscilloscope_input_and_output() { float floatValue1, floatValue2, floatValue3, floatValue4; // 准备数据类型 - char *charData = Uart_getReceiveData(); + char *charData = Uart_getReceiveData(); // 获取蓝牙串口的数据 + // 给通道四输出波形数据 floatValue4 = (floatValue4 > 33 ? -22 : (floatValue4 += 0.1)); // 将字符串中的字段的数值提取出来 // c11:14.12,c12:22,c13:33,c14: 55.66, @@ -640,7 +641,7 @@ void test_oscilloscope_input_and_output() SerialBT.printf("w:%0.2f,%0.2f,%0.2f,%0.2f\r\n", floatValue1, floatValue2, floatValue3, floatValue4); vTaskDelay(50 / portTICK_PERIOD_MS); // 延时函数,可以注释掉 } -/************************* example funtion end *************************/ +/************************* example end *************************/ // /************************* test begin *************************/ struct myStruct diff --git a/PlatformIO_ESP32_oscilloscope/src/main.cpp b/PlatformIO_ESP32_oscilloscope/src/main.cpp index 0cc68d8f..bbc73ec6 100644 --- a/PlatformIO_ESP32_oscilloscope/src/main.cpp +++ b/PlatformIO_ESP32_oscilloscope/src/main.cpp @@ -22,16 +22,12 @@ void setup() void loop() { - // ... + // 使用示波器,不用启用串口中断模式,否则会冲突 + // test_oscilloscope_input_and_output(); - delay(100); + delay(10); } - - - - - /************************* test code area begin *************************/ // char *data = Uart_ReceiveData(); -- Gitee From f7aa55b1c6041371976082182f7d28c78f463237 Mon Sep 17 00:00:00 2001 From: klein1412 <1148878282@qq.com> Date: Fri, 2 Aug 2024 18:35:15 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=81=A5=E6=8E=A7=E5=99=A8=E7=9A=84=E8=BF=94=E5=9B=9E=E5=80=BC?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E6=8A=8A=E6=95=B0=E5=80=BC=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E7=BB=93=E6=9E=84=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/myBlueTooth/myBlueTooth.cpp | 350 +++++++++--------- .../lib/myBlueTooth/myBlueTooth.h | 75 ++-- PlatformIO_ESP32_oscilloscope/src/main.cpp | 32 +- 3 files changed, 256 insertions(+), 201 deletions(-) diff --git a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp index b43b5894..d88d74b8 100644 --- a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp +++ b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp @@ -2,14 +2,15 @@ /************************* blueTooth part *************************/ BluetoothSerial SerialBT; // 蓝牙类实例化 -String BlueToothName = ""; // 蓝牙名称 static char blueToothBuffer[100]; // 接收缓冲区 /************************* XHZS part *************************/ -bool SERIAL_PORT_CALLBACK_FUNCTION_ENABLE = false; // 默认串口关闭 -char RemoteControlDataLength = 0; // 数据长度 -uint8_t DataFormat[8] = {0}; // 遥控器数据格式 +bool SERIAL_PORT_CALLBACK_ENABLE = false; // 默认串口关闭 +bool REMOTE_CONTROL_CALLBACK_ENABLE = false; // 默认遥控器关闭 +// 定义常量替代硬编码 +constexpr char DIGIT_ZERO = 0x30; +constexpr char DIGIT_ONE = 0x31; /************************* blueTooth begin *************************/ @@ -26,13 +27,16 @@ void BTinitialize(const String &deviceName) SerialBT.register_callback(Bluetooth_Event); // 设置事件回调函数 连接 断开 发送 接收 - if (SERIAL_PORT_CALLBACK_FUNCTION_ENABLE == true) + if (SERIAL_PORT_CALLBACK_ENABLE == true) { SerialBT.onData(Uart_onDataReceive); // 测试手柄功能未完成_2024-07-27 - // SerialBT.onData(BTcallbackFunction); + } + else if (REMOTE_CONTROL_CALLBACK_ENABLE == true) + { + SerialBT.onData(RemoteControlOnDataReceive); } SerialBT.begin(deviceName); // Bluetooth device name - BlueToothName = deviceName; + // BlueToothName = deviceName; } /*蓝牙发送浮点数据,转为字符串发送*/ @@ -122,9 +126,16 @@ void BTAuthCompleteCallback(boolean success) // /************************* XHZS begin *************************/ +void getInterruptJoystickvalue_XY(char *receiveBuffer, short *joystick_X, short *joystick_Y); +void RemoteControlInterruptMode(uint8_t *cmd, uint8_t *data, RemoteControlJoystick *Joystick); +void getJoystickValue(short *outputButton, char outputPosition, char *inputButton, char inputPosition); +void getDirectionalPad(short *outputButton, char outputPosition, char *inputButton, char inputPosition); +void getFunctionButtonValue(short *outputButton, char outputPosition, char *inputButton, char inputPosition); + // 当通过UART接收到数据时,此函数将被调用 void Uart_onDataReceive(const uint8_t *dataBuffer, size_t dataSize) { + // 判断接收到的数量 if (dataSize > 0) { SerialBT.write(dataBuffer, dataSize); // 输出到连接的设备 @@ -200,7 +211,7 @@ void SendWave() // line[3] = 0.0; // XHZS_SendWave(line, sizeof(line)); - // vTaskDelay(50 / portTICK_PERIOD_MS); // 延时 100ms + // vTaskDelay(50 / portTICK_PERIOD_MS); // 延时函数可以注释掉 // } // // 输出平行线测试 end ----------------------- @@ -215,7 +226,7 @@ void SendWave() Wave[3] = -cos(i); XHZS_SendWave(Wave, sizeof(Wave)); - vTaskDelay(50 / portTICK_PERIOD_MS); + vTaskDelay(50 / portTICK_PERIOD_MS); // 延时函数可以注释掉 } // 正弦波测试 end ----------------------- } @@ -300,8 +311,6 @@ char OscGetValue(const char *p, const char *name, float *value) return 2; } -/************************* XHZS end *************************/ - // 获取摇杆数据转换为 x and y void getInterruptJoystickvalue_XY(char *receiveBuffer, short *joystick_X, short *joystick_Y) { @@ -318,63 +327,27 @@ void getInterruptJoystickvalue_XY(char *receiveBuffer, short *joystick_X, short // cmd4 = receiveBuffer[3] & 0xF0; data[3] = receiveBuffer[3] & 0x0F; - // 对摇杆数值默认值做了修改,中心数值是0,偏离中心越远数值越大 0~100 + // 对摇杆数值默认值做了修改,中心数值是0,偏离中心越远数值越大 100~0~100 x = (data[0] * 16 + data[1]) - 100; *joystick_X = (x > 0) ? x : -x; y = (data[2] * 16 + data[3]) - 100; *joystick_Y = (y > 0) ? y : -y; } -// /************************************************************** -// *函数名称:test_remote_control -// *简 介:蓝牙数据接收,回调函数 -// *输 入:无 -// *输 出:默认输出按键状态 -// *注意事项:1)蓝牙接收到数据后,会调用此函数,不要在循环中使用,有卡死程序风险 -// 2)回调函数不能有耗时操作,延时操作禁止使用的,会触发看门狗,不断重启 -// 3)打印函数测试使用,注释掉写你的逻辑代码 -// **************************************************************/ - -void test_remote_control(const uint8_t *buffer, size_t size) +// 遥控器中断模式 +void RemoteControlInterruptMode(uint8_t *cmd, uint8_t *data, RemoteControlJoystick *Joystick) { - uint8_t cmd[4] = {0}; - uint8_t data[4] = {0}; - - // 摇杆相关变量 - short left_X = 0, left_Y = 0, right_X = 0, right_Y = 0; - char receiveBuffer[4] = {0}; // 中断接收数据 - char temp = 0; - memcpy(receiveBuffer, buffer, size); - - // 按键接收大小为1,摇杆接收大小为4 - if (size == 4) - { - temp = (receiveBuffer[0] & 0xF0); - // cmd[0] = (temp == 0x10) ? 0x9A : ((temp == 0x50) ? 0X9B : 0x00); - // data[0] = receiveBuffer[0] & 0x0F; - if (temp == 0x10) - { - cmd[0] = 0x9A; - getInterruptJoystickvalue_XY(receiveBuffer, &left_X, &left_Y); - } - else if (temp == 0x50) - { - cmd[0] = 0x9C; - getInterruptJoystickvalue_XY(receiveBuffer, &right_X, &right_Y); - } - } - else if (size == 1) - { - cmd[0] = (receiveBuffer[0] & 0xF0); - data[0] = (receiveBuffer[0] & 0x0F); - } - + // // 遥控器中断指令枚举定义 enum INTERRUPT_MODE_ORDER switch (cmd[0]) { case INTERRUPT_LEFT_UP: // 指令 cmd[0] 数据 data[0] + // 逻辑代码区 begin + SerialBT.printf("%X-%X\r\n", cmd[0], data[0]); + + // 逻辑代码区 end break; case INTERRUPT_LEFT_DOWN: @@ -407,17 +380,17 @@ void test_remote_control(const uint8_t *buffer, size_t size) case INTERRUPT_LEFT_X_Y: // 摇杆数值在 left_X and left_Y - // 逻辑代码区 start + // 逻辑代码区 begin - SerialBT.printf("x: %d y: %d\n", left_X, left_Y); + SerialBT.printf("x: %d y: %d\n", Joystick->left_X, Joystick->left_Y); // 逻辑代码区 end break; case INTERRUPT_RIGHT_X_Y: - // 逻辑代码区 start + // 逻辑代码区 begin - SerialBT.printf("x: %d y: %d\n", right_X, right_Y); + SerialBT.printf("x: %d y: %d\n", Joystick->right_X, Joystick->right_Y); // 逻辑代码区 end break; @@ -447,173 +420,180 @@ void test_remote_control(const uint8_t *buffer, size_t size) break; } } + /* - * 遥控器的界面选择,使用 enum INTERFACE_SIZE - */ -void XHZS_RemoteControlIntialization(INTERFACE_SIZE isDirectionalPad1, - INTERFACE_SIZE isDirectionalPad2, - INTERFACE_SIZE isButtonA, - INTERFACE_SIZE isButtonB, - INTERFACE_SIZE isButtonC, - INTERFACE_SIZE isButtonD, - INTERFACE_SIZE isSwitchE, - INTERFACE_SIZE isSwitchF) +1)蓝牙接收到数据后,会调用此函数,不要在循环中使用,有卡死程序风险 +2)回调函数不能有耗时操作,延时操作禁止使用的,会触发看门狗,不断重启 +*/ +void RemoteControlOnDataReceive(const uint8_t *buffer, size_t size) { - RemoteControlDataLength = isDirectionalPad1 + - isDirectionalPad2 + - isButtonA + - isButtonB + - isButtonC + - isButtonD + - isSwitchE + - isSwitchF; - DataFormat[0] = isDirectionalPad1; - DataFormat[1] = isDirectionalPad2; - DataFormat[2] = isButtonA; - DataFormat[3] = isButtonB; - DataFormat[4] = isButtonC; - DataFormat[5] = isButtonD; - DataFormat[6] = isSwitchE; - DataFormat[7] = isSwitchF; + struct RemoteControlJoystick Joystick = {0}; + uint8_t cmd[4] = {0}; + uint8_t data[4] = {0}; + + char receiveBuffer[4] = {0}; + char temp = 0; + memcpy(receiveBuffer, buffer, size); + + // 判断是否摇杆数据,在进行解释 + if (size == 4) + { + if ((receiveBuffer[0] & 0xF0) == 0x10) + { + cmd[0] = 0x9A; + getInterruptJoystickvalue_XY(receiveBuffer, &Joystick.left_X, &Joystick.left_Y); + } + else if ((receiveBuffer[0] & 0xF0) == 0x50) + { + cmd[0] = 0x9C; + getInterruptJoystickvalue_XY(receiveBuffer, &Joystick.right_X, &Joystick.right_Y); + } + } + else if (size == 1) + { + cmd[0] = (receiveBuffer[0] & 0xF0); + data[0] = (receiveBuffer[0] & 0x0F); + } + RemoteControlInterruptMode(cmd, data, &Joystick); } // 获取摇杆数值 // (inputButton[inputPosition + 0] - 0x30) 把字符转化为数字 -void getJoystickValue(short *outputButton, char outputPosition, char *inputButton, char inputPosition) +void getJoystickValue(short *outputButton, char outputPosition, const char *inputButton, char inputPosition) { - outputButton[outputPosition + 0] = (inputButton[inputPosition + 0] - 0x30) * 100 + - (inputButton[inputPosition + 1] - 0x30) * 10 + - (inputButton[inputPosition + 2] - 0x30) - 100; - outputButton[outputPosition + 0] = ((outputButton[outputPosition + 0]) > 0 ? (outputButton[outputPosition + 0]) : -(outputButton[outputPosition + 0])); - - outputButton[outputPosition + 1] = (inputButton[inputPosition + 3] - 0x30) * 100 + - (inputButton[inputPosition + 4] - 0x30) * 10 + - (inputButton[inputPosition + 5] - 0x30) - 100; - outputButton[outputPosition + 1] = ((outputButton[outputPosition + 1]) > 0 ? (outputButton[outputPosition + 1]) : -(outputButton[outputPosition + 1])); + outputButton[outputPosition] = (inputButton[inputPosition] - DIGIT_ZERO) * 100 + + (inputButton[inputPosition + 1] - DIGIT_ZERO) * 10 + + (inputButton[inputPosition + 2] - DIGIT_ZERO) - 100; + outputButton[outputPosition] = outputButton[outputPosition] > 0 ? outputButton[outputPosition] : -outputButton[outputPosition]; + + outputButton[outputPosition + 1] = (inputButton[inputPosition + 3] - DIGIT_ZERO) * 100 + + (inputButton[inputPosition + 4] - DIGIT_ZERO) * 10 + + (inputButton[inputPosition + 5] - DIGIT_ZERO) - 100; + outputButton[outputPosition + 1] = outputButton[outputPosition + 1] > 0 ? outputButton[outputPosition + 1] : -outputButton[outputPosition + 1]; } // 获取按钮数值 // (inputButton[inputPosition + i] == 0x31) 识别字符是否等于数字的1 -void getDirectionalPad(short *outputButton, char outputPosition, char *inputButton, char inputPosition) +void getDirectionalPad(short *outputButton, char outputPosition, const char *inputButton, char inputPosition) { for (size_t i = 0; i < DIRECTIONAL_PAD_SIZE; i++) { - if (inputButton[inputPosition + i] == 0x31) + if (inputButton[inputPosition + i] == DIGIT_ONE) { outputButton[outputPosition + i] = 1; } } } - // 获取按钮数值 // (inputButton[inputPosition + i] == 0x31) 识别字符是否等于数字的1 -void getFunctionButtonValue(short *outputButton, char outputPosition, char *inputButton, char inputPosition) +void getFunctionButtonValue(short *outputButton, char outputPosition, const char *inputButton, char inputPosition) { for (size_t i = 0; i < FUNCTION_BUTTON_SIZE; i++) { - if (inputButton[inputPosition + i] == 0x31) + if (inputButton[inputPosition + i] == DIGIT_ONE) { outputButton[outputPosition + i] = 1; } } } - -// 遥控器循环模式 -// 数组 outputBuffer[20] 数据格式在枚举 enum LOOP_MODE_ORDER 中定义 -// 返回是数组类型,元素必须大于20个 -short XHZS_RemoteControlLoopMode() +// 专门给 RemoteControlLoopMode 函数打印和测试使用 +void RemoteControlLoopModePritnf(char handle, RemoteControlOutput *outputBuffer) { - short outputBuffer[20] = {0}; // 输出的缓冲区 - char tempBuffer[20] = {0}; // 临时缓冲区 - // 判断手柄的方向按钮和摇杆的组合 - char handle = (DataFormat[0] == JOYSTICK_SIZE ? JOYSTICK_AND_DIRECTIONAL_PAD : TWO_DIRECTIONAL_PAD) + - (DataFormat[1] == JOYSTICK_SIZE ? DIRECTIONAL_PAD_AND_JOYSTICK : TWO_DIRECTIONAL_PAD); - - size_t data_len = strlen(Uart_getReceiveData()); // 获取长度用于复制 - memcpy(tempBuffer, Uart_getReceiveData(), data_len); // 内存复制 - - // 确定,方向按钮和摇杆组合方式 + // 不同的遥控器组合,使用不同显示 // 打印在串口监视器中 switch (handle) { - case TWO_DIRECTIONAL_PAD: - getDirectionalPad(outputBuffer, 0, tempBuffer, 0); - getFunctionButtonValue(outputBuffer, 8, tempBuffer, 8); + case DIRECTIONAL_PAD: + Serial.printf("up: %d down: %d left: %d right: %d - up: %d down: %d left: %d right: %d ", + outputBuffer->LEFT_up, outputBuffer->LEFT_down, outputBuffer->LEFT_left, outputBuffer->LEFT_right, + outputBuffer->RIGHT_up, outputBuffer->RIGHT_down, outputBuffer->RIGHT_left, outputBuffer->RIGHT_right); break; case DIRECTIONAL_PAD_AND_JOYSTICK: - getDirectionalPad(outputBuffer, 0, tempBuffer, 0); - getJoystickValue(outputBuffer, 16, tempBuffer, 4); - getFunctionButtonValue(outputBuffer, 8, tempBuffer, 10); + Serial.printf("up: %d down: %d left: %d right: %d - x: %d y: %d ", + outputBuffer->LEFT_up, outputBuffer->LEFT_down, outputBuffer->LEFT_left, outputBuffer->LEFT_right, + outputBuffer->RIGHT_x, outputBuffer->RIGHT_y); break; case JOYSTICK_AND_DIRECTIONAL_PAD: - getJoystickValue(outputBuffer, 14, tempBuffer, 0); - getDirectionalPad(outputBuffer, 4, tempBuffer, 6); - getFunctionButtonValue(outputBuffer, 8, tempBuffer, 10); + Serial.printf(" x: %d y: %d - up: %d down: %d left: %d right: %d ", + outputBuffer->LEFT_x, outputBuffer->LEFT_y, + outputBuffer->LEFT_up, outputBuffer->LEFT_down, outputBuffer->LEFT_left, outputBuffer->LEFT_right); break; - case TWO_JOYSTICKS: - getJoystickValue(outputBuffer, 14, tempBuffer, 0); - getJoystickValue(outputBuffer, 16, tempBuffer, 6); - getFunctionButtonValue(outputBuffer, 8, tempBuffer, 12); + case JOYSTICKS: + Serial.printf(" x: %d y: %d - x: %d y: %d ", + outputBuffer->LEFT_x, outputBuffer->LEFT_y, outputBuffer->RIGHT_x, outputBuffer->RIGHT_y); + break; } - return *outputBuffer; - // #if true - // 不同的遥控器组合,使用不同显示 // 打印在串口监视器中 + Serial.printf(" A: %d B: %d C: %d D: %d E: %d F: %d \n", + outputBuffer->A, outputBuffer->B, outputBuffer->C, outputBuffer->D, outputBuffer->E, outputBuffer->F); +} + +// 遥控器循环模式 +RemoteControlOutput RemoteControlLoopMode1(MODULE_SIZE RemoteControlLayoutLeft, MODULE_SIZE RemoteControlLayoutRight) +{ + RemoteControlOutput outputBuffer = {}; // 输出的缓冲区 + char tempBuffer[20] = {}; // 临时缓冲区 + // 判断手柄的方向按钮和摇杆的组合 + char handle = (RemoteControlLayoutLeft == JOYSTICK_SIZE ? JOYSTICK_AND_DIRECTIONAL_PAD : DIRECTIONAL_PAD) + + (RemoteControlLayoutRight == JOYSTICK_SIZE ? DIRECTIONAL_PAD_AND_JOYSTICK : DIRECTIONAL_PAD); + + size_t data_len = strlen(Uart_getReceiveData()); // 获取长度用于复制 + memcpy(tempBuffer, Uart_getReceiveData(), data_len); // 内存复制 + + // 确定,方向按钮和摇杆组合方式 switch (handle) { - case TWO_DIRECTIONAL_PAD: - Serial.printf("up: %d down: %d left: %d right: %d - up: %d down: %d left: %d right: %d ", - outputBuffer[LOOP_LEFT_UP], outputBuffer[LOOP_LEFT_DOWN], outputBuffer[LOOP_LEFT_LEFT], outputBuffer[LOOP_LEFT_RIGHT], - outputBuffer[LOOP_RIGHT_UP], outputBuffer[LOOP_RIGHT_DOWN], outputBuffer[LOOP_RIGHT_LEFT], outputBuffer[LOOP_RIGHT_RIGHT]); - + case DIRECTIONAL_PAD: + // 获取结构体的首地址,在基础上移动到指定位置,进行赋值或者读取 + getDirectionalPad(&outputBuffer.LEFT_up, 0, tempBuffer, 0); + getDirectionalPad(&outputBuffer.LEFT_up, 4, tempBuffer, 4); + getFunctionButtonValue(&outputBuffer.LEFT_up, 8, tempBuffer, 8); break; + case DIRECTIONAL_PAD_AND_JOYSTICK: - Serial.printf("up: %d down: %d left: %d right: %d - x: %d y: %d ", - outputBuffer[LOOP_LEFT_UP], outputBuffer[LOOP_LEFT_DOWN], outputBuffer[LOOP_LEFT_LEFT], outputBuffer[LOOP_LEFT_RIGHT], - outputBuffer[LOOP_RIGHT_X], outputBuffer[LOOP_RIGHT_Y]); + getDirectionalPad(&outputBuffer.LEFT_up, 0, tempBuffer, 0); + getJoystickValue(&outputBuffer.LEFT_up, 16, tempBuffer, 4); + getFunctionButtonValue(&outputBuffer.LEFT_up, 8, tempBuffer, 10); break; + case JOYSTICK_AND_DIRECTIONAL_PAD: - Serial.printf(" x: %d y: %d - up: %d down: %d left: %d right: %d ", - outputBuffer[LOOP_LEFT_X], outputBuffer[LOOP_LEFT_Y], - outputBuffer[LOOP_RIGHT_UP], outputBuffer[LOOP_RIGHT_DOWN], outputBuffer[LOOP_RIGHT_LEFT], outputBuffer[LOOP_RIGHT_RIGHT]); + getJoystickValue(&outputBuffer.LEFT_up, 14, tempBuffer, 0); + getDirectionalPad(&outputBuffer.LEFT_up, 4, tempBuffer, 6); + getFunctionButtonValue(&outputBuffer.LEFT_up, 8, tempBuffer, 10); break; - case TWO_JOYSTICKS: - Serial.printf("x: %d y: %d - x: %d y: %d ", - outputBuffer[LOOP_LEFT_X], outputBuffer[LOOP_LEFT_Y], - outputBuffer[LOOP_RIGHT_X], outputBuffer[LOOP_RIGHT_Y]); + + case JOYSTICKS: + getJoystickValue(&outputBuffer.LEFT_up, 14, tempBuffer, 0); + getJoystickValue(&outputBuffer.LEFT_up, 16, tempBuffer, 6); + getFunctionButtonValue(&outputBuffer.LEFT_up, 8, tempBuffer, 12); break; } - Serial.printf(" A: %d B: %d C: %d D: %d E: %d F: %d \n", - outputBuffer[LOOP_BUTTON_A], - outputBuffer[LOOP_BUTTON_B], - outputBuffer[LOOP_BUTTON_C], - outputBuffer[LOOP_BUTTON_D], - outputBuffer[LOOP_BUTTON_E], - outputBuffer[LOOP_BUTTON_F]); - // #endif -} - -// 遥控器中断模式 -void XHZS_RemoteControlInterruptMode() -{ - // 准备整合 + RemoteControlLoopModePritnf(handle, &outputBuffer); + return outputBuffer; } /************************* XHZS end *************************/ // /************************* example begin *************************/ -// 开启串口回调函数,需要在蓝牙初始化之前调用 // isEnable = true 开启,false 关闭 -// 串口(蓝牙)接收到数据触发回调函数 Uart_onDataReceive() -// 底层 blueTooth 库中 onData() 函数绑定回调函数 Uart_onDataReceive() 函数作为触发调用 -// 找到 Uart_onDataReceive() 在里面写你的逻辑代码,不要有延时操作,中断函数中不能有延时操作 -// 在不使用串口功能时,请关闭防止与其它功能模块的冲突 -void test_serial_port_callback_function(bool isEnable) +/** + * @brief 启用或禁用串口回调机制 + * + * 此函数应在蓝牙初始化前调用,以配置串口(蓝牙)接收数据时的行为。 + * 当 isEnable 设置为 true 时,开启串口回调;设置为 false 时,则禁用。 + * + * 在底层蓝牙库中,onData() 函数将绑定 Uart_onDataReceive() 作为其回调,从而在接收到数据时触发相应的处理逻辑。 + * + * 注意:Uart_onDataReceive() 函数中不应包含任何延时操作,因其可能在中断上下文中执行。 + * + * 在不使用串口功能时,务必将其关闭,以避免与其他功能模块产生潜在冲突。 + */ +void test_serial_port_callback_enable(bool isEnable) { - SERIAL_PORT_CALLBACK_FUNCTION_ENABLE = isEnable; + SERIAL_PORT_CALLBACK_ENABLE = isEnable; } // 发送波形数据的函数例子 @@ -622,15 +602,19 @@ void test_oscilloscope_send_wave() SendWave(); } -// 示波器输入和输出案例 -void test_oscilloscope_input_and_output() + +/** + * @brief 示波器输入和输出案例 + * + */ +void test_oscilloscope_send_and_Receive() { float floatValue1, floatValue2, floatValue3, floatValue4; // 准备数据类型 char *charData = Uart_getReceiveData(); // 获取蓝牙串口的数据 // 给通道四输出波形数据 floatValue4 = (floatValue4 > 33 ? -22 : (floatValue4 += 0.1)); - // 将字符串中的字段的数值提取出来 + // 将字符串中的字段的数值提取出来,字符串格式为:下方 // c11:14.12,c12:22,c13:33,c14: 55.66, // c13字段,数值为33 OscGetValue(charData, "c11", &floatValue1); @@ -641,9 +625,32 @@ void test_oscilloscope_input_and_output() SerialBT.printf("w:%0.2f,%0.2f,%0.2f,%0.2f\r\n", floatValue1, floatValue2, floatValue3, floatValue4); vTaskDelay(50 / portTICK_PERIOD_MS); // 延时函数,可以注释掉 } + +/** + * @brief 启用或禁用,遥控器的回调函数,非定时模式有用 + * + * 此函数应在蓝牙初始化前调用,以配置串口(蓝牙)接收数据时的行为。 + * 当 isEnable 设置为 true 时,开启串口回调;设置为 false 时,则禁用。 + */ +void test_remote_control_callback_enable(bool isEnable) +{ + REMOTE_CONTROL_CALLBACK_ENABLE = isEnable; +} + +/** + * @brief 遥控器的定时发送模式 + * + * + */ +void test_remote_control_loop_mode() +{ + // short shortArray[18] = {RemoteControlLoopMode(DIRECTIONAL_PAD_SIZE, JOYSTICK_SIZE)}; +} + /************************* example end *************************/ // /************************* test begin *************************/ + struct myStruct { char a; @@ -653,6 +660,9 @@ struct myStruct char e; }; +/* +如何把结构体像数组一样使用? +*/ void test_struct_array() { myStruct box = {}; diff --git a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h index 5f8096a2..4bbdbdc2 100644 --- a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h +++ b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h @@ -12,6 +12,31 @@ #include // 字符串操作库 #include // ESP32蓝牙库 +struct RemoteControlOutput +{ + short LEFT_up; // 0 + short LEFT_down; + short LEFT_left; + short LEFT_right; + + short RIGHT_up; + short RIGHT_down; + short RIGHT_left; + short RIGHT_right; // 7 + + short A; // 8 + short B; + short C; + short D; + short E; + short F; // 13 + + short LEFT_x; // 14 + short LEFT_y; + short RIGHT_x; + short RIGHT_y; // 17 +}; + // 遥控器循环指令枚举定义 enum LOOP_MODE_ORDER { @@ -74,22 +99,29 @@ typedef enum MODULE_SIZE JOYSTICK_SIZE = 6, // 手柄摇杆,占位6 DIRECTIONAL_PAD_SIZE = 4, // 方向按钮,占位4 FUNCTION_BUTTON_SIZE = 6, // 功能按键,占位6 - BUTTON_SIZE = 1, // 按键,占位1 - SWITCH_SIZE = 1 // 开关,占位1 + // BUTTON_SIZE = 1, // 按键,占位1 + // SWITCH_SIZE = 1 // 开关,占位1 } INTERFACE_SIZE; // 遥控器的方向按钮和摇杆组合 enum POLYTYPE { - TWO_DIRECTIONAL_PAD = 0x00, // 0x00 + DIRECTIONAL_PAD = 0x00, // 0x00 DIRECTIONAL_PAD_AND_JOYSTICK = 0x01, // 0x01 JOYSTICK_AND_DIRECTIONAL_PAD = 0x10, // 0x10 - TWO_JOYSTICKS = 0x11 // 0x11 + JOYSTICKS = 0x11 // 0x11 +}; + +struct RemoteControlJoystick +{ + short left_X; + short left_Y; + short right_X; + short right_Y; }; -extern bool SERIAL_PORT_CALLBACK_FUNCTION_ENABLE; -/************************* 蓝牙功能核心接口 *************************/ +/************************* 蓝牙功能接口 *************************/ // 设定蓝牙名称,默认为"mini_bot" void BTinitialize(const String &deviceName = "mini_bot"); @@ -103,7 +135,7 @@ void BTsendStringVia(const char *stringData); // 返回一个指针指向接收到的字符串数据。 char *BTgetReceivedData(); -/************************* 高级数据处理接口 ************************/ +/************************* 学会助手接口 ************************/ // 当通过UART接收到数据时,此函数将被调用 void Uart_onDataReceive(const uint8_t *dataBuffer, size_t dataSize); @@ -129,32 +161,27 @@ char OscGetFloat(const char *p, float *value); // 从示波器获取的数据格式,按字段解析为数值 char OscGetValue(const char *p, const char *name, float *value); -/************************* 演示示例函数 ************************/ +void RemoteControlOnDataReceive(const uint8_t *buffer, size_t size); -void test_serial_port_callback_function(bool isEnable = false); // 开启串口回调函数,需要在蓝牙初始化之前调用 +void RemoteControlInterruptMode(uint8_t *cmd, uint8_t *data, RemoteControlJoystick *Joystick); + +/************************* 演示函数 ************************/ + +void test_serial_port_callback_enable(bool isEnable = false); // 开启串口回调函数,在蓝牙初始化之前调用 void test_oscilloscope_send_wave(); // 发送波形数据的函数 -void test_oscilloscope_input_and_output(); // 示波器输入和输出案例 +void test_oscilloscope_send_and_Receive(); // 示波器输入和输出案例 -/************************* 其它模块适配,适配中... ************************/ +void test_remote_control_callback_enable(bool isEnable=false); // 遥控器回调函数,在蓝牙初始化之前调用 -void test_remote_control(const uint8_t *buffer, size_t size); // 遥控器 +/************************* 其它模块适配,适配中... ************************/ -void XHZS_RemoteControlIntialization(INTERFACE_SIZE isDirectionalPad1, - INTERFACE_SIZE isDirectionalPad2, - INTERFACE_SIZE isButtonA = BUTTON_SIZE, - INTERFACE_SIZE isButtonB = BUTTON_SIZE, - INTERFACE_SIZE isButtonC = BUTTON_SIZE, - INTERFACE_SIZE isButtonD = BUTTON_SIZE, - INTERFACE_SIZE isSwitchE = SWITCH_SIZE, - INTERFACE_SIZE isSwitchF = SWITCH_SIZE); +RemoteControlOutput RemoteControlLoopMode1(MODULE_SIZE RemoteControlLayoutLeft, MODULE_SIZE RemoteControlLayoutRight); -void XHZS_RemoteControlIntialization(); // 遥控器初始化 -// void XHZS_RemoteControlLoopMode(); // 遥控器循环模式 -void XHZS_RemoteControlInterruptMode(); // 遥控器中断模式 +void test_remote_control(const uint8_t *buffer, size_t size); // 遥控器 -short XHZS_RemoteControlLoopMode(); +void RemoteControlInterruptMode(); // 遥控器中断模式 void test_struct_array(); diff --git a/PlatformIO_ESP32_oscilloscope/src/main.cpp b/PlatformIO_ESP32_oscilloscope/src/main.cpp index bbc73ec6..f8f923dc 100644 --- a/PlatformIO_ESP32_oscilloscope/src/main.cpp +++ b/PlatformIO_ESP32_oscilloscope/src/main.cpp @@ -13,19 +13,18 @@ void setup() { Serial.begin(115200); // 开启串口通信:115200 - // 此函数执行一次,可以了 - // 开启串口中断模式 - test_serial_port_callback_function(true); + // 开启串口中断模式 // 此函数执行一次,可以了 + // test_serial_port_callback_enable(true); - BTinitialize("mini_car"); // 蓝牙初始化 // 默认蓝牙名称:mini_bot + BTinitialize("mini_car"); // 蓝牙初始化,默认蓝牙名称:mini_bot } void loop() { - // 使用示波器,不用启用串口中断模式,否则会冲突 - // test_oscilloscope_input_and_output(); + // 使用示波器功能,不用启用串口中断模式,否则会冲突 + // test_oscilloscope_send_and_Receive(); - delay(10); + delay(100); } /************************* test code area begin *************************/ @@ -53,4 +52,23 @@ void loop() // test_oscilloscope_input_and_output(); +// RemoteControlOutput outputBuffer = RemoteControlLoopMode1(JOYSTICK_AND_DIRECTIONAL_PAD, DIRECTIONAL_PAD); +// // RemoteControlOutput outputBuffer={}; +// // outputBuffer.Lup = 1; +// // outputBuffer.Ldown = 2; +// // outputBuffer.Lleft = 3; +// // outputBuffer.Lright = 4; +// // outputBuffer.Rup = 5; +// // outputBuffer.Rdown = 6; +// // outputBuffer.Rleft = 7; +// // outputBuffer.Rright = 8; + +// short *ptr = &outputBuffer.Lup; + +// for (size_t i = 0; i < 18; i++) +// { +// Serial.printf("%d-%d ", i, ptr[i]); +// } +// Serial.println(); + /************************* test code area end *************************/ \ No newline at end of file -- Gitee From d00adf6253ef7cd2fddfb762446e558f867ff54a Mon Sep 17 00:00:00 2001 From: klein1412 <1148878282@qq.com> Date: Sat, 3 Aug 2024 00:35:39 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E6=8A=8A=E9=81=A5=E6=8E=A7=E5=99=A8?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E7=9A=84=E5=87=BD=E6=95=B0=E9=87=8D=E6=96=B0?= =?UTF-8?q?=E8=B0=83=E6=95=B4=EF=BC=8C=E6=8A=8A=E6=95=B0=E6=8D=AE=E8=A3=85?= =?UTF-8?q?=E8=BF=9B=E7=BB=93=E6=9E=84=E4=BD=93=EF=BC=8C=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=88=90=E5=91=98=20OK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/myBlueTooth/myBlueTooth.cpp | 143 ++++++++++-------- .../lib/myBlueTooth/myBlueTooth.h | 127 +++++++++------- PlatformIO_ESP32_oscilloscope/src/main.cpp | 14 +- 3 files changed, 170 insertions(+), 114 deletions(-) diff --git a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp index d88d74b8..0135c26a 100644 --- a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp +++ b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp @@ -311,6 +311,38 @@ char OscGetValue(const char *p, const char *name, float *value) return 2; } +// // 定义遥控器输出结构体 +// struct RemoteControlOutput +// { +// short begin; + +// short LEFT_up; // 向上 // 1 +// short LEFT_down; // 向下 +// short LEFT_left; // 向左 +// short LEFT_right; // 向右 + +// short RIGHT_up; // 向上 // 5 +// short RIGHT_down; // 向下 +// short RIGHT_left; // 向左 +// short RIGHT_right; // 向右 + +// short middle; + +// short A; // 按钮A // 10 +// short B; // 按钮B +// short C; // 按钮C +// short D; // 按钮D +// short E; // 按钮E +// short F; // 按钮F + +// short LEFT_x; // 左摇杆X轴 // 16 +// short LEFT_y; // 左摇杆Y轴 +// short RIGHT_x; // 右摇杆X轴 +// short RIGHT_y; // 右摇杆Y轴 + +// short end; +// }; + // 获取摇杆数据转换为 x and y void getInterruptJoystickvalue_XY(char *receiveBuffer, short *joystick_X, short *joystick_Y) { @@ -378,7 +410,7 @@ void RemoteControlInterruptMode(uint8_t *cmd, uint8_t *data, RemoteControlJoysti SerialBT.printf("%X-%X\r\n", cmd[0], data[0]); break; - case INTERRUPT_LEFT_X_Y: + case INTERRUPT_LEFT_X: // 摇杆数值在 left_X and left_Y // 逻辑代码区 begin @@ -387,7 +419,7 @@ void RemoteControlInterruptMode(uint8_t *cmd, uint8_t *data, RemoteControlJoysti // 逻辑代码区 end break; - case INTERRUPT_RIGHT_X_Y: + case INTERRUPT_RIGHT_X: // 逻辑代码区 begin SerialBT.printf("x: %d y: %d\n", Joystick->right_X, Joystick->right_Y); @@ -421,19 +453,32 @@ void RemoteControlInterruptMode(uint8_t *cmd, uint8_t *data, RemoteControlJoysti } } +// 接收数据解析了放进结构体里面,使用成员 OK +void RemoteControlInterruptMode(RemoteControlOutput *structBuffer) +{ + short *ptr = &structBuffer->begin; + for (size_t i = 0; i < structBuffer->end, i < 20; i++) + { + Serial.printf("%d-%d ", i, ptr[i]); + } + Serial.println(); +} + /* 1)蓝牙接收到数据后,会调用此函数,不要在循环中使用,有卡死程序风险 2)回调函数不能有耗时操作,延时操作禁止使用的,会触发看门狗,不断重启 */ void RemoteControlOnDataReceive(const uint8_t *buffer, size_t size) { - struct RemoteControlJoystick Joystick = {0}; + RemoteControlOutput outputBuffer = {}; // 输出的缓冲区 + outputBuffer.end = 20; + // RemoteControlJoystick Joystick = {0}; uint8_t cmd[4] = {0}; uint8_t data[4] = {0}; char receiveBuffer[4] = {0}; - char temp = 0; memcpy(receiveBuffer, buffer, size); + short *ptr = &outputBuffer.begin; // 判断是否摇杆数据,在进行解释 if (size == 4) @@ -441,20 +486,26 @@ void RemoteControlOnDataReceive(const uint8_t *buffer, size_t size) if ((receiveBuffer[0] & 0xF0) == 0x10) { cmd[0] = 0x9A; - getInterruptJoystickvalue_XY(receiveBuffer, &Joystick.left_X, &Joystick.left_Y); + getInterruptJoystickvalue_XY(receiveBuffer, &outputBuffer.LEFT_x, &outputBuffer.LEFT_y); } else if ((receiveBuffer[0] & 0xF0) == 0x50) { cmd[0] = 0x9C; - getInterruptJoystickvalue_XY(receiveBuffer, &Joystick.right_X, &Joystick.right_Y); + getInterruptJoystickvalue_XY(receiveBuffer, &outputBuffer.RIGHT_x, &outputBuffer.RIGHT_y); } + // Serial.printf("x: %d y: %d - x: %d y: %d\n", outputBuffer.LEFT_x, outputBuffer.LEFT_y, outputBuffer.RIGHT_x, outputBuffer.RIGHT_y); } else if (size == 1) { - cmd[0] = (receiveBuffer[0] & 0xF0); + cmd[0] = (receiveBuffer[0] & 0xF0) / 16; data[0] = (receiveBuffer[0] & 0x0F); + + ptr[cmd[0]] = data[0]; + + // Serial.printf("cmd: %d data: %d\n", cmd[0], data[0]); } - RemoteControlInterruptMode(cmd, data, &Joystick); + + RemoteControlInterruptMode(&outputBuffer); } // 获取摇杆数值 @@ -484,6 +535,7 @@ void getDirectionalPad(short *outputButton, char outputPosition, const char *inp } } } + // 获取按钮数值 // (inputButton[inputPosition + i] == 0x31) 识别字符是否等于数字的1 void getFunctionButtonValue(short *outputButton, char outputPosition, const char *inputButton, char inputPosition) @@ -496,46 +548,13 @@ void getFunctionButtonValue(short *outputButton, char outputPosition, const char } } } -// 专门给 RemoteControlLoopMode 函数打印和测试使用 -void RemoteControlLoopModePritnf(char handle, RemoteControlOutput *outputBuffer) -{ - // 不同的遥控器组合,使用不同显示 // 打印在串口监视器中 - switch (handle) - { - case DIRECTIONAL_PAD: - Serial.printf("up: %d down: %d left: %d right: %d - up: %d down: %d left: %d right: %d ", - outputBuffer->LEFT_up, outputBuffer->LEFT_down, outputBuffer->LEFT_left, outputBuffer->LEFT_right, - outputBuffer->RIGHT_up, outputBuffer->RIGHT_down, outputBuffer->RIGHT_left, outputBuffer->RIGHT_right); - break; - - case DIRECTIONAL_PAD_AND_JOYSTICK: - Serial.printf("up: %d down: %d left: %d right: %d - x: %d y: %d ", - outputBuffer->LEFT_up, outputBuffer->LEFT_down, outputBuffer->LEFT_left, outputBuffer->LEFT_right, - outputBuffer->RIGHT_x, outputBuffer->RIGHT_y); - break; - - case JOYSTICK_AND_DIRECTIONAL_PAD: - Serial.printf(" x: %d y: %d - up: %d down: %d left: %d right: %d ", - outputBuffer->LEFT_x, outputBuffer->LEFT_y, - outputBuffer->LEFT_up, outputBuffer->LEFT_down, outputBuffer->LEFT_left, outputBuffer->LEFT_right); - break; - - case JOYSTICKS: - Serial.printf(" x: %d y: %d - x: %d y: %d ", - outputBuffer->LEFT_x, outputBuffer->LEFT_y, outputBuffer->RIGHT_x, outputBuffer->RIGHT_y); - - break; - } - - Serial.printf(" A: %d B: %d C: %d D: %d E: %d F: %d \n", - outputBuffer->A, outputBuffer->B, outputBuffer->C, outputBuffer->D, outputBuffer->E, outputBuffer->F); -} // 遥控器循环模式 -RemoteControlOutput RemoteControlLoopMode1(MODULE_SIZE RemoteControlLayoutLeft, MODULE_SIZE RemoteControlLayoutRight) +RemoteControlOutput RemoteControlLoopMode(MODULE_SIZE RemoteControlLayoutLeft, MODULE_SIZE RemoteControlLayoutRight) { RemoteControlOutput outputBuffer = {}; // 输出的缓冲区 - char tempBuffer[20] = {}; // 临时缓冲区 + outputBuffer.end = 20; + char tempBuffer[20] = {}; // 临时缓冲区 // 判断手柄的方向按钮和摇杆的组合 char handle = (RemoteControlLayoutLeft == JOYSTICK_SIZE ? JOYSTICK_AND_DIRECTIONAL_PAD : DIRECTIONAL_PAD) + (RemoteControlLayoutRight == JOYSTICK_SIZE ? DIRECTIONAL_PAD_AND_JOYSTICK : DIRECTIONAL_PAD); @@ -548,30 +567,29 @@ RemoteControlOutput RemoteControlLoopMode1(MODULE_SIZE RemoteControlLayoutLeft, { case DIRECTIONAL_PAD: // 获取结构体的首地址,在基础上移动到指定位置,进行赋值或者读取 - getDirectionalPad(&outputBuffer.LEFT_up, 0, tempBuffer, 0); - getDirectionalPad(&outputBuffer.LEFT_up, 4, tempBuffer, 4); + getDirectionalPad(&outputBuffer.LEFT_up, 1, tempBuffer, 0); + getDirectionalPad(&outputBuffer.LEFT_up, 5, tempBuffer, 4); getFunctionButtonValue(&outputBuffer.LEFT_up, 8, tempBuffer, 8); break; case DIRECTIONAL_PAD_AND_JOYSTICK: - getDirectionalPad(&outputBuffer.LEFT_up, 0, tempBuffer, 0); - getJoystickValue(&outputBuffer.LEFT_up, 16, tempBuffer, 4); + getDirectionalPad(&outputBuffer.LEFT_up, 1, tempBuffer, 0); + getJoystickValue(&outputBuffer.LEFT_up, 17, tempBuffer, 4); getFunctionButtonValue(&outputBuffer.LEFT_up, 8, tempBuffer, 10); break; case JOYSTICK_AND_DIRECTIONAL_PAD: - getJoystickValue(&outputBuffer.LEFT_up, 14, tempBuffer, 0); - getDirectionalPad(&outputBuffer.LEFT_up, 4, tempBuffer, 6); - getFunctionButtonValue(&outputBuffer.LEFT_up, 8, tempBuffer, 10); + getJoystickValue(&outputBuffer.LEFT_up, 15, tempBuffer, 0); + getDirectionalPad(&outputBuffer.LEFT_up, 5, tempBuffer, 6); + getFunctionButtonValue(&outputBuffer.LEFT_up, 9, tempBuffer, 10); break; case JOYSTICKS: - getJoystickValue(&outputBuffer.LEFT_up, 14, tempBuffer, 0); - getJoystickValue(&outputBuffer.LEFT_up, 16, tempBuffer, 6); - getFunctionButtonValue(&outputBuffer.LEFT_up, 8, tempBuffer, 12); + getJoystickValue(&outputBuffer.LEFT_up, 15, tempBuffer, 0); + getJoystickValue(&outputBuffer.LEFT_up, 17, tempBuffer, 6); + getFunctionButtonValue(&outputBuffer.LEFT_up, 9, tempBuffer, 12); break; } - RemoteControlLoopModePritnf(handle, &outputBuffer); return outputBuffer; } @@ -602,7 +620,6 @@ void test_oscilloscope_send_wave() SendWave(); } - /** * @brief 示波器输入和输出案例 * @@ -640,17 +657,23 @@ void test_remote_control_callback_enable(bool isEnable) /** * @brief 遥控器的定时发送模式 * - * + * */ void test_remote_control_loop_mode() { - // short shortArray[18] = {RemoteControlLoopMode(DIRECTIONAL_PAD_SIZE, JOYSTICK_SIZE)}; } /************************* example end *************************/ // /************************* test begin *************************/ +/* +在处理十六进制的时候发现一个问题,如何把 0x10 and 0x20 转化成数字的 1 and 2, +第一想到的字节的移位操作,但是这样最少操作四次,一个字节八位, +在计算十六进制大小发现一个规律,高位每加一位相差15 +0x50 升一位需要加15,降一位需要15 +*/ + struct myStruct { char a; @@ -661,7 +684,9 @@ struct myStruct }; /* -如何把结构体像数组一样使用? +如何把结构体像数组一样使用?可以做到,前提条件时是结构体成员是单一类型时,结构体内部就像一个数组, +获取结构体的首地址,在基础上进行偏移,可以像数组一样访问了 +问题来了,结构体的大小,或者说时长度问题,需要手动计算,使用for循环遍历警惕循环次数 */ void test_struct_array() { diff --git a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h index 4bbdbdc2..a6a70e02 100644 --- a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h +++ b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h @@ -12,29 +12,36 @@ #include // 字符串操作库 #include // ESP32蓝牙库 +// 定义遥控器输出结构体 struct RemoteControlOutput { - short LEFT_up; // 0 - short LEFT_down; - short LEFT_left; - short LEFT_right; - - short RIGHT_up; - short RIGHT_down; - short RIGHT_left; - short RIGHT_right; // 7 - - short A; // 8 - short B; - short C; - short D; - short E; - short F; // 13 - - short LEFT_x; // 14 - short LEFT_y; - short RIGHT_x; - short RIGHT_y; // 17 + short begin; + + short LEFT_up; // 向上 // 1 + short LEFT_down; // 向下 + short LEFT_left; // 向左 + short LEFT_right; // 向右 + + short RIGHT_up; // 向上 // 5 + short RIGHT_down; // 向下 + short RIGHT_left; // 向左 + short RIGHT_right; // 向右 + + short middle; + + short A; // 按钮A // 10 + short B; // 按钮B + short C; // 按钮C + short D; // 按钮D + short E; // 按钮E + short F; // 按钮F + + short LEFT_x; // 左摇杆X轴 // 16 + short LEFT_y; // 左摇杆Y轴 + short RIGHT_x; // 右摇杆X轴 + short RIGHT_y; // 右摇杆Y轴 + + short end; }; // 遥控器循环指令枚举定义 @@ -66,25 +73,24 @@ enum LOOP_MODE_ORDER // 遥控器中断指令枚举定义 enum INTERRUPT_MODE_ORDER { - // 按键状态指令 INTERRUPT_BUTTON_RELEASE = 0X00, // 按键释放指令 INTERRUPT_BUTTON_PRESS = 0X01, // 按键按下指令 - // 左侧方向键指令 INTERRUPT_LEFT_UP = 0X10, // 左侧方向键上 INTERRUPT_LEFT_DOWN = 0X20, // 左侧方向键下 INTERRUPT_LEFT_LEFT = 0X30, // 左侧方向键左 INTERRUPT_LEFT_RIGHT = 0X40, // 左侧方向键右 - // 右侧方向键指令 INTERRUPT_RIGHT_UP = 0X50, // 右侧方向键上 INTERRUPT_RIGHT_DOWN = 0X60, // 右侧方向键下 INTERRUPT_RIGHT_LEFT = 0X70, // 右侧方向键左 INTERRUPT_RIGHT_RIGHT = 0X80, // 右侧方向键右 - INTERRUPT_LEFT_X_Y = 0X9A, - INTERRUPT_RIGHT_X_Y = 0X9C, - // 左右功能按键指令 + INTERRUPT_LEFT_X = 0X9A, + INTERRUPT_LEFT_Y = 0X9B, + INTERRUPT_RIGHT_X = 0X9C, + INTERRUPT_RIGHT_Y = 0X9D, + INTERRUPT_BUTTON_A = 0XA0, // 左侧A功能键 INTERRUPT_BUTTON_B = 0XB0, // 左侧B功能键 INTERRUPT_BUTTON_C = 0XC0, // 右侧C功能键 @@ -106,10 +112,10 @@ typedef enum MODULE_SIZE // 遥控器的方向按钮和摇杆组合 enum POLYTYPE { - DIRECTIONAL_PAD = 0x00, // 0x00 + DIRECTIONAL_PAD = 0x00, // 0x00 DIRECTIONAL_PAD_AND_JOYSTICK = 0x01, // 0x01 JOYSTICK_AND_DIRECTIONAL_PAD = 0x10, // 0x10 - JOYSTICKS = 0x11 // 0x11 + JOYSTICKS = 0x11 // 0x11 }; struct RemoteControlJoystick @@ -120,69 +126,82 @@ struct RemoteControlJoystick short right_Y; }; +/************************* 蓝牙功能相关函数 *************************/ -/************************* 蓝牙功能接口 *************************/ - -// 设定蓝牙名称,默认为"mini_bot" +// **初始化蓝牙模块**,设置设备名,默认为"mini_bot" void BTinitialize(const String &deviceName = "mini_bot"); -// 将浮点数转换字符串通过蓝牙发送 +// **发送浮点数**通过蓝牙 void BTsendFloatVia(const float *data); -// 发送字符串到蓝牙连接的设备 +// **发送字符串**到蓝牙连接的设备 void BTsendStringVia(const char *stringData); -// 返回一个指针指向接收到的字符串数据。 +// **获取蓝牙接收的字符串** char *BTgetReceivedData(); -/************************* 学会助手接口 ************************/ +/************************* 串口通讯辅助函数 ************************/ -// 当通过UART接收到数据时,此函数将被调用 +// **串口数据接收回调**,当有数据通过UART接收到时调用 void Uart_onDataReceive(const uint8_t *dataBuffer, size_t dataSize); -// 获取接收到的数据 +// **获取串口接收数据** char *Uart_getReceiveData(); -// 通过UART发送一个字节的数据 +// **发送单个字节**通过UART void Uart_SendByte(const uint8_t *byte); -// 通过UART发送一个字节数组 +// **发送字节数组**通过UART void Uart_SendArray(const uint8_t *array, size_t arraySize); -// 发送指定数据格式 +// **发送特定格式数据**,如波形数据 void XHZS_SendWave(const void *waveAddr, uint16_t waveSize); -// 发送波形数据的函数 +/************************* 示波器相关函数 ************************/ + +// **实际发送波形数据的函数** void SendWave(); -// 输入 char *p 解析为 float *value +// **解析字符串为浮点数** char OscGetFloat(const char *p, float *value); -// 从示波器获取的数据格式,按字段解析为数值 +// **从特定格式数据中提取浮点数** char OscGetValue(const char *p, const char *name, float *value); +/************************* 遥控器交互相关函数 ************************/ + +// 遥控器数据接收处理回调 void RemoteControlOnDataReceive(const uint8_t *buffer, size_t size); -void RemoteControlInterruptMode(uint8_t *cmd, uint8_t *data, RemoteControlJoystick *Joystick); +// 处理遥控器中断模式下的命令 +void RemoteControlInterruptMode(RemoteControlOutput *structBuffer); -/************************* 演示函数 ************************/ +// 根据布局获取遥控器循环模式的输出 +RemoteControlOutput RemoteControlLoopMode(MODULE_SIZE RemoteControlLayoutLeft, MODULE_SIZE RemoteControlLayoutRight); -void test_serial_port_callback_enable(bool isEnable = false); // 开启串口回调函数,在蓝牙初始化之前调用 +/************************* 示例与测试函数 ************************/ -void test_oscilloscope_send_wave(); // 发送波形数据的函数 +// 启用串口回调功能,通常在蓝牙初始化前调用 +void test_serial_port_callback_enable(bool isEnable = false); -void test_oscilloscope_send_and_Receive(); // 示波器输入和输出案例 +// 测试发送波形数据到其他设备 +void test_oscilloscope_send_wave(); -void test_remote_control_callback_enable(bool isEnable=false); // 遥控器回调函数,在蓝牙初始化之前调用 +// 示例:示波器数据收发互动 +void test_oscilloscope_send_and_Receive(); -/************************* 其它模块适配,适配中... ************************/ +// 启用遥控器数据接收的回调处理 +void test_remote_control_callback_enable(bool isEnable = false); -RemoteControlOutput RemoteControlLoopMode1(MODULE_SIZE RemoteControlLayoutLeft, MODULE_SIZE RemoteControlLayoutRight); +/************************* 其它模块适配,适配中... ************************/ -void test_remote_control(const uint8_t *buffer, size_t size); // 遥控器 +// 遥控器数据处理测试函数 +void test_remote_control(const uint8_t *buffer, size_t size); -void RemoteControlInterruptMode(); // 遥控器中断模式 +// 测试遥控器中断模式下的功能 +void XHZS_RemoteControlInterruptMode(); +// 结构体数组的使用示例 void test_struct_array(); #endif diff --git a/PlatformIO_ESP32_oscilloscope/src/main.cpp b/PlatformIO_ESP32_oscilloscope/src/main.cpp index f8f923dc..c0235f2c 100644 --- a/PlatformIO_ESP32_oscilloscope/src/main.cpp +++ b/PlatformIO_ESP32_oscilloscope/src/main.cpp @@ -6,6 +6,8 @@ select engineering environment: ESP32_WROVER_Kit(all_versions) #include #include "myBlueTooth.h" +#include +#include BluetoothSerial SerialBlueTooth; @@ -15,6 +17,7 @@ void setup() // 开启串口中断模式 // 此函数执行一次,可以了 // test_serial_port_callback_enable(true); + test_remote_control_callback_enable(true); BTinitialize("mini_car"); // 蓝牙初始化,默认蓝牙名称:mini_bot } @@ -24,7 +27,16 @@ void loop() // 使用示波器功能,不用启用串口中断模式,否则会冲突 // test_oscilloscope_send_and_Receive(); - delay(100); + // unsigned char ch[6] = {0x10, 0x20, 0x30, 0xA0, 0xB0, 0xC0}; + + // for (size_t i = 0; i < sizeof(ch); i++) + // { + // ch[i] = (ch[i] & 0xF0) / 16; + // Serial.printf("%d-%x ", ch[i], ch[i]); + // } + // Serial.println(); + + delay(10); } /************************* test code area begin *************************/ -- Gitee From 6b75fdba85306655a20b924ada08bf152b78c15e Mon Sep 17 00:00:00 2001 From: klein1412 <1148878282@qq.com> Date: Sat, 3 Aug 2024 18:36:08 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E9=81=A5=E6=8E=A7=E5=99=A8=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/myBlueTooth/myBlueTooth.cpp | 203 ++++++++---------- .../lib/myBlueTooth/myBlueTooth.h | 75 +++---- PlatformIO_ESP32_oscilloscope/src/main.cpp | 83 ++----- 3 files changed, 135 insertions(+), 226 deletions(-) diff --git a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp index 0135c26a..801e57dc 100644 --- a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp +++ b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp @@ -29,7 +29,7 @@ void BTinitialize(const String &deviceName) if (SERIAL_PORT_CALLBACK_ENABLE == true) { - SerialBT.onData(Uart_onDataReceive); // 测试手柄功能未完成_2024-07-27 + SerialBT.onData(Uart_onDataReceive); } else if (REMOTE_CONTROL_CALLBACK_ENABLE == true) { @@ -123,16 +123,14 @@ void BTAuthCompleteCallback(boolean success) } /************************* blueTooth end *************************/ -// +// 函数前置声明 /************************* XHZS begin *************************/ -void getInterruptJoystickvalue_XY(char *receiveBuffer, short *joystick_X, short *joystick_Y); -void RemoteControlInterruptMode(uint8_t *cmd, uint8_t *data, RemoteControlJoystick *Joystick); -void getJoystickValue(short *outputButton, char outputPosition, char *inputButton, char inputPosition); -void getDirectionalPad(short *outputButton, char outputPosition, char *inputButton, char inputPosition); -void getFunctionButtonValue(short *outputButton, char outputPosition, char *inputButton, char inputPosition); - -// 当通过UART接收到数据时,此函数将被调用 +/* + * 串口接收到数据开启调用,和stm32的中断函数一样 + * 需要在串口发送和接收实现自己逻辑代码,直接写代码逻辑 + * 回调函数不能有耗时操作,延时操作禁止使用的,会触发看门狗,不断重启 + */ void Uart_onDataReceive(const uint8_t *dataBuffer, size_t dataSize) { // 判断接收到的数量 @@ -143,7 +141,7 @@ void Uart_onDataReceive(const uint8_t *dataBuffer, size_t dataSize) } } -// 获取接收到的数据 +// 获取串口接收到的数据 char *Uart_getReceiveData() { return blueToothBuffer; @@ -311,38 +309,6 @@ char OscGetValue(const char *p, const char *name, float *value) return 2; } -// // 定义遥控器输出结构体 -// struct RemoteControlOutput -// { -// short begin; - -// short LEFT_up; // 向上 // 1 -// short LEFT_down; // 向下 -// short LEFT_left; // 向左 -// short LEFT_right; // 向右 - -// short RIGHT_up; // 向上 // 5 -// short RIGHT_down; // 向下 -// short RIGHT_left; // 向左 -// short RIGHT_right; // 向右 - -// short middle; - -// short A; // 按钮A // 10 -// short B; // 按钮B -// short C; // 按钮C -// short D; // 按钮D -// short E; // 按钮E -// short F; // 按钮F - -// short LEFT_x; // 左摇杆X轴 // 16 -// short LEFT_y; // 左摇杆Y轴 -// short RIGHT_x; // 右摇杆X轴 -// short RIGHT_y; // 右摇杆Y轴 - -// short end; -// }; - // 获取摇杆数据转换为 x and y void getInterruptJoystickvalue_XY(char *receiveBuffer, short *joystick_X, short *joystick_Y) { @@ -366,11 +332,15 @@ void getInterruptJoystickvalue_XY(char *receiveBuffer, short *joystick_X, short *joystick_Y = (y > 0) ? y : -y; } -// 遥控器中断模式 -void RemoteControlInterruptMode(uint8_t *cmd, uint8_t *data, RemoteControlJoystick *Joystick) +/* + * 遥控器的非定时模式 + * RemoteControlOnDataReceive() 前面的函数解析好了,遥控器的每个按键对应着一个 case, + * 在 case INTERRUPT_RIGHT_UP 表示,右边的方向按钮的向上按钮,根据按键的状态,写自己的逻辑代码 + * cmd[0] 遥控器的指令,data[0] 表示遥控器的状态,0 表示松开,1 表示按下,摇杆显示 x and y 数值 + */ +void RemoteControlInterruptMode33(uint8_t *cmd, uint8_t *data, short left_X, short left_Y, short right_X, short right_Y) { - // - // 遥控器中断指令枚举定义 enum INTERRUPT_MODE_ORDER + // 在指定的按钮 case 中实现逻辑代码,中断不用有延时操作 switch (cmd[0]) { case INTERRUPT_LEFT_UP: @@ -414,7 +384,7 @@ void RemoteControlInterruptMode(uint8_t *cmd, uint8_t *data, RemoteControlJoysti // 摇杆数值在 left_X and left_Y // 逻辑代码区 begin - SerialBT.printf("x: %d y: %d\n", Joystick->left_X, Joystick->left_Y); + SerialBT.printf("x: %d y: %d\n", left_X, left_Y); // 逻辑代码区 end break; @@ -422,7 +392,7 @@ void RemoteControlInterruptMode(uint8_t *cmd, uint8_t *data, RemoteControlJoysti case INTERRUPT_RIGHT_X: // 逻辑代码区 begin - SerialBT.printf("x: %d y: %d\n", Joystick->right_X, Joystick->right_Y); + SerialBT.printf("x: %d y: %d\n", right_X, right_Y); // 逻辑代码区 end break; @@ -453,10 +423,15 @@ void RemoteControlInterruptMode(uint8_t *cmd, uint8_t *data, RemoteControlJoysti } } -// 接收数据解析了放进结构体里面,使用成员 OK -void RemoteControlInterruptMode(RemoteControlOutput *structBuffer) +/* + * RemoteControlOnDataReceive() 前面的函数解析好了,在这里使用结构体成员的方法,获取数值 + * 遥控器的非定时模式,1 表示按下,0 表示松开,摇杆显示 x and y 数值 + */ +void RemoteControlInterruptMode22(structRemoteControlFormat *structBuffer) { - short *ptr = &structBuffer->begin; + // 遍历结构体成员代码,了解 struct structRemoteControlFormat 格式内容 + // structBuffer->A 和 ptr[10] 这两个表达都是同一个地址,他们位置都是:10 + short *ptr = &structBuffer->begin; // 获取结构体首地址 for (size_t i = 0; i < structBuffer->end, i < 20; i++) { Serial.printf("%d-%d ", i, ptr[i]); @@ -465,16 +440,17 @@ void RemoteControlInterruptMode(RemoteControlOutput *structBuffer) } /* -1)蓝牙接收到数据后,会调用此函数,不要在循环中使用,有卡死程序风险 -2)回调函数不能有耗时操作,延时操作禁止使用的,会触发看门狗,不断重启 -*/ + * 串口接收到数据开启调用,和stm32的中断函数一样,在 RemoteControlOnDataReceive() 函数实现数据解析工作, + * 你的逻辑代码建议在 RemoteControlInterruptMode22() 或者在 RemoteControlInterruptMode33() 实现 + * 回调函数不能有耗时操作,延时操作禁止使用的,会触发看门狗,不断重启 + * 函数功能:把不同的按钮指令,存放在指定的结构体中 + */ void RemoteControlOnDataReceive(const uint8_t *buffer, size_t size) { - RemoteControlOutput outputBuffer = {}; // 输出的缓冲区 + structRemoteControlFormat outputBuffer = {}; // 输出的缓冲区 outputBuffer.end = 20; - // RemoteControlJoystick Joystick = {0}; - uint8_t cmd[4] = {0}; - uint8_t data[4] = {0}; + uint8_t cmd[4] = {0}; // 指令 + uint8_t data[4] = {0}; // 数据 char receiveBuffer[4] = {0}; memcpy(receiveBuffer, buffer, size); @@ -493,19 +469,19 @@ void RemoteControlOnDataReceive(const uint8_t *buffer, size_t size) cmd[0] = 0x9C; getInterruptJoystickvalue_XY(receiveBuffer, &outputBuffer.RIGHT_x, &outputBuffer.RIGHT_y); } - // Serial.printf("x: %d y: %d - x: %d y: %d\n", outputBuffer.LEFT_x, outputBuffer.LEFT_y, outputBuffer.RIGHT_x, outputBuffer.RIGHT_y); } else if (size == 1) { cmd[0] = (receiveBuffer[0] & 0xF0) / 16; data[0] = (receiveBuffer[0] & 0x0F); - + // 在这里把结构体当成一个数组来使用 ptr[cmd[0]] = data[0]; - - // Serial.printf("cmd: %d data: %d\n", cmd[0], data[0]); + // switch case 模式 * 16 + cmd[0] = cmd[0] * 16; } - - RemoteControlInterruptMode(&outputBuffer); + // 选择一个函数使用 + RemoteControlInterruptMode22(&outputBuffer); // 使用结构体的成员方法 + // RemoteControlInterruptMode33(cmd, data, outputBuffer.LEFT_x, outputBuffer.LEFT_y, outputBuffer.RIGHT_x, outputBuffer.RIGHT_y); // 使用 switch case 模式 } // 获取摇杆数值 @@ -549,12 +525,18 @@ void getFunctionButtonValue(short *outputButton, char outputPosition, const char } } -// 遥控器循环模式 -RemoteControlOutput RemoteControlLoopMode(MODULE_SIZE RemoteControlLayoutLeft, MODULE_SIZE RemoteControlLayoutRight) +/* + * 遥控器的定时模式 + * 功能:对一串有规律的字符串解析处理,放在指定结构体成员中 + * 使用了数组的方式,将结构体当成一个数组来使用,结构体的偏移量来确定成员位置 + */ +structRemoteControlFormat RemoteControlTimerMode(MODULE_SIZE RemoteControlLayoutLeft, MODULE_SIZE RemoteControlLayoutRight) { - RemoteControlOutput outputBuffer = {}; // 输出的缓冲区 + structRemoteControlFormat outputBuffer = {0}; // 输出的缓冲区 + outputBuffer.begin = 0; outputBuffer.end = 20; - char tempBuffer[20] = {}; // 临时缓冲区 + char tempBuffer[20] = {0}; // 临时缓冲区 + // 判断手柄的方向按钮和摇杆的组合 char handle = (RemoteControlLayoutLeft == JOYSTICK_SIZE ? JOYSTICK_AND_DIRECTIONAL_PAD : DIRECTIONAL_PAD) + (RemoteControlLayoutRight == JOYSTICK_SIZE ? DIRECTIONAL_PAD_AND_JOYSTICK : DIRECTIONAL_PAD); @@ -567,27 +549,27 @@ RemoteControlOutput RemoteControlLoopMode(MODULE_SIZE RemoteControlLayoutLeft, M { case DIRECTIONAL_PAD: // 获取结构体的首地址,在基础上移动到指定位置,进行赋值或者读取 - getDirectionalPad(&outputBuffer.LEFT_up, 1, tempBuffer, 0); - getDirectionalPad(&outputBuffer.LEFT_up, 5, tempBuffer, 4); - getFunctionButtonValue(&outputBuffer.LEFT_up, 8, tempBuffer, 8); + getDirectionalPad(&outputBuffer.begin, 1, tempBuffer, 0); + getDirectionalPad(&outputBuffer.begin, 5, tempBuffer, 4); + getFunctionButtonValue(&outputBuffer.begin, 10, tempBuffer, 8); break; case DIRECTIONAL_PAD_AND_JOYSTICK: - getDirectionalPad(&outputBuffer.LEFT_up, 1, tempBuffer, 0); - getJoystickValue(&outputBuffer.LEFT_up, 17, tempBuffer, 4); - getFunctionButtonValue(&outputBuffer.LEFT_up, 8, tempBuffer, 10); + getDirectionalPad(&outputBuffer.begin, 1, tempBuffer, 0); + getJoystickValue(&outputBuffer.begin, 18, tempBuffer, 4); + getFunctionButtonValue(&outputBuffer.begin, 10, tempBuffer, 10); break; case JOYSTICK_AND_DIRECTIONAL_PAD: - getJoystickValue(&outputBuffer.LEFT_up, 15, tempBuffer, 0); - getDirectionalPad(&outputBuffer.LEFT_up, 5, tempBuffer, 6); - getFunctionButtonValue(&outputBuffer.LEFT_up, 9, tempBuffer, 10); + getJoystickValue(&outputBuffer.begin, 16, tempBuffer, 0); + getDirectionalPad(&outputBuffer.begin, 5, tempBuffer, 6); + getFunctionButtonValue(&outputBuffer.begin, 10, tempBuffer, 10); break; case JOYSTICKS: - getJoystickValue(&outputBuffer.LEFT_up, 15, tempBuffer, 0); - getJoystickValue(&outputBuffer.LEFT_up, 17, tempBuffer, 6); - getFunctionButtonValue(&outputBuffer.LEFT_up, 9, tempBuffer, 12); + getJoystickValue(&outputBuffer.begin, 16, tempBuffer, 0); + getJoystickValue(&outputBuffer.begin, 18, tempBuffer, 6); + getFunctionButtonValue(&outputBuffer.begin, 10, tempBuffer, 12); break; } return outputBuffer; @@ -598,16 +580,9 @@ RemoteControlOutput RemoteControlLoopMode(MODULE_SIZE RemoteControlLayoutLeft, M /************************* example begin *************************/ /** - * @brief 启用或禁用串口回调机制 - * - * 此函数应在蓝牙初始化前调用,以配置串口(蓝牙)接收数据时的行为。 - * 当 isEnable 设置为 true 时,开启串口回调;设置为 false 时,则禁用。 - * + * 此函数应在蓝牙初始化前调用,当 isEnable 数值为 true 时开启,false 则禁用。 * 在底层蓝牙库中,onData() 函数将绑定 Uart_onDataReceive() 作为其回调,从而在接收到数据时触发相应的处理逻辑。 - * - * 注意:Uart_onDataReceive() 函数中不应包含任何延时操作,因其可能在中断上下文中执行。 - * - * 在不使用串口功能时,务必将其关闭,以避免与其他功能模块产生潜在冲突。 + * 串口回调时实现自己的代码逻辑,找到 Uart_onDataReceive() 修改里面代码 */ void test_serial_port_callback_enable(bool isEnable) { @@ -621,8 +596,7 @@ void test_oscilloscope_send_wave() } /** - * @brief 示波器输入和输出案例 - * + * 示波器发送和接收函数示例 */ void test_oscilloscope_send_and_Receive() { @@ -640,14 +614,13 @@ void test_oscilloscope_send_and_Receive() OscGetValue(charData, "c14", &floatValue4); SerialBT.printf("w:%0.2f,%0.2f,%0.2f,%0.2f\r\n", floatValue1, floatValue2, floatValue3, floatValue4); - vTaskDelay(50 / portTICK_PERIOD_MS); // 延时函数,可以注释掉 + delay(50); // 延时函数,可以注释掉 } -/** - * @brief 启用或禁用,遥控器的回调函数,非定时模式有用 - * - * 此函数应在蓝牙初始化前调用,以配置串口(蓝牙)接收数据时的行为。 - * 当 isEnable 设置为 true 时,开启串口回调;设置为 false 时,则禁用。 +/* + * 此函数应在蓝牙初始化前调用,当 isEnable 数值为 true 时开启,false 则禁用。 + * 在底层蓝牙库中,onData() 函数将绑定 RemoteControlOnDataReceive() 作为其回调,从而在接收到数据时触发相应的处理逻辑。 + * 串口回调时实现自己的代码逻辑,找到 RemoteControlOnDataReceive() 修改里面代码 */ void test_remote_control_callback_enable(bool isEnable) { @@ -655,18 +628,26 @@ void test_remote_control_callback_enable(bool isEnable) } /** - * @brief 遥控器的定时发送模式 - * + * 遥控器的定时发送模式 * */ -void test_remote_control_loop_mode() +void test_remote_control_Timer_function() { + structRemoteControlFormat buffer = RemoteControlTimerMode(DIRECTIONAL_PAD_SIZE, JOYSTICK_SIZE); + + short *ptr = &buffer.begin; + for (size_t i = 0; i < 20, i < buffer.end; i++) + { + Serial.printf("%d-%d ", i, ptr[i]); + } + Serial.println(); + delay(50); // 延时函数可以删除 } /************************* example end *************************/ // /************************* test begin *************************/ - +#if false /* 在处理十六进制的时候发现一个问题,如何把 0x10 and 0x20 转化成数字的 1 and 2, 第一想到的字节的移位操作,但是这样最少操作四次,一个字节八位, @@ -705,19 +686,21 @@ void test_struct_array() delay(100); } -/* -struct MyStruct { +struct MyStruct +{ int a; int b; int c; // 假设a, b, c是连续存储的 }; - -MyStruct s; -int* ptr = &s.a; // 获取a的地址 -for (int i = 0; i < 3; ++i) { - *(ptr + i) = i; // 通过指针偏移访问,尽管能工作但不推荐 +void test_struct_move() +{ + MyStruct s; + int *ptr = &s.a; // 获取a的地址 + for (int i = 0; i < 3; ++i) + { + *(ptr + i) = i; // 通过指针偏移访问,尽管能工作但不推荐 + } } -*/ - +#endif /************************* test end *************************/ diff --git a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h index a6a70e02..238b94d0 100644 --- a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h +++ b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h @@ -9,11 +9,11 @@ #define MYBLUETOOTH_H_ #include -#include // 字符串操作库 -#include // ESP32蓝牙库 +#include +#include // 定义遥控器输出结构体 -struct RemoteControlOutput +struct structRemoteControlFormat { short begin; @@ -44,32 +44,6 @@ struct RemoteControlOutput short end; }; -// 遥控器循环指令枚举定义 -enum LOOP_MODE_ORDER -{ - LOOP_LEFT_UP = 0, // 左上方向 - LOOP_LEFT_DOWN = 1, // 左下方向 - LOOP_LEFT_LEFT = 2, // 左方向 - LOOP_LEFT_RIGHT = 3, // 右方向 - - LOOP_RIGHT_UP = 4, // 右上方向 - LOOP_RIGHT_DOWN = 5, // 右下方向 - LOOP_RIGHT_LEFT = 6, // 右左方向 - LOOP_RIGHT_RIGHT = 7, // 右右方向 - - LOOP_BUTTON_A = 8, // 按钮A - LOOP_BUTTON_B = 9, // 按钮B - LOOP_BUTTON_C = 10, // 按钮C - LOOP_BUTTON_D = 11, // 按钮D - LOOP_BUTTON_E = 12, // 按钮E - LOOP_BUTTON_F = 13, // 按钮F - - LOOP_LEFT_X = 14, // 左摇杆X轴 - LOOP_LEFT_Y = 15, // 左摇杆Y轴 - LOOP_RIGHT_X = 16, // 右摇杆X轴 - LOOP_RIGHT_Y = 17 // 右摇杆Y轴 -}; - // 遥控器中断指令枚举定义 enum INTERRUPT_MODE_ORDER { @@ -86,7 +60,7 @@ enum INTERRUPT_MODE_ORDER INTERRUPT_RIGHT_LEFT = 0X70, // 右侧方向键左 INTERRUPT_RIGHT_RIGHT = 0X80, // 右侧方向键右 - INTERRUPT_LEFT_X = 0X9A, + INTERRUPT_LEFT_X = 0X9A, // 摇杆的指令 INTERRUPT_LEFT_Y = 0X9B, INTERRUPT_RIGHT_X = 0X9C, INTERRUPT_RIGHT_Y = 0X9D, @@ -105,8 +79,7 @@ typedef enum MODULE_SIZE JOYSTICK_SIZE = 6, // 手柄摇杆,占位6 DIRECTIONAL_PAD_SIZE = 4, // 方向按钮,占位4 FUNCTION_BUTTON_SIZE = 6, // 功能按键,占位6 - // BUTTON_SIZE = 1, // 按键,占位1 - // SWITCH_SIZE = 1 // 开关,占位1 + } INTERFACE_SIZE; // 遥控器的方向按钮和摇杆组合 @@ -118,13 +91,6 @@ enum POLYTYPE JOYSTICKS = 0x11 // 0x11 }; -struct RemoteControlJoystick -{ - short left_X; - short left_Y; - short right_X; - short right_Y; -}; /************************* 蓝牙功能相关函数 *************************/ @@ -174,14 +140,17 @@ char OscGetValue(const char *p, const char *name, float *value); void RemoteControlOnDataReceive(const uint8_t *buffer, size_t size); // 处理遥控器中断模式下的命令 -void RemoteControlInterruptMode(RemoteControlOutput *structBuffer); +void RemoteControlInterruptMode22(structRemoteControlFormat *structBuffer); + +// 处理遥控器中断模式下的命令 // 备用 +void RemoteControlInterruptMode33(uint8_t *cmd, uint8_t *data, short left_X, short left_Y, short right_X, short right_Y); -// 根据布局获取遥控器循环模式的输出 -RemoteControlOutput RemoteControlLoopMode(MODULE_SIZE RemoteControlLayoutLeft, MODULE_SIZE RemoteControlLayoutRight); +// 获取遥控器定时模式的数据 +structRemoteControlFormat RemoteControlTimerMode(MODULE_SIZE RemoteControlLayoutLeft, MODULE_SIZE RemoteControlLayoutRight); /************************* 示例与测试函数 ************************/ -// 启用串口回调功能,通常在蓝牙初始化前调用 +// 启用串口函数回调功能,在蓝牙初始化前调用 void test_serial_port_callback_enable(bool isEnable = false); // 测试发送波形数据到其他设备 @@ -190,18 +159,24 @@ void test_oscilloscope_send_wave(); // 示例:示波器数据收发互动 void test_oscilloscope_send_and_Receive(); -// 启用遥控器数据接收的回调处理 +// 启用遥控器函数回调函数,在蓝牙初始化前调用 void test_remote_control_callback_enable(bool isEnable = false); +// 示例:遥控器定时模式下的功能 +void test_remote_control_Timer_function(); + /************************* 其它模块适配,适配中... ************************/ -// 遥控器数据处理测试函数 -void test_remote_control(const uint8_t *buffer, size_t size); +// // 遥控器数据处理测试函数 +// void test_remote_control(const uint8_t *buffer, size_t size); + +// // 测试遥控器中断模式下的功能 +// void XHZS_RemoteControlInterruptMode(); -// 测试遥控器中断模式下的功能 -void XHZS_RemoteControlInterruptMode(); +// // 结构体数组的使用示例 +// void test_struct_array(); -// 结构体数组的使用示例 -void test_struct_array(); +// // 结构体移动示例 +// void test_struct_move(); #endif diff --git a/PlatformIO_ESP32_oscilloscope/src/main.cpp b/PlatformIO_ESP32_oscilloscope/src/main.cpp index c0235f2c..9580ecc6 100644 --- a/PlatformIO_ESP32_oscilloscope/src/main.cpp +++ b/PlatformIO_ESP32_oscilloscope/src/main.cpp @@ -1,86 +1,37 @@ /* -select engineering environment: ESP32_WROVER_Kit(all_versions) -想使用“学会助手”功能,查看 myBlueTooth.h 头文件里面有相关说明 -学会助手的串口和示波器功能,可以使用了 ^_^ +选择工程环境:ESP32_WROVER_Kit +如需使用“学会助手”功能,请参阅myBlueTooth.h头文件中的相关说明 +“学会助手”的串口功能、示波器功能和遥控器功能现已可用 ^_^ */ #include #include "myBlueTooth.h" -#include #include -BluetoothSerial SerialBlueTooth; +BluetoothSerial SerialBlueTooth; // 定义蓝牙串口对象 +// 串口回调函数和遥控器回调函数不能同时使用 +// 回调函数和示波器和遥控器功能不能同时使用 void setup() { - Serial.begin(115200); // 开启串口通信:115200 + // 初始化串口通信,设置波特率为115200 + Serial.begin(115200); - // 开启串口中断模式 // 此函数执行一次,可以了 + // // 启用串口通信的回调功能 // test_serial_port_callback_enable(true); + + // 启用遥控器功能的回调 ok test_remote_control_callback_enable(true); - BTinitialize("mini_car"); // 蓝牙初始化,默认蓝牙名称:mini_bot + // 初始化蓝牙模块,设置蓝牙名称为"mini_car" + BTinitialize("mini_car"); } void loop() { - // 使用示波器功能,不用启用串口中断模式,否则会冲突 + // // 执行示波器功能的数据发送和接收 // test_oscilloscope_send_and_Receive(); - // unsigned char ch[6] = {0x10, 0x20, 0x30, 0xA0, 0xB0, 0xC0}; - - // for (size_t i = 0; i < sizeof(ch); i++) - // { - // ch[i] = (ch[i] & 0xF0) / 16; - // Serial.printf("%d-%x ", ch[i], ch[i]); - // } - // Serial.println(); - - delay(10); -} - -/************************* test code area begin *************************/ - -// char *data = Uart_ReceiveData(); -// SerialBlueTooth.write((uint8_t *)data, strlen(data)); // 输出到连接的设备 -// SerialBlueTooth.println(); -// SerialBlueTooth.printf(data, strlen(data)); // 输出到连接的设备 -// SerialBlueTooth.println(); - -// delay(1000); - -// Serial.write(data, strlen(data)); // 输出到串行监视器 -// Serial.println(); -// Serial.printf(data, strlen(data)); // 输出到串行监视器 -// Serial.println(); - -// char ch[] = "hello"; - -// Uart_SendByte((uint8_t *)ch); - -// Uart_SendArray((uint8_t *)ch, sizeof(ch)); - -// SendWave(); - -// test_oscilloscope_input_and_output(); - -// RemoteControlOutput outputBuffer = RemoteControlLoopMode1(JOYSTICK_AND_DIRECTIONAL_PAD, DIRECTIONAL_PAD); -// // RemoteControlOutput outputBuffer={}; -// // outputBuffer.Lup = 1; -// // outputBuffer.Ldown = 2; -// // outputBuffer.Lleft = 3; -// // outputBuffer.Lright = 4; -// // outputBuffer.Rup = 5; -// // outputBuffer.Rdown = 6; -// // outputBuffer.Rleft = 7; -// // outputBuffer.Rright = 8; - -// short *ptr = &outputBuffer.Lup; - -// for (size_t i = 0; i < 18; i++) -// { -// Serial.printf("%d-%d ", i, ptr[i]); -// } -// Serial.println(); - -/************************* test code area end *************************/ \ No newline at end of file + // // 遥控器的定时功能演示 + // test_remote_control_Timer_function(); +} \ No newline at end of file -- Gitee From cae3291c7e2d26896175f7620ce6b9e3e077c693 Mon Sep 17 00:00:00 2001 From: klein1412 <1148878282@qq.com> Date: Sun, 4 Aug 2024 00:54:55 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BA=86=E4=B9=8B?= =?UTF-8?q?=E5=89=8D=E7=9A=84=E9=81=A5=E6=8E=A7=E5=99=A8=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E6=8A=8A=E9=81=A5=E6=8E=A7=E5=99=A8=E7=9A=84=E6=8C=89?= =?UTF-8?q?=E9=94=AE=E6=95=B0=E5=80=BC=E6=B1=87=E6=80=BB=E5=9C=A8=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E7=BB=93=E6=9E=84=E4=BD=93=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.vscode/settings.json | 3 +- PlatformIO_ESP32_oscilloscope/include/note.h | 11 ++++ .../lib/myBlueTooth/myBlueTooth.cpp | 59 +++++++++++++++---- .../lib/myBlueTooth/myBlueTooth.h | 2 +- PlatformIO_ESP32_oscilloscope/src/main.cpp | 9 ++- 5 files changed, 68 insertions(+), 16 deletions(-) diff --git a/PlatformIO_ESP32_oscilloscope/.vscode/settings.json b/PlatformIO_ESP32_oscilloscope/.vscode/settings.json index 0146d6b9..70cc27c7 100644 --- a/PlatformIO_ESP32_oscilloscope/.vscode/settings.json +++ b/PlatformIO_ESP32_oscilloscope/.vscode/settings.json @@ -15,5 +15,6 @@ "streambuf": "cpp", "initializer_list": "cpp", "utility": "cpp" - } + }, + "C_Cpp.errorSquiggles": "disabled" } \ No newline at end of file diff --git a/PlatformIO_ESP32_oscilloscope/include/note.h b/PlatformIO_ESP32_oscilloscope/include/note.h index f0d7683e..72b60dca 100644 --- a/PlatformIO_ESP32_oscilloscope/include/note.h +++ b/PlatformIO_ESP32_oscilloscope/include/note.h @@ -18,6 +18,17 @@ # 硬件层:GPIO 输出高低电平,电机旋转,蓝牙发送和接收 +# 在 platformIO 中遇到函数问题 + 在其它文件声明的函数 void test_output(); + 在 main() 主函数中重新写一遍不会报错,默认为新的的函数 + 当时处理没有发现前面加了 void 的函数,导致编译器认为这个函数是新的函数,而不是之前的函数 + 导致你的代码逻辑没有被执行 + + + + + + // ESP32-WROOM-32E 引脚功能 start -------------------- diff --git a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp index 801e57dc..12775e41 100644 --- a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp +++ b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp @@ -175,7 +175,7 @@ void Uart_SendArray(const uint8_t *array, size_t arraySize) *注意事项:示波器支持 uin16_t,建立一个 uint16_t fun[4] 数组, 元素是通道数量 **************************************************************/ -void XHZS_SendWave(const void *waveAddr, uint16_t waveSize) +void XHZS_SendWave(const uint8_t *waveAddr, uint16_t waveSize) { // 参数检查 if (waveAddr == nullptr || waveSize == 0) @@ -186,7 +186,7 @@ void XHZS_SendWave(const void *waveAddr, uint16_t waveSize) uint8_t cmd_tail[2] = {0xFC, 0x03}; // 帧尾 Uart_SendArray(cmd_head, sizeof(cmd_head)); // 发送帧头 - Uart_SendArray((uint8_t *)waveAddr, waveSize); // 发送数据 + Uart_SendArray(waveAddr, waveSize); // 发送数据 Uart_SendArray(cmd_tail, sizeof(cmd_tail)); // 发送帧尾 } @@ -200,7 +200,7 @@ void XHZS_SendWave(const void *waveAddr, uint16_t waveSize) void SendWave() { // // 输出平行线测试 start ----------------------- - // int32_t line[4] = {0}; // 注意数据类型;数组大小即为通道数量,最多四条通道 + // char line[4] = {0}; // 注意数据类型;数组大小即为通道数量,最多四条通道 // for (size_t i = 0; i < 500; i += 0.1) // { // line[0] = (line[0] > 10 ? -10 : (line[0] += 1)); @@ -208,8 +208,9 @@ void SendWave() // line[2] = 5.0; // line[3] = 0.0; - // XHZS_SendWave(line, sizeof(line)); + // XHZS_SendWave((uint8_t *)line, sizeof(line)); // vTaskDelay(50 / portTICK_PERIOD_MS); // 延时函数可以注释掉 + // // } // // 输出平行线测试 end ----------------------- @@ -222,7 +223,7 @@ void SendWave() Wave[1] = cos(i); Wave[2] = -sin(i); Wave[3] = -cos(i); - XHZS_SendWave(Wave, sizeof(Wave)); + XHZS_SendWave((uint8_t *)Wave, sizeof(Wave)); vTaskDelay(50 / portTICK_PERIOD_MS); // 延时函数可以注释掉 } @@ -480,7 +481,7 @@ void RemoteControlOnDataReceive(const uint8_t *buffer, size_t size) cmd[0] = cmd[0] * 16; } // 选择一个函数使用 - RemoteControlInterruptMode22(&outputBuffer); // 使用结构体的成员方法 + RemoteControlInterruptMode22(&outputBuffer); // 使用结构体的成员方法 // RemoteControlInterruptMode33(cmd, data, outputBuffer.LEFT_x, outputBuffer.LEFT_y, outputBuffer.RIGHT_x, outputBuffer.RIGHT_y); // 使用 switch case 模式 } @@ -525,6 +526,17 @@ void getFunctionButtonValue(short *outputButton, char outputPosition, const char } } +// 截取字符串 +void substring(char *dest, const char *src, size_t start, size_t length) +{ + size_t i; + for (i = 0; i < length && src[start + i] != '\0'; ++i) + { + dest[i] = src[start + i]; + } + dest[i] = '\0'; // 确保字符串以空字符结尾 +} + /* * 遥控器的定时模式 * 功能:对一串有规律的字符串解析处理,放在指定结构体成员中 @@ -544,11 +556,30 @@ structRemoteControlFormat RemoteControlTimerMode(MODULE_SIZE RemoteControlLayout size_t data_len = strlen(Uart_getReceiveData()); // 获取长度用于复制 memcpy(tempBuffer, Uart_getReceiveData(), data_len); // 内存复制 + //// 尝试使用串口改变,手柄的组合,失败 + // if (tempBuffer[0] == 's' && tempBuffer[1] == 'e' && tempBuffer[2] == 't') + // { + // char *end; + // char tempBufferCopy[data_len]; + + // substring(tempBufferCopy, tempBuffer, 4, 4); // 截取字符串 + // tempBufferCopy[0] = (char)strtol(tempBufferCopy, &end, 16); // 字符串转换十六进制 + // // SerialBT.printf("%s-%d\n", "pad", tempBufferCopy[0]); + + // if (tempBufferCopy[0] == 0x00 || tempBufferCopy[0] == 0x01 || tempBufferCopy[0] == 0x10 || tempBufferCopy[0] == 0x11) + // { + // // handle = *tempBufferCopy; + // handle = tempBufferCopy[0]; + // tempBufferCopy[0] = 100; + // SerialBT.printf("%s-%d\n", "ok", tempBufferCopy[0]); + // } + // } + // 确定,方向按钮和摇杆组合方式 switch (handle) { case DIRECTIONAL_PAD: - // 获取结构体的首地址,在基础上移动到指定位置,进行赋值或者读取 + // 获取结构体的首地址,在基础上移动到指定位置,进行赋值或者读取操作 getDirectionalPad(&outputBuffer.begin, 1, tempBuffer, 0); getDirectionalPad(&outputBuffer.begin, 5, tempBuffer, 4); getFunctionButtonValue(&outputBuffer.begin, 10, tempBuffer, 8); @@ -597,6 +628,8 @@ void test_oscilloscope_send_wave() /** * 示波器发送和接收函数示例 + * 数据类型:字符串,通道数量:4,开始接收 + * 参数调试:开启定时发送,选择参数调整 */ void test_oscilloscope_send_and_Receive() { @@ -628,12 +661,13 @@ void test_remote_control_callback_enable(bool isEnable) } /** - * 遥控器的定时发送模式 - * + * 遥控器的定时发送模式,函数的参数决定摇杆和方向按钮组合 + * 摇杆:JOYSTICK_SIZE and 方向按钮:DIRECTIONAL_PAD_SIZE + * 手柄组合有4种,配合学会助手的遥控器功能一起使用 */ void test_remote_control_Timer_function() { - structRemoteControlFormat buffer = RemoteControlTimerMode(DIRECTIONAL_PAD_SIZE, JOYSTICK_SIZE); + structRemoteControlFormat buffer = RemoteControlTimerMode(DIRECTIONAL_PAD_SIZE, DIRECTIONAL_PAD_SIZE); short *ptr = &buffer.begin; for (size_t i = 0; i < 20, i < buffer.end; i++) @@ -641,7 +675,8 @@ void test_remote_control_Timer_function() Serial.printf("%d-%d ", i, ptr[i]); } Serial.println(); - delay(50); // 延时函数可以删除 + + // delay(50); // 延时函数可以删除 } /************************* example end *************************/ @@ -683,7 +718,7 @@ void test_struct_array() Serial.printf("%d-%d- ", i, *(ptr + i)); } Serial.printf("a: %d b: %d c: %d d: %d e: %d\n", box.a, box.b, box.c, box.d, box.e); - delay(100); + delay(10); } struct MyStruct diff --git a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h index 238b94d0..a7ea9dae 100644 --- a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h +++ b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h @@ -121,7 +121,7 @@ void Uart_SendByte(const uint8_t *byte); void Uart_SendArray(const uint8_t *array, size_t arraySize); // **发送特定格式数据**,如波形数据 -void XHZS_SendWave(const void *waveAddr, uint16_t waveSize); +void XHZS_SendWave(const uint8_t *waveAddr, uint16_t waveSize); /************************* 示波器相关函数 ************************/ diff --git a/PlatformIO_ESP32_oscilloscope/src/main.cpp b/PlatformIO_ESP32_oscilloscope/src/main.cpp index 9580ecc6..7bbfd76a 100644 --- a/PlatformIO_ESP32_oscilloscope/src/main.cpp +++ b/PlatformIO_ESP32_oscilloscope/src/main.cpp @@ -20,8 +20,8 @@ void setup() // // 启用串口通信的回调功能 // test_serial_port_callback_enable(true); - // 启用遥控器功能的回调 ok - test_remote_control_callback_enable(true); + // // 启用遥控器功能的回调 + // test_remote_control_callback_enable(true); // 初始化蓝牙模块,设置蓝牙名称为"mini_car" BTinitialize("mini_car"); @@ -29,9 +29,14 @@ void setup() void loop() { + // 测试发送波形数据到其他设备 + test_oscilloscope_send_wave(); + // // 执行示波器功能的数据发送和接收 // test_oscilloscope_send_and_Receive(); // // 遥控器的定时功能演示 // test_remote_control_Timer_function(); + + delay(10); } \ No newline at end of file -- Gitee From 770c23446829d41472e56b497f8538fabc482a96 Mon Sep 17 00:00:00 2001 From: klein1412 <1148878282@qq.com> Date: Tue, 6 Aug 2024 17:24:26 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PlatformIO_ESP32_oscilloscope/.pio/build/project.checksum | 2 +- PlatformIO_ESP32_oscilloscope/.vscode/c_cpp_properties.json | 6 ++++-- PlatformIO_ESP32_oscilloscope/platformio.ini | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/PlatformIO_ESP32_oscilloscope/.pio/build/project.checksum b/PlatformIO_ESP32_oscilloscope/.pio/build/project.checksum index 33530321..63e3322f 100644 --- a/PlatformIO_ESP32_oscilloscope/.pio/build/project.checksum +++ b/PlatformIO_ESP32_oscilloscope/.pio/build/project.checksum @@ -1 +1 @@ -8a68528b3a0642cb871621c8627966e55583f040 \ No newline at end of file +097eeba9cb2968a7879a3ff516436d31058be27a \ No newline at end of file diff --git a/PlatformIO_ESP32_oscilloscope/.vscode/c_cpp_properties.json b/PlatformIO_ESP32_oscilloscope/.vscode/c_cpp_properties.json index d944b690..e1a02ab6 100644 --- a/PlatformIO_ESP32_oscilloscope/.vscode/c_cpp_properties.json +++ b/PlatformIO_ESP32_oscilloscope/.vscode/c_cpp_properties.json @@ -12,6 +12,7 @@ "E:/PlatformIO_vscode/git_XHZS/esp32_oscilloscope/PlatformIO_ESP32_oscilloscope/src", "E:/PlatformIO_vscode/git_XHZS/esp32_oscilloscope/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/BluetoothSerial/src", + "E:/PlatformIO_vscode/git_XHZS/esp32_oscilloscope/PlatformIO_ESP32_oscilloscope/.pio/libdeps/esp32dev/FastLED/src", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/newlib/platform_include", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/include", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/include/esp_additions/freertos", @@ -208,6 +209,7 @@ "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/dio_qspi/include", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/cores/esp32", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/variants/esp32", + "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src", "E:/PlatformIO_vscode/git_XHZS/esp32_oscilloscope/PlatformIO_ESP32_oscilloscope/lib/Interrupts_and_timers", "E:/PlatformIO_vscode/git_XHZS/esp32_oscilloscope/PlatformIO_ESP32_oscilloscope/lib/WS2812B_LED", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src", @@ -231,7 +233,6 @@ "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/RainMaker/src", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/SD/src", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/SD_MMC/src", - "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/src", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/SimpleBLE/src", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/Ticker/src", @@ -251,6 +252,7 @@ "E:/PlatformIO_vscode/git_XHZS/esp32_oscilloscope/PlatformIO_ESP32_oscilloscope/src", "E:/PlatformIO_vscode/git_XHZS/esp32_oscilloscope/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/BluetoothSerial/src", + "E:/PlatformIO_vscode/git_XHZS/esp32_oscilloscope/PlatformIO_ESP32_oscilloscope/.pio/libdeps/esp32dev/FastLED/src", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/newlib/platform_include", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/include", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/include/esp_additions/freertos", @@ -447,6 +449,7 @@ "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/dio_qspi/include", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/cores/esp32", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/variants/esp32", + "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src", "E:/PlatformIO_vscode/git_XHZS/esp32_oscilloscope/PlatformIO_ESP32_oscilloscope/lib/Interrupts_and_timers", "E:/PlatformIO_vscode/git_XHZS/esp32_oscilloscope/PlatformIO_ESP32_oscilloscope/lib/WS2812B_LED", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src", @@ -470,7 +473,6 @@ "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/RainMaker/src", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/SD/src", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/SD_MMC/src", - "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/src", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/SimpleBLE/src", "C:/Users/Sword/.platformio/packages/framework-arduinoespressif32/libraries/Ticker/src", diff --git a/PlatformIO_ESP32_oscilloscope/platformio.ini b/PlatformIO_ESP32_oscilloscope/platformio.ini index 9bf8b360..316e35ea 100644 --- a/PlatformIO_ESP32_oscilloscope/platformio.ini +++ b/PlatformIO_ESP32_oscilloscope/platformio.ini @@ -12,4 +12,5 @@ platform = espressif32 board = esp32dev framework = arduino -board_build.partitions = partitions.csv \ No newline at end of file +board_build.partitions = partitions.csv +lib_deps = fastled/FastLED@^3.7.0 -- Gitee From 22d28d53f33ca0a16b5bfe06ea16c9b00786889a Mon Sep 17 00:00:00 2001 From: klein1412 <1148878282@qq.com> Date: Tue, 6 Aug 2024 09:50:07 +0000 Subject: [PATCH 7/8] =?UTF-8?q?update=20README.md.=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=81=A5=E6=8E=A7=E5=99=A8=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: klein1412 <1148878282@qq.com> --- README.md | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 39713223..5e15d360 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,38 @@ # ESP32_oscilloscope #### 项目介绍 -这是一个将原来基于STM32F1的keil工程移植到ESP32中的项目,旨在实现与原工程一致的功能和逻辑。 -通讯方式采样蓝牙,本项目适配了“学会助手”软件的部分模块,工程适配工作在更新中,会有改动的地方,有其它问题,欢迎在群里提问 -或在 gitee 的 issue 中发起讨论 ^_^ +此项目旨在将原本基于STM32F1在Keil环境中开发的工程成功移植至ESP32平台,保持原有功能与逻辑的实现。通过蓝牙通信技术,项目已初步适配“学会助手”应用的若干功能模块,正处于工程迭代阶段。我们鼓励用户在遇到任何疑问时,积极在项目社群提问 ^_^ +##### 适配功能 - 串口功能 - 示波器功能 - - x... + - 遥控器功能 + - 待添加... #### 软件架构 -本项目采用ESP32微控制器,结合Arduino环境或PlatformIO进行开发 +采用ESP32微控制器为核心,项目支持在Arduino IDE或PlatformIO for VSCode环境下进行开发。 #### 安装教程 -1. 已经工程情况下,下载 myBluetTooth.h 头文件和 myBluetooth.cpp 源文件到工程文件夹中,在main.cpp中添加头文件 -2. xxxx +1. 现有工程整合:下载myBluetooth.h头文件及myBluetooth.cpp源码至项目目录。随后,在main.cpp顶部加入对myBluetooth.h的引用。 +2. 配置环境:请确保您的开发环境已正确配置为支持ESP32开发。 3. xxxx #### 使用说明 -1. 硬件:ESP32-WROOM-32E -2. 软件:Arduino IDE or PlatfromIO for vsCode -3. 在工程中包含 myBlueTooth.h 头文件(已经下载到本地) -4. myBlueTooth_头文件_有注释和_源文件_有测试案例 +1. 硬件需求:ESP32-WROOM-32E作为基础硬件平台 +2. 开发软件:推荐使用Arduino IDE或PlatformIO插件配合VSCode +4. 测试示例:库文件内含详细注释及测试用例,便于快速验证功能 #### 参与贡献 -0. 感谢来自 bilibili 的 一品芝麻糕 分享 thank you -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request +0. 感谢分享:Bilibili用户“一品芝麻糕”的分享与启发 +1. xxxx #### 特技 -1)神乎其技,爱折腾 -2)来,看你如何表演 +1)在路上,探索中... +2)xxxx -- Gitee From ddc812218880909e7013f0cdaa34439cfc1dd798 Mon Sep 17 00:00:00 2001 From: klein1412 <1148878282@qq.com> Date: Sat, 17 Aug 2024 14:45:55 +0800 Subject: [PATCH 8/8] =?UTF-8?q?platfromIO=20=E6=B5=8B=E8=AF=95=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E9=97=AE=E9=A2=98=EF=BC=8C=E5=90=8C=E6=AD=A5=E5=88=B0?= =?UTF-8?q?=20arduino=20=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Arduino_ESP32_oscilloscope.ino | 67 +-- Arduino_ESP32_oscilloscope/myBlueTooth.cpp | 448 ++++++++++-------- Arduino_ESP32_oscilloscope/myBlueTooth.h | 159 ++++--- .../lib/myBlueTooth/myBlueTooth.cpp | 8 +- .../lib/myBlueTooth/myBlueTooth.h | 22 +- PlatformIO_ESP32_oscilloscope/src/main.cpp | 1 + 6 files changed, 384 insertions(+), 321 deletions(-) diff --git a/Arduino_ESP32_oscilloscope/Arduino_ESP32_oscilloscope.ino b/Arduino_ESP32_oscilloscope/Arduino_ESP32_oscilloscope.ino index 0cc68d8f..a9e7f7d9 100644 --- a/Arduino_ESP32_oscilloscope/Arduino_ESP32_oscilloscope.ino +++ b/Arduino_ESP32_oscilloscope/Arduino_ESP32_oscilloscope.ino @@ -1,60 +1,43 @@ /* -select engineering environment: ESP32_WROVER_Kit(all_versions) -想使用“学会助手”功能,查看 myBlueTooth.h 头文件里面有相关说明 -学会助手的串口和示波器功能,可以使用了 ^_^ +选择工程环境:ESP32_WROVER_Kit +如需使用“学会助手”功能,请参阅myBlueTooth.h头文件中的相关说明 +“学会助手”的串口功能、示波器功能和遥控器功能现已可用 ^_^ */ #include #include "myBlueTooth.h" +#include -BluetoothSerial SerialBlueTooth; +BluetoothSerial SerialBlueTooth; // 定义蓝牙串口对象 + +// 串口回调函数和遥控器回调函数不能同时使用 +// 回调函数和示波器和遥控器功能不能同时使用 void setup() { - Serial.begin(115200); // 开启串口通信:115200 + // 初始化串口通信,设置波特率为115200 + Serial.begin(115200); + + // // 启用串口通信的回调功能 + // test_serial_port_callback_enable(true); - // 此函数执行一次,可以了 - // 开启串口中断模式 - test_serial_port_callback_function(true); + // // 启用遥控器功能的回调 + // test_remote_control_callback_enable(true); - BTinitialize("mini_car"); // 蓝牙初始化 // 默认蓝牙名称:mini_bot + // 初始化蓝牙模块,设置蓝牙名称为"mini_car" + BTinitialize("mini_car"); } void loop() { - // ... - - delay(100); -} - - - - - - -/************************* test code area begin *************************/ - -// char *data = Uart_ReceiveData(); -// SerialBlueTooth.write((uint8_t *)data, strlen(data)); // 输出到连接的设备 -// SerialBlueTooth.println(); -// SerialBlueTooth.printf(data, strlen(data)); // 输出到连接的设备 -// SerialBlueTooth.println(); - -// delay(1000); - -// Serial.write(data, strlen(data)); // 输出到串行监视器 -// Serial.println(); -// Serial.printf(data, strlen(data)); // 输出到串行监视器 -// Serial.println(); - -// char ch[] = "hello"; - -// Uart_SendByte((uint8_t *)ch); - -// Uart_SendArray((uint8_t *)ch, sizeof(ch)); + // 测试发送波形数据到其他设备 + test_oscilloscope_send_wave(); -// SendWave(); + // // 执行示波器功能的数据发送和接收 + // test_oscilloscope_send_and_Receive(); -// test_oscilloscope_input_and_output(); + // // 遥控器的定时功能演示 + // test_remote_control_Timer_function(); -/************************* test code area end *************************/ \ No newline at end of file + delay(10); +} \ No newline at end of file diff --git a/Arduino_ESP32_oscilloscope/myBlueTooth.cpp b/Arduino_ESP32_oscilloscope/myBlueTooth.cpp index 9c1e5161..dd48703d 100644 --- a/Arduino_ESP32_oscilloscope/myBlueTooth.cpp +++ b/Arduino_ESP32_oscilloscope/myBlueTooth.cpp @@ -2,14 +2,15 @@ /************************* blueTooth part *************************/ BluetoothSerial SerialBT; // 蓝牙类实例化 -String BlueToothName = ""; // 蓝牙名称 static char blueToothBuffer[100]; // 接收缓冲区 /************************* XHZS part *************************/ -bool SERIAL_PORT_CALLBACK_FUNCTION_ENABLE = false; // 默认串口关闭 -char RemoteControlDataLength = 0; // 数据长度 -uint8_t DataFormat[8] = {0}; // 遥控器数据格式 +bool SERIAL_PORT_CALLBACK_ENABLE = false; // 默认串口关闭 +bool REMOTE_CONTROL_CALLBACK_ENABLE = false; // 默认遥控器关闭 +// 定义常量替代硬编码 +constexpr char DIGIT_ZERO = 0x30; +constexpr char DIGIT_ONE = 0x31; /************************* blueTooth begin *************************/ @@ -26,13 +27,16 @@ void BTinitialize(const String &deviceName) SerialBT.register_callback(Bluetooth_Event); // 设置事件回调函数 连接 断开 发送 接收 - if (SERIAL_PORT_CALLBACK_FUNCTION_ENABLE == true) + if (SERIAL_PORT_CALLBACK_ENABLE == true) { - SerialBT.onData(Uart_onDataReceive); // 测试手柄功能未完成_2024-07-27 - // SerialBT.onData(BTcallbackFunction); + SerialBT.onData(Uart_onDataReceive); + } + else if (REMOTE_CONTROL_CALLBACK_ENABLE == true) + { + SerialBT.onData(RemoteControlOnDataReceive); } SerialBT.begin(deviceName); // Bluetooth device name - BlueToothName = deviceName; + // BlueToothName = deviceName; } /*蓝牙发送浮点数据,转为字符串发送*/ @@ -119,12 +123,17 @@ void BTAuthCompleteCallback(boolean success) } /************************* blueTooth end *************************/ -// +// 函数前置声明 /************************* XHZS begin *************************/ -// 当通过UART接收到数据时,此函数将被调用 +/* + * 串口接收到数据开启调用,和stm32的中断函数一样 + * 需要在串口发送和接收实现自己逻辑代码,直接写代码逻辑 + * 回调函数不能有耗时操作,延时操作禁止使用的,会触发看门狗,不断重启 + */ void Uart_onDataReceive(const uint8_t *dataBuffer, size_t dataSize) { + // 判断接收到的数量 if (dataSize > 0) { SerialBT.write(dataBuffer, dataSize); // 输出到连接的设备 @@ -132,7 +141,7 @@ void Uart_onDataReceive(const uint8_t *dataBuffer, size_t dataSize) } } -// 获取接收到的数据 +// 获取串口接收到的数据 char *Uart_getReceiveData() { return blueToothBuffer; @@ -166,7 +175,7 @@ void Uart_SendArray(const uint8_t *array, size_t arraySize) *注意事项:示波器支持 uin16_t,建立一个 uint16_t fun[4] 数组, 元素是通道数量 **************************************************************/ -void XHZS_SendWave(const void *waveAddr, uint16_t waveSize) +void XHZS_SendWave(const uint8_t *waveAddr, uint16_t waveSize) { // 参数检查 if (waveAddr == nullptr || waveSize == 0) @@ -177,7 +186,7 @@ void XHZS_SendWave(const void *waveAddr, uint16_t waveSize) uint8_t cmd_tail[2] = {0xFC, 0x03}; // 帧尾 Uart_SendArray(cmd_head, sizeof(cmd_head)); // 发送帧头 - Uart_SendArray((uint8_t *)waveAddr, waveSize); // 发送数据 + Uart_SendArray(waveAddr, waveSize); // 发送数据 Uart_SendArray(cmd_tail, sizeof(cmd_tail)); // 发送帧尾 } @@ -191,7 +200,7 @@ void XHZS_SendWave(const void *waveAddr, uint16_t waveSize) void SendWave() { // // 输出平行线测试 start ----------------------- - // int32_t line[4] = {0}; // 注意数据类型;数组大小即为通道数量,最多四条通道 + // char line[4] = {0}; // 注意数据类型;数组大小即为通道数量,最多四条通道 // for (size_t i = 0; i < 500; i += 0.1) // { // line[0] = (line[0] > 10 ? -10 : (line[0] += 1)); @@ -199,8 +208,9 @@ void SendWave() // line[2] = 5.0; // line[3] = 0.0; - // XHZS_SendWave(line, sizeof(line)); - // vTaskDelay(50 / portTICK_PERIOD_MS); // 延时 100ms + // XHZS_SendWave((uint8_t *)line, sizeof(line)); + // vTaskDelay(50 / portTICK_PERIOD_MS); // 延时函数可以注释掉 + // // } // // 输出平行线测试 end ----------------------- @@ -213,9 +223,9 @@ void SendWave() Wave[1] = cos(i); Wave[2] = -sin(i); Wave[3] = -cos(i); - XHZS_SendWave(Wave, sizeof(Wave)); + XHZS_SendWave((uint8_t *)Wave, sizeof(Wave)); - vTaskDelay(50 / portTICK_PERIOD_MS); + vTaskDelay(50 / portTICK_PERIOD_MS); // 延时函数可以注释掉 } // 正弦波测试 end ----------------------- } @@ -300,8 +310,6 @@ char OscGetValue(const char *p, const char *name, float *value) return 2; } -/************************* XHZS end *************************/ - // 获取摇杆数据转换为 x and y void getInterruptJoystickvalue_XY(char *receiveBuffer, short *joystick_X, short *joystick_Y) { @@ -318,63 +326,31 @@ void getInterruptJoystickvalue_XY(char *receiveBuffer, short *joystick_X, short // cmd4 = receiveBuffer[3] & 0xF0; data[3] = receiveBuffer[3] & 0x0F; - // 对摇杆数值默认值做了修改,中心数值是0,偏离中心越远数值越大 0~100 + // 对摇杆数值默认值做了修改,中心数值是0,偏离中心越远数值越大 100~0~100 x = (data[0] * 16 + data[1]) - 100; *joystick_X = (x > 0) ? x : -x; y = (data[2] * 16 + data[3]) - 100; *joystick_Y = (y > 0) ? y : -y; } -// /************************************************************** -// *函数名称:test_remote_control -// *简 介:蓝牙数据接收,回调函数 -// *输 入:无 -// *输 出:默认输出按键状态 -// *注意事项:1)蓝牙接收到数据后,会调用此函数,不要在循环中使用,有卡死程序风险 -// 2)回调函数不能有耗时操作,延时操作禁止使用的,会触发看门狗,不断重启 -// 3)打印函数测试使用,注释掉写你的逻辑代码 -// **************************************************************/ - -void test_remote_control(const uint8_t *buffer, size_t size) +/* + * 遥控器的非定时模式 + * RemoteControlOnDataReceive() 前面的函数解析好了,遥控器的每个按键对应着一个 case, + * 在 case INTERRUPT_RIGHT_UP 表示,右边的方向按钮的向上按钮,根据按键的状态,写自己的逻辑代码 + * cmd[0] 遥控器的指令,data[0] 表示遥控器的状态,0 表示松开,1 表示按下,摇杆显示 x and y 数值 + */ +void RemoteControlInterruptMode33(uint8_t *cmd, uint8_t *data, short left_X, short left_Y, short right_X, short right_Y) { - uint8_t cmd[4] = {0}; - uint8_t data[4] = {0}; - - // 摇杆相关变量 - short left_X = 0, left_Y = 0, right_X = 0, right_Y = 0; - char receiveBuffer[4] = {0}; // 中断接收数据 - char temp = 0; - memcpy(receiveBuffer, buffer, size); - - // 按键接收大小为1,摇杆接收大小为4 - if (size == 4) - { - temp = (receiveBuffer[0] & 0xF0); - // cmd[0] = (temp == 0x10) ? 0x9A : ((temp == 0x50) ? 0X9B : 0x00); - // data[0] = receiveBuffer[0] & 0x0F; - if (temp == 0x10) - { - cmd[0] = 0x9A; - getInterruptJoystickvalue_XY(receiveBuffer, &left_X, &left_Y); - } - else if (temp == 0x50) - { - cmd[0] = 0x9C; - getInterruptJoystickvalue_XY(receiveBuffer, &right_X, &right_Y); - } - } - else if (size == 1) - { - cmd[0] = (receiveBuffer[0] & 0xF0); - data[0] = (receiveBuffer[0] & 0x0F); - } - - // 遥控器中断指令枚举定义 enum INTERRUPT_MODE_ORDER + // 在指定的按钮 case 中实现逻辑代码,中断不用有延时操作 switch (cmd[0]) { case INTERRUPT_LEFT_UP: // 指令 cmd[0] 数据 data[0] + // 逻辑代码区 begin + SerialBT.printf("%X-%X\r\n", cmd[0], data[0]); + + // 逻辑代码区 end break; case INTERRUPT_LEFT_DOWN: @@ -405,17 +381,17 @@ void test_remote_control(const uint8_t *buffer, size_t size) SerialBT.printf("%X-%X\r\n", cmd[0], data[0]); break; - case INTERRUPT_LEFT_X_Y: + case INTERRUPT_LEFT_X: // 摇杆数值在 left_X and left_Y - // 逻辑代码区 start + // 逻辑代码区 begin SerialBT.printf("x: %d y: %d\n", left_X, left_Y); // 逻辑代码区 end break; - case INTERRUPT_RIGHT_X_Y: - // 逻辑代码区 start + case INTERRUPT_RIGHT_X: + // 逻辑代码区 begin SerialBT.printf("x: %d y: %d\n", right_X, right_Y); @@ -447,58 +423,92 @@ void test_remote_control(const uint8_t *buffer, size_t size) break; } } + /* - * 遥控器的界面选择,使用 enum INTERFACE_SIZE + * RemoteControlOnDataReceive() 前面的函数解析好了,在这里使用结构体成员的方法,获取数值 + * 遥控器的非定时模式,1 表示按下,0 表示松开,摇杆显示 x and y 数值 */ -void XHZS_RemoteControlIntialization(INTERFACE_SIZE isDirectionalPad1, - INTERFACE_SIZE isDirectionalPad2, - INTERFACE_SIZE isButtonA, - INTERFACE_SIZE isButtonB, - INTERFACE_SIZE isButtonC, - INTERFACE_SIZE isButtonD, - INTERFACE_SIZE isSwitchE, - INTERFACE_SIZE isSwitchF) -{ - RemoteControlDataLength = isDirectionalPad1 + - isDirectionalPad2 + - isButtonA + - isButtonB + - isButtonC + - isButtonD + - isSwitchE + - isSwitchF; - DataFormat[0] = isDirectionalPad1; - DataFormat[1] = isDirectionalPad2; - DataFormat[2] = isButtonA; - DataFormat[3] = isButtonB; - DataFormat[4] = isButtonC; - DataFormat[5] = isButtonD; - DataFormat[6] = isSwitchE; - DataFormat[7] = isSwitchF; +void RemoteControlInterruptMode22(structRemoteControlFormat *structBuffer) +{ + // 遍历结构体成员代码,了解 struct structRemoteControlFormat 格式内容 + // structBuffer->A 和 ptr[10] 这两个表达都是同一个地址,他们位置都是:10 + short *ptr = &structBuffer->begin; // 获取结构体首地址 + for (size_t i = 0; i < structBuffer->end, i < 20; i++) + { + Serial.printf("%d-%d ", i, ptr[i]); + } + Serial.println(); +} + +/* + * 串口接收到数据开启调用,和stm32的中断函数一样,在 RemoteControlOnDataReceive() 函数实现数据解析工作, + * 你的逻辑代码建议在 RemoteControlInterruptMode22() 或者在 RemoteControlInterruptMode33() 实现 + * 回调函数不能有耗时操作,延时操作禁止使用的,会触发看门狗,不断重启 + * 函数功能:把不同的按钮指令,存放在指定的结构体中 + */ +void RemoteControlOnDataReceive(const uint8_t *buffer, size_t size) +{ + structRemoteControlFormat outputBuffer = {}; // 输出的缓冲区 + outputBuffer.end = 20; + uint8_t cmd[4] = {0}; // 指令 + uint8_t data[4] = {0}; // 数据 + + char receiveBuffer[4] = {0}; + memcpy(receiveBuffer, buffer, size); + short *ptr = &outputBuffer.begin; + + // 判断是否摇杆数据,在进行解释 + if (size == 4) + { + if ((receiveBuffer[0] & 0xF0) == 0x10) + { + cmd[0] = 0x9A; + getInterruptJoystickvalue_XY(receiveBuffer, &outputBuffer.LEFT_x, &outputBuffer.LEFT_y); + } + else if ((receiveBuffer[0] & 0xF0) == 0x50) + { + cmd[0] = 0x9C; + getInterruptJoystickvalue_XY(receiveBuffer, &outputBuffer.RIGHT_x, &outputBuffer.RIGHT_y); + } + } + else if (size == 1) + { + cmd[0] = (receiveBuffer[0] & 0xF0) / 16; + data[0] = (receiveBuffer[0] & 0x0F); + // 在这里把结构体当成一个数组来使用 + ptr[cmd[0]] = data[0]; + // switch case 模式 * 16 + cmd[0] = cmd[0] * 16; + } + // 选择一个函数使用 + // 使用结构体的成员方法 + RemoteControlInterruptMode22(&outputBuffer); + // 使用 switch case 模式 + // RemoteControlInterruptMode33(cmd, data, outputBuffer.LEFT_x, outputBuffer.LEFT_y, outputBuffer.RIGHT_x, outputBuffer.RIGHT_y); } // 获取摇杆数值 // (inputButton[inputPosition + 0] - 0x30) 把字符转化为数字 -void getJoystickValue(short *outputButton, char outputPosition, char *inputButton, char inputPosition) +void getJoystickValue(short *outputButton, char outputPosition, const char *inputButton, char inputPosition) { - outputButton[outputPosition + 0] = (inputButton[inputPosition + 0] - 0x30) * 100 + - (inputButton[inputPosition + 1] - 0x30) * 10 + - (inputButton[inputPosition + 2] - 0x30) - 100; - outputButton[outputPosition + 0] = ((outputButton[outputPosition + 0]) > 0 ? (outputButton[outputPosition + 0]) : -(outputButton[outputPosition + 0])); - - outputButton[outputPosition + 1] = (inputButton[inputPosition + 3] - 0x30) * 100 + - (inputButton[inputPosition + 4] - 0x30) * 10 + - (inputButton[inputPosition + 5] - 0x30) - 100; - outputButton[outputPosition + 1] = ((outputButton[outputPosition + 1]) > 0 ? (outputButton[outputPosition + 1]) : -(outputButton[outputPosition + 1])); + outputButton[outputPosition] = (inputButton[inputPosition] - DIGIT_ZERO) * 100 + + (inputButton[inputPosition + 1] - DIGIT_ZERO) * 10 + + (inputButton[inputPosition + 2] - DIGIT_ZERO) - 100; + outputButton[outputPosition] = outputButton[outputPosition] > 0 ? outputButton[outputPosition] : -outputButton[outputPosition]; + + outputButton[outputPosition + 1] = (inputButton[inputPosition + 3] - DIGIT_ZERO) * 100 + + (inputButton[inputPosition + 4] - DIGIT_ZERO) * 10 + + (inputButton[inputPosition + 5] - DIGIT_ZERO) - 100; + outputButton[outputPosition + 1] = outputButton[outputPosition + 1] > 0 ? outputButton[outputPosition + 1] : -outputButton[outputPosition + 1]; } // 获取按钮数值 // (inputButton[inputPosition + i] == 0x31) 识别字符是否等于数字的1 -void getDirectionalPad(short *outputButton, char outputPosition, char *inputButton, char inputPosition) +void getDirectionalPad(short *outputButton, char outputPosition, const char *inputButton, char inputPosition) { for (size_t i = 0; i < DIRECTIONAL_PAD_SIZE; i++) { - if (inputButton[inputPosition + i] == 0x31) + if (inputButton[inputPosition + i] == DIGIT_ONE) { outputButton[outputPosition + i] = 1; } @@ -507,113 +517,109 @@ void getDirectionalPad(short *outputButton, char outputPosition, char *inputButt // 获取按钮数值 // (inputButton[inputPosition + i] == 0x31) 识别字符是否等于数字的1 -void getFunctionButtonValue(short *outputButton, char outputPosition, char *inputButton, char inputPosition) +void getFunctionButtonValue(short *outputButton, char outputPosition, const char *inputButton, char inputPosition) { for (size_t i = 0; i < FUNCTION_BUTTON_SIZE; i++) { - if (inputButton[inputPosition + i] == 0x31) + if (inputButton[inputPosition + i] == DIGIT_ONE) { outputButton[outputPosition + i] = 1; } } } -// 遥控器循环模式 -// 数组 outputBuffer[20] 数据格式在枚举 enum LOOP_MODE_ORDER 中定义 -// 返回是数组类型,元素必须大于20个 -short XHZS_RemoteControlLoopMode() +// 截取字符串 +void substring(char *dest, const char *src, size_t start, size_t length) { - short outputBuffer[20] = {0}; // 输出的缓冲区 - char tempBuffer[20] = {0}; // 临时缓冲区 + size_t i; + for (i = 0; i < length && src[start + i] != '\0'; ++i) + { + dest[i] = src[start + i]; + } + dest[i] = '\0'; // 确保字符串以空字符结尾 +} + +/* + * 遥控器的定时模式 + * 功能:对一串有规律的字符串解析处理,放在指定结构体成员中 + * 使用了数组的方式,将结构体当成一个数组来使用,结构体的偏移量来确定成员位置 + */ +structRemoteControlFormat RemoteControlTimerMode(MODULE_SIZE RemoteControlLayoutLeft, MODULE_SIZE RemoteControlLayoutRight) +{ + structRemoteControlFormat outputBuffer = {0}; // 输出的缓冲区 + outputBuffer.begin = 0; + outputBuffer.end = 20; + char tempBuffer[20] = {0}; // 临时缓冲区 + // 判断手柄的方向按钮和摇杆的组合 - char handle = (DataFormat[0] == JOYSTICK_SIZE ? JOYSTICK_AND_DIRECTIONAL_PAD : TWO_DIRECTIONAL_PAD) + - (DataFormat[1] == JOYSTICK_SIZE ? DIRECTIONAL_PAD_AND_JOYSTICK : TWO_DIRECTIONAL_PAD); + char handle = (RemoteControlLayoutLeft == JOYSTICK_SIZE ? JOYSTICK_AND_DIRECTIONAL_PAD : DIRECTIONAL_PAD) + + (RemoteControlLayoutRight == JOYSTICK_SIZE ? DIRECTIONAL_PAD_AND_JOYSTICK : DIRECTIONAL_PAD); size_t data_len = strlen(Uart_getReceiveData()); // 获取长度用于复制 memcpy(tempBuffer, Uart_getReceiveData(), data_len); // 内存复制 + //// 尝试使用 cmd 串口改变,手柄的组合,失败 + // if (tempBuffer[0] == 's' && tempBuffer[1] == 'e' && tempBuffer[2] == 't') + // { + // char *end; + // char tempBufferCopy[data_len]; + + // substring(tempBufferCopy, tempBuffer, 4, 4); // 截取字符串 + // tempBufferCopy[0] = (char)strtol(tempBufferCopy, &end, 16); // 字符串转换十六进制 + // // SerialBT.printf("%s-%d\n", "pad", tempBufferCopy[0]); + + // if (tempBufferCopy[0] == 0x00 || tempBufferCopy[0] == 0x01 || tempBufferCopy[0] == 0x10 || tempBufferCopy[0] == 0x11) + // { + // // handle = *tempBufferCopy; + // handle = tempBufferCopy[0]; + // tempBufferCopy[0] = 100; + // SerialBT.printf("%s-%d\n", "ok", tempBufferCopy[0]); + // } + // } + // 确定,方向按钮和摇杆组合方式 switch (handle) { - case TWO_DIRECTIONAL_PAD: - getDirectionalPad(outputBuffer, 0, tempBuffer, 0); - getFunctionButtonValue(outputBuffer, 8, tempBuffer, 8); + case DIRECTIONAL_PAD: + // 获取结构体的首地址,在基础上移动到指定位置,进行赋值或者读取操作 + getDirectionalPad(&outputBuffer.begin, 1, tempBuffer, 0); + getDirectionalPad(&outputBuffer.begin, 5, tempBuffer, 4); + getFunctionButtonValue(&outputBuffer.begin, 10, tempBuffer, 8); break; case DIRECTIONAL_PAD_AND_JOYSTICK: - getDirectionalPad(outputBuffer, 0, tempBuffer, 0); - getJoystickValue(outputBuffer, 16, tempBuffer, 4); - getFunctionButtonValue(outputBuffer, 8, tempBuffer, 10); + getDirectionalPad(&outputBuffer.begin, 1, tempBuffer, 0); + getJoystickValue(&outputBuffer.begin, 18, tempBuffer, 4); + getFunctionButtonValue(&outputBuffer.begin, 10, tempBuffer, 10); break; case JOYSTICK_AND_DIRECTIONAL_PAD: - getJoystickValue(outputBuffer, 14, tempBuffer, 0); - getDirectionalPad(outputBuffer, 4, tempBuffer, 6); - getFunctionButtonValue(outputBuffer, 8, tempBuffer, 10); + getJoystickValue(&outputBuffer.begin, 16, tempBuffer, 0); + getDirectionalPad(&outputBuffer.begin, 5, tempBuffer, 6); + getFunctionButtonValue(&outputBuffer.begin, 10, tempBuffer, 10); break; - case TWO_JOYSTICKS: - getJoystickValue(outputBuffer, 14, tempBuffer, 0); - getJoystickValue(outputBuffer, 16, tempBuffer, 6); - getFunctionButtonValue(outputBuffer, 8, tempBuffer, 12); + case JOYSTICKS: + getJoystickValue(&outputBuffer.begin, 16, tempBuffer, 0); + getJoystickValue(&outputBuffer.begin, 18, tempBuffer, 6); + getFunctionButtonValue(&outputBuffer.begin, 10, tempBuffer, 12); break; } - return *outputBuffer; - - // #if true - // 不同的遥控器组合,使用不同显示 // 打印在串口监视器中 - switch (handle) - { - case TWO_DIRECTIONAL_PAD: - Serial.printf("up: %d down: %d left: %d right: %d - up: %d down: %d left: %d right: %d ", - outputBuffer[LOOP_LEFT_UP], outputBuffer[LOOP_LEFT_DOWN], outputBuffer[LOOP_LEFT_LEFT], outputBuffer[LOOP_LEFT_RIGHT], - outputBuffer[LOOP_RIGHT_UP], outputBuffer[LOOP_RIGHT_DOWN], outputBuffer[LOOP_RIGHT_LEFT], outputBuffer[LOOP_RIGHT_RIGHT]); - - break; - case DIRECTIONAL_PAD_AND_JOYSTICK: - Serial.printf("up: %d down: %d left: %d right: %d - x: %d y: %d ", - outputBuffer[LOOP_LEFT_UP], outputBuffer[LOOP_LEFT_DOWN], outputBuffer[LOOP_LEFT_LEFT], outputBuffer[LOOP_LEFT_RIGHT], - outputBuffer[LOOP_RIGHT_X], outputBuffer[LOOP_RIGHT_Y]); - break; - case JOYSTICK_AND_DIRECTIONAL_PAD: - Serial.printf(" x: %d y: %d - up: %d down: %d left: %d right: %d ", - outputBuffer[LOOP_LEFT_X], outputBuffer[LOOP_LEFT_Y], - outputBuffer[LOOP_RIGHT_UP], outputBuffer[LOOP_RIGHT_DOWN], outputBuffer[LOOP_RIGHT_LEFT], outputBuffer[LOOP_RIGHT_RIGHT]); - break; - case TWO_JOYSTICKS: - Serial.printf("x: %d y: %d - x: %d y: %d ", - outputBuffer[LOOP_LEFT_X], outputBuffer[LOOP_LEFT_Y], - outputBuffer[LOOP_RIGHT_X], outputBuffer[LOOP_RIGHT_Y]); - break; - } - Serial.printf(" A: %d B: %d C: %d D: %d E: %d F: %d \n", - outputBuffer[LOOP_BUTTON_A], - outputBuffer[LOOP_BUTTON_B], - outputBuffer[LOOP_BUTTON_C], - outputBuffer[LOOP_BUTTON_D], - outputBuffer[LOOP_BUTTON_E], - outputBuffer[LOOP_BUTTON_F]); - // #endif -} - -// 遥控器中断模式 -void XHZS_RemoteControlInterruptMode() -{ - // 准备整合 + return outputBuffer; } /************************* XHZS end *************************/ // -/************************* example funtion begin *************************/ +/************************* example begin *************************/ -// 开启串口回调函数,需要在蓝牙初始化之前调用 // isEnable = true 开启,false 关闭 -// 串口(蓝牙)接收到数据触发回调函数 Uart_onDataReceive() -// 底层 blueTooth 库中 onData() 函数绑定回调函数 Uart_onDataReceive() 函数作为触发调用 -// 找到 Uart_onDataReceive() 在里面写你的逻辑代码,不要有延时操作,中断函数中不能有延时操作 -// 在不使用串口功能时,请关闭防止与其它功能模块的冲突 -void test_serial_port_callback_function(bool isEnable) +/** + * 此函数应在蓝牙初始化前调用,当 isEnable 数值为 true 时开启,false 则禁用。 + * 在底层蓝牙库中,onData() 函数将绑定 Uart_onDataReceive() 作为其回调,从而在接收到数据时触发相应的处理逻辑。 + * 串口回调时实现自己的代码逻辑,找到 Uart_onDataReceive() 修改里面代码 + */ +void test_serial_port_callback_enable(bool isEnable) { - SERIAL_PORT_CALLBACK_FUNCTION_ENABLE = isEnable; + SERIAL_PORT_CALLBACK_ENABLE = isEnable; } // 发送波形数据的函数例子 @@ -622,14 +628,19 @@ void test_oscilloscope_send_wave() SendWave(); } -// 示波器输入和输出案例 -void test_oscilloscope_input_and_output() +/** + * 示波器发送和接收函数示例 + * 数据类型:字符串,通道数量:4,开始接收 + * 参数调试:开启定时发送,选择参数调整 + */ +void test_oscilloscope_send_and_Receive() { float floatValue1, floatValue2, floatValue3, floatValue4; // 准备数据类型 - char *charData = Uart_getReceiveData(); + char *charData = Uart_getReceiveData(); // 获取蓝牙串口的数据 + // 给通道四输出波形数据 floatValue4 = (floatValue4 > 33 ? -22 : (floatValue4 += 0.1)); - // 将字符串中的字段的数值提取出来 + // 将字符串中的字段的数值提取出来,字符串格式为:下方 // c11:14.12,c12:22,c13:33,c14: 55.66, // c13字段,数值为33 OscGetValue(charData, "c11", &floatValue1); @@ -638,11 +649,49 @@ void test_oscilloscope_input_and_output() OscGetValue(charData, "c14", &floatValue4); SerialBT.printf("w:%0.2f,%0.2f,%0.2f,%0.2f\r\n", floatValue1, floatValue2, floatValue3, floatValue4); - vTaskDelay(50 / portTICK_PERIOD_MS); // 延时函数,可以注释掉 + delay(50); // 延时函数,可以注释掉 +} + +/* + * 此函数应在蓝牙初始化前调用,当 isEnable 数值为 true 时开启,false 则禁用。 + * 在底层蓝牙库中,onData() 函数将绑定 RemoteControlOnDataReceive() 作为其回调,从而在接收到数据时触发相应的处理逻辑。 + * 串口回调时实现自己的代码逻辑,找到 RemoteControlOnDataReceive() 修改里面代码 + */ +void test_remote_control_callback_enable(bool isEnable) +{ + REMOTE_CONTROL_CALLBACK_ENABLE = isEnable; +} + +/** + * 遥控器的定时发送模式,函数的参数决定摇杆和方向按钮组合 + * 摇杆:JOYSTICK_SIZE and 方向按钮:DIRECTIONAL_PAD_SIZE + * 手柄组合有4种,配合学会助手的遥控器功能一起使用 + */ +void test_remote_control_Timer_function() +{ + structRemoteControlFormat buffer = RemoteControlTimerMode(DIRECTIONAL_PAD_SIZE, DIRECTIONAL_PAD_SIZE); + + short *ptr = &buffer.begin; + for (size_t i = 0; i < 20, i < buffer.end; i++) + { + Serial.printf("%d-%d ", i, ptr[i]); + } + Serial.println(); + + // delay(50); // 延时函数可以删除 } -/************************* example funtion end *************************/ + +/************************* example end *************************/ // /************************* test begin *************************/ +#if false +/* +在处理十六进制的时候发现一个问题,如何把 0x10 and 0x20 转化成数字的 1 and 2, +第一想到的字节的移位操作,但是这样最少操作四次,一个字节八位, +在计算十六进制大小发现一个规律,高位每加一位相差15 +0x50 升一位需要加15,降一位需要15 +*/ + struct myStruct { char a; @@ -652,6 +701,11 @@ struct myStruct char e; }; +/* +如何把结构体像数组一样使用?可以做到,前提条件时是结构体成员是单一类型时,结构体内部就像一个数组, +获取结构体的首地址,在基础上进行偏移,可以像数组一样访问了 +问题来了,结构体的大小,或者说时长度问题,需要手动计算,使用for循环遍历警惕循环次数 +*/ void test_struct_array() { myStruct box = {}; @@ -666,22 +720,24 @@ void test_struct_array() Serial.printf("%d-%d- ", i, *(ptr + i)); } Serial.printf("a: %d b: %d c: %d d: %d e: %d\n", box.a, box.b, box.c, box.d, box.e); - delay(100); + delay(10); } -/* -struct MyStruct { +struct MyStruct +{ int a; int b; int c; // 假设a, b, c是连续存储的 }; - -MyStruct s; -int* ptr = &s.a; // 获取a的地址 -for (int i = 0; i < 3; ++i) { - *(ptr + i) = i; // 通过指针偏移访问,尽管能工作但不推荐 +void test_struct_move() +{ + MyStruct s; + int *ptr = &s.a; // 获取a的地址 + for (int i = 0; i < 3; ++i) + { + *(ptr + i) = i; // 通过指针偏移访问,尽管能工作但不推荐 + } } -*/ - +#endif /************************* test end *************************/ diff --git a/Arduino_ESP32_oscilloscope/myBlueTooth.h b/Arduino_ESP32_oscilloscope/myBlueTooth.h index 5f8096a2..38631171 100644 --- a/Arduino_ESP32_oscilloscope/myBlueTooth.h +++ b/Arduino_ESP32_oscilloscope/myBlueTooth.h @@ -9,57 +9,62 @@ #define MYBLUETOOTH_H_ #include -#include // 字符串操作库 -#include // ESP32蓝牙库 +#include +#include -// 遥控器循环指令枚举定义 -enum LOOP_MODE_ORDER +// 定义遥控器输出结构体 +struct structRemoteControlFormat { - LOOP_LEFT_UP = 0, // 左上方向 - LOOP_LEFT_DOWN = 1, // 左下方向 - LOOP_LEFT_LEFT = 2, // 左方向 - LOOP_LEFT_RIGHT = 3, // 右方向 - - LOOP_RIGHT_UP = 4, // 右上方向 - LOOP_RIGHT_DOWN = 5, // 右下方向 - LOOP_RIGHT_LEFT = 6, // 右左方向 - LOOP_RIGHT_RIGHT = 7, // 右右方向 - - LOOP_BUTTON_A = 8, // 按钮A - LOOP_BUTTON_B = 9, // 按钮B - LOOP_BUTTON_C = 10, // 按钮C - LOOP_BUTTON_D = 11, // 按钮D - LOOP_BUTTON_E = 12, // 按钮E - LOOP_BUTTON_F = 13, // 按钮F - - LOOP_LEFT_X = 14, // 左摇杆X轴 - LOOP_LEFT_Y = 15, // 左摇杆Y轴 - LOOP_RIGHT_X = 16, // 右摇杆X轴 - LOOP_RIGHT_Y = 17 // 右摇杆Y轴 + short begin; + + short LEFT_up; // 向上 // 1 + short LEFT_down; // 向下 + short LEFT_left; // 向左 + short LEFT_right; // 向右 + + short RIGHT_up; // 向上 // 5 + short RIGHT_down; // 向下 + short RIGHT_left; // 向左 + short RIGHT_right; // 向右 + + short middle; + + short A; // 按钮A // 10 + short B; // 按钮B + short C; // 按钮C + short D; // 按钮D + short E; // 按钮E + short F; // 按钮F + + short LEFT_x; // 左摇杆X轴 // 16 + short LEFT_y; // 左摇杆Y轴 + short RIGHT_x; // 右摇杆X轴 + short RIGHT_y; // 右摇杆Y轴 + + short end; // 结束标志位 // 20 }; // 遥控器中断指令枚举定义 enum INTERRUPT_MODE_ORDER { - // 按键状态指令 INTERRUPT_BUTTON_RELEASE = 0X00, // 按键释放指令 INTERRUPT_BUTTON_PRESS = 0X01, // 按键按下指令 - // 左侧方向键指令 INTERRUPT_LEFT_UP = 0X10, // 左侧方向键上 INTERRUPT_LEFT_DOWN = 0X20, // 左侧方向键下 INTERRUPT_LEFT_LEFT = 0X30, // 左侧方向键左 INTERRUPT_LEFT_RIGHT = 0X40, // 左侧方向键右 - // 右侧方向键指令 INTERRUPT_RIGHT_UP = 0X50, // 右侧方向键上 INTERRUPT_RIGHT_DOWN = 0X60, // 右侧方向键下 INTERRUPT_RIGHT_LEFT = 0X70, // 右侧方向键左 INTERRUPT_RIGHT_RIGHT = 0X80, // 右侧方向键右 - INTERRUPT_LEFT_X_Y = 0X9A, - INTERRUPT_RIGHT_X_Y = 0X9C, - // 左右功能按键指令 + INTERRUPT_LEFT_X = 0X9A, // 摇杆的指令 + INTERRUPT_LEFT_Y = 0X9B, + INTERRUPT_RIGHT_X = 0X9C, + INTERRUPT_RIGHT_Y = 0X9D, + INTERRUPT_BUTTON_A = 0XA0, // 左侧A功能键 INTERRUPT_BUTTON_B = 0XB0, // 左侧B功能键 INTERRUPT_BUTTON_C = 0XC0, // 右侧C功能键 @@ -74,88 +79,104 @@ typedef enum MODULE_SIZE JOYSTICK_SIZE = 6, // 手柄摇杆,占位6 DIRECTIONAL_PAD_SIZE = 4, // 方向按钮,占位4 FUNCTION_BUTTON_SIZE = 6, // 功能按键,占位6 - BUTTON_SIZE = 1, // 按键,占位1 - SWITCH_SIZE = 1 // 开关,占位1 + } INTERFACE_SIZE; // 遥控器的方向按钮和摇杆组合 enum POLYTYPE { - TWO_DIRECTIONAL_PAD = 0x00, // 0x00 + DIRECTIONAL_PAD = 0x00, // 0x00 DIRECTIONAL_PAD_AND_JOYSTICK = 0x01, // 0x01 JOYSTICK_AND_DIRECTIONAL_PAD = 0x10, // 0x10 - TWO_JOYSTICKS = 0x11 // 0x11 + JOYSTICKS = 0x11 // 0x11 }; -extern bool SERIAL_PORT_CALLBACK_FUNCTION_ENABLE; -/************************* 蓝牙功能核心接口 *************************/ +/************************* 蓝牙功能相关函数 *************************/ -// 设定蓝牙名称,默认为"mini_bot" +// **初始化蓝牙模块**,设置设备名,默认为"mini_bot" void BTinitialize(const String &deviceName = "mini_bot"); -// 将浮点数转换字符串通过蓝牙发送 +// **发送浮点数**通过蓝牙 void BTsendFloatVia(const float *data); -// 发送字符串到蓝牙连接的设备 +// **发送字符串**到蓝牙连接的设备 void BTsendStringVia(const char *stringData); -// 返回一个指针指向接收到的字符串数据。 +// **获取蓝牙接收的字符串** char *BTgetReceivedData(); -/************************* 高级数据处理接口 ************************/ +/************************* 串口通讯辅助函数 ************************/ -// 当通过UART接收到数据时,此函数将被调用 +// 串口数据接收回调,当有数据通过UART接收到时调用 void Uart_onDataReceive(const uint8_t *dataBuffer, size_t dataSize); -// 获取接收到的数据 +// 获取串口接收数据 char *Uart_getReceiveData(); -// 通过UART发送一个字节的数据 +// 发送单个字节,通过UART void Uart_SendByte(const uint8_t *byte); -// 通过UART发送一个字节数组 +// 发送字节数组,通过UART void Uart_SendArray(const uint8_t *array, size_t arraySize); -// 发送指定数据格式 -void XHZS_SendWave(const void *waveAddr, uint16_t waveSize); +// 发送特定格式数据,如波形数据 +void XHZS_SendWave(const uint8_t *waveAddr, uint16_t waveSize); + +/************************* 示波器相关函数 ************************/ // 发送波形数据的函数 void SendWave(); -// 输入 char *p 解析为 float *value +// 解析字符串为浮点数 char OscGetFloat(const char *p, float *value); -// 从示波器获取的数据格式,按字段解析为数值 +// 从特定格式数据中提取浮点数 char OscGetValue(const char *p, const char *name, float *value); -/************************* 演示示例函数 ************************/ +/************************* 遥控器交互相关函数 ************************/ + +// 遥控器数据接收处理回调 +void RemoteControlOnDataReceive(const uint8_t *buffer, size_t size); + +// 处理遥控器中断模式下的命令 +void RemoteControlInterruptMode22(structRemoteControlFormat *structBuffer); + +// 处理遥控器中断模式下的命令 // 备用 +void RemoteControlInterruptMode33(uint8_t *cmd, uint8_t *data, short left_X, short left_Y, short right_X, short right_Y); + +// 获取遥控器定时模式的数据 +structRemoteControlFormat RemoteControlTimerMode(MODULE_SIZE RemoteControlLayoutLeft, MODULE_SIZE RemoteControlLayoutRight); + +/************************* 示例与测试函数 ************************/ + +// 启用串口函数回调功能,在蓝牙初始化前调用 +void test_serial_port_callback_enable(bool isEnable = false); -void test_serial_port_callback_function(bool isEnable = false); // 开启串口回调函数,需要在蓝牙初始化之前调用 +// 测试发送波形数据到其他设备 +void test_oscilloscope_send_wave(); -void test_oscilloscope_send_wave(); // 发送波形数据的函数 +// 示例:示波器数据收发互动 +void test_oscilloscope_send_and_Receive(); -void test_oscilloscope_input_and_output(); // 示波器输入和输出案例 +// 启用遥控器函数回调函数,在蓝牙初始化前调用 +void test_remote_control_callback_enable(bool isEnable = false); -/************************* 其它模块适配,适配中... ************************/ +// 遥控器定时模式下的功能 +void test_remote_control_Timer_function(); -void test_remote_control(const uint8_t *buffer, size_t size); // 遥控器 +/************************* 功能测试,适配中... ************************/ -void XHZS_RemoteControlIntialization(INTERFACE_SIZE isDirectionalPad1, - INTERFACE_SIZE isDirectionalPad2, - INTERFACE_SIZE isButtonA = BUTTON_SIZE, - INTERFACE_SIZE isButtonB = BUTTON_SIZE, - INTERFACE_SIZE isButtonC = BUTTON_SIZE, - INTERFACE_SIZE isButtonD = BUTTON_SIZE, - INTERFACE_SIZE isSwitchE = SWITCH_SIZE, - INTERFACE_SIZE isSwitchF = SWITCH_SIZE); +// // 遥控器数据处理测试函数 +// void test_remote_control(const uint8_t *buffer, size_t size); -void XHZS_RemoteControlIntialization(); // 遥控器初始化 -// void XHZS_RemoteControlLoopMode(); // 遥控器循环模式 -void XHZS_RemoteControlInterruptMode(); // 遥控器中断模式 +// // 测试遥控器中断模式下的功能 +// void XHZS_RemoteControlInterruptMode(); -short XHZS_RemoteControlLoopMode(); +// // 结构体数组的使用示例 +// void test_struct_array(); -void test_struct_array(); +// // 结构体移动示例 +// void test_struct_move(); #endif diff --git a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp index 12775e41..dd48703d 100644 --- a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp +++ b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.cpp @@ -481,8 +481,10 @@ void RemoteControlOnDataReceive(const uint8_t *buffer, size_t size) cmd[0] = cmd[0] * 16; } // 选择一个函数使用 - RemoteControlInterruptMode22(&outputBuffer); // 使用结构体的成员方法 - // RemoteControlInterruptMode33(cmd, data, outputBuffer.LEFT_x, outputBuffer.LEFT_y, outputBuffer.RIGHT_x, outputBuffer.RIGHT_y); // 使用 switch case 模式 + // 使用结构体的成员方法 + RemoteControlInterruptMode22(&outputBuffer); + // 使用 switch case 模式 + // RemoteControlInterruptMode33(cmd, data, outputBuffer.LEFT_x, outputBuffer.LEFT_y, outputBuffer.RIGHT_x, outputBuffer.RIGHT_y); } // 获取摇杆数值 @@ -556,7 +558,7 @@ structRemoteControlFormat RemoteControlTimerMode(MODULE_SIZE RemoteControlLayout size_t data_len = strlen(Uart_getReceiveData()); // 获取长度用于复制 memcpy(tempBuffer, Uart_getReceiveData(), data_len); // 内存复制 - //// 尝试使用串口改变,手柄的组合,失败 + //// 尝试使用 cmd 串口改变,手柄的组合,失败 // if (tempBuffer[0] == 's' && tempBuffer[1] == 'e' && tempBuffer[2] == 't') // { // char *end; diff --git a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h index a7ea9dae..38631171 100644 --- a/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h +++ b/PlatformIO_ESP32_oscilloscope/lib/myBlueTooth/myBlueTooth.h @@ -41,7 +41,7 @@ struct structRemoteControlFormat short RIGHT_x; // 右摇杆X轴 short RIGHT_y; // 右摇杆Y轴 - short end; + short end; // 结束标志位 // 20 }; // 遥控器中断指令枚举定义 @@ -108,30 +108,30 @@ char *BTgetReceivedData(); /************************* 串口通讯辅助函数 ************************/ -// **串口数据接收回调**,当有数据通过UART接收到时调用 +// 串口数据接收回调,当有数据通过UART接收到时调用 void Uart_onDataReceive(const uint8_t *dataBuffer, size_t dataSize); -// **获取串口接收数据** +// 获取串口接收数据 char *Uart_getReceiveData(); -// **发送单个字节**通过UART +// 发送单个字节,通过UART void Uart_SendByte(const uint8_t *byte); -// **发送字节数组**通过UART +// 发送字节数组,通过UART void Uart_SendArray(const uint8_t *array, size_t arraySize); -// **发送特定格式数据**,如波形数据 +// 发送特定格式数据,如波形数据 void XHZS_SendWave(const uint8_t *waveAddr, uint16_t waveSize); /************************* 示波器相关函数 ************************/ -// **实际发送波形数据的函数** +// 发送波形数据的函数 void SendWave(); -// **解析字符串为浮点数** +// 解析字符串为浮点数 char OscGetFloat(const char *p, float *value); -// **从特定格式数据中提取浮点数** +// 从特定格式数据中提取浮点数 char OscGetValue(const char *p, const char *name, float *value); /************************* 遥控器交互相关函数 ************************/ @@ -162,10 +162,10 @@ void test_oscilloscope_send_and_Receive(); // 启用遥控器函数回调函数,在蓝牙初始化前调用 void test_remote_control_callback_enable(bool isEnable = false); -// 示例:遥控器定时模式下的功能 +// 遥控器定时模式下的功能 void test_remote_control_Timer_function(); -/************************* 其它模块适配,适配中... ************************/ +/************************* 功能测试,适配中... ************************/ // // 遥控器数据处理测试函数 // void test_remote_control(const uint8_t *buffer, size_t size); diff --git a/PlatformIO_ESP32_oscilloscope/src/main.cpp b/PlatformIO_ESP32_oscilloscope/src/main.cpp index 7bbfd76a..a9e7f7d9 100644 --- a/PlatformIO_ESP32_oscilloscope/src/main.cpp +++ b/PlatformIO_ESP32_oscilloscope/src/main.cpp @@ -12,6 +12,7 @@ BluetoothSerial SerialBlueTooth; // 定义蓝牙串口对象 // 串口回调函数和遥控器回调函数不能同时使用 // 回调函数和示波器和遥控器功能不能同时使用 + void setup() { // 初始化串口通信,设置波特率为115200 -- Gitee