optical/NxFuncs/modbus/ef_a.c
2025-09-04 09:45:08 +08:00

544 lines
9.3 KiB
C

#include "ef_a.h"
#include "inout.h"
#include "delay.h"
#include "trigger.h"
#ifndef EF_NUM
#define EF_NUM 1
#endif
EFCommCtrl g_efCommCtrl[EF_NUM];
void EFDefOutEn(void)
{
}
void EFDefOutDis(void)
{
}
void RegisterEFCommFunc(EFCommCtrl* pCtrl, UsartSendData send, UsartGetData get, UsartCleanRsBuf clean, IsUsartSendOver sdover, CommOutFunc outen, CommOutFunc outdis)
{
pCtrl->EFCommSend = send;
pCtrl->EFCommReceive = get;
pCtrl->EFCommCleanRsBuf = clean;
pCtrl->IsEFCommSendOver = sdover;
pCtrl->CommOutEn = outen;
pCtrl->CommOutDis = outdis;
}
void InitEF(int idx, int usart, BAUD_TypeDef baud, char dat, char parity, char stop)
{
if (idx < 0 || idx >= EF_NUM)
{
return;
}
memset(&g_efCommCtrl[idx], 0, sizeof(EFCommCtrl));
// 延时
switch(baud)
{
// 数据位 + 1个起始位 + 奇偶校验位(无校验则没有) + 停止位
// 根据波特率来计算 通讯延时, 单位us = 10000000 / baud(按照一个字节10位计算, 8 N 1)
case B4800:
{
g_efCommCtrl[idx].efSendWait = 2200;
break;
}
case B9600:
{
g_efCommCtrl[idx].efSendWait = 1100;
break;
}
case B14400:
{
g_efCommCtrl[idx].efSendWait = 750;
break;
}
case B19200:
{
g_efCommCtrl[idx].efSendWait = 600;
break;
}
case B38400:
{
g_efCommCtrl[idx].efSendWait = 300;
break;
}
case B57600:
{
g_efCommCtrl[idx].efSendWait = 200;
break;
}
case B115200:
{
g_efCommCtrl[idx].efSendWait = 100;
break;
}
case B230400:
{
g_efCommCtrl[idx].efSendWait = 50;
break;
}
case B460800:
{
g_efCommCtrl[idx].efSendWait = 25;
break;
}
case B921600:
{
g_efCommCtrl[idx].efSendWait = 13;
break;
}
default:
{
g_efCommCtrl[idx].efSendWait = 0;
}
}
#ifndef USART1_485OutEn
#define USART1_485OutEn EFDefOutEn
#endif
#ifndef USART1_485OutDis
#define USART1_485OutDis EFDefOutDis
#endif
#ifndef USART2_485OutEn
#define USART2_485OutEn EFDefOutEn
#endif
#ifndef USART2_485OutDis
#define USART2_485OutDis EFDefOutDis
#endif
#ifndef USART3_485OutEn
#define USART3_485OutEn EFDefOutEn
#endif
#ifndef USART3_485OutDis
#define USART3_485OutDis EFDefOutDis
#endif
#ifndef USART4_485OutEn
#define USART4_485OutEn EFDefOutEn
#endif
#ifndef USART4_485OutDis
#define USART4_485OutDis EFDefOutDis
#endif
#ifndef USART5_485OutEn
#define USART5_485OutEn EFDefOutEn
#endif
#ifndef USART5_485OutDis
#define USART5_485OutDis EFDefOutDis
#endif
#ifndef USART6_485OutEn
#define USART6_485OutEn EFDefOutEn
#endif
#ifndef USART6_485OutDis
#define USART6_485OutDis EFDefOutDis
#endif
// 初始化串口
switch(usart)
{
#ifdef COMM_USART1
case COMM_USART1:
{
InitUsart1(baud, dat, parity, stop); // 串口1
RegisterEFCommFunc(&g_efCommCtrl[idx], Usart1SendData, Usart1GetData, Usart1CleanRsBuf, IsUsart1SendOver, USART1_485OutEn, USART1_485OutDis);
break;
}
#endif
#ifdef COMM_USART2
case COMM_USART2:
{
InitUsart2(baud, dat, parity, stop); // 串口2
RegisterEFCommFunc(&g_efCommCtrl[idx], Usart2SendData, Usart2GetData, Usart2CleanRsBuf, IsUsart2SendOver, USART2_485OutEn, USART2_485OutDis);
break;
}
#endif
#ifdef COMM_USART3
case COMM_USART3:
{
InitUsart3(baud, dat, parity, stop); // 串口3
RegisterEFCommFunc(&g_efCommCtrl[idx], Usart3SendData, Usart3GetData, Usart3CleanRsBuf, IsUsart3SendOver, USART3_485OutEn, USART3_485OutDis);
break;
}
#endif
#ifdef COMM_USART4
case COMM_USART4:
{
InitUsart4(baud, dat, parity, stop); // 串口4
RegisterEFCommFunc(&g_efCommCtrl[idx], Usart4SendData, Usart4GetData, Usart4CleanRsBuf, IsUsart4SendOver, USART4_485OutEn, USART4_485OutDis);
break;
}
#endif
#ifdef COMM_USART5
case COMM_USART5:
{
InitUsart5(baud, dat, parity, stop); // 串口5
RegisterEFCommFunc(&g_efCommCtrl[idx], Usart5SendData, Usart5GetData, Usart5CleanRsBuf, IsUsart5SendOver, USART5_485OutEn, USART5_485OutDis);
break;
}
#endif
#ifdef COMM_USART6
case COMM_USART6:
{
InitUsart6(baud, dat, parity, stop); // 串口6
RegisterEFCommFunc(&g_efCommCtrl[idx], Usart6SendData, Usart6GetData, Usart6CleanRsBuf, IsUsart6SendOver, USART6_485OutEn, USART6_485OutDis);
break;
}
#endif
default:
{
break;
}
}
g_efCommCtrl[idx].CommOutDis(); // 关闭发送
}
int EFTx(int idx, u8 addr, u16 data, int steps)
{
int i, timeout, result;
u8 pSDat[3];
if ( ((addr & 0xF0) != 0xE0) && ((addr & 0xF0) != 0xF0) )
{
return -1;
}
if (steps == 1 || steps == -1)
{
g_efCommCtrl[idx].CommOutEn(); // 打开发送
if (steps == -1)
{
DelayUs(100);
}
}
if (steps == 2 || steps == -1)
{
i = 0;
result = 0;
pSDat[i++] = addr;
if ((addr & 0xF0) == 0xF0)
{
pSDat[i++] = HIBYTE(data);
pSDat[i++] = LOBYTE(data);
}
else
{
pSDat[i++] = data;
}
g_efCommCtrl[idx].EFCommSend(pSDat, i);
}
if (steps == 3)
{
if (g_efCommCtrl[idx].IsEFCommSendOver() != TRUE)
{
return 0;
}
}
else if (steps == -1) // 同步发送
{
timeout = (i*2 + 4) * g_efCommCtrl[idx].efSendWait; // 超时时间,单位us((字节数*2 + 4) * 每个字节发送时长)
do //等待发送完成
{
if (g_efCommCtrl[idx].IsEFCommSendOver() == TRUE)
{
break;
}
DelayUs(1);
if (timeout-- <= 0)
{
result = -2;
break;
}
}while(1);
DelayUs(g_efCommCtrl[idx].efSendWait); // 等待最后一个字节发送完成
}
if (steps == 4 || steps == -1)
{
g_efCommCtrl[idx].EFCommCleanRsBuf(); // 清空已接收的数据
g_efCommCtrl[idx].CommOutDis(); // 关闭发送
}
if (steps != -1)
{
return steps;
}
return result;
}
int EFRx(int idx, u16 * pData, int steps)
{
int exlen, timeout, result;
u8 pRDat[3];
if (pData == NULL || (steps != 1 && steps != -1))
{
return -1;
}
memset(pRDat, 0, 3);
exlen = 3;
timeout = exlen*2 + 200; // 超时时间
do
{
result = g_efCommCtrl[idx].EFCommReceive(pRDat, exlen); // 从缓冲区读取数据
if (result >= exlen)
{
// 处理数据包
if (pRDat[0] != 0xE0)
{
result = -4; // 接收错误
break;
}
*pData = MAKEWORD(pRDat[2], pRDat[1]);
break;
}
else if (result < 0)
{
if (result == -2) // 串口没有初始化
{
printf("usart is not inited\r\n");
}
else if (result == -3) // 接收缓冲区控制错误
{
printf("usart receive buf ctrl error\r\n");
}
break;
}
if (steps == -1)
{
// 等待接收完成
DelayUs(g_efCommCtrl[idx].efSendWait);
if (timeout-- <= 0)
{
printf("2. call EFRx timeout\r\n");
result = -5; //接收超时
break;
}
}
else
{
result = 0;
break;
}
}while(1);
return result;
}
int EFComm(int idx, u8 addr, u16 wrDat, u16 * pRdBuf)
{
int result;
result = EFTx(idx, addr, wrDat, -1);
if (result == 0)
{
// 等待回包
if (addr == 0xE0 && wrDat >= 32 && wrDat <= 63)
{
if (pRdBuf != NULL)
{
result = EFRx(idx, pRdBuf, -1);
}
}
}
return result;
}
AsyncEFCtrl g_asyncefCtrl[EF_NUM];
void InitAsyncEFCtrl(int idx, int rsvtimout)
{
memset(&g_asyncefCtrl[idx], 0, sizeof(AsyncEFCtrl));
// 读取超时时间
if (rsvtimout < 20)
{
g_asyncefCtrl[idx].efrsvTimout = 20;
}
else if (rsvtimout > 200)
{
g_asyncefCtrl[idx].efrsvTimout = 200;
}
else
{
g_asyncefCtrl[idx].efrsvTimout = rsvtimout;
}
}
void RegEFCmdProc(int idx, ResvEFProc proc)
{
g_asyncefCtrl[idx].resvefproc = proc;
}
int AddEFCmd(EFCmd * pCmd)
{
if (pCmd != NULL)
{
AsyncEFCtrl * p485Ctrl = &g_asyncefCtrl[pCmd->idx];
if (p485Ctrl != NULL)
{
if (p485Ctrl->bufCmdNum < MAX_EF_CMD && p485Ctrl->bufTail < MAX_EF_CMD)
{
memcpy(&(p485Ctrl->cmdbuf[p485Ctrl->bufTail]), pCmd, sizeof(EFCmd));
p485Ctrl->bufTail++;
if (p485Ctrl->bufTail >= MAX_EF_CMD)
{
p485Ctrl->bufTail = 0;
}
p485Ctrl->bufCmdNum++;
return p485Ctrl->bufCmdNum;
}
else
{
printf("ef %d cmd buff full\r\n", pCmd->idx);
return -2;
}
}
return -1;
}
return -1;
}
int GetEFCmdBufLen(int idx)
{
return g_asyncefCtrl[idx].bufCmdNum;
}
int AsyncEFTask(int idx)
{
// 分步骤执行
int rslt;
u32 curIime;
EFCmd *pCmd;
AsyncEFCtrl * p485Ctrl = &g_asyncefCtrl[idx];
if (p485Ctrl == NULL)
{
return -1;
}
pCmd = &(p485Ctrl->cmdbuf[p485Ctrl->bufHead]);
// 读取当前时间
curIime = GetUsSoftTimer();
if ((curIime - p485Ctrl->stepTime) > g_efCommCtrl[pCmd->idx].efSendWait)
{
p485Ctrl->stepTime = curIime;
if (p485Ctrl->working == 0 &&
p485Ctrl->bufCmdNum > 0 &&
p485Ctrl->steps == 0)
{
p485Ctrl->working = 1;
p485Ctrl->steps = 1;
}
if (p485Ctrl->working == 0)
{
p485Ctrl->steps = 0;
return 0;
}
if (p485Ctrl->steps > 0 && p485Ctrl->steps < 5)
{
rslt = EFTx(pCmd->idx, pCmd->addr, pCmd->wrdat, p485Ctrl->steps);
if (rslt == p485Ctrl->steps)
{
p485Ctrl->steps++;
}
}
else if (p485Ctrl->steps >= 5 && p485Ctrl->steps < p485Ctrl->efrsvTimout)
{
// 等待回包
if (pCmd->addr == 0xE0 && pCmd->wrdat >= 32 && pCmd->wrdat <= 63)
{
rslt = EFRx(pCmd->idx, &pCmd->rddat, 1);
if (rslt == 3) // 读到正确数据
{
// 执行读到数据函数
if (p485Ctrl->resvefproc != NULL)
{
p485Ctrl->resvefproc(pCmd);
}
p485Ctrl->steps = p485Ctrl->efrsvTimout;
}
else
{
p485Ctrl->steps++;
}
}
else
{
p485Ctrl->steps = p485Ctrl->efrsvTimout;
}
}
else
{
p485Ctrl->steps++;
}
if (p485Ctrl->steps >= p485Ctrl->efrsvTimout)
{
if (p485Ctrl->bufCmdNum > 0)
{
p485Ctrl->bufCmdNum--;
}
p485Ctrl->steps = 0;
p485Ctrl->working = 0;
p485Ctrl->bufHead++;
if (p485Ctrl->bufHead >= MAX_EF_CMD)
{
p485Ctrl->bufHead = 0;
}
}
}
return p485Ctrl->steps;
}