#include "includes.h" // 任务主体 void Modbus_Task(uint8_t c); // modbus通讯处理 #pragma pack(push, 1) typedef struct { uint8_t id; // 通信地址 uint8_t cmd; // 功能码 uint16_t reg; // 寄存器地址 union { uint16_t cnt; // 读取:寄存器数量 uint16_t data; // 写入:寄存器数据 }; uint16_t crc; } modbus_request_t; typedef struct { uint8_t id; // 通信地址 uint8_t cmd; // 功能码 uint16_t reg; // 寄存器地址 // union // { // uint16_t data[13]; // // }; uint16_t staDiff; //30001 uint16_t diff; //差压值 uint16_t volumePct; //30003 容积百分比 uint16_t volumeH; // 容积H uint16_t volumeL; // 容积L uint16_t weightH; // 重量H uint16_t weightL; // 重量L uint16_t highMMWC; uint16_t press; int16_t tempr; //30010温度 uint16_t source; //30011介质 uint16_t v_H; // uint16_t v_L; // // uint16_t staVacuum; // 真空计状态 // uint16_t vacuum; // 真空度, // int16_t vacuum_tempr;//30016 真空计温度 /////////////////// uint16_t crc; } modbus_readdata_t; #pragma pack(pop) // modbus rtu 数据缓冲区 #define MODBUS_1ST_REG (30001) // 第1个数据地址 #define MODBUS_LAST_REG (30016) // 最后一个数据地址 #define MODBUS_ADR_REG (40001) // 通信地址的数据地址 // modbus rtu错误代码 #define MODBUS_ERR_ILF (0x01) // 无效功能码 #define MODBUS_ERR_ILA (0x02) // 无效通讯地址 #define MODBUS_ERR_ILD (0x03) // 无效数据值 #define MODBUS_ERR_FID (0x04) // 执行失败 #define MODBUS_ERR_ACK (0x05) // ACK(命令已接受并在处理中) #define MODBUS_ERR_BUSY (0x06) // 设备忙,拒绝 #define MODBUS_ERR_NAK (0x07) // NAK(命令无法执行) // modbus rtu 数据缓冲区 //uint8_t MODBUS_RTU_Buf[(MODBUS_LAST_REG - MODBUS_1ST_REG + 1) * 2]; modbus_readdata_t modbus_data; void Slave_IRQHandler(USART_Handle *huart) { uint8_t u8DTU = (uint8_t) huart->Instance->RDR; /* Handle received data */ Modbus_Task(u8DTU); } void Slave_Init() { LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; //LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); /**USART3 GPIO Configuration PC10 ------> USART3_TX PC11 ------> USART3_RX PA15 ------> USART3_DE Pb10 ------> LPRX Pb11 ------> LPTX Pb1 ------> LP_DE */ GPIO_InitStruct.Pin = LL_GPIO_PIN_10|LL_GPIO_PIN_11; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF_8; LL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_1; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; //GPIO_InitStruct.Alternate = LL_GPIO_AF_7; LL_GPIO_Init(GPIOB, &GPIO_InitStruct); } #define RS485_EN() LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_1); #define RS485_DIS() LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_1); /*---------------------------------------------------------------------------------------------------------*/ /* RS485 Transmit Control (Address Byte: Parity Bit =1 , Data Byte:Parity Bit =0) */ /*---------------------------------------------------------------------------------------------------------*/ static void RS485_SendDataByte(uint8_t *pu8TxBuf, uint32_t u32WriteBytes) { /* Set UART parity as SPACE and skip baud rate setting */ // UART_SetLine_Config(UART1, 0, UART_WORD_LEN_8, UART_PARITY_SPACE, UART_STOP_BIT_1); /* Send data */ // UART_Transmit_IT(&huart3, pu8TxBuf, u32WriteBytes); RS485_EN(); delay_us(1); // 设置超时和结果 modbus_outTick = GetDelayTick(500); UART_Transmit_IT(&hlpuart1, pu8TxBuf, u32WriteBytes); delay_ms(9); // 至少8ms,保险起见9ms RS485_DIS(); } void Slave_Open() { // LL_USART_InitTypeDef USART_InitStruct = {0}; // huart3.RxISR = Slave_IRQHandler; // /* Peripheral clock enable */ // LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3); // /* USART3 interrupt Init */ // NVIC_SetPriority(USART3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0)); // NVIC_EnableIRQ(USART3_IRQn); // /* USER CODE BEGIN USART3_Init 1 */ // /* USER CODE END USART3_Init 1 */ // USART_InitStruct.BaudRate = 9600; // USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B; // USART_InitStruct.StopBits = LL_USART_STOPBITS_1; // USART_InitStruct.Parity = LL_USART_PARITY_NONE; // USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; // USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; // USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; // LL_USART_Init(USART3, &USART_InitStruct); // LL_USART_EnableDEMode(USART3); // LL_USART_SetDESignalPolarity(USART3, LL_USART_DE_POLARITY_HIGH); // LL_USART_SetDEAssertionTime(USART3, 0); // LL_USART_SetDEDeassertionTime(USART3, 0); // LL_USART_ConfigAsyncMode(USART3); // SET_BIT(USART3->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); // LL_USART_Enable(USART3); LL_LPUART_InitTypeDef LPUART_InitStruct = {0}; hlpuart1.RxISR = Slave_IRQHandler; /* Peripheral clock enable */ LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1); NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0)); NVIC_EnableIRQ(LPUART1_IRQn); LPUART_InitStruct.BaudRate = 9600; LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B; LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1; LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE; LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX; LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE; LL_LPUART_Init(LPUART1, &LPUART_InitStruct); LL_LPUART_EnableDEMode(LPUART1); LL_LPUART_SetDESignalPolarity(LPUART1, LL_LPUART_DE_POLARITY_HIGH); LL_LPUART_SetDEAssertionTime(LPUART1, 0); LL_LPUART_SetDEDeassertionTime(LPUART1, 0); SET_BIT(LPUART1->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); LL_LPUART_Enable(LPUART1); } uint32_t Fill_MODBUS_RTU_Buf() { return 1; } // 处理modbus rtu命令(已经验证过长度和CRC的包) void MODBUS_RTU_CMD(modbus_readdata_t *req) { // 检查通信地址 if(req->id != 0x01) return; if(req->cmd != 0x04) return; } // 模块任务主体:处理射频接收数据 // 任务主体 uint8_t modbus_idx2 = 0; uint8_t MODBUS_BUFF[sizeof(modbus_readdata_t)] = {0}; uint16_t CRC2=0; void Modbus_Task(uint8_t c) { uint8_t len = 0; //////////// uint16_t i; uint8_t frameOk, frameErr; uint32_t mask; //rs_data_t *rsData = (rs_data_t *) (RS_TranFrame.data + sizeof(mask)); if(modbus_idx2 == 0 && c != 0x01) return; MODBUS_BUFF[modbus_idx2++] = c; // printf("\n***\n***\n*** read data[%d]=%d ***\n***\n***\n",len,c); // 验证长度和CRC值 len=sizeof(modbus_readdata_t)-1; if(modbus_idx2 == len) { if(MODBUS_RTU_CRC16(MODBUS_BUFF, sizeof(modbus_readdata_t)) == 0) { MODBUS_RTU_CMD((modbus_readdata_t *) MODBUS_BUFF); modbus_idx2 = 0; } else { // 丢掉第一个字节 memmove(MODBUS_BUFF, MODBUS_BUFF + 1, --modbus_idx2); } } } void modbus_read_data(void) { // uint8_t id; // 通信地址 // uint8_t cmd; // 功能码 // uint16_t reg; // 寄存器地址 // union // { // uint16_t cnt; // 读取:寄存器数量 // uint16_t data; // 写入:寄存器数据 //// }; uint16_t crc; // static uint8_t BUFF2[sizeof(modbus_request_t)] = {0x01,0x04,0x00,0x00,0x00,0x0d,0x31,0xcf}; static uint8_t BUFF2[sizeof(modbus_request_t)] = {0}; uint8_t len=0; // 计算CRC BUFF2[len++]=0x01; //addr BUFF2[len++]=0x04; //cmd BUFF2[len++]=0x00; //regaddr BUFF2[len++]=0x00; //regaddr BUFF2[len++]=0x00; //cnt BUFF2[len++]=0x0d; //cnt crc = MODBUS_RTU_CRC16(BUFF2, len); crc = htons(crc); memmove(BUFF2 + len, &crc, 2); len += 2; RS485_SendDataByte(BUFF2, len); }