Na nete som nasiel jednu schemu ale nebol k nej kod v HEXe alebo ASM iba daco podobne C.
Kód: Vybrat vše
/****************************************************************************
BCHAR18.C
This is a battery characterizer for NiMH and NiCD cells.
Four 5V ADC inputs (1.2V cells) and one 8V input (3.6 or 4.8V cells) collect samples.
Control and display is done via two pushbuttons and an LCD display.
Menus and results are viewed on the display.
WORKING CODE
Next:
put in overvoltage sense
---------
+5--20-|Vdd |
+5---1-|Mclr |
Gnd---8-|Vss |
Gnd--19-|Vss |
4MHz--10-|Xtal |
4MHz---9-|Xtal |
| |
| |
SOCKET 1 --2-|AN0 B4|-24----load 0 FET gate
SOCKET 2 --3-|AN1 B3|-24----load 1 FET gate
SOCKET 3 --4-|AN2 B2|-23----load 2 FET gate
SOCKET 4 --5-|AN3 B1|-22----load 3 FET gate
SOCKET 5 --7-|AN4 B0|-21----load 4 FET gate
| |
SW 1 ----28-|B7 |
| |
| | ---------
| C2|-13--11-|D4 |
| C3|-14--12-|D5 |
| C5|-16--13-|D6 |
| C4|-15--14-|D7 |
| | | |-3--20K pot (contrast)
| C1|-12---6-|EN |
| C0|-11---4-|RS |
| | | |
| | +5-2-| |
| | Gnd-1-| |
| 18F252 | Gnd-5-| |
| | | DISPLAY |
--------- ---------
*/
#include < 18f252.h >
#device *=16 ADC=10 /* allow RAM addresses over 255 */
#include < jonsinc.h >
#fuses XT, NOPROTECT, NOOSCSEN, BROWNOUT, NOWDT, BORV20, PUT, NOSTVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOWRTB
//=============================================================
// crystal frequency (Hz)
#define CRYSTAL_FREQ 4000000
// actual power supply voltage (volts)
#define VDD 5.02
// cell nominal voltage (volts)
#define CELL_NOM_VOLTAGE 1.2
// voltage at which mAh accumlation stops (volts)
#define CUTOFF_VOLTAGE 1.0
// actual load resistances (ohms)
#define LOAD_0_OHMS 4.9
#define LOAD_1_OHMS 4.9
#define LOAD_2_OHMS 4.9
#define LOAD_3_OHMS 4.9
#define LOAD_4_OHMS 19.5
// actual FET RDS(on) resistance (ohms)
#define FET_RDS_OHMS 0.17
// actual scaling resistors R1 and R2 for channel 5 (ohms)
#define R1 5350
#define R2 10220
// display time for logo screens (normally 750 mS)
#define LOGO_TIME 750
// wait time for which voltage is displayed after a cell is inserted into a socket (seconds)
#define INITIAL_DELAY 2
// wait time after which display goes into rolling status mode (seconds)
#define STATUS_DELAY 10
// screen cycle time when in rolling status mode (seconds)
#define SCREEN_CYCLE_DELAY 2
// screen cycle time when in cell detail mode (mS)
#define DETAIL_CYCLE_DELAY 1500
// restart IRQ timer at adjusted value for 1-second accuracy (0-255, higher makes shorter IRQ tick)
#define IRQ_RESTART_TICK 3
// time at cutoff voltage required to end test (seconds, normally 60)
#define AUTOSTOP_TIME 60
// button time after which unit will display cell details (31mS interrupt counts, normally 16, ~= 0.5 second)
#define BUTTON_DETAIL_TIME 16
// button time after which unit will reset (31mS interrupt counts, normally 128, ~= 4 seconds)
#define BUTTON_RESET_TIME 128
// round to nearest 10's or 100's
#define ROUNDNUM 100
// socket definitions
#define SOCKET_1 0
#define SOCKET_5 4
// overvoltage definitions
#define CH_1_4_OVERVOLTAGE 2.0
#define CH_5_OVERVOLTAGE 6.0
//=============================================================
// LCD STUFF
#define LCD_D0 PIN_C2
#define LCD_D1 PIN_C3
#define LCD_D2 PIN_C5
#define LCD_D3 PIN_C4
#define LCD_EN PIN_C1
#define LCD_RS PIN_C0
#define LOAD_0 PIN_B4
#define LOAD_1 PIN_B3
#define LOAD_2 PIN_B2
#define LOAD_3 PIN_B1
#define LOAD_4 PIN_B0
#define BUTTON PIN_B7
#define OHM_SYM 0xF4
#define FIRST_LINE 0
#define CLEAR_DISP 0x01
#define CELL_STATE_READY 'R'
#define CELL_STATE_TEST 'T'
#define CELL_STATE_DONE 'D'
#define FMULT ( float ) R1 / ( float ) ( R1 + R2 )
// sample interval is normally 60 seconds
#define SAMPLE_INTERVAL_SEC 60
#use delay ( clock=CRYSTAL_FREQ )
#use standard_io ( A )
#use standard_io ( B )
#use standard_io ( C )
separate void DelayMs ( long cDelay ); // prototype statements
separate long Round ( float fNum, int cNearest );
float ReadAdc ( unsigned int cChannel );
void LoadControl ( char cChannel, char cState );
void LCD_Init ( void );
void LCD_SetPosition ( unsigned int cX );
void LCD_PutChar ( unsigned int cX );
void LCD_PutCmd ( unsigned int cX );
void LCD_PulseEnable ( void );
void LCD_SetData ( unsigned int cX );
static char cCellDetailWanted, cSwitchCount, cInitialDelayCount;
static char cInterruptCount1s, cInterruptScreenCycleCount;
static long iInterruptStatusCount, iRunMinutes [ 5 ];
static char cSocket, cSocketDisp, cY, cSkip, cStatusMode;
static char cLogging [ 5 ], cAutoStopCount [ 5 ], cCellCount [ 5 ];
static char cSampleCount [ 5 ], cCellPresent [ 5 ];
static char cSocketState [ 5 ], cSampleFlag [ 5 ], cIntResCount [ 5 ];
static float fIntRes [ 5 ], fLoadRes [ 5 ], fAccumMa [ 5 ];
static float fCutoffVoltage [ 5 ], fMultiplier [ 5 ], fOverVoltage [ 5 ];
static float fStartVoltageUnloaded [ 5 ], fStartVoltageLoaded [ 5 ];
static float fPresentVoltage [ 5 ];
//************************************************************************
#int_timer0
void TimerInterrupt ( void ) // 32.768mS tic @ 4MHz, ~31 interrupts per second
{
// ONE-SECOND TICK
if ( cInterruptCount1s++ >= 31 ) // if one second yet
{
cInterruptCount1s = 0;
for ( cY = SOCKET_1; cY <= SOCKET_5; cY++ )
{
cAutoStopCount [ cY ]++;
if ( cLogging [ cY ] == YES )
{
if ( cSampleCount [ cY ]++ >= SAMPLE_INTERVAL_SEC - 1 ) // if sample time yet
{
iRunMinutes [ cY ]++; // accumulate minutes
cSampleFlag [ cY ] = ON; // signal time to sample
cSampleCount[ cY ] = 0; // start count over
}
}
}
}
// INITIAL DELAY TIMER (delay during which voltage is displayed)
if ( cInitialDelayCount < INITIAL_DELAY * 32 ) // hold at end of delay
{
cInitialDelayCount++; // otherwise increment
}
// STATUS DELAY (time after which in rolling status display mode)
if ( iInterruptStatusCount >= ( STATUS_DELAY * 32 ) ) // if ready to change screen yet
{
cStatusMode = YES;
}
else
{
cStatusMode = NO;
iInterruptStatusCount++;
}
// SCREEN CYCLE (screen cycle rate once in status display mode)
if ( cInterruptScreenCycleCount++ >= ( SCREEN_CYCLE_DELAY * 32 ) ) // if ready to change screen yet
{
if ( ( cStatusMode == YES ) && ( cCellDetailWanted == NO ) ) // if ready to change screen yet
{
cSocketDisp++; // point to next cell
if ( cSocketDisp > SOCKET_5 ) // if last socket
{
cSocketDisp = SOCKET_1; // wrap to first socket
}
}
cInterruptScreenCycleCount = 0;
}
// SWITCH HANDLER (momentary cycles which cell, hold one second displays cell details, hold four seconds resets)
if ( input ( BUTTON ) == LOW ) // if button is low
{
if ( cSwitchCount < 128 ) // hold at 128 (~4 seconds)
{
cSwitchCount++; // otherwise increment
}
}
else
{
if ( cSwitchCount > 2 ) // filter out glitches
{
// If button is held for a really long time, do cold reset
if ( cSwitchCount == BUTTON_RESET_TIME )
{
reset_cpu();
}
// If button is held for shorter time
if ( ( cSwitchCount > BUTTON_DETAIL_TIME ) && ( cSwitchCount < BUTTON_RESET_TIME ) )
{
cCellDetailWanted = YES; // signal that switch was pressed
cInterruptScreenCycleCount = 0;
iInterruptStatusCount = 0; // stop status cycling
cSkip = NO;
}
// If button press is pressed only momentarily
if ( cSwitchCount <= BUTTON_DETAIL_TIME )
{
cSocketDisp++; // point to next cell
if ( cSocketDisp > SOCKET_5 ) // if last socket
{
cSocketDisp = SOCKET_1; // wrap to first socket
}
cSkip = YES;
cCellDetailWanted = NO;
}
cInterruptScreenCycleCount = 0;
iInterruptStatusCount = 0; // stop status cycling
cSwitchCount = 0; // reset
}
else
{
cSwitchCount = 0; // switch was released prematurely, restart count
}
}
// Adjust timing
set_rtcc ( IRQ_RESTART_TICK ); // restart at adjusted value for 1-second accuracy (higher to make shorter tick)
}
//*****************************************************************
void main ( void )
{
char cX;
long iX;
float fV, fX, fVload, fLastV;
cSwitchCount = 0;
cSocket = SOCKET_1;
cSocketDisp = SOCKET_1;
setup_timer_0 ( RTCC_INTERNAL | RTCC_DIV_128 | RTCC_8_BIT ); // ~32mS timer wrap
setup_adc_ports ( ALL_ANALOG ); // these three statements set up the ADC
setup_adc ( ADC_CLOCK_INTERNAL ); // clock source
enable_interrupts ( INT_RTCC ); // turn on timer interrupt
enable_interrupts ( GLOBAL ); // enable interrupts
output_float ( PIN_A4 ); // because Socket#5 was wrongly connected to Pin RA4 as well as Pin RA5 (AN4) in "bc01" circuit board
cCellDetailWanted = NO;
iInterruptStatusCount = 0;
cInitialDelayCount = 0;
cSkip = NO;
for ( cX = SOCKET_1; cX <= SOCKET_5; cX++ ) // preset
{
cSocketState [ cX ] = CELL_STATE_READY;
LoadControl ( cX, OFF );
cLogging [ cX ] = NO;
cSampleFlag [ cX ] = OFF;
cCellPresent [ cX ] = NO;
cIntResCount [ cX ] = 0;
iRunMinutes [ cSocket ] = 0;
}
fLoadRes [ 0 ] = LOAD_0_OHMS + FET_RDS_OHMS;
fLoadRes [ 1 ] = LOAD_1_OHMS + FET_RDS_OHMS;
fLoadRes [ 2 ] = LOAD_2_OHMS + FET_RDS_OHMS;
fLoadRes [ 3 ] = LOAD_3_OHMS + FET_RDS_OHMS;
fLoadRes [ 4 ] = LOAD_4_OHMS + FET_RDS_OHMS;
fOverVoltage [ 0 ] = CH_1_4_OVERVOLTAGE;
fOverVoltage [ 1 ] = CH_1_4_OVERVOLTAGE;
fOverVoltage [ 2 ] = CH_1_4_OVERVOLTAGE;
fOverVoltage [ 3 ] = CH_1_4_OVERVOLTAGE;
fOverVoltage [ 4 ] = CH_5_OVERVOLTAGE;
fMultiplier [ 0 ] = 1.0;
fMultiplier [ 1 ] = 1.0;
fMultiplier [ 2 ] = 1.0;
fMultiplier [ 3 ] = 1.0;
fMultiplier [ 4 ] = FMULT;
LCD_Init();
LCD_PutCmd ( CLEAR_DISP );
LCD_SetPosition ( FIRST_LINE );
printf ( LCD_PutChar, " NiCd & NiMH " );
delay_ms ( LOGO_TIME );
LCD_SetPosition ( FIRST_LINE );
printf ( LCD_PutChar, " BATTERY " );
delay_ms ( LOGO_TIME );
LCD_SetPosition ( FIRST_LINE );
printf ( LCD_PutChar, " CHARACTERIZER " );
delay_ms ( LOGO_TIME );
LCD_SetPosition ( FIRST_LINE );
printf ( LCD_PutChar, "Jon Fick 030405" );
delay_ms ( LOGO_TIME );
LCD_SetPosition ( FIRST_LINE );
printf ( LCD_PutChar, "PressShort=next " );
delay_ms ( LOGO_TIME * 2 );
LCD_SetPosition ( FIRST_LINE );
printf ( LCD_PutChar, "PressLong=detail" );
delay_ms ( LOGO_TIME * 2 );
LCD_SetPosition ( FIRST_LINE );
printf ( LCD_PutChar, " #1 #2 #3 #4 " );
delay_ms ( LOGO_TIME * 2 );
LCD_SetPosition ( FIRST_LINE );
printf ( LCD_PutChar, "#5 is external " );
delay_ms ( LOGO_TIME * 2 );
LCD_PutCmd ( CLEAR_DISP );
while ( TRUE ) // do forever
{
cSkip = NO; // reset
// CALCULATION SECTION, USES CELL POINTER "cSocket" ///////////////////////////////
for ( cSocket = SOCKET_1; cSocket <= SOCKET_5; cSocket++ )
{
// read cell voltage
fV = ReadAdc( cSocket ); // read voltage at this cell
// if ( fVopen > fOverVoltage [ cSocket ] )
// {
// cCellPresent [ cSocket ] = NO;
// printf ( LCD_PutChar, "#%u Overvoltage!!", cSocketNum );
// }
if ( fV <= 0.4 ) // check if this socket is empty
{
cCellPresent [ cSocket ] = NO;
cSocketState [ cSocket ] = CELL_STATE_READY;
}
else // if socket is not empty
{
fPresentVoltage [ cSocket ] = fV; // save present measurement
switch ( cSocketState [ cSocket ] )
{
case CELL_STATE_READY:
{
if ( cCellPresent [ cSocket ] == NO ) // if socket was previously empty
{
// do all the preliminary stuff one time before changing to TEST state
// now that the voltage is greater than empty socket,
// read cell again to ensure voltage is stable after a delay
fLastV = 0; // restart
for ( cX = 0; cX < 10; cX++ )
{
fV = ReadAdc( cSocket ); // read voltage at this cell
if ( ( fV < fLastV - 0.010 ) || ( fV > fLastV + 0.010 ) )
{
cX = 0; // restart count
}
fLastV = fV; // update
DelayMs ( 10 );
}
// determine number of cells in socket
fStartVoltageUnloaded [ cSocket ] = fV; // save unloaded start voltage
cX = ( char ) ( fV / CELL_NOM_VOLTAGE ); // calculate number of cells
if ( cX < 1 )
{
cX = 1; // one cell minimum, just in case so cutoff isn't ever zero volts
}
cCellCount [ cSocket ] = cX; // save count
// calculate cutoff voltage
fCutoffVoltage [ cSocket ] = ( ( float ) ( cCellcount [ cSocket ] ) ) * CUTOFF_VOLTAGE; // calculate cutoff voltage based on the number of cells
// measure internal resistance
LoadControl ( cSocket, ON ); // load cell
DelayMs ( 100 ); // stabilize time
fVload = ReadAdc( cSocket ); // read ADC
LoadControl ( cSocket, OFF ); // unload cell
fStartVoltageLoaded [ cSocket ] = fVLoad; // save loaded start voltage
fIntRes [ cSocket ] = ( fV - fVload ) / ( fVload / fLoadRes [ cSocket ] ); // calc R and store it
// initialize test
cSampleCount [ cSocket ] = 0; // reset
fAccumMa [ cSocket ] = 0; // reset accumulated mAh
cAutoStopCount [ cSocket ] = 0; // reset
cLogging [ cSocket ] = YES; // allow interrupt to flag accumulating
iInterruptStatusCount = 0; // stop rolling status display for awhile
cSocketDisp = cSocket; // display this cell immediately
cInitialDelayCount = 0; // initialize delay for voltage display
iRunMinutes [ cSocket ] = 0; // reset test duration
cSocketState [ cSocket ] = CELL_STATE_TEST; // put in TEST state
}
break;
}
case CELL_STATE_TEST:
{
if ( fV <= fCutoffVoltage [ cSocket ] ) // check if below cutoff voltage yet
{
// finish up, change state to DONE
if ( cAutoStopCount [ cSocket ] >= AUTOSTOP_TIME ) // need this many seconds in a row to end
{
cLogging [ cSocket ] = NO; // stop interrupt from flagging accumulating
LoadControl ( cSocket, OFF ); // unload cell
cSocketState [ cSocket ] = CELL_STATE_DONE;
}
}
else // if still above autostop voltage
{
// still testing, reset stop count
cAutoStopCount [ cSocket ] = 0; // reset count
}
break;
}
}
cCellPresent [ cSocket ] = YES;
}
// is it time to sample this particular cell?
if ( cSampleFlag [ cSocket ] == ON )
{
cSampleFlag [ cSocket ] = OFF; // reset flag
fX = fV / fLoadRes [ cSocket ]; // calc mA for this sample
fAccumMa [ cSocket ] += fX; // accumulate mA
}
} // end of calculation section
// DISPLAY SECTION, USES CELL POINTER "cSocketDisp" /////////////////////////////////
LCD_SetPosition ( FIRST_LINE + 0 );
// check if any cells in any sockets at all
if ( ( cCellPresent [ 0 ] == NO ) && ( cCellPresent [ 1 ] == NO ) && ( cCellPresent [ 2 ] == NO ) && ( cCellPresent [ 3 ] == NO ) && ( cCellPresent [ 4 ] == NO ) )
{
printf ( LCD_PutChar, " Sockets empty " );
for ( cX = SOCKET_1; cX <= SOCKET_5; cX++ ) // preset
{
LoadControl ( cX, OFF );
}
}
else // some cells are in sockets
{
for ( cX = 0; cX <= 5; cX++ )
{
if ( cCellPresent [ cSocketDisp ] == NO ) // find next socket that has a cell
{
cSocketDisp++;
if ( cSocketDisp > SOCKET_5 ) // if last socket
{
cSocketDisp = SOCKET_1; // wrap to first socket
}
}
else
{
break; // found a cell, skip out
}
}
// check if detail screens are wanted
if ( cCellDetailWanted == YES )
{
while ( TRUE )
{
if ( cSkip == YES ) { break; }
// display cell number and status
printf ( LCD_PutChar, "Cell #%u: ", cSocketDisp + 1 );
if ( cSocketState [ cSocketDisp ] == CELL_STATE_TEST )
{
printf ( LCD_PutChar, "in TEST" );
}
if ( cSocketState [ cSocketDisp ] == CELL_STATE_DONE )
{
printf ( LCD_PutChar, "is DONE" );
}
DelayMs ( DETAIL_CYCLE_DELAY );
// display number of cells
if ( cSkip == YES ) { break; }
LCD_SetPosition ( FIRST_LINE + 0 );
printf ( LCD_PutChar, "Num cells: %u ", cCellCount [ cSocketDisp ] );
DelayMs ( DETAIL_CYCLE_DELAY );
// display initial unloaded voltage
if ( cSkip == YES ) { break; }
LCD_SetPosition ( FIRST_LINE + 0 );
printf ( LCD_PutChar, "Init Vopen: %01.2f", fStartVoltageUnloaded [ cSocketDisp ] );
DelayMs ( DETAIL_CYCLE_DELAY );
// display present or final loaded voltage
if ( cSkip == YES ) { break; }
if ( cSocketState [ cSocketDisp ] == CELL_STATE_TEST )
{
LCD_SetPosition ( FIRST_LINE + 0 );
printf ( LCD_PutChar, "Vloaded: %01.2f ", fPresentVoltage [ cSocketDisp ] );
DelayMs ( DETAIL_CYCLE_DELAY );
LCD_SetPosition ( FIRST_LINE + 0 );
printf ( LCD_PutChar, "Int Res: %01.2f%c ", fIntRes [ cSocketDisp ], OHM_SYM );
DelayMs ( DETAIL_CYCLE_DELAY );
}
// display average mA load
if ( cSkip == YES ) { break; }
LCD_SetPosition ( FIRST_LINE + 0 );
fX = ( fPresentVoltage [ cSocketDisp ] + ( fStartVoltageLoaded [ cSocketDisp ] - fPresentVoltage [ cSocketDisp ] ) / 2 );
if ( cSocketDisp == 0 )
{
fX /= LOAD_0_OHMS;
}
if ( cSocketDisp == 1 )
{
fX /= LOAD_1_OHMS;
}
if ( cSocketDisp == 2 )
{
fX /= LOAD_2_OHMS;
}
if ( cSocketDisp == 3 )
{
fX /= LOAD_3_OHMS;
}
if ( cSocketDisp == 4 )
{
fX /= LOAD_4_OHMS;
}
// convert to long
printf ( LCD_PutChar, "Avg Load: %04.0fmA ", fX * 1000 );
DelayMs ( DETAIL_CYCLE_DELAY );
// display accumulated mAh
if ( cSkip == YES ) { break; }
LCD_SetPosition ( FIRST_LINE + 0 );
if ( cSocketState [ cSocketDisp ] == CELL_STATE_TEST )
{
printf ( LCD_PutChar, "Accum" );
}
if ( cSocketState [ cSocketDisp ] == CELL_STATE_DONE )
{
printf ( LCD_PutChar, "Final" );
}
iX = ( long ) ( fAccumMa [ cSocketDisp ] * 1000 / SAMPLE_INTERVAL_SEC );
printf ( LCD_PutChar, ": %lumAh ", iX );
DelayMs ( DETAIL_CYCLE_DELAY );
// display test time
if ( cSkip == YES ) { break; }
LCD_SetPosition ( FIRST_LINE + 0 );
printf ( LCD_PutChar, "Time %02.1f hrs ", ( float ) iRunMinutes [ cSocketDisp ] / 60 );
DelayMs ( DETAIL_CYCLE_DELAY );
iInterruptStatusCount = 0; // stop status cycling
cCellDetailWanted = NO;
break;
}
}
else
{
switch ( cSocketState [ cSocketDisp ] )
{
case CELL_STATE_TEST:
{
if ( cInitialDelayCount < INITIAL_DELAY * 32 ) // if cell was just inserted in socket
{
// display initial unloaded voltage for a short time
fV = ReadAdc( cSocketDisp ); // read voltage at this cell
printf ( LCD_PutChar, "T#%u meas: %01.2fV ", cSocketDisp + 1, fStartVoltageUnloaded [ cSocketDisp ] );
}
else
{
// display present mAh thereafter
LoadControl ( cSocketDisp, ON ); // turn load on
iX = ( long ) ( fAccumMa [ cSocketDisp ] * 1000 / SAMPLE_INTERVAL_SEC );
printf ( LCD_PutChar, "T#%u %lumAh ", cSocketDisp + 1, iX );
}
break;
}
case CELL_STATE_DONE:
{
// display result
fX = fAccumMa [ cSocketDisp ] * 1000 / SAMPLE_INTERVAL_SEC;
iX = Round ( fX, ROUNDNUM ); // store final mAh value
printf ( LCD_PutChar, "D#%u %lumAh %01.1f%c ", cSocketDisp + 1, iX, fIntRes [ cSocketDisp ], OHM_SYM );
break;
}
}
} // end of display section
}
}
}
separate void DelayMs ( long iDelay )
{
long iX;
for ( iX = 0; iX < iDelay; iX++ )
{
delay_ms ( 1 );
if ( cSkip == YES )
{
//cSkip = NO; // reset flag
break;
}
}
}
separate long Round ( float fNum, int cNearest )
{
long iM, iX;
iX = ( long ) fNum;
if ( iX >= ( long ) cNearest ) // if greater than rounding factor, otherwise return actual number
{
iM = iX % cNearest; // fractional part
iX = iX / cNearest;
if ( iM < ( cNearest / 2 ) )
{
iX = iX * cNearest; // bump down
}
else
{
iX = ( iX + 1 ) * cNearest; // bump up
}
}
return ( iX );
}
float ReadAdc ( unsigned int cChannel )
{
long iAdcVal;
char cCnt;
set_adc_channel ( cChannel );
delay_us ( 50 );
iAdcVal = 0;
for ( cCnt = 0; cCnt < 10; cCnt++ ) // average over 10 readings
{
iAdcVal += read_adc();
DelayMs ( 5 );
}
// return average of ten readings, scaled to proper range
return ( ( ( float ) iAdcVal ) / ( float ) 10 / ( float ) 1024 * ( float ) VDD / fMultiplier [ cChannel ] );
}
void LoadControl ( char cChannel, char cState )
{
switch ( cChannel )
{
case 0:
{
output_bit ( LOAD_0, cState );
break;
}
case 1:
{
output_bit ( LOAD_1, cState );
break;
}
case 2:
{
output_bit ( LOAD_2, cState );
break;
}
case 3:
{
output_bit ( LOAD_3, cState );
break;
}
case 4:
{
output_bit ( LOAD_4, cState );
break;
}
}
}
//*****************************************************************************
void LCD_Init ( void )
{
LCD_SetData ( 0x00 );
DelayMs ( 200 ); // wait enough time after Vdd rise
output_low ( LCD_RS );
LCD_SetData ( 0x03 ); // init with specific nibbles to start 4-bit mode
LCD_PulseEnable();
LCD_PulseEnable();
LCD_PulseEnable();
LCD_SetData ( 0x02 ); // set 4-bit interface
LCD_PulseEnable(); // send dual nibbles hereafter, MSN first
LCD_PutCmd ( 0x2C ); // function set (all lines, 5x7 characters)
LCD_PutCmd ( 0x0C ); // display ON, cursor off, no blink
LCD_PutCmd ( 0x01 ); // clear display
LCD_PutCmd ( 0x06 ); // entry mode set, increment
}
void LCD_SetPosition ( unsigned int cX )
{
// this subroutine works specifically for 4-bit Port A
LCD_SetData ( swap ( cX ) | 0x08 );
LCD_PulseEnable();
LCD_SetData ( swap ( cX ) );
LCD_PulseEnable();
}
void LCD_PutChar ( unsigned int cX )
{
// this subroutine works specifically for 4-bit Port A
output_high ( LCD_RS );
LCD_SetData ( swap ( cX ) ); // send high nibble
LCD_PulseEnable();
LCD_SetData ( swap ( cX ) ); // send low nibble
LCD_PulseEnable();
output_low ( LCD_RS );
}
void LCD_PutCmd ( unsigned int cX )
{
// this subroutine works specifically for 4-bit Port A
LCD_SetData ( swap ( cX ) ); // send high nibble
LCD_PulseEnable();
LCD_SetData ( swap ( cX ) ); // send low nibble
LCD_PulseEnable();
}
void LCD_PulseEnable ( void )
{
output_high ( LCD_EN );
delay_us ( 10 );
output_low ( LCD_EN );
DelayMs ( 5 );
}
void LCD_SetData ( unsigned int cX )
{
output_bit ( LCD_D0, cX & 0x01 );
output_bit ( LCD_D1, cX & 0x02 );
output_bit ( LCD_D2, cX & 0x04 );
output_bit ( LCD_D3, cX & 0x08 );
}
Diky