📄 dio.c
字号:
/*
*********************************************************************************************************
* Embedded Systems Building Blocks
* Complete and Ready-to-Use Modules in C
*
* Discrete I/O Module
*
* (c) Copyright 1999, Jean J. Labrosse, Weston, FL
* All Rights Reserved
*
* Filename : DIO.C
* Programmer : Jean J. Labrosse
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#define DIO_GLOBALS
#include "includes.h"
/*
*********************************************************************************************************
* LOCAL VARIABLES
*********************************************************************************************************
*/
static OS_STK DIOTaskStk[DIO_TASK_STK_SIZE];
/*
*********************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/
static void DIIsTrig(DIO_DI *pdi);
static void DIOTask(void *data);
static void DIUpdate(void);
static BOOLEAN DOIsBlinkEn(DIO_DO *pdo);
static void DOUpdate(void);
/*$PAGE*/
/*
*********************************************************************************************************
* CONFIGURE DISCRETE INPUT EDGE DETECTION
*
* Description : This function is used to configure the edge detection capability of the discrete input
* channel.
* Arguments : n is the discrete input channel to configure (0..DIO_MAX_DI-1).
* fnct is a pointer to a function that will be executed if the desired edge has been
* detected.
* arg is a pointer to arguments that are passed to the function called.
* Returns : None.
*********************************************************************************************************
*/
#if DI_EDGE_EN
void DICfgEdgeDetectFnct (INT8U n, void (*fnct)(void *), void *arg)
{
DIO_DI *pdi;
if (n < DIO_MAX_DI) {
pdi = &DITbl[n];
OS_ENTER_CRITICAL();
pdi->DITrigFnct = fnct;
pdi->DITrigFnctArg = arg;
OS_EXIT_CRITICAL();
}
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* CONFIGURE DISCRETE INPUT MODE
*
* Description : This function is used to configure the mode of a discrete input channel.
* Arguments : n is the discrete input channel to configure (0..DIO_MAX_DI-1).
* mode is the desired mode and can be:
* DI_MODE_LOW input is forced LOW
* DI_MODE_HIGH input is forced HIGH
* DI_MODE_DIRECT input is based on state of physical sensor (default)
* DI_MODE_INV input is based on the complement of physical sensor
* DI_MODE_EDGE_LOW_GOING a LOW-going transition is detected
* DI_MODE_EDGE_HIGH_GOING a HIGH-going transition is detected
* DI_MODE_EDGE_BOTH both a LOW-going and a HIGH-going transition are detected
* DI_MODE_TOGGLE_LOW_GOING a LOW-going transition is detected in toggle mode
* DI_MODE_TOGGLE_HIGH_GOING a HIGH-going transition is detected in toggle mode
* Returns : None.
* Notes : Edge detection is only available if the configuration constant DI_EDGE_EN is set to 1.
*********************************************************************************************************
*/
void DICfgMode (INT8U n, INT8U mode)
{
if (n < DIO_MAX_DI) {
OS_ENTER_CRITICAL();
DITbl[n].DIModeSel = mode;
OS_EXIT_CRITICAL();
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* CLEAR A DISCRETE INPUT CHANNEL
*
* Description : This function clears the number of edges detected if the discrete input channel is
* configured to count edges.
* Arguments : n is the discrete input channel (0..DIO_MAX_DI-1) to clear.
* Returns : none
*********************************************************************************************************
*/
#if DI_EDGE_EN
void DIClr (INT8U n)
{
DIO_DI *pdi;
if (n < DIO_MAX_DI) {
pdi = &DITbl[n];
OS_ENTER_CRITICAL();
if (pdi->DIModeSel == DI_MODE_EDGE_LOW_GOING || /* See if edge detection mode selected */
pdi->DIModeSel == DI_MODE_EDGE_HIGH_GOING ||
pdi->DIModeSel == DI_MODE_EDGE_BOTH) {
pdi->DIVal = 0; /* Clear the number of edges detected */
}
OS_EXIT_CRITICAL();
}
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* GET THE STATE OF A DISCRETE INPUT CHANNEL
*
* Description : This function is used to get the current state of a discrete input channel. If the input
* mode is set to one of the edge detection modes, the number of edges detected is returned.
* Arguments : n is the discrete input channel (0..DIO_MAX_DI-1).
* Returns : 0 if the discrete input is negated or, if an edge has not been detected
* 1 if the discrete input is asserted
* > 0 if edges have been detected
*********************************************************************************************************
*/
INT16U DIGet (INT8U n)
{
INT16U val;
if (n < DIO_MAX_DI) {
OS_ENTER_CRITICAL();
val = DITbl[n].DIVal; /* Get state of DI channel */
OS_EXIT_CRITICAL();
return (val);
} else {
return (0); /* Return negated for invalid channel */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* DETECT EDGE ON INPUT
*
* Description : This function is called to detect an edge (low-going, high-going or both) on the selected
* discrete input.
* Arguments : pdi is a pointer to the discrete input data structure.
* Returns : none
*********************************************************************************************************
*/
#if DI_EDGE_EN
static void DIIsTrig (DIO_DI *pdi)
{
BOOLEAN trig;
trig = FALSE;
switch (pdi->DIModeSel) {
case DI_MODE_EDGE_LOW_GOING: /* Negative going edge */
if (pdi->DIPrev == 1 && pdi->DIIn == 0) {
trig = TRUE;
}
break;
case DI_MODE_EDGE_HIGH_GOING: /* Positive going edge */
if (pdi->DIPrev == 0 && pdi->DIIn == 1) {
trig = TRUE;
}
break;
case DI_MODE_EDGE_BOTH: /* Both positive and negative going */
if ((pdi->DIPrev == 1 && pdi->DIIn == 0) ||
(pdi->DIPrev == 0 && pdi->DIIn == 1)) {
trig = TRUE;
}
break;
}
if (trig == TRUE) { /* See if edge detected */
if (pdi->DITrigFnct != NULL) { /* Yes, see used defined a function */
(*pdi->DITrigFnct)(pdi->DITrigFnctArg); /* Yes, execute the user function */
}
if (pdi->DIVal < 255) { /* Increment number of edges counted */
pdi->DIVal++;
}
}
pdi->DIPrev = pdi->DIIn; /* Memorize previous input state */
}
#endif
/*$PAGE*/
/*$PAGE*/
/*
*********************************************************************************************************
* UPDATE DISCRETE IN CHANNELS
*
* Description : This function processes all of the discrete input channels.
* Arguments : None.
* Returns : None.
*********************************************************************************************************
*/
static void DIUpdate (void)
{
INT8U i;
DIO_DI *pdi;
pdi = &DITbl[0];
for (i = 0; i < DIO_MAX_DI; i++) {
if (pdi->DIBypassEn == FALSE) { /* See if discrete input channel is bypassed */
switch (pdi->DIModeSel) { /* No, process channel */
case DI_MODE_LOW: /* Input is forced low */
pdi->DIVal = 0;
break;
case DI_MODE_HIGH: /* Input is forced high */
pdi->DIVal = 1;
break;
case DI_MODE_DIRECT: /* Input is based on state of physical input */
pdi->DIVal = (INT8U)pdi->DIIn; /* Obtain the state of the sensor */
break;
case DI_MODE_INV: /* Input is based on the complement state of input */
pdi->DIVal = (INT8U)(pdi->DIIn ? 0 : 1);
break;
#if DI_EDGE_EN
case DI_MODE_EDGE_LOW_GOING:
case DI_MODE_EDGE_HIGH_GOING:
case DI_MODE_EDGE_BOTH:
DIIsTrig(pdi); /* Handle edge triggered mode */
break;
#endif
/*$PAGE*/
case DI_MODE_TOGGLE_LOW_GOING:
if (pdi->DIPrev == 1 && pdi->DIIn == 0) {
pdi->DIVal = pdi->DIVal ? 0 : 1;
}
pdi->DIPrev = pdi->DIIn;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -