NANO130_H2Press/User/485_sensor.c

1009 lines
27 KiB
C
Raw Permalink 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.

/*
*********************************************************************************************************
* IAR Development Kits
* on the
*
* M451
*
* Filename : spi_adc.c
* Version : V1.00
* Programmer(s) : Qian Xianghong
*********************************************************************************************************
*/
#include "includes.h"
// 默认为斯达易思的流量计
//
// 是否SMAR C的流量计
//#define _SMARC_FLOWMETER_
// 是否天信流量计MODBUS/A4协议
//#define _TIANCYA4_FLOWMETER_
// 定义中断处理的回到函数
typedef void (*RS485_Read_CallBack)(uint8_t c);
RS485_Read_CallBack RS485_Read = NULL;
#define RS485_EN PC7
const uint8_t VACUUM_ID[] = {1, 2}; // 真空计通信地址
#define VACUUM_CMD 4 // 真空计读取命令
#define VACUUM_ADDR 608 // 真空计起始寄存器地址
#define VACUUM_LEN 8 // 真空计读取寄存器个数
const uint8_t LEAK_ID = 3; // 泄露报警控制器通信地址
#define LEAK_CMD 3 // 泄露报警控制器读取命令
#define LEAK_ADDR 0x08 // 泄露报警控制器起始寄存器地址
#define LEAK_LEN 8 // 泄露报警控制器读取寄存器个数
const uint8_t FLOW_ID = 4; // 流量计通信地址
#if defined(_SMARC_FLOWMETER_)
#define FLOW_CMD 3 // 流量计读取命令
#define FLOW_ADDR 4068 // 流量计起始寄存器地址
#define FLOW_LEN 12 // 流量计读取寄存器个数
#elif defined(_TIANCYA4_FLOWMETER_)
#define FLOW_CMD 3 // 流量计读取命令
#define FLOW_ADDR 0 // 流量计起始寄存器地址
#define FLOW_LEN 12 // 流量计读取寄存器个数
#else
#define FLOW_CMD 3 // 流量计读取命令
#define FLOW_ADDR 0 // 流量计起始寄存器地址
#define FLOW_LEN 15 // 流量计读取寄存器个数
#endif
#pragma pack(push, 1)
typedef struct
{
uint8_t id;
uint8_t cmd;
uint16_t addr;
uint16_t len;
uint16_t crc;
} modbus_send_t;
typedef struct
{
struct
{
uint8_t id;
uint8_t cmd;
uint8_t len;
} header;
union{
// 真空计数据
struct
{
uint16_t staVacuum; // 状态
uint16_t lifeVacuum; // 使用年限
uint32_t vacuum; // 真空度float型先用整形交换字节序
uint32_t rateVacuum; // 漏放气速率float型先用整形交换字节序
uint32_t tempr; // 温度float型先用整形交换字节序
} vacuum;
// 泄漏报警器数据
struct
{
unsigned unit : 4; // 气体单位
unsigned ratio : 4; // 数值单位
uint8_t type; // 气体类型
uint16_t A1; // A1报警值
uint16_t A2;
uint16_t A3;
uint16_t A4;
uint16_t range; // 量程
uint16_t concentrations; // 浓度
uint8_t staLeak; // 传感器状态
unsigned : 8;
} leak;
// 流量计数据
struct
{
uint32_t nM3_int; // 标况累积总量整数部分
uint16_t nM3_frac; // 标况累积总量小数部分放大10000倍
uint32_t M3_int; // 工况累积总量整数部分
uint16_t M3_frac; // 工况累积总量小数部分放大10000倍
uint32_t nM3_h; // 标况流量nM3/h放大100倍
uint32_t M3_h; // 工况流量M3/h放大100倍
int16_t tempr; // 温度放大10倍第一位正负位(即数值大于0x7FFF为负)
uint32_t pressure; // 压力(绝压KPa, 放大10倍)
uint16_t err1; // 异常标志位1
//温度错误标志位: 0x0003
//压力错误标志位: 0x0030
//电池电量低标志位: 0x0300
//工况流量超最大工况流量: 0x3000
//无异常0x0000
uint16_t err2; // 异常标志位2
//存储器异常标志位: 0x0003
//无异常0x0000
} flow;
// SMARC流量计数据
struct
{
uint32_t nM3_h; // 标况流量: float, 方便颠倒顺序用uint32_t型接收
uint32_t M3_h; // 工况流量: float, 方便颠倒顺序用uint32_t型接收
uint32_t tempr; // 温度: float, 方便颠倒顺序用uint32_t型接收
uint32_t pressure; // 压力: float, 方便颠倒顺序用uint32_t型接收
uint16_t warnFlag; // 报警标志
uint8_t nM3_BCD[6]; // 标况体积
} flow_SMARC;
// 天信流量计数据Modbus/A4通信协议
struct
{
double nM3; // 标况体积
uint32_t nM3_h; // 标况流量: float, 方便颠倒顺序用uint32_t型接收
uint32_t M3_h; // 工况流量: float, 方便颠倒顺序用uint32_t型接收
uint32_t tempr; // 温度: float, 方便颠倒顺序用uint32_t型接收
uint32_t pressure; // 压力: float, 方便颠倒顺序用uint32_t型接收
} flow_TancyA4;
};
uint16_t crc; // 占位置
} modbus_recv_t;
typedef union
{
modbus_send_t send;
modbus_recv_t recv;
uint8_t buff[sizeof(modbus_recv_t)];
} modbus_comm_t;
// DYQ-7通信协议的泄露报警器
#define RS_MIN_FRAME_LEN (15)
#define RS_MAX_FRAME_LEN (39)
#define RS_MIN_DATA_LEN (0)
#define RS_MAX_DATA_LEN (RS_MAX_FRAME_LEN - RS_MIN_FRAME_LEN)
#define RS_FRAME_SOF (0x1B) // 标识一个帧的开始
#define RS_DIR_M2S (0) // Master->Slave
#define RS_DIR_S2M (1) // Slave->Master
#define RS_PROTOCOL_VER_1 (1)
// 请求命令
#define RS_CMD_READ_DATA (5) // 读采集数据
// 处理结果
#define RS_RESULT_SUCC (0) // 处理成功
#define RS_RESULT_FAIL (-1) // 处理失败
// 通信协议版本
const uint8_t RS_PROTOCOL_VER = RS_PROTOCOL_VER_1;
// 485泄露报警器请求数据
typedef struct // size = RS_MAX_FRAME_LEN
{
uint8_t sof; // RS_FRMAE_SOF
uint8_t len; // bytes from sof to crcRS_MIN_FRAME_LEN~RS_MAX_FRAME_LEN
uint8_t destAddr;
uint8_t srcAddr;
uint8_t srcPSN[6];
uint8_t dir;
uint8_t protocol_ver; // RS_PROTOCOL
uint8_t cmd;
uint8_t data[RS_MAX_DATA_LEN];
uint16_t crc; // 占位置实际crc可能更靠前
} rs_frame_t;
// 485泄露报警器应答数据
typedef struct // size = 20
{
uint16_t adc; // 采集ADC值
float measureValue; // 采集值
uint8_t measureState; // 测量值状态
uint16_t levelHeight; // 液位高度
uint16_t volume; // 剩余液量
uint16_t volumeMax; // 有效容积
uint16_t quality; // 剩余重量
uint8_t warnState; // 报警状态
uint16_t envAdc; // 环境温度ADC
int16_t envTempr; // 环境温度
} rs_data_t;
#pragma pack(pop)
rs_frame_t RS_TranFrame;
modbus_comm_t modbus;
uint8_t modbus_idx = 0;
uint8_t vaccum_idx = 0;
data_sample_t *modbus_sample;
// MODBUS的CRC算法
uint16_t MODBUS_RTU_CRC16(const uint8_t *puchMsg, uint16_t usDataLen)
{
uint16_t crc = 0xFFFF;
uint8_t i;
while (usDataLen--) // 传输消息缓冲区
{
crc ^= *puchMsg++;
for(i = 0; i < 8; i++)
{
if(crc & 0x0001)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
// 交换高低字节顺序
return ((crc & 0xFF) << 8) | ((crc >> 8) & 0xFF);
}
// 将十进制转换成BCD
void dec2bcd(uint32_t dec, uint8_t *bcd, uint8_t len)
{
char fmt[10], str[20];
uint8_t i;
// 生成格式串(如:%010u
sprintf(fmt, "%%0%du", len * 2);
// 将dec值转换成前面补0的字符串000000123456)
sprintf(str, fmt, dec);
// 转换
for(i = 0; i < strlen(str); i += 2)
{
bcd[i / 2] = ((str[i] - '0') << 4) | (str[i + 1] - '0');
}
}
// 本函数由规管设计者Zhang Jm提供用于对读出的真空值进行修正
// 本函数只适用于规管量程为-20.01Pa)的情况
/**
* @brief Function of Fuzzy Processing.
* @param value: vacuun value.
* @retval None.
*/
float Mode1_Fuzzy_Process(float value)
{
static const float beta1 = -0.2539755;
static const float beta2 = 13.15659;
static const float theta = 0.011666666;
static const float eta = 0.9999999;
static const float kappa = 0.006666666;
float temp1, temp2, result, lower_t = 0.0101;
if((value < 0.09f) && (value > 0.04f))
{
temp1 = -beta1 * value;
temp2 = beta2 * pow(value, 2.0);
return(1 - exp(temp1 - temp2));
}
else if((value <= 0.04f) && (value > 0.005f))
{/*y = theta*x^eta/(kappa^eta+x^eta)*/
temp1 = pow(value, eta);
temp2 = pow(kappa, eta) + temp1;
result = theta * temp1 / temp2;
if(result < lower_t)
return(lower_t);
else
return(result);
}
else
return(value);
}
void Modbus_Read(uint8_t c)
{
uint8_t i;
uint32_t reversed;
int32_t i_reversed;
float f;
uint8_t d_reversed[8];
double d;
/* Receive data */
if(modbus_idx < sizeof(modbus_recv_t))
{
modbus.buff[modbus_idx++] = c;
if(modbus.recv.header.id == LEAK_ID && modbus.recv.header.cmd == LEAK_CMD
&& modbus.recv.header.len == sizeof(modbus.recv.leak)
&& modbus_idx == sizeof(modbus.recv.header) + sizeof(modbus.recv.leak) + sizeof(modbus.recv.crc)
&& MODBUS_RTU_CRC16(modbus.buff, modbus_idx) == 0)
{
/* Print the received data */
// printf("Received data:\n");
// for(i = 0; i < modbus_idx; i++)
// {
// printf("%02X ", modbus.buff[i]);
// }
// printf("\n");
// 探测器状态
modbus_sample->leak.staLeak = modbus.recv.leak.staLeak;
// 浓度
modbus_sample->leak.concentrations = ntohs(modbus.recv.leak.concentrations);
if(modbus.recv.leak.ratio == 1)
modbus_sample->leak.concentrations /= 10;
else if(modbus.recv.leak.ratio == 2)
modbus_sample->leak.concentrations /= 100;
else if(modbus.recv.leak.ratio == 3)
modbus_sample->leak.concentrations /= 1000;
NVIC_SetPendingIRQ(TMR1_IRQn);
}
else if(modbus.recv.header.id == VACUUM_ID[vaccum_idx] && modbus.recv.header.cmd == VACUUM_CMD
&& modbus.recv.header.len == sizeof(modbus.recv.vacuum)
&& modbus_idx == sizeof(modbus.recv.header) + sizeof(modbus.recv.vacuum) + sizeof(modbus.recv.crc)
&& MODBUS_RTU_CRC16(modbus.buff, modbus_idx) == 0)
{
/* Print the received data */
printf("Received data:\n");
for(i = 0; i < modbus_idx; i++)
{
printf("%02X ", modbus.buff[i]);
}
printf("\n");
// 传感器状态
modbus_sample->vacuum[vaccum_idx].staVacuum = ntohs(modbus.recv.vacuum.staVacuum);
// 使用年限
modbus_sample->vacuum[vaccum_idx].lifeVacuum = ntohs(modbus.recv.vacuum.lifeVacuum);
// 真空度
reversed = ntohl(modbus.recv.vacuum.vacuum);
memmove(&modbus_sample->vacuum[vaccum_idx].vacuum, &reversed, sizeof(modbus_sample->vacuum[vaccum_idx].vacuum));
// 调用真空值修正函数2021.11.03
modbus_sample->vacuum[vaccum_idx].vacuum = Mode1_Fuzzy_Process(modbus_sample->vacuum[vaccum_idx].vacuum);
// 漏放气速率
reversed = ntohl(modbus.recv.vacuum.rateVacuum);
memmove(&modbus_sample->vacuum[vaccum_idx].rateVacuum, &reversed, sizeof(modbus_sample->vacuum[vaccum_idx].rateVacuum));
// 温度
reversed = ntohl(modbus.recv.vacuum.tempr);
memmove(&modbus_sample->vacuum[vaccum_idx].tempr, &reversed, sizeof(modbus_sample->vacuum[vaccum_idx].tempr));
NVIC_SetPendingIRQ(TMR1_IRQn);
}
#if defined(_SMARC_FLOWMETER_)
else if(modbus.recv.header.id == FLOW_ID && modbus.recv.header.cmd == FLOW_CMD
&& modbus.recv.header.len == sizeof(modbus.recv.flow_SMARC)
&& modbus_idx == sizeof(modbus.recv.header) + sizeof(modbus.recv.flow_SMARC) + sizeof(modbus.recv.crc)
&& MODBUS_RTU_CRC16(modbus.buff, modbus_idx) == 0)
{
// /* Print the received data */
// printf("Received data:\n");
// for(i = 0; i < modbus_idx; i++)
// {
// printf("%02X ", modbus.buff[i]);
// }
// printf("\n");
// 标况体积总量
// 整数部分
reversed = 0;
for(i = 0; i < 9; i++)
{
reversed *= 10;
if(i % 2 == 0)
reversed += (modbus.recv.flow_SMARC.nM3_BCD[i / 2] >> 4);
else
reversed += (modbus.recv.flow_SMARC.nM3_BCD[i / 2] & 0x0F);
}
dec2bcd(reversed, modbus_sample->flow.nM3, 5);
// 小数部分
reversed = 0;
for(i = 9; i < 11; i++)
{
reversed *= 10;
if(i % 2 == 0)
reversed += (modbus.recv.flow_SMARC.nM3_BCD[i / 2] >> 4);
else
reversed += (modbus.recv.flow_SMARC.nM3_BCD[i / 2] & 0x0F);
}
dec2bcd(reversed, modbus_sample->flow.nM3 + 5, 1);
// 标况流量
reversed = ntohl(modbus.recv.flow_SMARC.nM3_h);
memmove(&f, &reversed, 4);
reversed = f * 100;
dec2bcd(reversed, modbus_sample->flow.nM3_h, 4);
// 工况流量
reversed = ntohl(modbus.recv.flow_SMARC.M3_h);
memmove(&f, &reversed, 4);
reversed = f * 100;
dec2bcd(reversed, modbus_sample->flow.M3_h, 4);
// 温度
reversed = ntohl(modbus.recv.flow_SMARC.tempr);
memmove(&f, &reversed, 4);
i_reversed = f * 100;
if(i_reversed >= 0)
dec2bcd(i_reversed, modbus_sample->flow.tempr, 4);
else
{
dec2bcd(-i_reversed, modbus_sample->flow.tempr, 4);
modbus_sample->flow.tempr[0] = 0x80;
}
// 压力
reversed = ntohl(modbus.recv.flow_SMARC.pressure);
memmove(&f, &reversed, 4);
reversed = f * 100;
dec2bcd(reversed, modbus_sample->flow.pressure, 4);
/* Print the converted bcd data */
printf("Flowmeter BCD data:\n");
for(i = 0; i < sizeof(modbus_sample->flow); i++)
{
printf("%02X ", *(((uint8_t *) &modbus_sample->flow) + i));
}
printf("\n");
NVIC_SetPendingIRQ(TMR1_IRQn);
}
#elif defined(_TIANCYA4_FLOWMETER_)
else if(modbus.recv.header.id == FLOW_ID && modbus.recv.header.cmd == FLOW_CMD
&& modbus.recv.header.len == sizeof(modbus.recv.flow_TancyA4)
&& modbus_idx == sizeof(modbus.recv.header) + sizeof(modbus.recv.flow_TancyA4) + sizeof(modbus.recv.crc)
&& MODBUS_RTU_CRC16(modbus.buff, modbus_idx) == 0)
{
// /* Print the received data */
// printf("Received data:\n");
// for(i = 0; i < modbus_idx; i++)
// {
// printf("%02X ", modbus.buff[i]);
// }
// printf("\n");
// 标况体积总量: double型, 先颠倒顺序
memmove(d_reversed, &modbus.recv.flow_TancyA4.nM3, 8);
i = d_reversed[0];
d_reversed[0] = d_reversed[7];
d_reversed[7] = i;
i = d_reversed[1];
d_reversed[1] = d_reversed[6];
d_reversed[6] = i;
i = d_reversed[2];
d_reversed[2] = d_reversed[5];
d_reversed[5] = i;
i = d_reversed[3];
d_reversed[3] = d_reversed[4];
d_reversed[4] = i;
memmove(&d, &d_reversed, 8);
// 整数部分
reversed = (uint32_t) d;
dec2bcd(reversed, modbus_sample->flow.nM3, 5);
// 小数部分
reversed = (uint32_t) ((d - reversed) * 100);
dec2bcd(reversed, modbus_sample->flow.nM3 + 5, 1);
// 标况流量
reversed = ntohl(modbus.recv.flow_TancyA4.nM3_h);
memmove(&f, &reversed, 4);
reversed = f * 100;
dec2bcd(reversed, modbus_sample->flow.nM3_h, 4);
// 工况流量
reversed = ntohl(modbus.recv.flow_TancyA4.M3_h);
memmove(&f, &reversed, 4);
reversed = f * 100;
dec2bcd(reversed, modbus_sample->flow.M3_h, 4);
// 温度
reversed = ntohl(modbus.recv.flow_TancyA4.tempr);
memmove(&f, &reversed, 4);
i_reversed = f * 100;
if(i_reversed >= 0)
dec2bcd(i_reversed, modbus_sample->flow.tempr, 4);
else
{
dec2bcd(-i_reversed, modbus_sample->flow.tempr, 4);
modbus_sample->flow.tempr[0] = 0x80;
}
// 压力
reversed = ntohl(modbus.recv.flow_TancyA4.pressure);
memmove(&f, &reversed, 4);
reversed = f * 100;
dec2bcd(reversed, modbus_sample->flow.pressure, 4);
/* Print the converted bcd data */
printf("Flowmeter BCD data:\n");
for(i = 0; i < sizeof(modbus_sample->flow); i++)
{
printf("%02X ", *(((uint8_t *) &modbus_sample->flow) + i));
}
printf("\n");
NVIC_SetPendingIRQ(TMR1_IRQn);
}
#else
else if(modbus.recv.header.id == FLOW_ID && modbus.recv.header.cmd == FLOW_CMD
&& modbus.recv.header.len == sizeof(modbus.recv.flow)
&& modbus_idx == sizeof(modbus.recv.header) + sizeof(modbus.recv.flow) + sizeof(modbus.recv.crc)
&& MODBUS_RTU_CRC16(modbus.buff, modbus_idx) == 0)
{
// /* Print the received data */
// printf("Received data:\n");
// for(i = 0; i < modbus_idx; i++)
// {
// printf("%02X ", modbus.buff[i]);
// }
// printf("\n");
// 标况体积总量BCD码放大100倍
if((htons(modbus.recv.flow.err2) & 0x000F) == 0x0003) // 是否存储器错误?
dec2bcd(0, modbus_sample->flow.nM3, 6);
else
{
reversed = ntohl(modbus.recv.flow.nM3_int); // 整数部分
dec2bcd(reversed, modbus_sample->flow.nM3, 5);
reversed = ntohs(modbus.recv.flow.nM3_frac); // 小数部分
reversed /= 100; // 放大10000倍->放大100倍
dec2bcd(reversed, modbus_sample->flow.nM3 + 5, 1);
}
// 标况流量BCD码放大100倍
reversed = ntohl(modbus.recv.flow.nM3_h);
dec2bcd(reversed, modbus_sample->flow.nM3_h, 4);
// 工况流量BCD码放大100倍
reversed = ntohl(modbus.recv.flow.M3_h);
dec2bcd(reversed, modbus_sample->flow.M3_h, 4);
// 温度BCD码放大100倍第一字节为符号 80H 为负00H 为正)
if((htons(modbus.recv.flow.err1) & 0x000F) == 0x0003) // 是否温度传感器错误?
i_reversed = 0;
else
{
i_reversed = ntohs(modbus.recv.flow.tempr);
i_reversed *= 10; // 放大10倍->放大100倍
}
if(i_reversed >= 0)
dec2bcd(i_reversed, modbus_sample->flow.tempr, 4);
else
{
dec2bcd(-i_reversed, modbus_sample->flow.tempr, 4);
modbus_sample->flow.tempr[0] = 0x80;
}
// 压力BCD码放大100倍
if((htons(modbus.recv.flow.err1) & 0x00F0) == 0x0030) // 是否压力传感器错误?
reversed = 0;
else
{
reversed = ntohl(modbus.recv.flow.pressure);
reversed *= 10; // 放大10倍->放大100倍
}
dec2bcd(reversed, modbus_sample->flow.pressure, 4);
/* Print the converted bcd data */
printf("Flowmeter BCD data:\n");
for(i = 0; i < sizeof(modbus_sample->flow); i++)
{
printf("%02X ", *(((uint8_t *) &modbus_sample->flow) + i));
}
printf("\n");
NVIC_SetPendingIRQ(TMR1_IRQn);
}
#endif
}
}
// 物理层校验
uint8_t rs_phy_valid(rs_frame_t *frame)
{
if(frame->protocol_ver != RS_PROTOCOL_VER || frame->dir != RS_DIR_S2M)
{
// 物理层校验失败
return 0;
}
return 1;
}
// mac层校验
uint8_t rs_mac_valid(rs_frame_t *frame, uint8_t dir)
{
if(frame->destAddr != dcBuff.configBottle.addr)
{
// mac层校验失败
return 0;
}
return 1;
}
// 初始化帧
void rs_initial_frame(rs_frame_t *frame)
{
memset((uint8_t *) frame, 0, sizeof(rs_frame_t));
frame->len = RS_MIN_FRAME_LEN;
}
// 追加负载数据
uint8_t rs_append_data(rs_frame_t *frame, uint8_t *data, uint8_t len)
{
if(frame->len < RS_MIN_FRAME_LEN || frame->len + len > RS_MAX_FRAME_LEN)
return 0;
if(len > 0)
memmove(frame->data + (frame->len - RS_MIN_FRAME_LEN), data, len);
frame->len += len;
return 1;
}
// 重新寻找SOF
void RS_SearchSOF(uint8_t *buf, uint16_t fromPos, uint8_t *len)
{
uint8_t i;
for(i = fromPos; i < *len && buf[i] != RS_FRAME_SOF; i++)
{
}
*len -= i;
memmove(buf, buf + i, *len);
}
// 模块任务主体:处理射频接收数据
void RS_ParseFrame(uint8_t c)
{
uint8_t *RS_ModuleData = (uint8_t *) &RS_TranFrame;
uint16_t i;
uint8_t frameOk, frameErr;
uint32_t mask;
rs_data_t *rsData = (rs_data_t *) (RS_TranFrame.data + sizeof(mask));
if(modbus_idx == 0 && c != RS_FRAME_SOF)
return;
RS_ModuleData[modbus_idx++] = c;
do
{
frameErr = (modbus_idx >= 2 &&
(RS_ModuleData[1] < RS_MIN_FRAME_LEN || RS_ModuleData[1] > RS_MAX_FRAME_LEN));
if(frameErr)
{
// 从1开始寻找SOF
RS_SearchSOF(RS_ModuleData, 1, &modbus_idx);
}
frameOk = (modbus_idx >= 2 && RS_ModuleData[1] >= RS_MIN_FRAME_LEN && RS_ModuleData[1] <= RS_MAX_FRAME_LEN
&& modbus_idx >= RS_ModuleData[1]);
if(frameOk)
{
if(MODBUS_RTU_CRC16(RS_ModuleData, RS_ModuleData[1]) == 0)
{
if(rs_phy_valid(&RS_TranFrame) && rs_mac_valid(&RS_TranFrame, RS_DIR_M2S))
{
// 收到一帧
printf("\r\nRS recv %d bytes:\r\n", RS_ModuleData[1]);
for(i = 0; i < RS_ModuleData[1]; i++)
printf(" %02X", RS_ModuleData[i]);
printf("\r\n");
// 处理这一帧
{
memmove(&mask, RS_TranFrame.data, 4);
mask = ntohl(mask);
if((mask & 0x61000000) == 0x61000000) // 检查数据掩码
{
modbus_sample->leak.typeLeak = LEAK_TYPE_MODBUS;
if(rsData->measureState > 1)
modbus_sample->leak.staLeak = LEAK_STATUS_FAULT;
else if(rsData->warnState == 4)
modbus_sample->leak.staLeak = LEAK_STATUS_A2_ALARM;
else
modbus_sample->leak.staLeak = LEAK_STATUS_OK;
if(rsData->warnState < 3)
modbus_sample->leak.concentrations = 0;
else
{
memmove(&mask, &rsData->measureValue, 4);
mask = ntohl(mask);
memmove(&rsData->measureValue, &mask, 4);
modbus_sample->leak.concentrations = rsData->measureValue / 1000;
}
}
NVIC_SetPendingIRQ(TMR1_IRQn);
}
}
// 继续寻找下一帧
modbus_idx -= RS_ModuleData[1];
memmove(RS_ModuleData, RS_ModuleData + RS_ModuleData[1], modbus_idx);
// 从0开始寻找SOF
RS_SearchSOF(RS_ModuleData, 0, &modbus_idx);
}
else
{
// 从1开始寻找SOF
RS_SearchSOF(RS_ModuleData, 1, &modbus_idx);
}
}
} while(frameOk || frameErr);
}
void SC0_IRQHandler(void)
{
uint8_t c;
// 接收中断
if(SCUART_GET_INT_FLAG(SC0, SC_ISR_RDA_IS_Msk) || SCUART_GET_INT_FLAG(SC0, SC_ISR_RTMR_IS_Msk)) /* Rx Ready or Time-out INT*/
{
c = SC0->RBR;
//printf("<%02X>", c);
if(RS485_Read != NULL)
RS485_Read(c);
}
// 错误中断
if(SCUART_GET_INT_FLAG(SC0, SC_ISR_TERR_IS_Msk))
{
SCUART_CLR_INT_FLAG(SC0, SC_ISR_TERR_IS_Msk);
}
}
void Sensor_Init()
{
/* Select SC UART module clock source as HXT and UART module clock divider as 1 */
CLK_SetModuleClock(SC0_MODULE, CLK_CLKSEL2_SC_S_HXT, CLK_SC0_CLK_DIVIDER(1));
/* Set PA.8 and PA.9 pin for SC UART mode */
SYS->PA_H_MFP &= ~(SYS_PA_H_MFP_PA8_MFP_Msk | SYS_PA_H_MFP_PA9_MFP_Msk);
SYS->PA_H_MFP |= (SYS_PA_H_MFP_PA8_MFP_SC0_CLK | SYS_PA_H_MFP_PA9_MFP_SC0_DAT);
GPIO_ENABLE_PULL_UP(PA, BIT9);
/* Enable SC UART module clock */
CLK_EnableModuleClock(SC0_MODULE);
SYS->PC_L_MFP &= ~SYS_PC_L_MFP_PC7_MFP_Msk;
SYS->PC_L_MFP |= SYS_PC_L_MFP_PC7_MFP_GPC7;
GPIO_SetMode(PC, 1 << 7, GPIO_PMD_OUTPUT);
RS485_EN = 0;
}
void Sensor_Open()
{
SCUART_Open(SC0, 9600);
SCUART_ENABLE_INT(SC0, (SC_IER_RDA_IE_Msk)); // | SC_IER_RTMR_IE_Msk));// | SC_IER_TERR_IE_Msk));
NVIC_SetPriority(SC0_IRQn, 1);
NVIC_EnableIRQ(SC0_IRQn);
}
static void RS485_SendDataByte(uint8_t *pu8TxBuf, uint32_t u32WriteBytes)
{
RS485_EN = 1;
delay_us(1);
/* Send data */
SCUART_Write(SC0, pu8TxBuf, u32WriteBytes);
delay_ms(6); // 至少5ms保险起见6ms
RS485_EN = 0;
}
// 物理层发送
uint8_t rs_uart_send(rs_frame_t *frame, uint8_t destAddr, uint8_t dir)
{
uint16_t crc;
uint8_t i;
// 填写固定字段
frame->sof = RS_FRAME_SOF;
frame->destAddr = destAddr;
frame->srcAddr = dcBuff.configBottle.addr;
memmove(frame->srcPSN, dcBuff.configBottle.PSN, 6);
frame->dir = dir;
frame->protocol_ver = RS_PROTOCOL_VER;
crc = MODBUS_RTU_CRC16((uint8_t *) frame, frame->len - 2);
((uint8_t *) frame)[frame->len - 2] = crc >> 8;
((uint8_t *) frame)[frame->len - 1] = crc & 0xFF;
printf("\r\nRS send %d bytes:\r\n", frame->len);
for(i = 0; i < frame->len; i++)
printf(" %02X", ((uint8_t *) frame)[i]);
printf("\r\n");
RS485_SendDataByte((uint8_t *) frame, frame->len);
return 1;
}
// 读取真空计数据
void Sensor_ReadVacuum(uint8_t sensorIdx, data_sample_t *sample)
{
// 设置中断回调函数
RS485_Read = Modbus_Read;
// 修改波特率
SCUART_Open(SC0, 9600);
// 默认读取失败
sample->vacuum[sensorIdx].staVacuum = VACUUM_STATUS_COMM_FAULT;
sample->vacuum[sensorIdx].lifeVacuum = 0;
sample->vacuum[sensorIdx].vacuum = 0;
sample->vacuum[sensorIdx].rateVacuum = 0;
/* Flush FIFO */
while(SCUART_GET_RX_EMPTY(SC0) == 0)
{
SCUART_READ(SC0);
}
// 初始化
modbus_sample = sample;
vaccum_idx = sensorIdx;
modbus_idx = 0;
// 发送
modbus.send.id = VACUUM_ID[sensorIdx];
modbus.send.cmd = VACUUM_CMD;
modbus.send.addr = htons(VACUUM_ADDR - 1);
modbus.send.len = htons(VACUUM_LEN);
modbus.send.crc = htons(MODBUS_RTU_CRC16(modbus.buff, sizeof(modbus_send_t) - 2));
RS485_SendDataByte(modbus.buff, sizeof(modbus_send_t));
// 等待中断处理
}
// 读取流量计数据
void Sensor_ReadFlow(data_sample_t *sample)
{
// 设置中断回调函数
RS485_Read = Modbus_Read;
// 修改波特率
SCUART_Open(SC0, 9600);
// 默认读取失败
memset(&sample->flow, 0, sizeof(sample->flow));
/* Flush FIFO */
while(SCUART_GET_RX_EMPTY(SC0) == 0)
{
SCUART_READ(SC0);
}
// 初始化
modbus_sample = sample;
modbus_idx = 0;
// 发送
modbus.send.id = FLOW_ID;
modbus.send.cmd = FLOW_CMD;
modbus.send.addr = htons(FLOW_ADDR);
modbus.send.len = htons(FLOW_LEN);
modbus.send.crc = htons(MODBUS_RTU_CRC16(modbus.buff, sizeof(modbus_send_t) - 2));
RS485_SendDataByte(modbus.buff, sizeof(modbus_send_t));
// 等待中断处理
}
// 读取泄漏报警数据
void Sensor_ReadLeak(data_sample_t *sample)
{
uint8_t reSample = 0;
#if 0
// 设置中断回调函数
RS485_Read = Modbus_Read;
// 修改波特率
SCUART_Open(SC0, 9600);
#else
// 设置中断回调函数
RS485_Read = RS_ParseFrame;
// 修改波特率
SCUART_Open(SC0, 19200);
#endif
// 默认读取失败
sample->leak.staLeak = LEAK_STATUS_COMM_FAULT;
sample->leak.concentrations = 0;
// 传感器类型
sample->leak.typeLeak = LEAK_TYPE_SWITCH | LEAK_TYPE_CURRENT | LEAK_TYPE_MODBUS;
/* Flush FIFO */
while(SCUART_GET_RX_EMPTY(SC0) == 0)
{
SCUART_READ(SC0);
}
// 初始化
modbus_sample = sample;
modbus_idx = 0;
// 发送
#if 0
modbus.send.id = LEAK_ID;
modbus.send.cmd = LEAK_CMD;
modbus.send.addr = htons(LEAK_ADDR);
modbus.send.len = htons(LEAK_LEN);
modbus.send.crc = htons(MODBUS_RTU_CRC16(modbus.buff, sizeof(modbus_send_t) - 2));
RS485_SendDataByte(modbus.buff, sizeof(modbus_send_t));
#else
rs_initial_frame(&RS_TranFrame);
RS_TranFrame.cmd = RS_CMD_READ_DATA;
rs_append_data(&RS_TranFrame, (uint8_t *) &reSample, 1);
rs_uart_send(&RS_TranFrame, 0x50, RS_DIR_M2S);
#endif
// 等待中断处理
}
uint32_t Sensor_ReadDOL()
{
uint8_t buf[14];
uint8_t c, i;
uint8_t idx = 0;
int16_t fld;
uint32_t adc[20] = {-1};
uint8_t cnt = 0;
uint32_t tick = GetDelayTick(1000);
// 禁止中断
NVIC_DisableIRQ(UART0_IRQn);
// 将串口更改为19200bps
UART_Open(UART0, 19200);
while(!IsTickOut(tick))
{
if(UART_GET_INT_FLAG(UART0, UART_ISR_BUF_ERR_IS_Msk)) /* Buffer Error INT */
{
UART_ClearIntFlag(UART0, UART_ISR_BUF_ERR_IS_Msk);
}
if(UART_GET_INT_FLAG(UART0, UART_ISR_RLS_IS_Msk)) /* RLS INT */
{
UART_ClearIntFlag(UART0, UART_ISR_RLS_IS_Msk);
}
// 解析DOL传感器的TTL数据每13个字节为一帧以0x35开头。
// 由于不知道帧校验方式所以将检测连续2个帧头一头一尾且第10个字节为0x81作为合法帧的标准
if(UART_GET_INT_FLAG(UART0, UART_ISR_RDA_IS_Msk) || UART_GET_INT_FLAG(UART0, UART_ISR_RTO_IS_Msk))
{
c = UART0->RBR;
// 定位第1个帧头
if(idx == 0 && c != 0x35)
continue;
buf[idx++] = c;
// 检查第2个帧头确保收到正确的一帧
if(idx == 14 && (buf[13] != 0x35 || buf[10] != 0x81))
{
// 查找有没有中间的帧头
for(i = 1; i < idx; i++)
{
if(buf[i] == 0x35)
break;
}
// 如果没有找到则i等于idxidx将变为0
idx -= i;
memmove(buf, buf + i, idx);
}
// 收到一帧
if(idx == 14)
{
// 取第2~3字节组成的有符号整数除以系数27.3,即为英寸水柱的值
memmove(&fld, buf + 2, 2);
if(fld < 0)
adc[cnt] = 0;
else
adc[cnt] = fld;
// 收够20帧
if(++cnt == 20)
{
// 排序以后取中间10帧的平均值
sort(adc, cnt);
adc[0] = 0;
for(i = 5; i < 15; i++)
adc[0] += adc[i];
adc[0] /= 10;
break;
}
// 准备接收下一帧,将当前帧头用起来
idx = 0;
buf[idx++] = c;
}
}
}
// 恢复中断
UART_Open(UART0, 115200ul);
NVIC_EnableIRQ(UART0_IRQn);
return adc[0];
}