单片机开发过程中,GPIO上升沿和下降沿检测应用的地方还是很多,但是怎么样编写这个功能模块,网上资料参差不齐,结合实际和参考PLC逻辑,自行编写了一套逻辑。
以下是全部代码:
头文件 EdgewaysJudge.h
/*
* EdgewaysJudge.h
*
* Created on: 2022年6月10日
* Author: duola_rain
*/
#ifndef APP_EDGEWAYSJUDGE_H_
#define APP_EDGEWAYSJUDGE_H_
#include "Type.h"
#define PLS_SUM 100
#define PLF_SUM 100
//定时 触点 经过值 设定值
#define STIMER_EMPTY 0
#define STIMER_VALID 1
//ms
#define STIMER_BASETIME 10
typedef u16 (*StimerProcFunc)();
typedef s8 (*EdgeFunc)(u8 xOldValue,u8 xId);
typedef struct
{
bool ucPlsValue;
bool ucPlfValue;
bool rtResult;
bool Result;
}Edgeways_t;
typedef struct
{
StimerProcFunc ProcFunc;
EdgeFunc pEdge;
// 传入参数 0:上升沿检查 1:下降沿检查
u32 uiArgParam;
//时间间隔
u32 uiTimerSet ;
// 时间计数
u32 uiTimerCnt;
//定时器状态
u32 ucTimerStatus;
//超时标志
u8 ucTimeOutFlag;
//保持时间
u32 ucKeepTime;
//保持时间计数
u32 ucKeepTimeCnt;
// 循环周期,-1为无限循环
u32 iCycle;
} Stimer ;
#define MAX_TIMER 2
extern void EdgewaysJudge_Init(void);
extern void AxStimerProc(void);
extern void AxStimerTaskManage(void);
extern bool AxCommonUtilCheck(u8 xId);
extern void AxCommonUtilClearn(u8 xId);
extern bool ISD2_isAxNege(void);
extern void ISD2_CLearn(void);
extern s32 AxStartStimer(u8 xId, StimerProcFunc xProcFunc, u8 xTimeSet,
u32 xArgParam, u32 KeepTime, s32 xCycle);
#endif /* APP_EDGEWAYSJUDGE_H_ */
源码:
#include "string.h"
#include "EdgewaysJudge.h"
#include "Global.h"
//typedef void (*DataChgeFunc)(void);
// vale
Edgeways_t Edgeways[MAX_TIMER];
typedef s8 (*EdgewaysJudgeFunc)(u8 xOldValue,u8 xId);
EdgewaysJudgeFunc JudgeFunc[2];
//extern
extern u16 DI_ReadISD2(void);
static s8 AxPoseEdgeFuc(u8 xOldValue,u8 xId);
static s8 AxNegeEdgeFuc(u8 xOldValue,u8 xId);
void EdgewaysJudge_Init(void)
{
JudgeFunc[0] = AxPoseEdgeFuc;
JudgeFunc[1] = AxNegeEdgeFuc;
memset(Edgeways,0,sizeof(Edgeways));
AxStartStimer(0, DI_ReadISD2, 1, 0, 500 , -1);
}
bool ISD2_isAxNege(void)
{
return AxCommonUtilCheck(0);
}
void ISD2_CLearn(void)
{
AxCommonUtilClearn(0);
}
//上升沿
static s8 AxPoseEdgeFuc(u8 xOldValue,u8 xId)
{
u8 cPls;
s8 ret = -1;
if((xId < MAX_TIMER)&&(xOldValue^Edgeways[xId].ucPlsValue))
{
cPls =xOldValue&(xOldValue^Edgeways[xId].ucPlsValue);
Edgeways[xId].ucPlsValue = xOldValue;
Edgeways[xId].rtResult = cPls;
ret = cPls;
}
return ret;
}
//下降沿
static s8 AxNegeEdgeFuc(u8 xOldValue,u8 xId)
{
u8 cPlf;
s8 ret = -1;
if((xId < MAX_TIMER)&&(!xOldValue^Edgeways[xId].ucPlfValue))
{
cPlf = !xOldValue&(!xOldValue^Edgeways[xId].ucPlfValue);
Edgeways[xId].ucPlfValue = !xOldValue;
Edgeways[xId].rtResult = cPlf;
ret = cPlf;
}
return ret;
}
static Stimer tStimerBuf[MAX_TIMER];
s32 AxStartStimer(u8 xId, StimerProcFunc xProcFunc, u8 xTimeSet,
u32 xArgParam, u32 KeepTime, s32 xCycle)
{
u16 tmpVale;
StimerProcFunc cFunc;
if (xId >= MAX_TIMER)
{
return -1;
}
if (STIMER_EMPTY == tStimerBuf[xId].ucTimerStatus)
{
tStimerBuf[xId].ucTimerStatus = STIMER_VALID;
tStimerBuf[xId].uiTimerCnt = 0;
tStimerBuf[xId].ucTimeOutFlag = 0;
tStimerBuf[xId].uiTimerSet = xTimeSet;
tStimerBuf[xId].ProcFunc = xProcFunc;
tStimerBuf[xId].uiArgParam = xArgParam;
tStimerBuf[xId].ucKeepTime = KeepTime;
tStimerBuf[xId]. iCycle = xCycle;
cFunc = tStimerBuf[xId].ProcFunc;
if ( cFunc != 0)
{
tmpVale = (*cFunc)(tStimerBuf[xId].uiArgParam);
}
switch(tStimerBuf[xId].uiArgParam)
{
case 0:
Edgeways[xId].ucPlsValue = tmpVale;
break;
case 1:
Edgeways[xId].ucPlfValue = !tmpVale;
break;
}
return 1;
}
return -1;
}
void AxStopStimer(u8 xId)
{
if (xId >= MAX_TIMER) return;
if (STIMER_VALID == tStimerBuf[xId].ucTimerStatus)
{
tStimerBuf[xId].ucTimerStatus = STIMER_EMPTY;
tStimerBuf[xId].uiTimerCnt = 0;
tStimerBuf[xId]. iCycle = 0;
tStimerBuf[xId].ucTimeOutFlag = 0;
tStimerBuf[xId].uiTimerSet = 0;
}
}
//1ms
void AxStimerProc(void)
{
int i;
for (i = 0; i < MAX_TIMER; i++)
{
if (STIMER_VALID == tStimerBuf[i].ucTimerStatus)
{
if (tStimerBuf[i].uiTimerCnt < tStimerBuf[i].uiTimerSet)
{
tStimerBuf[i].uiTimerCnt++;
}
else
{
tStimerBuf[i].ucTimeOutFlag = 1;
}
}
}
}
//1ms
void AxStimerTaskManage(void)
{
u32 i;
u16 tmpVale;
StimerProcFunc cFunc;
for (i = 0; i < MAX_TIMER; i++)
{
if (STIMER_VALID == tStimerBuf[i].ucTimerStatus)
{
if (tStimerBuf[i].ucTimeOutFlag)
{
cFunc = tStimerBuf[i].ProcFunc;
if ( cFunc != 0)
{
tmpVale = (*cFunc)(tStimerBuf[i].uiArgParam);
}
if(tStimerBuf[i].ucKeepTimeCnt <= tStimerBuf[i].ucKeepTime)
{
switch(tStimerBuf[i].uiArgParam)
{
case 0:
(*JudgeFunc[0])(tmpVale,i);
break;
case 1:
(*JudgeFunc[1])(tmpVale,i);
break;
}
if(Edgeways[i].rtResult)
{
tStimerBuf[i].ucKeepTimeCnt ++;
}
else
{
tStimerBuf[i].ucKeepTimeCnt = 0;
Edgeways[i].Result = Edgeways[i].rtResult;
}
}
else
{
else
{
tStimerBuf[i].ucKeepTimeCnt = 0;
Edgeways[i].Result = Edgeways[i].rtResult;
}
if (0 == tStimerBuf[i].iCycle)
{
AxStopStimer(i);
}
if (tStimerBuf[i].iCycle > 0)
{
tStimerBuf[i].iCycle--;
}
}
}
}
}
void AxCommonUtilClearn(u8 xId)
{
Edgeways[xId].rtResult = 0;
Edgeways[xId].Result = 0;
}
bool AxCommonUtilCheck(u8 xId)
{
return Edgeways[xId].Result > 0? true : false;
}