Код
#include <pic.h>
#define _XTAL_FREQ 20000000
__CONFIG (INTIO & WDTDIS & PWRTEN & MCLRDIS & BOREN & LVPDIS & UNPROTECT);
struct adc_result
{
int value; // ADC built-in functions default to 8 bit result.
int new_flag; // 1-bit falg to indicate a new (fresh) value
} adc_conversion;
void init_io()
{
// set up PORTA so RA0 is an input for the ADC, RA1-RA7 are outputs
TRISA = 0xFF; // bit 0 = output, 1 = input
// set up PORTB so RB0 is an input for the switch SW1, RB1-RB7 are outputs
TRISB = 0x00; // bit 0 = output, 1 = input
// set up remaining ports to be all outputs
PORTC = 0x00;
PORTD = 0x00;
PORTE = 0x00;
ANSEL = 0xFF;
T0CS = 0;
PSA = 0;
PS0 = PS1 = PS2 = 1;
T0IE = 1; //enable timer0 int
GIE = 1; //enable ints (global)
}
void init_adc()
{
//ADC setup
ADCON1 = 0b10000000; // bit7 = ADFM, set to 0 - left justified;
//bit 4-5 - reference voltage select, 00s are VDD and VSS
ADCON0 = 0b01000001; //ADCS1:0 = 01, Fosc/8; CHS5:2 = 0000, select AN0; GO = 1; ADON = 1;
GODONE = 1;
}
// This function will be called on a Timer0 interrupt
void interrupt int_rtcc ()
{
// channel is always set to AN0. Otherwise we might change
// it here
// Get last conversion result.
adc_conversion.value = ADRESH;
adc_conversion.new_flag = 1; // new value
// start next conversion
GODONE= 1;
/*PORTD = ~PORTD;
__delay_ms(150);*/
}
void main (void)
{
int led_bar_right = 0; // default is led bar graph starting on the left (DS0)
int switch_count = 0; // used for debouncing the switch
int bars = 0; // used to compute the number of LED "bars" to display
int temp1 = 0; // temporary working variable
int led_display = 0; // led display value
// initialize global variables
adc_conversion.value = 0;
adc_conversion.new_flag = 0;
// Set up MCU
init_io();
init_adc();
// Timer 0 runs off internal clock with 1:256 prescaler
// This means it should run over every ((256*256)/(4MHz/4)) = 65.5ms
// It will be used to start an ADC conversion.
while(1)
{
// look for a new conversion result
__delay_us(5);
if (1)
{
bars = adc_conversion.value;
adc_conversion.new_flag = 0; // reset flag
// We'll use the 3 most significant bits of the conversion result
// to determine whether to display 1 to 8 "bars" on the LED display
bars = (bars >> 5) + 1; // add one to make it 1 to 8 (vs 0 to 7)
led_display = 0; // clear display variable
for (temp1 = 0; temp1 < bars; temp1++)
{
// shift in a '1' for each bar
led_display = (led_display << 1) + 1;
}
}
// check for a switch press & debounce
if (RB0 == 0)
{ // switch is low when pressed
if (switch_count < 8)
{ // increment the count on all consecutive checks where switch is pressed
// to a max of 8
switch_count ++;
// if we've seen 8 consecutive checks where the switch is pressed
// it's considered a valid switch press. Reverse the bar graph
if (switch_count == 8)
{
led_bar_right = ~led_bar_right;
}
}
}
else
{ // anytime switch is detected as not pressed, reset the count
switch_count = 0;
}
// update display
if (led_bar_right == 0)
{ // from left
PORTD = led_display;
}
else
{ // from right
// we have to shift it so it displays 1-8 bars. Just complementing
// would display 0-7.
PORTD = ~(led_display >> 1);
}
}
/*
while (1)
{
if (GODONE == 0)
{
PORTD = 0;
for ( int i=0; i= (ADRESH >> 5); i++)
{
PORTD = ( PORTD << 1 ) + 1;
}
GODONE = 1;
}
} */
}
#define _XTAL_FREQ 20000000
__CONFIG (INTIO & WDTDIS & PWRTEN & MCLRDIS & BOREN & LVPDIS & UNPROTECT);
struct adc_result
{
int value; // ADC built-in functions default to 8 bit result.
int new_flag; // 1-bit falg to indicate a new (fresh) value
} adc_conversion;
void init_io()
{
// set up PORTA so RA0 is an input for the ADC, RA1-RA7 are outputs
TRISA = 0xFF; // bit 0 = output, 1 = input
// set up PORTB so RB0 is an input for the switch SW1, RB1-RB7 are outputs
TRISB = 0x00; // bit 0 = output, 1 = input
// set up remaining ports to be all outputs
PORTC = 0x00;
PORTD = 0x00;
PORTE = 0x00;
ANSEL = 0xFF;
T0CS = 0;
PSA = 0;
PS0 = PS1 = PS2 = 1;
T0IE = 1; //enable timer0 int
GIE = 1; //enable ints (global)
}
void init_adc()
{
//ADC setup
ADCON1 = 0b10000000; // bit7 = ADFM, set to 0 - left justified;
//bit 4-5 - reference voltage select, 00s are VDD and VSS
ADCON0 = 0b01000001; //ADCS1:0 = 01, Fosc/8; CHS5:2 = 0000, select AN0; GO = 1; ADON = 1;
GODONE = 1;
}
// This function will be called on a Timer0 interrupt
void interrupt int_rtcc ()
{
// channel is always set to AN0. Otherwise we might change
// it here
// Get last conversion result.
adc_conversion.value = ADRESH;
adc_conversion.new_flag = 1; // new value
// start next conversion
GODONE= 1;
/*PORTD = ~PORTD;
__delay_ms(150);*/
}
void main (void)
{
int led_bar_right = 0; // default is led bar graph starting on the left (DS0)
int switch_count = 0; // used for debouncing the switch
int bars = 0; // used to compute the number of LED "bars" to display
int temp1 = 0; // temporary working variable
int led_display = 0; // led display value
// initialize global variables
adc_conversion.value = 0;
adc_conversion.new_flag = 0;
// Set up MCU
init_io();
init_adc();
// Timer 0 runs off internal clock with 1:256 prescaler
// This means it should run over every ((256*256)/(4MHz/4)) = 65.5ms
// It will be used to start an ADC conversion.
while(1)
{
// look for a new conversion result
__delay_us(5);
if (1)
{
bars = adc_conversion.value;
adc_conversion.new_flag = 0; // reset flag
// We'll use the 3 most significant bits of the conversion result
// to determine whether to display 1 to 8 "bars" on the LED display
bars = (bars >> 5) + 1; // add one to make it 1 to 8 (vs 0 to 7)
led_display = 0; // clear display variable
for (temp1 = 0; temp1 < bars; temp1++)
{
// shift in a '1' for each bar
led_display = (led_display << 1) + 1;
}
}
// check for a switch press & debounce
if (RB0 == 0)
{ // switch is low when pressed
if (switch_count < 8)
{ // increment the count on all consecutive checks where switch is pressed
// to a max of 8
switch_count ++;
// if we've seen 8 consecutive checks where the switch is pressed
// it's considered a valid switch press. Reverse the bar graph
if (switch_count == 8)
{
led_bar_right = ~led_bar_right;
}
}
}
else
{ // anytime switch is detected as not pressed, reset the count
switch_count = 0;
}
// update display
if (led_bar_right == 0)
{ // from left
PORTD = led_display;
}
else
{ // from right
// we have to shift it so it displays 1-8 bars. Just complementing
// would display 0-7.
PORTD = ~(led_display >> 1);
}
}
/*
while (1)
{
if (GODONE == 0)
{
PORTD = 0;
for ( int i=0; i= (ADRESH >> 5); i++)
{
PORTD = ( PORTD << 1 ) + 1;
}
GODONE = 1;
}
} */
}
И "заодно" вопросик - какой смысл в этом примере использовать прерывание? Почему не запускать новое преобразование по окончанию предыдущего (ну понятно, со всеми задержками необходимыми)?