#include<p18f45k20.h>
typedef enum { LEFT2RIGHT,
RIGHT2LEFT} LEDDirections;
typedef enum {FALSE, TRUE} BOOL;
#define Switch_Pin PORTBbits.RB0
#define DetectsInARow 5
void Timer0_Init(void);
void ADC_Init(void);
unsigned char ADC_Convert(void);
unsigned char LED_Display;
void main (void)
{
LEDDirections Direction = RIGHT2LEFT;
BOOL SwitchPressed = FALSE;
LED_Display = 1; // initialize
// Init I/O
TRISD = 0b00000000; // PORTD bits 7:0 are all outputs (0)
TRISAbits.TRISA0 = 1; // TRISA0 input
INTCON2bits.RBPU = 0; // enable PORTB internal pullups
WPUBbits.WPUB0 = 1; // enable pull up on RB0
// ADCON1 is now set up in the InitADC() function.
TRISBbits.TRISB0 = 1; // PORTB bit 0 (connected to switch) is input (1)
// Init Timer0
Timer0_Init();
// Init ADC
ADC_Init();
while (1)
{
if (Direction == LEFT2RIGHT)
{
LED_Display <<= 1; // rotate display by 1 from 0 to 7
if (LED_Display == 0)
LED_Display = 1; // rotated bit out, so set bit 0
}
if (Direction == RIGHT2LEFT)
{
LED_Display >>= 1; // rotate display by 1 from 7 to 0
if (LED_Display == 0)
LED_Display = 0x80; // rotated bit out, so set bit 7
}
LATD = LED_Display; // output LED_Display value to PORTD LEDs
do
{ // poll the switch while waiting for the timer to roll over.
if (Switch_Pin == 1)
{ // look for switch released.
SwitchPressed = FALSE;
}
else if (SwitchPressed == FALSE) // && (Switch_Pin == 0) due to if-else
{ // switch was just pressed
SwitchPressed = TRUE;
// change direction
if (Direction == LEFT2RIGHT)
Direction = RIGHT2LEFT;
else
Direction = LEFT2RIGHT;
}
} while (INTCONbits.TMR0IF == 0);
// Timer expired
INTCONbits.TMR0IF = 0; // Reset Timer flag
// Take an ADC conversion and use it to set Timer0
TMR0H = ADC_Convert(); // MSB from ADC
TMR0L = 0; // LSB = 0
}
}
void Timer0_Init(void)
{
INTCONbits.TMR0IF = 0; // clear roll-over interrupt flag
T0CON = 0b00000001; // prescale 1:4 - about 1 second maximum delay.
TMR0H = 0; // clear timer - always write upper byte first
TMR0L = 0;
T0CONbits.TMR0ON = 1; // start timer
}
void ADC_Init(void)
{ // initialize the Analog-To-Digital converter.
// First, we need to make sure the AN0 pin is enabled as an analog input
// as the demo board potentiometer is connected to RA0/AN0
// Don't forget that RB0/AN12 must be digital!
ANSEL = 0; //turn off all other analog inputs
ANSELH = 0;
ANSELbits.ANS0 = 1; // turn on RA0 analog
// Sets bits VCFG1 and VCFG0 in ADCON1 so the ADC voltage reference is VSS to VDD
ADCON1 = 0;
// The ADC clock must as short as possible but still greater than the
// minimum TAD time, datasheet parameter 130. At the time this lesson was
// written TAD minimum for the PIC18F45K20 is 1.4us.
// At 1MHz clock, selecting ADCS = FOSC/2 = 500kHz. One clock period
// 1 / 500kHz = 2us, which greater than minimum required 1.4us.
// So ADCON2 bits ADCS2-0 = 000
//
// The ACQT aquisition time should take into accound the internal aquisition
// time TACQ of the ADC, datasheet paramter 130, and the settling time of
// of the application circuit connected to the ADC pin. Since the actual
// settling time of the RC circuit with the demo board potentiometer is very
// long but accuracy is not very important to this demo, we'll set ACQT2-0 to
// 20TAD = 111
//
// ADFM = 0 so we can easily read the 8 Most Significant bits from the ADRESH
// Special Function Register
ADCON2 = 0b00111000;
// Select channel 0 (AN0) to read the potentiometer voltage and turn on ADC
ADCON0 = 0b00000001;
}
unsigned char ADC_Convert(void)
{ // start an ADC conversion and return the 8 most-significant bits of the result
ADCON0bits.GO_DONE = 1; // start conversion
while (ADCON0bits.GO_DONE == 1); // wait for it to complete
return ADRESH; // return high byte of result
}