#include <string.h>
#include "cmsis_os.h"
#include "main.h"
#include "Modbus.h"
#include "ModbusRegs.h"
#include "DLT645.h"
#include "settings.h"
#define DLT645_output(s, l) UART2_Send(s, l)
extern osSemaphoreId osSemRefresh;
//int DLT645NewAddr;
/**************************************************************************************************/
/* 数据集 */
//typedef struct{
//}DATASET_Result_t;
/* 04 05 01 FF */
typedef struct{
uint8_t address[6]; /* 01, 6字节, 地址 */
uint8_t uart1Spd; /* 02, 1字节, COM1速率. DLT645协议(北向)COM口波特率) */
uint8_t uart2Spd; /* 03, 1字节, COM2速率. modbus协议(南向)COM口波特率) */
uint8_t modbusSlave; /* 04, 1字节, modbus从站地址 */
}DATASET_Settings_t;
#pragma pack(push, 2)
typedef struct{
uint8_t address[6];
uint8_t SN[6];
uint8_t PSN[32];
uint8_t RateVolt[6];
uint8_t RateAmp[6];
uint8_t MaxAmp[6];
uint32_t kWhClass;
uint32_t kVarhClass;
uint8_t kWhCNT[3];
uint8_t kVarhCNT[3];
uint8_t type[10];
uint8_t date[10];
uint8_t version[16];
}DATA_TEST_t;
#pragma pack(pop)
//DATA_TEST_t testData;
//uint32_t InvectorData[29];
uint8_t msgDataBuf[256 + 64];
/**************************************************************************************************/
typedef struct _tag_frameCtrl{
uint8_t devAddress[6];
/* -- */
uint8_t err;
uint8_t preWordCts;
uint16_t frameStep;
uint32_t byteRefTick; /* 超时tick */
/* -- */
uint8_t *inBuf;
uint16_t inCts;
uint16_t dataLen; /* 报文中的数据长度信息 */
uint8_t dataCts;
uint8_t addrCts;
uint8_t opCode; /* 报文中的操作码 */
uint8_t CSWord;
uint32_t CSSum;
}FRAME_CTRL_t;
FRAME_CTRL_t FrmCtrl;
/* */
uint16_t settingsCtrl;
uint8_t inputBuf[300]; /* 输入报文缓存 */
uint8_t outputBuf[300]; /* 响应报文缓存 */
/**************************************************************************************************/
void ASCIItoBCD(long asciiVal, uint8_t *pBCD, uint8_t BCDLen);
void BCDtoASCII_Byte(uint8_t *pBCD, uint8_t *pASCII, uint8_t BCDBytes);
void BCDtoASCII_Word(uint8_t *pBCD, void *pASCII, uint8_t wordCts, uint8_t wordSize, uint8_t ifSigned);
/**************************************************************************************************/
void DLT645HostPickPkt(FRAME_CTRL_t *pInfo);
void DLT64SlavePickPkt(uint16_t *pRecvBuf, FRAME_CTRL_t *pInfo);
/* 提取地址(主站写) */
int pollAddress(uint8_t *pRespBuf, FRAME_CTRL_t *pInfo);
int fillAddress(uint8_t *pRespBuf, FRAME_CTRL_t *pInfo);
void ASCIItoBCD(long asciiVal, uint8_t *pBCD, uint8_t BCDLen);
int pollData(uint8_t *pRespBuf, FRAME_CTRL_t *pInfo);
int fillData(uint8_t *pRespBuf, FRAME_CTRL_t *pInfo);
int pollPassword(uint8_t *pRespBuf, FRAME_CTRL_t *pInfo);
/**************************************************************************************************/
void DLT645_Init(void)
{
int i;
memset(&FrmCtrl, 0, sizeof(FRAME_CTRL_t));
FrmCtrl.inBuf = inputBuf;
for(i = 0; i < 6; i++){
ASCIItoBCD(devSettings.address[i], (uint8_t *)&FrmCtrl.devAddress[i], 2);
// FrmCtrl.devAddress[i] = devSettings.address[i];
}
}
void DLT645HostResponse(uint8_t *pData, uint16_t usMsgLen, uint8_t PE)
{
uint16_t dataSize = usMsgLen;
uint8_t *in = pData;
if(PE){
FrmCtrl.frameStep = 0;
return;
}
while(dataSize > 0){
dataSize--;
if(FrmCtrl.err != 0){
FrmCtrl.frameStep = 0;
FrmCtrl.preWordCts = 0;
FrmCtrl.err = 0;
}
if((FrmCtrl.frameStep != 0) && (FrmCtrl.frameStep < 7)){
if(FrmCtrl.inCts >= 300){
FrmCtrl.inCts = 299;
}
FrmCtrl.inBuf[FrmCtrl.inCts] = *in; /* 数据写入缓存 */
FrmCtrl.CSSum += *in;
FrmCtrl.inCts++;
}
switch(FrmCtrl.frameStep){
case 0: /* 检测前导字节 0xFE * 4 */
FrmCtrl.CSSum = 0;
FrmCtrl.inCts = 0;
if(*in == 0xFE){
FrmCtrl.preWordCts++;
if(FrmCtrl.preWordCts == 4){
FrmCtrl.frameStep++;
}
}else{
FrmCtrl.preWordCts = 0;
}
break;
case 1:
FrmCtrl.addrCts = 0;
case 3:
if(*in != 0x68){
FrmCtrl.err = 3;
break;
}
FrmCtrl.frameStep++;
break;
case 2:
FrmCtrl.addrCts++;
if(FrmCtrl.addrCts == 6)
FrmCtrl.frameStep++;
break;
case 4: /* 操作码 */
FrmCtrl.opCode = *in;
if(FrmCtrl.opCode & 0x80){ /* 不是主站发送的报文 */
FrmCtrl.err = 4;
}else FrmCtrl.frameStep++;
break;
case 5: /* 数据域长度 */
FrmCtrl.dataLen = *in;
FrmCtrl.frameStep++;
if(FrmCtrl.dataLen == 0){
FrmCtrl.frameStep++;
}
FrmCtrl.dataCts = 0;
break;
case 6:
FrmCtrl.dataCts++;
if(FrmCtrl.dataCts == FrmCtrl.dataLen){
FrmCtrl.frameStep++;
}
break;
case 7:
FrmCtrl.CSWord = *in;
FrmCtrl.frameStep++;
if(FrmCtrl.CSWord != (FrmCtrl.CSSum & 0xFF)){
FrmCtrl.err = 7;
}
break;
case 8:
FrmCtrl.frameStep = 0;
if(*in != 0x16){ /* 错误的结束符 */
break;
}
/* 完整正确的报文 */
DLT645HostPickPkt(&FrmCtrl);
FrmCtrl.err = 8;
break;
}
in++;
}
}
extern ModbusQueryCtrl_t QueryCtrl;
void DLT645SlaveResponse(uint8_t *pData, uint16_t usMsgLen, uint8_t PE)
{
uint16_t dataSize = usMsgLen;
uint8_t *in = pData;
if(QueryCtrl.pWaitResp == (HostQueryMsg_t *)0)
return;
if(PE){
FrmCtrl.frameStep = 0;
return;
}
while(dataSize > 0){
dataSize--;
if(FrmCtrl.err != 0){
FrmCtrl.frameStep = 0;
FrmCtrl.preWordCts = 0;
FrmCtrl.err = 0;
}
if((FrmCtrl.frameStep != 0) && (FrmCtrl.frameStep < 7)){
if(FrmCtrl.inCts >= 300){
FrmCtrl.inCts = 299;
}
FrmCtrl.inBuf[FrmCtrl.inCts] = *in; /* 数据写入缓存 */
FrmCtrl.CSSum += *in;
FrmCtrl.inCts++;
}
switch(FrmCtrl.frameStep){
case 0: /* 检测前导字节 0xFE * 4 */
FrmCtrl.CSSum = 0;
FrmCtrl.inCts = 0;
if(*in == 0xFE){
FrmCtrl.preWordCts++;
if(FrmCtrl.preWordCts == 4){
FrmCtrl.frameStep++;
}
}else{
FrmCtrl.preWordCts = 0;
}
break;
case 1:
FrmCtrl.addrCts = 0;
case 3:
if(*in != 0x68){
FrmCtrl.err = 3;
break;
}
FrmCtrl.frameStep++;
break;
case 2:
FrmCtrl.addrCts++;
if(FrmCtrl.addrCts == 6)
FrmCtrl.frameStep++;
break;
case 4: /* 操作码 */
FrmCtrl.opCode = *in;
if(!(FrmCtrl.opCode & 0x80)){ /* 不是从站发送的报文 */
FrmCtrl.err = 4;
}else FrmCtrl.frameStep++;
break;
case 5: /* 数据域长度 */
FrmCtrl.dataLen = *in;
FrmCtrl.frameStep++;
if(FrmCtrl.dataLen == 0){
FrmCtrl.frameStep++;
}
FrmCtrl.dataCts = 0;
break;
case 6:
FrmCtrl.dataCts++;
if(FrmCtrl.dataCts == FrmCtrl.dataLen){
FrmCtrl.frameStep++;
}
break;
case 7:
FrmCtrl.CSWord = *in;
FrmCtrl.frameStep++;
if(FrmCtrl.CSWord != (FrmCtrl.CSSum & 0xFF)){
FrmCtrl.err = 7;
}
break;
case 8:
FrmCtrl.frameStep = 0;
if(*in != 0x16){ /* 错误的结束符 */
break;
}
/* 完整正确的报文 */
DLT64SlavePickPkt(QueryCtrl.pWaitResp->pHoldRegs, &FrmCtrl);
FrmCtrl.err = 8;
QueryCtrl.pWaitResp = NULL;
break;
}
in++;
}
}
/* 本设备为从站时的响应 */
void DLT645HostPickPkt(FRAME_CTRL_t *pInfo)
{
int i;
int respLen = 0;
uint8_t ucTmp;
uint8_t broad = 0;
for(i = 0; i < 6; i++){
ucTmp = pInfo->inBuf[1 + i];
if((ucTmp != 0xAA) && (ucTmp != pInfo->devAddress[i])){
broad = 1;
for(i = 0; i < 6; i++){
ucTmp = pInfo->inBuf[1 + i];
if(ucTmp != 0x99){
broad = 0;
break;
}
}
if(broa