📄 digio.c
字号:
/* ------------------------------------------------------------------------
File : digio.c
Descr : Functions for Digital-input and -output handling.
History: 21JUL.00; Henk B&B; Definition; for the time being a single 8-bit
in- and two 8-bit output ports are defined.
21AUG.00; Henk B&B; Add a polling counter for the change-of-state
of inputs in order to implement 'debouncing'.
30NOV.00; Henk B&B; Added interrupt enable: DigInIntrptEna.
19MAR.01; Henk B&B; Added storage of digital output setting(s)
for restore after reset/power-up.
18JUL.01; Henk B&B; Changed output-at-reset policy:
keep settings at soft-reset (= NMT-Reset).
23JUL.01; Henk B&B; Share 2nd Port between in- and outputs
(configurable);
add interrupt masks for both 8-bit input ports.
04FEB.02; Henk B&B; Digital Outputs set to high, by default.
16JAN.03; Henk B&B; Ported to ATmega128.
--------------------------------------------------------------------------- */
#include "general.h"
#include "can.h"
#include "digio.h"
#include "eeprom.h"
#include "store.h"
/* After a hard reset Digital Outputs are initialized to either low or high;
after a soft reset (= NMT Reset-Node) existing settings are kept */
/* ------------------------------------------------------------------------ */
/* Globals */
static BYTE DigInDebouncePolls; /* (stored in EEPROM) */
static BOOL DigInIntrptEna; /* (stored in EEPROM) */
static BOOL DigOutInitHi; /* (stored in EEPROM) */
static BYTE DigOutMask2; /* (stored in EEPROM) */
static BYTE DigInMask2;
static BYTE DigInIntrptMask1; /* (stored in EEPROM) */
static BYTE DigInIntrptMask2; /* (stored in EEPROM) */
static BYTE DigInStateOld1;
static BYTE DigInStateOld2;
static BYTE DigInStatePolls;
/* ------------------------------------------------------------------------ */
/* Local prototypes */
static void digio_load_config( void );
/* ------------------------------------------------------------------------ */
void digio_init( BOOL hard_reset )
{
/* Initialise Digital-I/O configuration parameters */
digio_load_config();
DigInStatePolls = 0;
/* Digital input port 1
ATmega103: PORTF cannot be initialized (no pull-ups present) */
#ifndef __ELMB103__
DIGIN1_PORT = 0xFF; /* Use pull-ups */
DIGIN1_DDR = 0x00;
#endif /* __ELMB103__ */
DigInStateOld1 = DIGIN1_PIN & DigInIntrptMask1;
/* Digital input port 2: is shared between inputs and outputs !
set DDRA/PORTA: use pull-ups (=1) */
DigInMask2 = ~DigOutMask2;
DIGIN2_PORT |= DigInMask2;
DIGIN2_DDR = ~DigInMask2;
DigInStateOld2 = (DIGIN2_PIN & DigInMask2) & DigInIntrptMask2;
/* Digital output port 1: set PORTC (output only on ATmega103);
keep old setting at soft-reset (NMT Reset-Node) */
#ifndef __ELMB103__
DIGOUT1_DDR = 0xFF;
#endif /* __ELMB103__ */
if( (hard_reset & TRUE) == TRUE )
{
/* Initialize to required setting */
if( DigOutInitHi )
DIGOUT1_PORT = 0xFF;
else
DIGOUT1_PORT = 0x00;
}
/* Digital output port 2: set DDRA/PORTA;
keep old setting at soft-reset (NMT Reset-Node) */
DIGOUT2_DDR = DigOutMask2;
if( (hard_reset & TRUE) == TRUE )
{
/* Initialize to required setting */
if( DigOutInitHi )
DIGOUT2_PORT |= DigOutMask2;
else
DIGOUT2_PORT &= (~DigOutMask2);
}
}
/* ------------------------------------------------------------------------ */
BYTE digin_port_cnt( void )
{
return DIGIO_INPORT_CNT;
}
/* ------------------------------------------------------------------------ */
BYTE digin_get_port( BYTE port_no )
{
if( port_no == 1 )
{
#ifndef __ELMB103__
/* Refresh the DDR and pull-up setting */
DIGIN1_DDR = 0x00;
DIGIN1_PORT = 0xFF; /* Use pull-ups */
#endif /* __ELMB103__ */
return DIGIN1_PIN;
}
if( port_no == 2 )
{
#ifdef __VARS_IN_EEPROM__
DigInMask2 = ~eeprom_read( EE_DIGOUTMASK2 );
#endif /* __VARS_IN_EEPROM__ */
/* Refresh the DDR and pull-up setting */
DIGIN2_DDR &= (~DigInMask2);
DIGIN2_PORT |= DigInMask2;
return (DIGIN2_PIN & DigInMask2);
}
return 0x00;
}
/* ------------------------------------------------------------------------ */
void digin_pdo( void )
{
BYTE pdo_data[DIGIO_INPORT_CNT];
/* Read the digital-inputs and put in the message */
pdo_data[0] = digin_get_port( 1 );
pdo_data[1] = digin_get_port( 2 );
/* Send as a Transmit-PDO1 CAN-message */
can_write( C91_TPDO1, DIGIO_INPORT_CNT, pdo_data );
}
/* ------------------------------------------------------------------------ */
void digin_pdo_on_cos( void )
{
/* Send a PDO on change-of-state of the digital inputs;
a simple debounce-mechanism is implemented */
BYTE current_state1, current_state2;
#ifdef __VARS_IN_EEPROM__
DigInIntrptEna = eeprom_read( EE_DIGININTRPTENA );
#endif /* __VARS_IN_EEPROM__ */
if( !DigInIntrptEna ) return;
#ifdef __VARS_IN_EEPROM__
DigInIntrptMask1 = eeprom_read( EE_DIGININTRPTMASK1 );
DigInIntrptMask2 = eeprom_read( EE_DIGININTRPTMASK2 );
DigInMask2 = ~eeprom_read( EE_DIGOUTMASK2 );
#endif /* __VARS_IN_EEPROM__ */
/* Read current state of (interrupt-enabled) digital inputs */
current_state1 = DIGIN1_PIN & DigInIntrptMask1;
current_state2 = (DIGIN2_PIN & DigInMask2) & DigInIntrptMask2;
if( current_state1 != DigInStateOld1 || current_state2 != DigInStateOld2 )
{
#ifdef __VARS_IN_EEPROM__
DigInDebouncePolls = eeprom_read( EE_DIGINDEBOUNCEPOLLS );
#endif /* __VARS_IN_EEPROM__ */
/* Assuming that a 'bouncing' switch causes the input to go
from a new state to the old state and back, we just wait
until we have seen a new state a number of times in a row */
++DigInStatePolls;
if( DigInStatePolls > DigInDebouncePolls )
{
/* Assume changed state of digital inputs now stable: send the PDO;
if this is not possible don't 'discard' this change:
we'll miss it if this is the last change that occurs */
if( can_transmitting(C91_TPDO1) ) return;
digin_pdo();
/* Remember the current state */
DigInStateOld1 = current_state1;
DigInStateOld2 = current_state2;
}
}
else
{
DigInStatePolls = 0;
}
}
/* ------------------------------------------------------------------------ */
BYTE digout_port_cnt( void )
{
return DIGIO_OUTPORT_CNT;
}
/* ------------------------------------------------------------------------ */
void digout_set_port( BYTE port_no, BYTE digout_data )
{
/* Set digital outputs according to databyte */
if( port_no == 1 )
{
#ifndef __ELMB103__
/* Refresh the DDR */
DIGOUT1_DDR = 0xFF;
#endif /* __ELMB103__ */
DIGOUT1_PORT = digout_data;
}
if( port_no == 2 )
{
BYTE out_curr;
#ifdef __VARS_IN_EEPROM__
DigOutMask2 = eeprom_read( EE_DIGOUTMASK2 );
#endif /* __VARS_IN_EEPROM__ */
/* Refresh the (output-part of the) DDR */
DIGOUT2_DDR |= DigOutMask2;
/* Get setting of non-output pins (pull-ups) */
out_curr = DIGOUT2_PORT & (~DigOutMask2);
/* Combine this setting with the new output setting */
DIGOUT2_PORT = out_curr | (digout_data & DigOutMask2);
}
}
/* ------------------------------------------------------------------------ */
BYTE digout_get_port( BYTE port_no )
{
BYTE portdata = 0x00;
if( port_no == 1 )
{
#ifndef __ELMB103__
/* Refresh the DDR */
DIGOUT1_DDR = 0xFF;
#endif /* __ELMB103__ */
portdata = DIGOUT1_PORT;
}
if( port_no == 2 )
{
#ifdef __VARS_IN_EEPROM__
DigOutMask2 = eeprom_read( EE_DIGOUTMASK2 );
#endif /* __VARS_IN_EEPROM__ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -