stm32l431_xl_current/App/Src/frt_protocol.c

556 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "frt_protocol.h"
#include "assertions.h"
#include "inflash.h"
#include "e22.h"
extern u_int8_t lora_out_buff[50];
extern uart_device_info uart_devices[];
/* 静态函数申明 */
static void send_uart_pack(device_handle device,FRT_MsgFunctionCode_e cmd_type, const void *data, u_int16_t len);
static void FRT_MsgProc_ReadRegister(device_handle device, void *pMsg);
static void FRT_MsgProc_WriteRegister(device_handle device, void *pMsg);
static u_int16_t FRT_ReadReg(unsigned char regId);
static u_int16_t FRT_ReadRegCurrent(void *pMsg);
static u_int16_t FRT_ReadRegMaxCurrent(void *pMsg);
static u_int16_t FRT_ReadRegPulseCount(void *pMsg);
static u_int16_t FRT_ReadRegBat_V(void *pMsg);
static u_int16_t FRT_ReadRegBat_Charge(void *pMsg);
static u_int16_t FRT_ReadRegMACINFO(void *pMsg);
static u_int16_t FRT_WriteRegDeviceAddr(void *pMsg);
static u_int16_t FRT_WriteRegNetId(void *pMsg);
static u_int16_t FRT_WriteRegMaxCurrent(void *pMsg);
static u_int16_t FRT_WriteRegPulseCount(void *pMsg);
static u_int16_t FRT_WriteRegReboot(void *pMsg);
static void pdebug_mcs_info();
mcs_para g_stMcs_Para = {0};
/* 功能码处理表 */
FRT_FuncionMsgProcTable_s g_MsgTbl[] =
{
{ FRT_FUNCTION_CODE_READ_REGISTER, FRT_MsgProc_ReadRegister },
{ FRT_FUNCTION_CODE_WRITE_REGISTER, FRT_MsgProc_WriteRegister },
};
/* 读寄存器处理表 */
FRT_RegProcTable_s g_RegTbl[] =
{
{ FRT_REGISTER_CURRENT, FRT_ReadRegCurrent }, /* 泄漏电流 */
{ FRT_REGISTER_MAX_CURRENT, FRT_ReadRegMaxCurrent }, /* 最大电流 */
{ FRT_REGISTER_PULSE_COUNT, FRT_ReadRegPulseCount }, /* 脉冲次数 */
{ FRT_REGISTER_BAT_V, FRT_ReadRegBat_V }, /* 电池电压 */
{ FRT_REGISTER_BAT_CHARGE, FRT_ReadRegBat_Charge }, /* 充电状态 */
{ FRT_REGISTER_MAC_INFO, FRT_ReadRegMACINFO }, /* MAC信息 */
};
/* 写寄存器处理表 */
FRT_RegProcTable_s g_Write_RegTbl[] =
{
{ FRT_REGISTER_DEVICE_ADDR, FRT_WriteRegDeviceAddr }, /* 写设备地址 */
{ FRT_REGISTER_NET_ID, FRT_WriteRegNetId }, /* 写网络ID */
{ FRT_REGISTER_CLEAR_MAX_CURRENT, FRT_WriteRegMaxCurrent }, /* 清空最大泄漏电流统计值 */
{ FRT_REGISTER_CLEAR_PULSE_COUNT, FRT_WriteRegPulseCount }, /* 清空脉冲次数 */
{ FRT_REGISTER_REBOOT, FRT_WriteRegReboot }, /* 重启 */
};
/**
* @brief modbus crc16算法
* @param
* @retval
*/
unsigned short CRC16(unsigned char *arr_buff, unsigned char len)
{
unsigned short crc=0xFFFF;
unsigned char i, j;
for ( j=0; j<len; j++){
crc=crc ^*arr_buff++;
for ( i=0; i<8; i++){
if( ( crc&0x0001) >0){
crc=crc>>1;
crc=crc^ 0xa001;
}else{
crc=crc>>1;
}
}
}
return crc << 8 | crc >> 8;
}
/**
* @brief 交换高低字节
* @param
* @retval
*/
static u_int16_t FRT_swap_endian_16(u_int16_t value)
{
return ((value << 8) | (value >> 8));
}
/**
* @brief 读泄漏电流寄存器值
* @param
* @retval
*/
static u_int16_t FRT_ReadRegCurrent(void *pMsg)
{
u_int16_t value = (u_int16_t)(g_stMcs_Para.current * 100);
return FRT_swap_endian_16(value);//百倍泄漏电流
}
/**
* @brief 读最大电流寄存器值
* @param
* @retval
*/
static u_int16_t FRT_ReadRegMaxCurrent(void *pMsg)
{
u_int16_t value = (u_int16_t)(g_stMcs_Para.max_current * 100);
return FRT_swap_endian_16(value);//百倍最大泄漏电流
}
/**
* @brief 读脉冲次数寄存器值
* @param
* @retval
*/
static u_int16_t FRT_ReadRegPulseCount(void *pMsg)
{
u_int16_t value = (u_int16_t)(g_stMcs_Para.pulse_count);
return FRT_swap_endian_16(value);
}
/**
* @brief 读电池电压寄存器值
* @param
* @retval
*/
static u_int16_t FRT_ReadRegBat_V(void *pMsg)
{
u_int16_t value = (u_int16_t)(g_stMcs_Para.bat_v * 1000);
return FRT_swap_endian_16(value);
}
/**
* @brief 读充电状态寄存器值
* @param
* @retval
*/
static u_int16_t FRT_ReadRegBat_Charge(void *pMsg)
{
g_stMcs_Para.bat_charge = HAL_GPIO_ReadPin(CN3791_CHRG_GPIO_Port, CN3791_CHRG_Pin);
u_int16_t value = (u_int16_t)(g_stMcs_Para.bat_charge);
return FRT_swap_endian_16(value);
}
/**
* @brief 读MAC信息寄存器值
* @param
* @retval
*/
static u_int16_t FRT_ReadRegMACINFO(void *pMsg)
{
u_int16_t value = (u_int16_t)(g_stConfigInfo.mac_info_h << 8 | g_stConfigInfo.mac_info_l);
return FRT_swap_endian_16(value);
}
/**
* @brief 写设备地址
* @param
* @retval
*/
static u_int16_t FRT_WriteRegDeviceAddr(void *pMsg)
{
//改传感器地址
uint16_t *pMsgAddr = (uint16_t *)pMsg;
uint16_t data = *pMsgAddr;
g_stConfigInfo.addr = data;
save_config_info(g_stConfigInfo);
//改无线模块地址
e22_init();
return 0;
}
/**
* @brief 写网络地址
* @param
* @retval
*/
static u_int16_t FRT_WriteRegNetId(void *pMsg)
{
//改传感器网址
uint16_t *pMsgAddr = (uint16_t *)pMsg;
uint16_t data = *pMsgAddr;
g_stConfigInfo.net_id = data;
save_config_info(g_stConfigInfo);
//改无线模块网址
e22_init();
return 0;
}
/**
* @brief 清空最大电流
* @param
* @retval
*/
static u_int16_t FRT_WriteRegMaxCurrent(void *pMsg)
{
uint16_t *pMsgAddr = (uint16_t *)pMsg;
uint16_t data = *pMsgAddr;
if(data == 0x0001){
g_stMcs_Para.max_current = 0;
max_rms_mA = 0;
}
}
/**
* @brief 清空脉冲次数
* @param
* @retval
*/
static u_int16_t FRT_WriteRegPulseCount(void *pMsg)
{
uint16_t *pMsgAddr = (uint16_t *)pMsg;
uint16_t data = *pMsgAddr;
if(data == 0x0001){
g_stMcs_Para.pulse_count = 0;
Pulse_Count = 0;
}
}
/**
* @brief 重启
* @param
* @retval
*/
static u_int16_t FRT_WriteRegReboot(void *pMsg)
{
uint16_t *pMsgAddr = (uint16_t *)pMsg;
uint16_t data = *pMsgAddr;
if(data == 0x0001)
{
__iar_builtin_set_FAULTMASK(1);
NVIC_SystemReset();
}
return 0;
}
/**
* @brief 封装协议发送
* @param
* @retval 数据正确返回TRUE数据异常返回FALSE
*/
static void send_uart_pack(device_handle device,FRT_MsgFunctionCode_e cmd_type, const void *data, u_int16_t len)
{
memset(lora_out_buff,0,sizeof(lora_out_buff));
frt_climate_pack_resp *pack = (frt_climate_pack_resp*)lora_out_buff;
pack->up_addr_h = 0x00;
pack->up_addr_l = 0x00;
pack->chanel = g_stConfigInfo.net_id % 27 + 10;
pack->addr = g_stConfigInfo.addr;
pack->func = FRT_FUNCTION_CODE_READ_REGISTER;
pack->data_len = len;
memcpy(pack->data, data, len);
*(u_int16_t*)&pack->data[len] = CRC16((u_int8_t *)&pack->addr,pack->data_len+3);//加数据之前的字节
uart_dev_write(device,(u_int8_t*)pack,pack->data_len+3+2+3); // 加数据之前的字节+校验位+E22地址信道
}
/**
* @brief 遍历读取寄存器
* @param
* @retval
*/
u_int16_t FRT_ReadReg(unsigned char regId)
{
for(u_int16_t i = 0; i < sizeof(g_RegTbl) / sizeof(FRT_RegProcTable_s); i++){
//term_printf("regId:%d, g_RegTbl.regId :%d\r\n",regId,g_RegTbl[i].regId);
if (regId == g_RegTbl[i].regId){
return g_RegTbl[i].pRegProc(NULL);
}
}
return 0;
}
/**
* @brief 处理读取寄存器数据
* @param
* @retval
*/
void FRT_MsgProc_ReadRegister(device_handle device, void *pMsg)
{
uint8_t *data = (uint8_t *)pMsg;
u_int16_t start_reg_addr = (data[2] << 8)| data[3];
u_int16_t reg_num= (data[4] << 8)| data[5];
if (start_reg_addr < 0x00 || start_reg_addr > 0x05)
{
term_printf("start_reg_addr error:%d", start_reg_addr);
return;
}
if (reg_num < 0x01 || ((reg_num + start_reg_addr - 1) < 0x00) || ((reg_num + start_reg_addr -1) > 0x05))
{
term_printf("reg_num error:%d", reg_num);
return;
}
static u_int8_t reg_value_buff[2*100]={0x00};
memset(reg_value_buff,0,sizeof(reg_value_buff));
for(u_int16_t pos=0; pos <reg_num; pos++){
*(u_int16_t*)&reg_value_buff[pos*2] = FRT_ReadReg((start_reg_addr+pos));
}
if(device == g_term_uart_handle)
{
send_uart_pack(device, FRT_FUNCTION_CODE_READ_REGISTER, (u_int8_t*)&reg_value_buff, reg_num*2);
// pdebug_mcs_info();
}
if(device == g_lora_uart_handle)
{
send_uart_pack(device, FRT_FUNCTION_CODE_READ_REGISTER, (u_int8_t*)&reg_value_buff, reg_num*2);
// pdebug_mcs_info();
}
}
/**
* @brief 处理写入寄存器数据
* @param
* @retval
*/
void FRT_MsgProc_WriteRegister(device_handle device, void *pMsg)
{
uint8_t *data = (uint8_t *)pMsg;
u_int16_t start_reg_addr = (data[2] << 8)| data[3];
u_int16_t reg_num= (data[4] << 8)| data[5];
u_int16_t byte_num= data[6];
unsigned short return_crc_value;
// 校验
if (start_reg_addr < 0x31 || start_reg_addr > 0x35 )
{
term_printf("start_reg_addr error:%d", start_reg_addr);
return;
}
if (reg_num < 0x01 || ((reg_num + start_reg_addr - 1) < 0x31) || ((reg_num + start_reg_addr -1) > 0x35))
{
term_printf("reg_num error:%d", reg_num);
return;
}
//发回数据
uint8_t Trans_data[11];
Trans_data[0] = 0x00;
Trans_data[1] = 0x00;
Trans_data[2] = g_stConfigInfo.net_id % 27 + 10;
Trans_data[3] = g_stConfigInfo.addr;
Trans_data[4] = FRT_FUNCTION_CODE_WRITE_REGISTER;
Trans_data[5] = data[2] << 8;
Trans_data[6] = data[3];
Trans_data[7] = data[4] << 8;
Trans_data[8] = data[5];
return_crc_value = CRC16(&Trans_data[3], 6);
Trans_data[9] = return_crc_value;
Trans_data[10] = return_crc_value >> 8;
uart_dev_write(g_lora_uart_handle, Trans_data, sizeof(Trans_data)/sizeof(uint8_t));
// 取出数据
uint16_t content[50] = {0};
for (uint16_t var = 0; var < reg_num; var++)
{
content[var] = data[7 + 2 * var] << 8 | data[7 + 2 * var + 1];
}
for(u_int16_t pos=0; pos <reg_num; pos++)
{
for (uint16_t i = 0; i < sizeof(g_Write_RegTbl) / sizeof(FRT_RegProcTable_s); i++)
{
if (g_Write_RegTbl[i].regId == (start_reg_addr + pos))
{
g_Write_RegTbl[i].pRegProc(&content[pos]);
}
}
}
}
/**
* @brief 读取串口数据
* @param
* @retval
*/
static int uart_read_frt_climate_pack(device_handle uart_handle,u_int8_t *buff, u_int32_t buff_size)
{
u_int32_t offset = 0;
char c = 0;
// frt_climate_pack *pack = (frt_climate_pack *)buff;
unsigned char new_buff[50];
buff_size--; //预留一个'\0'位置
for (int i = 0; i < buff_size;i++)
{
c = uart_dev_in_char(uart_handle);
buff[i] = c;
}
int start_index = buff_size; // 初始化为一个不可能的值
// 遍历数组以找到符合条件的字节对
for (int i = 0; i < buff_size; i += 1)
{
if ((buff[i] == g_stConfigInfo.addr) && ((buff[i + 1] == FRT_FUNCTION_CODE_READ_REGISTER) || (buff[i + 1] == FRT_FUNCTION_CODE_WRITE_REGISTER)))
{
start_index = i; // 从符合条件的字节对开始复制
// term_printf("%d", i);
break;
}
}
if (start_index == buff_size)
{
return 0;
}
memcpy(new_buff, buff + start_index, buff_size - start_index);
// for (int i = 0; i < buff_size; i++) {
// term_printf("%x ", new_buff[i]);
// }
// term_printf("\r\n");
memcpy(buff, 0, buff_size);
memcpy(buff, new_buff, buff_size - start_index);
if (new_buff[1] == FRT_FUNCTION_CODE_READ_REGISTER)
{
offset = 8;
return offset;
}
if (new_buff[1] == FRT_FUNCTION_CODE_WRITE_REGISTER)
{
u_int32_t regnum = 0;
offset = 7;
regnum = new_buff[6];
offset = offset + regnum + 2;
return offset;
}
// for (offset = 0; offset < buff_size;){
// c = uart_dev_in_char(uart_handle);
// buff[offset++] = c;
// if (offset == sizeof(pack->addr)){
// if (pack->addr != g_stConfigInfo.addr){
// memcpy(buff, buff+1, offset-1);
// offset--;
// buff_size--;
// }
// }else if (offset == FRT_CLIMATE_PACK_SIZE(pack)){
// return offset;
// }
// }
return 0;
}
/**
* @brief 处理一条消息
* @param
* @retval
*/
void FRT_MsgHandler(device_handle device, u_int8_t *pMsg, u_int32_t MsgLen)
{
if(CRC16(pMsg, MsgLen-2) != FRT_CLIMATE_BUFF_CRC16(pMsg))
{
// term_printf("CRC不过");
return;
}
if((pMsg[1] != FRT_FUNCTION_CODE_READ_REGISTER) && (pMsg[1] != FRT_FUNCTION_CODE_WRITE_REGISTER))
{
// term_printf("功能码不过");
return;
}
for (u_int16_t i = 0; i < sizeof(g_MsgTbl) / sizeof(FRT_FuncionMsgProcTable_s); i++){
if (pMsg[1] == g_MsgTbl[i].msgId){
g_MsgTbl[i].pMsgProc(device, pMsg);
}
}
}
/**
* @brief 读取并解析串口数据
* @param
* @retval
*/
static u_int8_t rs485_buff[50]={0x00};
void read_and_process_uart_data(device_handle device)
{
if(uart_dev_char_present(device)){
//BUFFER里面第一次有数据后返回等下一次调用
if(read_uart_flag < 1)
{
read_uart_flag++;
return;
}
read_uart_flag = 0;
memset(rs485_buff,0,sizeof(rs485_buff));
int ret = uart_read_frt_climate_pack(device, rs485_buff, sizeof(rs485_buff));
if(ret > 0){
FRT_MsgHandler(device, rs485_buff, ret);
}
}
}
/* 打印寄存器数据 */
static void pdebug_mcs_info()
{
term_printf("current: %.2f\r\n", g_stMcs_Para.current);
term_printf("max_current: %.2f\r\n", g_stMcs_Para.max_current);
term_printf("pulse_count: %.2f\r\n", g_stMcs_Para.pulse_count);
term_printf("bat_v: %.2f\r\n", g_stMcs_Para.bat_v);
term_printf("bat_charge: %.2f\r\n", g_stMcs_Para.bat_charge);
term_printf("mac_info: %.2f\r\n", g_stConfigInfo.mac_info_h);
term_printf("mac_info: %.2f\r\n", g_stConfigInfo.mac_info_l);
term_printf("address: %.2f\r\n", g_stConfigInfo.addr);
term_printf("NetId: %.2f\r\n", g_stConfigInfo.net_id);
// term_printf("precipitation_intensity: %.2f\r\n", g_stMcs_Para.precipitation_intensity);
}
// 30 03 00 00 00 0B 00 2C