пятница, 5 апреля 2013 г.

Программирование АЦП в C

Для обеспечения максимальной скорости преобразования, считывание из АЦП необходимо осуществлять по прерыванию готовности данных. Если же необходимо запускать АЦП через определенные промежутки времени, то запуск необходимо осуществлять по прерыванию от таймера.

Для программирования АЦП рекомендую ознакомиться со следующей информацией:
В программе будем считывать напряжение на входе ADC5 (28 ножка) АЦП с потенциометра, в диапазоне от 0 до Vпит (5 В).  Считывание будет происходить от прерывания по переполнению таймера T0. Тактирование будет осуществляться от внутреннего генератора 8 МГц, предделитель таймера устанавливается на 1024, соответственно прерывание по переполнению генерируется примерно 30 раз в секунду. По окончании преобразования АЦП генерирует прерывание, в нем считывается значение, полученное с АЦП, преобразуется и выводится на 8 светодиодов, подключенных к порту B.
Рисунок 1 - Схема подключения

Текст программы:

#include <avr/io.h> //подключение стандартной библиотеки ввода/вывода
#include <avr/interrupt.h> //подключаем библиотеку работы с прерываниями

ISR(TIMER0_OVF_vect) //подпрограмма обработки прерывания по переполнению таймера
{
// !!!ВНИМАНИЕ!!!
// при отсутствии подпрограммы прерывания от таймера, даже если в ней ничего не делается, АЦП запускаться не будет!
}

ISR(ADC_vect) //подпрограмма обработки прерывания от АЦП
{
int a=(ADCW+1)/128; //считываем значение с АЦП и преобразуем его в значение от 0 до 8
if (a == 0) //если 0, гасим светодиоды
PORTB=0x00;
else //иначе зажигаем светодиод, соответствующий входному значению
PORTB = 1 << (a-1);
}

int main(void)
{
//SETUP
//I/O
DDRB=0xFF; //порт B как выход
//T0
TCCR0A=0x00; //обычный режим работы T0
TCCR0B=0x05; //предделитель на 1024
TIMSK0=0x01; //разрешение прерывания по переполнению
//ADC
ADMUX=0x45; //опорное напряжение - Vпит, вход ADC5
ADCSRA=0xA8; //включение АЦП, запуск от периферии, разрешение прерывания от АЦП, предделитель на 2
ADCSRB=0x04; //запуск от прерывания по переполнению таймера T0
sei(); //глобальное разрешение прерываний
while(1)
{
//любая программа
}
}

После записи программы в микроконтроллер, при повороте ручки потенциометра, будет изменяться уровень на столбике из светодиодов.