Программа работы АЦП в PIC16 • Все своими руками






Программа работы АЦП в PIC16

Модуль аналого-цифрового преобразования PIC микроконтроллеров

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

     Пересмотр алгоритма коснулся всех подпрограмм, но, на мой взгляд, самые интересные изменения коснулись подпрограммы работы модуля АЦП. Когда начинал освоение программирования пикконтроллеров, скачал из Сети свободно распространяемую программу работы этого модуля. К сожалению, я уже не помню первоисточника. Изначальный текст программы показан на скриншоте — текст 1. Так как статья предназначается для начинающих программистов, то давайте сначала разберемся с этим текстом.

Программа работы АЦП, text

     После того, как мы определили в регистре ADCON0 вывод порта A, через который будем производить оцифровку входного сигнала, выбрали источник тактового сигнала, и подключили модуль АЦП, программа будет находиться в режиме ожидания заряда конденсатора в течение 15 мксек. Об этом говорит команда CALL MKS15. Программа самой задержки в файле не показана. Далее поднимаем флаг начала преобразования АЦП, т.е. записываем «1» в разряд GO_DONE в регистре ADCON0. С этого момента модуль начинает оцифровывать аналоговый сигнал на входе RA0 микроконтроллера. Все это время программа зацикливается на проверке этого флага, команда btfsc ADCO0,GO_DONE. И как только флаг опустится, что свидетельствует об окончании преобразования, программа проигнорирует команду goto $-1 и перейдет к выполнению команд по считыванию результата преобразования с одновременным сдвигом содержимого регистров ADRESL и ADRESH вправо и переноса полученных данных во временные регистры REZ_L и REZ_H. Одноразовый сдвиг вправо, это не что иное, как деление значения регистров на 2. Почему делим и почему на два. Так как преобразователь у нас десятиразрядный, т.е. максимальное число преобразования будет равно в двоичном коде 11 1111 1111, а в десятичной системе счисления — 1023. Значит, если в качестве опорного напряжения для АЦП использовать источник опорного напряжения — ИОН с напряжением 10,23 вольта, то самый бы младший разряд двоичного числа соответствовал 0,01 вольта. Но такое напряжение нельзя подавать на выводы микроконтроллера. Из этого положения есть простой выход. Разделим результат преобразования на 2, получим 1023 : 2 = 511,5, а в качестве опорного напряжения будем использовать напряжение питания микроконтроллера величиной 5,115 вольта. Благо, сконфигурировав микроконтроллер соответствующим образом, это возможно. Но это не самый лучший способ получения оцифрованного сигнала, хотя и самый простой.

Точность оцифровки намного повышается, если использовать отдельный специализированный источник опорного напряжения — ИОН.
И так, по команде BSF bank_1, (bank_1 — это замена текста и соответствует STATUS,PR0), переходим в первый банк, так как младший регистр результата преобразования находится в нем. Сдвигая содержимое этого регистра, делим его на 2 и одновременно запоминаем результат деления в рабочем регистре WREG. Запомнив результат, возвращаемся в нулевой банк и переписываем данные из WREG во вспомогательный регистр REZ_L — команда MOVWF REZ_L. После выполнения инструкции сдвига вправо младший разряд регистра ADRESL переместился в регистр STATUS разряд С известный, как флаг заема /переноса, и теперь, при сдвиге регистра ADRESH, это значение будет вдвинуто в старший разряд старшего байта ADRESH. Но нам этого не нужно, поэтому мы инструкцией BCF STATUS,C мы обнуляем значение этого бита. Теперь сдвигаем старший байт результата — RRF ADRESH,w. Запоминаем во WREG. При данном сдвиге в бит С, регистра STATUS, запишется значение младшего бита старшего байта результата оцифровки. Далее определяем его значение и записываем его в старший бит младшего байта результата. Этой программой, не соизволяя над ней задуматься, я и пользовался до сего времени, пока жизнь не заставила. Я не претендую на оригинальность этой программы, но про себя я очень рад. И так текст оптимизированной программы показан как «Текст 2». В данном случае, после окончания работы модуля АЦП, мы сначала сдвигаем старший байт результата и запоминаем в WREG, при этом значение младшего бита, выдвинутого бита, переходит в регистр STATUS, на место бита С — флага заема/переноса. Далее следует команда, выполнение которой не влияет на бит С — переход в банк 1. Теперь сдвигаем младший байт, одновременно значение бита С регистра STATUS принимает старший — седьмой бит младшего байта. Запоминаем новое значение в рабочем регистре WREG, возвращаемся в нулевой банк и переписываем полученные данные во вспомогательный регистр REZ_L. Все. И так выигрыш в шесть команд. А учитывая, что число преобразований, для увеличения достоверности, может быть и 256 и 1023, то это экономия и места и времени. Удачи всем! К.В.Ю.

Скачать файлы


Просмотров:5 287
Один комментарий




Один комментарий к “Программа работы АЦП в PIC16”

  • Евгений
    13 декабря, 2020, 15:33

    Здравствуйте, уже несколько дней подряд читаю статьи на Вашем сайте.

    Отличный материал, очень много полезного почерпнул.

    Нравится Ваш подход. Есть очень большое замечание к тексту 2 программы. Перед сдвигом вправо вы не сбрасываете бит переполнения/заема STATUS,C. Это очень критично. В зависимости от текста программы MKS15 могут быть нехорошие варианты.

    Если до сдвига он был сброшен, т.е. 0, то все отлично будет работать.

    Но с высокой вероятностью он может оказаться установленным. Вот тут и начнутся проблемы. Вот пример, ADRESH = b'00001010'(.10) C=0, сдвиг вправо, WREG = b'00000101'(.5) Все отлично. Но если С=1 до сдвига, то после сдвига получим WREG = b'10000101'(.133). При накапливании 16 измерений, например, и усреднении будут неприятности. Таким образом команда"BCF STATUS,C" перед «RRF ADRESH,W» необходима для отказоустойчивости подпрограммы. С уважением, Евгений.

Оставить комментарий