Демонстрация работы
CODE
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 1000000UL
#include <util/delay.h>
int ADC_data;
unsigned char i;
unsigned char d0,d1,d2,d3;
unsigned char kod_simvola[10]= //коды цифр для семисегментного индикатора
{
0b00111111, //0
0b00000110, //1
0b01011011, //2
0b01001111, //3
0b01100110, //4
0b01101101, //5
0b01111101, //6
0b00000111, //7
0b01111111, //8
0b01101111 //9
};
//=====================ВЫВОД 4-ех ЦИФР НА СЕМИСЕГМЕНТНЫЙ ИНДИКАТОР=====================
void vivod_led(unsigned char digit0,unsigned char digit1,unsigned char digit2,unsigned char digit3)
{
cli();
unsigned char razr, digit;
DDRC=0b11111111; //PORTC0:7 подключаем к сегментам индикатора
DDRB=0b00001111; //PORTB0:3 подключаем к разрядам индикатора
for(razr=0;razr<4;razr++)
{
switch (razr)
{
case 0: digit=digit0; break;
case 1: digit=digit1; break;
case 2: digit=digit2; break;
case 3: digit=digit3; break;
}
switch (digit)
{
case 0:
PORTC=kod_simvola[0]; //выводим в порт нужную цифру
break;
case 1:
PORTC=kod_simvola[1];
break;
case 2:
PORTC=kod_simvola[2];
break;
case 3:
PORTC=kod_simvola[3];
break;
case 4:
PORTC=kod_simvola[4];
break;
case 5:
PORTC=kod_simvola[5];
break;
case 6:
PORTC=kod_simvola[6];
break;
case 7:
PORTC=kod_simvola[7];
break;
case 8:
PORTC=kod_simvola[8];
break;
case 9:
PORTC=kod_simvola[9];
break;
default: //если задан некорректный символ - выводится "_"
PORTC=0b0001000;
break;
}
if (razr==0) PORTC |=0b10000000; //зажигаем точку после первого рязряда
PORTB=1<<razr; //зажигаем нужный разряд индикатора
_delay_us(500); //менее 200 мкс - падает яркость, более 5 мс - заметно мерцание
PORTB=0<<razr; //гасим разряд индикатора
}
sei();
}
int main(void)
{
DDRA=0b00000000;
int temp; //для хранения результата преобразования АЦП
//====================ИНИЦИАЛИЗАЦИЯ ТАЙМЕРА T0===================================
TCCR0=(1<<CS00) | (1<<CS01);
/*Timer/Counter Control Register
устанавливаем коэффициент делителя таймера 64*/
OCR0=156;
/*Output Compare Register
число тактов котое будет сравниватся с числом тактов таймера*/
/*TIMSK=(1<<OCIE0);
/ *Timer/Counter Interrupt Mask Register
разрешаем прерывания по совпадению значения таймера T0 и OCR0=156* /*/
TIMSK=(1<<TOIE0);
/*Timer/Counter Interrupt Mask Register
разрешаем прерывания по переполнению таймера T0*/
//======================ИНИЦИАЛИЗАЦИЯ АЦП=======================================
ADMUX=(1<<REFS0) | (1<<ADLAR);
/*ADC Multiplexer Selection Register
REFS1:0=01 - за ИОН берем Vcc контроллера (AVcc)
MUX4:0=0000 - выбераем канал для АЦП - PORTA.0
ADLAR=1 - выравнивание результата преобразования АЦП по левому краю байтов результата*/
ADCSRA=(1<<ADEN) | (1<<ADSC) | (1<<ADPS1) | (1<<ADPS2) | (1<<ADATE);// | (1<<ADIE);
/*ADC Control and Status Register A
ADEN=1 - включаем АЦП
ADSC=1 - запускаем первое преобразование АЦП, дальше само идет автоматически
ADPS2:0=110 - делитель тактовой частоты для АЦП 1 Мгц/64 = 15.625 кГц
ADATE=1 - запускаем АЦП в режиме непрерывных последовательных преобразовний одно за другим
ADIE=0 - запрещаем прерывания по окончанию преобразования АЦП*/
SFIOR &=~(1<<ADTS0) | (1<<ADTS1) | (1<<ADTS2);
/*Special FunctionIO Register
ADTS2:0=000 - преобразование идет в непрерывном режиме с момента запуска*/
sei(); //разрешаем глобальные прерывания
while(1)
{
//ADC_data=(ADCL>>6) | (ADCH<<2); //байт ADCH всегда должен читатся последним
temp=ADC_data*0.004858*1000; //0.0049 - значение напряжение на одну ступень 4.97/1023
d3=temp%10;
temp /=10;
d2=temp%10;
temp /=10;
d1=temp%10;
temp /=10;
d0=temp%10;
vivod_led(d0,d1,d2,d3);
}
}
ISR(TIMER0_OVF_vect) //обработчик прерывания по переполнению T0
{
if(i==5)
{
ADC_data=(ADCL>>6) | (ADCH<<2); //байт ADCH всегда должен читатся последним
i=0;
}
else i++;
}
#include <avr/interrupt.h>
#define F_CPU 1000000UL
#include <util/delay.h>
int ADC_data;
unsigned char i;
unsigned char d0,d1,d2,d3;
unsigned char kod_simvola[10]= //коды цифр для семисегментного индикатора
{
0b00111111, //0
0b00000110, //1
0b01011011, //2
0b01001111, //3
0b01100110, //4
0b01101101, //5
0b01111101, //6
0b00000111, //7
0b01111111, //8
0b01101111 //9
};
//=====================ВЫВОД 4-ех ЦИФР НА СЕМИСЕГМЕНТНЫЙ ИНДИКАТОР=====================
void vivod_led(unsigned char digit0,unsigned char digit1,unsigned char digit2,unsigned char digit3)
{
cli();
unsigned char razr, digit;
DDRC=0b11111111; //PORTC0:7 подключаем к сегментам индикатора
DDRB=0b00001111; //PORTB0:3 подключаем к разрядам индикатора
for(razr=0;razr<4;razr++)
{
switch (razr)
{
case 0: digit=digit0; break;
case 1: digit=digit1; break;
case 2: digit=digit2; break;
case 3: digit=digit3; break;
}
switch (digit)
{
case 0:
PORTC=kod_simvola[0]; //выводим в порт нужную цифру
break;
case 1:
PORTC=kod_simvola[1];
break;
case 2:
PORTC=kod_simvola[2];
break;
case 3:
PORTC=kod_simvola[3];
break;
case 4:
PORTC=kod_simvola[4];
break;
case 5:
PORTC=kod_simvola[5];
break;
case 6:
PORTC=kod_simvola[6];
break;
case 7:
PORTC=kod_simvola[7];
break;
case 8:
PORTC=kod_simvola[8];
break;
case 9:
PORTC=kod_simvola[9];
break;
default: //если задан некорректный символ - выводится "_"
PORTC=0b0001000;
break;
}
if (razr==0) PORTC |=0b10000000; //зажигаем точку после первого рязряда
PORTB=1<<razr; //зажигаем нужный разряд индикатора
_delay_us(500); //менее 200 мкс - падает яркость, более 5 мс - заметно мерцание
PORTB=0<<razr; //гасим разряд индикатора
}
sei();
}
int main(void)
{
DDRA=0b00000000;
int temp; //для хранения результата преобразования АЦП
//====================ИНИЦИАЛИЗАЦИЯ ТАЙМЕРА T0===================================
TCCR0=(1<<CS00) | (1<<CS01);
/*Timer/Counter Control Register
устанавливаем коэффициент делителя таймера 64*/
OCR0=156;
/*Output Compare Register
число тактов котое будет сравниватся с числом тактов таймера*/
/*TIMSK=(1<<OCIE0);
/ *Timer/Counter Interrupt Mask Register
разрешаем прерывания по совпадению значения таймера T0 и OCR0=156* /*/
TIMSK=(1<<TOIE0);
/*Timer/Counter Interrupt Mask Register
разрешаем прерывания по переполнению таймера T0*/
//======================ИНИЦИАЛИЗАЦИЯ АЦП=======================================
ADMUX=(1<<REFS0) | (1<<ADLAR);
/*ADC Multiplexer Selection Register
REFS1:0=01 - за ИОН берем Vcc контроллера (AVcc)
MUX4:0=0000 - выбераем канал для АЦП - PORTA.0
ADLAR=1 - выравнивание результата преобразования АЦП по левому краю байтов результата*/
ADCSRA=(1<<ADEN) | (1<<ADSC) | (1<<ADPS1) | (1<<ADPS2) | (1<<ADATE);// | (1<<ADIE);
/*ADC Control and Status Register A
ADEN=1 - включаем АЦП
ADSC=1 - запускаем первое преобразование АЦП, дальше само идет автоматически
ADPS2:0=110 - делитель тактовой частоты для АЦП 1 Мгц/64 = 15.625 кГц
ADATE=1 - запускаем АЦП в режиме непрерывных последовательных преобразовний одно за другим
ADIE=0 - запрещаем прерывания по окончанию преобразования АЦП*/
SFIOR &=~(1<<ADTS0) | (1<<ADTS1) | (1<<ADTS2);
/*Special FunctionIO Register
ADTS2:0=000 - преобразование идет в непрерывном режиме с момента запуска*/
sei(); //разрешаем глобальные прерывания
while(1)
{
//ADC_data=(ADCL>>6) | (ADCH<<2); //байт ADCH всегда должен читатся последним
temp=ADC_data*0.004858*1000; //0.0049 - значение напряжение на одну ступень 4.97/1023
d3=temp%10;
temp /=10;
d2=temp%10;
temp /=10;
d1=temp%10;
temp /=10;
d0=temp%10;
vivod_led(d0,d1,d2,d3);
}
}
ISR(TIMER0_OVF_vect) //обработчик прерывания по переполнению T0
{
if(i==5)
{
ADC_data=(ADCL>>6) | (ADCH<<2); //байт ADCH всегда должен читатся последним
i=0;
}
else i++;
}