串口 转发 成功 3.0.0
301
- admin管理员2天前
/* * STM32F407 串口双向透传 * ------------------------------------------------------------ * 485主机接口 : PB6(RX)/PB7(TX)/PB5(EN) 9600 * 井下数据口 : PA2(USART2_TX)/PA3(USART2_RX) 300 * 调试口 : PA9/PA10(USART1) 115200 */ #include <Arduino.h> #include <SoftwareSerial.h> // ==================== 硬件配置 ==================== #define RS485_RX PB7 #define RS485_TX PB6 #define RS485_EN PB5 #define EEPROM_BASE 0x080E0000 // ==================== 引脚定义 ==================== // 开关 控制引脚 #define CL_0 PB0 // PB0 长短缆切换 #define CL_1 PB1 // PB1 长短缆切换 #define KZ PE10 // PE10 KZ1 // 增益 编码输出引脚 (1-16) #define ENCODE_PB2 PB2 // PB2 (最高位) #define ENCODE_PE7 PE7 // PE7 #define ENCODE_PE8 PE8 // PE8 #define ENCODE_PE9 PE9 // PE9 (最低位) // ADC 输入引脚 #define ADC1_PIN PA5 // PA5/ADC1 长短缆检测 #define ADC2_PIN PA6 // PA6/ADC2 控制器输出电压 #define ADC3_PIN PA7 // PA7/ADC3 控制器输出电流 // 解码管脚 #define PCODE_PIN PA1 #define NCODE_PIN PA0 // 使用你的方式定义串口 Uart Serial1(USART1); Uart Serial2(USART2); SoftwareSerial rs485(RS485_RX, RS485_TX); // ==================== 485函数开始 ==================== // 切换到发送模式 void setTxMode() { digitalWrite(RS485_EN, HIGH); delayMicroseconds(200); // 等待方向稳定 } // 切换到接收模式 void setRxMode() { rs485.flush(); // 等待发送完成 delayMicroseconds(200); // 确保最后字节发送完成 digitalWrite(RS485_EN, LOW); } // 发送多个字节(基础版) void rs485Write(const uint8_t* data, size_t length) { setTxMode(); // 切换到发送模式 rs485.write(data, length); // 发送数据 setRxMode(); // 切换回接收模式 } // ==================== 485方向控制 ==================== void rs485SetReceive() { digitalWrite(RS485_EN, LOW); delayMicroseconds(10); } void rs485SetTransmit() { digitalWrite(RS485_EN, HIGH); delayMicroseconds(10); } // ==================== RS485发送 ==================== void rs485Write(uint8_t data) { rs485SetTransmit(); rs485.write(data); rs485.flush(); rs485SetReceive(); } void rs485WriteBuffer(uint8_t* buf, uint16_t len) { rs485SetTransmit(); for (uint16_t i = 0; i < len; i++) { rs485.write(buf[i]); } rs485.flush(); rs485SetReceive(); } // ==================== Flash写多个字节 ==================== // 保存数据到Flash(2字节对齐) void saveData(uint8_t* data, uint16_t len) { HAL_FLASH_Unlock(); // 擦除扇区 FLASH_EraseInitTypeDef e = {}; e.TypeErase = FLASH_TYPEERASE_SECTORS; e.Sector = 11; e.NbSectors = 1; e.VoltageRange = FLASH_VOLTAGE_RANGE_3; uint32_t err; HAL_FLASHEx_Erase(&e, &err); // 2字节对齐写入 for (int i = 0; i < len; i += 2) { uint16_t w = 0xFFFF; if (i < len) w = data[i]; if (i+1 < len) w |= (data[i+1] << 8); HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, EEPROM_BASE + i, w); } HAL_FLASH_Lock(); } // 读取数据 void loadData(uint8_t* buf, uint16_t len) { for (int i = 0; i < len; i++) { buf[i] = *(uint8_t*)(EEPROM_BASE + i); } } // ====================// ====================// ====================// ====================// ==================== // 长短缆管脚赋值 void setDecode(uint8_t val) { digitalWrite(PCODE_PIN, val & 0x01); digitalWrite(NCODE_PIN, (val >> 1) & 0x01); } // 增益管脚赋值 void setEncode(uint8_t val) { digitalWrite(ENCODE_PE9, val & 0x01); digitalWrite(ENCODE_PE8, (val >> 1) & 0x01); digitalWrite(ENCODE_PE7, (val >> 2) & 0x01); digitalWrite(ENCODE_PB2, (val >> 3) & 0x01); } // ====================// ====================// ====================// ====================// ==================== // 超时接收(精简版) bool readRs485(uint8_t* buffer, uint16_t maxLen, uint16_t* len, uint32_t timeoutMs = 100) { *len = 0; if (!buffer || maxLen == 0 || !rs485.available()) return false; uint32_t start = millis(); while (*len < maxLen && (millis() - start) < timeoutMs) { if (rs485.available()) { buffer[(*len)++] = rs485.read(); start = millis(); // 收到数据重置超时 } delayMicroseconds(50); } return (*len > 0); } // ==================== 数据转发 ==================== void forwardData() { // 1. RS485 -> 调试口 + 井下口 while (rs485.available()) { uint8_t data = rs485.read(); Serial1.write(data); Serial2.write(data); } // 2. 调试口 -> RS485 + 井下口 while (Serial1.available()) { uint8_t data = Serial1.read(); rs485Write(data); Serial2.write(data); } // 3. 井下口 -> RS485 + 调试口 while (Serial2.available()) { uint8_t data = Serial2.read(); rs485Write(data); Serial1.write(data); } } // ==================== Setup ==================== void setup() { pinMode(RS485_EN, OUTPUT); rs485SetReceive(); Serial1.begin(115200); // 调试口 Serial2.begin(300); // 井下口 rs485.begin(9600); // RS485 pinMode(RS485_RX, INPUT_PULLUP); pinMode(RS485_TX, OUTPUT); //////////////////////////adc设置//////////////////////////// pinMode(ADC1_PIN, INPUT_ANALOG); pinMode(ADC2_PIN, INPUT_ANALOG); pinMode(ADC3_PIN, INPUT_ANALOG); ///////////长短兰///////////////增益//////////////////////////// pinMode(PCODE_PIN, OUTPUT); pinMode(NCODE_PIN, OUTPUT); pinMode(ENCODE_PB2, OUTPUT); pinMode(ENCODE_PE7, OUTPUT); pinMode(ENCODE_PE8, OUTPUT); pinMode(ENCODE_PE9, OUTPUT); // 设置长短缆: PCODE=1, NCODE=0 // setDecode(0x01); // 设置增益: 0x0A (1010) // setEncode(0x0A); ///////////eprom 写入//////////////////////////// // 准备4字节数据 可以是编号 长短缆 和增益 uint8_t myData[4] = {0x0A, 0x01, 0x12, 0x34}; //saveData(myData, sizeof(myData)); Serial1.println("Saved!"); } // ==================== Loop ==================== void loop() { forwardData(); delay(1000); //============================================================================================ uint8_t readBuf[4]; loadData(readBuf, sizeof(readBuf)); for (int i = 0; i < 4; i++) { Serial1.printf("Byte%d: 0x%02X\r\n", i, readBuf[i]); } //============================================================================================ int a1 = analogRead(ADC1_PIN); int a2 = analogRead(ADC2_PIN); int a3 = analogRead(ADC3_PIN); Serial1.printf("%4d %4d %4d\r\n", a1, a2, a3); delay(5000); //============================================================================================ uint8_t buffer[64]; uint16_t len = 0; // 接收数据,超时100ms if (readRs485(buffer, sizeof(buffer), &len, 100)) { Serial.print("Received "); Serial.print(len); Serial.print(" bytes: "); for (uint16_t i = 0; i < len; i++) { Serial.printf("%02X ", buffer[i]); } Serial.println(); } } // ==================== 系统时钟配置 ==================== extern "C" void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {}; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 12; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 7; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } SystemCoreClock = 168000000UL; } 已经完成 eprom 增益 长短缆 的功能