CHPS – Выбор каналов, через которые будут осуществляться преобразования. Как уже ранее отмечалось, в контроллере есть 4 канала (фиксатора), так вот с помощью данного бита можно определить какие будем использовать, а какие не будем. Кстати, данный бит актуален только для 10-ти битного режима, так как при 12-ти битном режиме преобразование происходит однозначно через CH0.
1x – Преобразовывать с CH0, CH1, CH2 и CH3
01 – Преобразовывать с CH0 и CH1
00 – Преобразовывать с CH0
SMPI – Бит выбора момента прерывания
1111 = прерывание после каждых 16 преобразований
1110 = прерывания после каждых 15 преобразований
………….
0001 = прерывания после каждого 2-го преобразования
0000 = прерывания после каждого преобразования
Назначение данного бита должно быть понятно, только пару слов о буфере. Буфер состоит из 16 ячеек. Соответственно можно разрешить АЦП преобразовать входные значения и размещать их в буфер, при этом не отвлекая ядро на частые обработки прерывания АЦП. Далее, после выбранного числа преобразований происходит прерывание, в котором обрабатываются полученные значения.
BUFM – бит заполнения буфера. Ко всему прочему буфер условно разделён на две половины. Таким образом мы можем выбрать режим использования этого буфера.
1=Начать заполнения первой половины буфера до прерывания и второй после прерывания
0=Всегда начинать заполнять буфер сначала (т.е. буфер считается одним целым).
BUFS – Флаг заполнения буфера. Данный бит актуален, если буфер разбит на две области (BUFM=1)
1 = АЦП сейчас заполняет вторую половину буфера, поэтому программа может читать первую половину буфера
0 = АЦП сейчас заполняет первую половину буфера, приложение может читать вторую половину буфера.
10.3. Пример использования АЦП с внешним опорным напряжением
В примере будем делать акцент на изучения модуля АЦП, поэтому ничего лишнего, что не связано с АЦП. Поставим перед собой задачу: используя переменный резистор, формировать напряжение. Контроллер должен преобразовать данное напряжение в числовой код. Далее в зависимости от числового кода мы будем выводить уровень напряжения с помощью 4-х светодиодов.
Но чтобы задача не была очень простой, то в качестве опорного напряжения будем использовать внешний источник. Да не просто внешний, да ещё и не стандартный. Положительное опорное напряжение будет равно напряжению питания, а вот отрицательное мы зададим равное 2 В (а не 0 В как нам привычно).
Собираем схему в PROTEUS
В микроконтроллере будем использовать 10-ти битный режим АЦП, поэтому при минимальном входном напряжении мы получим значение 0, а при максимальном – 2^10 = 1023. Но для управления светодиодами нам необходимо лишь число до 4. Поэтому после преобразования мы число разделим на 256, тогда получится число не более 4. Однако в качестве операции деления мы будем использовать сдвиг. Ведь если сдвинуть число вправо, то это тоже самое, что и разделить на 2. Нам необходимо сдвинуть число 8 раз.
#include "p33Fxxxx.h" // библиотека DsPIC
_FOSCSEL(0x02); // настраиваем биты конфигурации
_FOSC(0xE2);
unsigned int pot=0; // состояние резистора
unsigned int pot_old=0; // старое состояние резистора
int main(void) // точка входа в программу
{
PORTB=0;
LATB=0; // к этому порту подключены светодиоды
TRISB=0; // настраиваем порт на выход
AD1PCFGL=0b011111111; // настраиваем AN8 как аналоговый вход
AD1CON2bits.VCFG=0b011; // внешнее опорное напряжение
AD1CON2bits.CHPS=0b00; // Всё преобразование через канал CH0
AD1CON1bits.SSRC=0b111; // внутренний источник запуска преобразования
AD1CON1bits.ASAM=1; // Автоматическое преобразование
AD1CON3bits.ADRC = 0; // Для тактирования АЦП используем частоту ядра
AD1CON2bits.SMPI =0b0000; // прерывания после каждой выборки
AD1CON3bits.SAMC = 0b11111; //выборка через 31Tad
AD1CON3bits.ADCS=0b11111111; //Tad = 256*Tcy
AD1CHS0bits.CH0SA = 8; // Положительный сигнал берём с канала AN8
AD1CHS0bits.CH0NA = 0; // отрицательный сигнал берём с VrefAD1CON1bits.FORM=0b00; //результат беззнаковый сдвинутый вправо
_AD1IF=0; // сбрасываем флаг прерывания АЦП
_AD1IP=1; // устанавливаем приоритет прерывания
_AD1IE=1; // Разрешаем прерывания по АЦП
AD1CON1bits.ADON=1; // Включаем модуль АЦП
AD1CON1bits.SAMP = 1; // Запускаем преобразование
while(1) // бесконечный цикл
{
if (pot != pot_old) // ...чтобы не повторяться (для PROTEUSA)
{
pot_old=pot; // текущие данные по АЦП - устарели
_RB3=0; // гасим все светодиоды
_RB2=0;
_RB1=0;
_RB0=0;
switch (pot) // зажигаем те светодиоды
{ // которые нужно
case 4: _RB0=1; // здесь заведомо не используются
case 3: _RB1=1; // операторы break;
case 2: _RB2=1; // чем больше цифра, тем больше
case 1: _RB3=1; // светодиодов в итоге будут отображены
}
}
} // while(1)
}
// прерывание АЦП
void __attribute__((__interrupt__,auto_psv)) _ADC1Interrupt(void)
{
pot= (ADC1BUF0 + 1) >> 8; // получаем из буфера значение
// и преобразовываем его
_AD1IF = 0; //сбрасываем флаг прерывания АЦП
}
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.