283 lines
7.9 KiB
C
283 lines
7.9 KiB
C
#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);
|
||
|
||
}
|