Модуль АЦП (ADC) в dsPIC. Описание модуля АЦП. Характеристики АЦП в 10-ти битном режиме работы, страница 2

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;                      //сбрасываем флаг прерывания АЦП

}