📄 adc_elmb.c
字号:
ADC_DESELECT();
/* Should only generate a next PDO when the previous one
has been sent */
if( can_transmitting(C91_TPDO2) )
{
/* A TPDO2 transmission is in progress, so wait... */
return TRUE;
}
/* Set to FALSE only if message can be sent... */
AdcConvInProgress = FALSE;
ADC_SELECT();
/* Generate 8 SCLKs to clear the SDO flag */
cs5523_write_byte( 0 );
/* Read 24 bits (3 bytes) of ADC conversion data */
pdo_data[3] = cs5523_read_byte();
pdo_data[2] = cs5523_read_byte();
adc_stat = cs5523_read_byte();
ADC_DESELECT();
#ifdef __VARS_IN_EEPROM__
AdcConfig = eeprom_read( EE_ADCCONFIG );
#endif
/* Replace the status byte with a byte containing
the ADC-configuration (wordrate, gain, uni/bipolar)
and one bit with an 'or' of the OF and OD bits
(here bit 7, the highest bit) */
if( adc_stat & CS23_DATA_ERROR )
pdo_data[1] = AdcConfig | ADC_ERR_CONVERSION;
else
pdo_data[1] = AdcConfig;
/* Put the ADC channel number in the message */
pdo_data[0] = AdcChanNo;
/* The ADC-count as a 16-bit (unsigned) integer */
adc_count = (((UINT16) pdo_data[2]) |
(((UINT16) pdo_data[3]) << 8));
if( AdcReadoutOnChange )
{
/* Do the necessary checks to determine whether
the data is to be sent */
send_pdo = FALSE;
/* Delta-change check */
if( AdcDeltaScanEnabled )
send_pdo = adc_delta_check( adc_count );
/* Upper/lower limit check */
if( AdcWindowScanEnabled && send_pdo == FALSE )
send_pdo = adc_window_check( adc_count );
}
else
{
send_pdo = TRUE;
}
/* Send data when required */
if( send_pdo )
{
if( AdcScanVolts )
{
BYTE microvolts[4];
BYTE i, *ptr;
/* Convert the ADC-count to microVolts */
adc_convert_to_volts( adc_count, microvolts );
/* Copy the resulting value into the output array */
ptr = &pdo_data[2];
for( i=0; i<4; ++i, ++ptr ) *ptr = microvolts[i];
/* Send as a Transmit-PDO3 CAN-message */
can_write( C91_TPDO3, C91_TPDO3_LEN, pdo_data );
}
else
{
/* Send as a Transmit-PDO2 CAN-message */
can_write( C91_TPDO2, C91_TPDO2_LEN, pdo_data );
}
}
/* Next time, next channel
(SEE-protected version of '++AdcChanNo;') */
AdcChanNo = (AdcChanNo & (ADC_MAX_INPUTS-1)) + 1;
#ifdef __VARS_IN_EEPROM__
AdcChans = eeprom_read( EE_ADCCHANS );
#endif
/* Are we done with the current scan cycle ? */
if( AdcChanNo == AdcChans )
{
/* Yes, we're done... */
AdcForcedReadout = FALSE;
AdcInitRefCount = FALSE;
return FALSE;
}
}
}
else
{
/* Conversion in progress...
check for possible timeout... */
/* ###Do not deselect/select during a conversion: may cause noise */
//ADC_DESELECT();
if( timer0_timeout(ADC_ELMB) )
{
/* Conversion timed out ! */
AdcError |= ADC_ERR_TIMEOUT;
/* CANopen Error Code 0x5000: device hardware */
can_write_emergency( 0x00, 0x50, EMG_ADC_CONVERSION, AdcChanNo,
0, 0, ERRREG_MANUFACTURER );
AdcConvInProgress = FALSE;
//adc_serial_init();
adc_reset_and_calibrate( TRUE );
/* Stop this scan... */
return FALSE;
}
/* Wait some more... */
return TRUE;
}
}
ADC_SELECT();
if( (AdcChanNo & 0x0F) == 0 && (AdcLatchSet & TRUE) == FALSE )
{
BYTE bank_no, log_chan;
bank_no = AdcChanNo/16;
/* Change of 16-chan inputs bank: select bank,
by initiating a (dummy) conversion;
LC 5 to 8 contain the proper setting of A1-A0
(set during initialization) to accomplish this */
/* The Logical Channel to use (4, 5, 6 or 7) */
log_chan = ((4 + bank_no) << CS23_CMD_LOGCHAN_SELECT_SHIFT);
/* Initiate the conversion */
cs5523_start_conversion_cmd( CS23_CMD_NORMAL_CONVERSION | log_chan );
/* When conversion done, don't send data... */
AdcLatchBeingSet = TRUE;
}
else
{
BYTE a1a0, cs1cs0;
BYTE csr_data[1*2*2];
#ifdef __VARS_IN_EEPROM__
AdcConfig = eeprom_read( EE_ADCCONFIG );
AdcOptoDelay = eeprom_read( EE_ADCOPTODELAY );
#endif
/* Set A1-A0 and physical channel in LC 1 (+2)
while maintaining proper wordrate and gain */
a1a0 = AdcChanNo & 3;
cs1cs0 = (AdcChanNo>>2) & 3;
csr_data[0] = (AdcConfig | ((cs1cs0 << CS23_CSR_PHYSCHAN_SEL_LO_SHIFT) &
CS23_CSR_PHYSCHAN_SEL_LO_MASK));
csr_data[1] = ((a1a0 << CS23_CSR_A1A0_SHIFT) |
((cs1cs0 >> CS23_CSR_PHYSCHAN_SEL_HI_SHIFT) &
CS23_CSR_PHYSCHAN_SEL_HI_MASK));
csr_data[2] = 0x00;
csr_data[3] = 0x00;
cs5523_write_csr( 1, csr_data );
/* Start a conversion of LC 1 */
cs5523_start_conversion_cmd( CS23_CMD_NORMAL_CONVERSION | 0 );
/* At next 16-chan inputs bank, first do a conversion to set latch */
AdcLatchSet = FALSE;
}
/* ###Do not deselect/select during a conversion: may cause noise */
//ADC_DESELECT();
AdcConvInProgress = TRUE;
/* Set a timeout on the conversion of about 800 ms... */
//timer0_set_timeout_10ms( ADC_ELMB, 80 );
timer0_set_timeout_10ms( ADC_ELMB, 120 ); // Make that 1200 ms... */
return TRUE;
}
/* ------------------------------------------------------------------------ */
static BOOL adc_delta_check( UINT16 adc_count )
{
UINT16 adc_delta, adc_diff;
/* Initialize reference value if necessary ! */
if( (AdcInitRefCount & TRUE) == TRUE ) AdcRefCount[AdcChanNo] = adc_count;
if( (AdcForcedReadout & TRUE) == TRUE )
{
/* Send the data */
return TRUE;
}
/* Get the delta-change value for this channel from
the working copy in EEPROM */
adc_delta = adc_get_delta_cnt( AdcChanNo );
/* Don't send the data when the delta is zero */
if( adc_delta == (UINT16) 0 ) return FALSE;
if( AdcConfig & CS23_CSR_UNIPOLAR )
{
/* Unipolar measurement: use unsigned numbers ! */
if( adc_count > AdcRefCount[AdcChanNo] )
adc_diff = adc_count - AdcRefCount[AdcChanNo];
else
adc_diff = AdcRefCount[AdcChanNo] - adc_count;
}
else
{
/* Bipolar measurement: use signed numbers ! */
INT16 *padc_count, *padc_last_sent;
padc_count = (INT16 *) &adc_count;
padc_last_sent = (INT16 *) &AdcRefCount[AdcChanNo];
if( *padc_count > *padc_last_sent )
adc_diff = (UINT16) (*padc_count - *padc_last_sent);
else
adc_diff = (UINT16) (*padc_last_sent - *padc_count);
}
if( adc_diff >= adc_delta )
{
BYTE cntr;
cntr = AdcDeltaCounter[AdcChanNo];
++cntr;
if( cntr >= AdcWindowCounterInit )
{
AdcDeltaCounter[AdcChanNo] = 0;
/* Store this value: new reference ! */
AdcRefCount[AdcChanNo] = adc_count;
/* Send the data */
return TRUE;
}
else
{
AdcDeltaCounter[AdcChanNo] = cntr;
/* Don't send the data (yet) */
return FALSE;
}
}
else
{
AdcDeltaCounter[AdcChanNo] = 0;
/* Don't send the data */
return FALSE;
}
}
/* ------------------------------------------------------------------------ */
static BOOL adc_window_check( UINT16 adc_count )
{
UINT16 adc_upper, adc_lower;
BOOL outside_window;
CHAR cntr;
if( (AdcForcedReadout & TRUE) == TRUE )
{
/* Send the data */
return TRUE;
}
/* Get the upper-limit value for this channel from
the working copy in EEPROM */
adc_upper = adc_get_upperlimit_cnt( AdcChanNo );
/* Get the lower-limit value for this channel from
the working copy in EEPROM */
adc_lower = adc_get_lowerlimit_cnt( AdcChanNo );
if( AdcConfig & CS23_CSR_UNIPOLAR )
{
/* Unipolar measurement: use unsigned numbers ! */
if( adc_lower >= adc_upper ) return FALSE;
if( adc_count > adc_upper || adc_count < adc_lower )
outside_window = TRUE;
else
outside_window = FALSE;
}
else
{
/* Bipolar measurement: use signed numbers ! */
INT16 *padc_count, *padc_upper, *padc_lower;
padc_count = (INT16 *) &adc_count;
padc_upper = (INT16 *) &adc_upper;
padc_lower = (INT16 *) &adc_lower;
if( *padc_lower >= *padc_upper ) return FALSE;
if( *padc_count > *padc_upper || *padc_count < *padc_lower )
outside_window = TRUE;
else
outside_window = FALSE;
}
cntr = AdcWindowCounter[AdcChanNo];
/* Some checks to counter SEE
(don't use counter anymore for inside-window cases) */
//if( cntr > AdcWindowCounterInit ) cntr = AdcWindowCounterInit;
if( cntr > 0 ) cntr = 0;
if( cntr < -(AdcWindowCounterInit + 1) ) cntr = -(AdcWindowCounterInit + 1);
/* Negative counter values mean 'currently being outside window',
positive counter values (and zero) mean 'currently being inside window'
(which is also the initial value) */
if( outside_window )
{
/*if( (AdcForcedReadout & TRUE) == TRUE )
{
AdcWindowCounter[AdcChanNo] = -1;
return TRUE;
}*/
/* Already reported ? */
if( cntr == -1 ) return FALSE;
/* First time outside window from being inside window ?
--> initialise counter for this channel */
if( cntr >= 0 ) cntr = -(AdcWindowCounterInit + 1);
++cntr;
AdcWindowCounter[AdcChanNo] = cntr;
/* Value -1 means: outside window and reported */
if( cntr == -1 )
{
/* Send the data */
return TRUE;
}
}
else
{
/*if( (AdcForcedReadout & TRUE) == TRUE )
{
AdcWindowCounter[AdcChanNo] = 0;
return TRUE;
}*/
/* Inside window: already reported ? */
if( cntr == 0 ) return FALSE;
/* We are 'inside window' */
AdcWindowCounter[AdcChanNo] = 0;
/* First time inside window from being outside window ?
(no counter used in this case!)
--> report it *only* if 'outside-window' has been reported,
--> cntr == -1 */
if( cntr == -1 )
{
/* Send the data */
return TRUE;
}
}
return FALSE;
}
/* ------------------------------------------------------------------------ */
#define ADC_STORE_SIZE 8
/* ------------------------------------------------------------------------ */
BOOL adc_store_config( void )
{
BYTE block[ADC_STORE_SIZE];
BOOL result = TRUE;
/* Store ADC delta-change parameters */
if( adc_store_deltas() == FALSE ) result = FALSE;
/* Store ADC upper-limit parameters */
if( adc_store_upperlimits() == FALSE ) result = FALSE;
/* Store ADC lower-limit parameters */
if( adc_store_lowerlimits() == FALSE ) result = FALSE;
#ifdef __VARS_IN_EEPROM__
AdcChans = eeprom_read( EE_ADCCHANS );
AdcConfig = eeprom_read( EE_ADCCONFIG );
AdcCalibBeforeScan = eeprom_read( EE_ADCCALIBBEFORESCAN );
AdcReadoutOnChange = eeprom_read( EE_ADCREADOUTONCHANGE );
AdcDeltaScanEnabled = eeprom_read( EE_ADCDELTASCANENABLED );
AdcWindowScanEnabled = eeprom_read( EE_ADCWINDOWSCANENABLED );
AdcWindowCounterInit = eeprom_read( EE_ADCWINDOWCOUNTERINIT );
AdcOptoDelay = eeprom_read( EE_ADCOPTODELAY );
#endif /* __VARS_IN_EEPROM__ */
block[0] = AdcChans;
block[1] = AdcConfig;
block[2] = AdcCalibBeforeScan;
block[3] = AdcReadoutOnChange;
block[4] = AdcDeltaScanEnabled;
block[5] = AdcWindowScanEnabled;
block[6] = AdcWindowCounterInit;
block[7] = AdcOptoDelay;
if( store_write_block( STORE_ADC, ADC_STORE_SIZE, block ) == FALSE )
result = FALSE;
return result;
}
/* ------------------------------------------------------------------------ */
static BOOL adc_load_config( void )
{
BYTE block[ADC_STORE_SIZE];
BOOL result = TRUE;
/* Read the configuration from EEPROM, if any
(errors in reading this datablock are caught and
reported by functions in store.c...) */
if( store_read_block( STORE_ADC, ADC_STORE_SIZE, block ) )
{
AdcChans = block[0];
AdcConfig = block[1];
AdcCalibBeforeScan = block[2];
AdcReadoutOnChange = block[3];
AdcDeltaScanEnabled = block[4];
AdcWindowScanEnabled = block[5];
AdcWindowCounterInit = block[6];
AdcOptoDelay = block[7];
}
else
{
/* No valid parameters in EEPROM: use defaults */
AdcChans = ADC_MAX_INPUTS;
AdcConfig = ADC_DFLT_CONV_PARS;
AdcCalibBeforeScan = FALSE;
AdcReadoutOnChange = FALSE;
AdcDeltaScanEnabled = TRUE;
AdcWindowScanEnabled = FALSE;
AdcWindowCounterInit = 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -