Файл: Учимся программировать микроконтроллеры Pic на языке PicBasicPro (В.В. Хилинский, 2007).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 17.06.2025

Просмотров: 1767

Скачиваний: 8

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

ADCON1 = 6

TRISA = %00000001

PORTA = %00000001

TRISB = %00000000

PORTB = %00000000

B0

var byte

‘ Введем служебную переменную для команды

‘ Button

b0

= 0

‘ Эту переменную вначале надо приравнять к 0

Main:

Button

PORTA.0,0,255,255,B0,1,LED

' Если кнопка нажата то

‘ перейти на метку LED

GOTO Main

' Если кнопка не нажата идти в начало

‘ программы

LED:

PORTB = PORTB + 1

GOTO Main

Работу оператора BUTTON мы здесь обсуждать не будем. Об этом достаточно подробно разъяснено в соответствующем разделе.

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

Пример № 4. Аналого-цифровое преобразование.

Вэтом примере мы рассмотрим одну из самых полезных особенностей микроконтроллеров, в состав которых входит аналого-цифровой преобразователь

(АЦП).

Почти все в реальном мире не цифровое, а аналоговое. Поэтому для того чтобы управлять чем-либо с помощью микроконтроллера, мы должны преобразовывать аналоговые данные реального мира в цифровую форму, которую понимает PIC контроллер. Это можно сделать с помощью аналого-цифрового преобразователя. Например, если Вы должны измерить температуру Вам будет нужен датчик, для того, чтобы преобразовать измеряемую температуру в напряжение, и АЦП, чтобы преобразовать полученное напряжение в цифровое значение.

Вэтом примере вместо такого датчика мы воспользуемся обычным переменным резистором, названным потенциометром (POT), который подключим

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

60


уровень напряжения на этом выводе микроконтроллера, который в свою очередь должен преобразовать значение напряжения на выводе ротора потенциометра в цифровую форму, а результат этого преобразования вывести на светодиоды, подключенные к PORTB. При повороте ротора светодиоды будут зажигаться, точно так же, как работает линейная шкала в стерео усилителях.

К счастью, мы сейчас не обязаны слишком много понимать в работе схемы АЦП; микроконтроллер и компилятор сами знают, как это преобразование осуществляется. Схемы АЦП многообразны, но они все делают одно и тоже - преобразуют аналоговое напряжение в цифровой код. Результат такого преобразования записывается во внутренний регистр микроконтроллера. На цифровом выходе регистра АЦП будет результат этого преобразования. Он может быть 8-разрядным или 10-разрядным. PIC 16F877 имеет 10-разрядный АЦП, но может также работать и как 8-разрядный. Для упрощения программы мы будем использовать здесь 8-разрядное преобразование. Восемь разрядов вписываются в один байт, что несколько упростит нашу программу.

На рис. 21 показана принципиальная схема этого проекта. Эта схема мало чем отличается от предыдущей. Единственное отличие состоит в том, что вместо кнопки к выводу микроконтроллера подключен переменный резистор.

Рис. 21. Схема с использованием АЦП.

Итак, вот текст программы:

Define

ADC_BITS 8

' Определяем количество разрядов в

‘ результате АЦП.

Define

ADC_CLOCK 3

' Устанавливаем источник синхронизации (3

‘ = RC).

ADC_SAMPLEUS 50 ' Устанавливаем время преобразования.

Define

adval var byte

' Создаем переменную adval для хранения

‘ результата преобразования

61

'

---[ Инициализация]-------------------------

Init:

' Устанавливаем все выводы PORTB в 0 (все

PortB = $00

‘ светодиоды не горят).

TrisB = %00000000

' Устанавливаем все выводы PORTB в состояние

‘ выход.

TRISA = %11111111

' Все выводы PORTA на вход.

ADCON1 = %00000010

' Устанавливаем все выводы PORTA как аналоговые.

' ---[ Основная программа ]--------------------------

main:

ADCIN 0, adval

' Читаем канал А0, а результат преобразования

сохраняем в переменную adval.

'----------

Управление светодиодами -------------------------------------------------------

if adval < 75 then

' Если результат преобразования меньше 75,

portb = %00000000

' то не горит ни один из светодиодов.

endif

if adval > 100 then

' Если результат преобразования больше

100,

portb = %00000001

' то светится D1.

endif

if adval > 120 then

' Если результат преобразования больше

120,

portb = %00000011

' то светится D2.

endif

if adval > 140 then

' Если результат преобразования больше 140,

portb = %00000111

' то светится D3.

endif

62


if adval > 160 then

' Если результат преобразования больше 160,

portb = %00001111

' то светится D4.

endif

if adval > 180 then

' Если результат преобразования больше 180,

portb = %00011111

' то светится D5.

endif

if adval > 200 then

' Если результат преобразования больше 200,

portb = %00111111

' то светится D6.

endif

if adval > 210 then

' Если результат преобразования больше 210,

portb = %01111111

' то светится D7.

endif

if adval > 220 then

' Если результат преобразования больше 220,

portb = %11111111

' то светится D8.

endif

Pause 100

' пауза в 100 мс.

goto main

' Идти в начало программы.

В этой программе Вы встретились с незнакомым оператором ADCIN 0, adval, который работает следующим образом. Программа при встрече с этим оператором начинает производить измерение аналогового сигнала на канале А0 и совершать АЦП с точностью, указанной в соответствующем определении DEFINE. Результат преобразования заносится в переменную (в нашем случае – adval).

Вы можете использовать этот пример всякий раз, когда хотите связать цифровую схему с реальным аналоговым миром. Чтение датчиков, вероятно, самое обычное дело, но не единственное. Программа для этого проекта может легко быть превращена в подпрограмму для более сложной программы. Вы можете даже изменить её так, чтобы читать больше чем один датчик, связанный с каждым контактом PORTA.

63


Я надеюсь, что этот пример не вызовет у Вас больших сложностей в понимании АЦП микроконтроллера.

Кроме светодиодов существует большое разнообразие других электронных изделий, управление которыми часто бывает необходимо. Одним из таких устройств, очень широко используемых в робототехнике, является сервомотор. Поэтому в следующем примере мы будем учится управлять сервомотором.

Пример № 5. Управление сервомотором.

Если Вы когда-либо строили радиоуправляемые модели самолетов или роботов, то вероятно, знакомы с сервомоторами. Сервомотор это двигатель постоянного тока с управлением направлением вращения и угла поворота. Угол поворота вала ограничен 180 градусами, но некоторые люди переделывает внутренности для того, чтобы заставить сервомотор поворачивать на полный угол - 360 градусов. Напряжение питания в большинстве случаев составляет +5 В.. Никаких сложных подключений сервоприводы не требуют. Чаще всего используются всего три внешних провода: напряжение питания, общий провод и входной сигнал управления. Серводвигатель является аналоговым устройством, управляемым с помощью широтно-импульсного модулированного сигнала (PWM). Сигнал должен быть длительностью от одной до двух миллисекунд и повторяться каждые 20 мс. Ширина импульса в 1 миллисекунду поворачивает вал на максимальный угол влево, а шириной в 2 миллисекунды - на максимальный угол вправо. Любая ширина импульса между этими значениями поворачивает вал между конечными точками в линейном масштабе. Импульс длительностью в 1,5 миллисекунды повернул бы вал в промежуточную точку лежащую на полпути к концевым точкам.

Принципиальная схема управления серводвигателем приведена на рисунке 22

Рис. 22 Схема подключения сервомотора.

64

В нашем примере мы с вами будем управлять вращением сервомотора с помощью потенциометра из предыдущего примера. Как Вы, наверное, заметили, на схеме не обнаруживаются цепи питания микроконтроллера. Это совершенно не значит, что перед Вами очередной проект Perpetuum Mobile. Это сделано, для того чтобы не отвлекать Ваше внимание на вещи, само собой разумеющиеся.

Ниже приведена программа управления серводвигателем. Программа работает следующим образом: если ротор потенциометра находится в среднем положении, то и сервомотор поворачивается в среднее положение. Если ротор повернуть в сторону уменьшения сопротивления, то сервомотор должен повернуться влево (против часовой стрелки) на угол обратно пропорциональный сопротивлению потенциометра. При повороте ротора от средней точки в сторону увеличения сопротивления сервомотор должен повернуться вправо на угол пропорциональный сопротивлению потенциометра.

Пример:

Define ADC_BITS 8

Define ADC_CLOCK 3 Define ADC_SAMPLEUS 50

'

---[ Определение переменных]

----------------------------

B2 var word

' Определим переменную формирующую длительность

‘ импульса поворота.

adval var byte

' Определим переменную в которую заносится

значение АЦП

' ---

[ Установки]-------------------------

TrisB = %00000000

' Все выводы PORTB на выход.

TRISA = %11111111

' Все выводы PORTA на вход.

ADCON1 = %00000010

' Устанавливаем выводы PORTA как

‘ аналоговые.

' ---[ Основная программа ]-----------------------

Main:

PORTB. 2 = 0

ADCIN porta.0, adval

' Читаем канал А0 и результат заносим в

‘ переменную adval

b2 = adval*10/256

' Рассчитываем значение В2 в зависимости от

значения adval.

65


PULSOUT PORTb.2, 100 + b2 ' Формируем импульс поворота сервомотора.

pause 20

goto main

' Возврат в начало программы

Вэтом примере появился незнакомый Вам оператор PULSOUT PORTb.2,100

+b2. Назначение этого оператора выдавать импульс указанной ширины на определенном выводе. В нашем случае этот вывод - PORTb.2, а длительность 100 + b2 мс. Импульс этот создается двойным изменением логического состояния на указанном контакте. Поэтому важно первоначальное состояние вывода. Поэтому в самом начале основной программы мы устанавливаем вывод PORTB. 2 в 0. Затем мы считываем значение потенциала на выводе PORTA.0 и оцифровав его сохраняем в переменной adval. Для управления сервомотором, мы должны формировать импульсы, длительность которых должна меняться от 1 до 2 мс, поэтому мы должны поставить в соответствие изменение потенциала от 0 В до 5

Визменению длительности импульса в 1 мс. Переменную adval мы определили размером в 8 бит (byte) поэтому в нашем случае она может меняться от 0 до 256. Отсюда один бит этой переменной будет соответствовать adval/256 мВ. В связи с тем, что PicBasicPro не поддерживает переменных с плавающей точкой, мы избавимся от дробной части получающегося числа. Для этого мы вначале умножим значение переменной adval на 10 и только потом его разделим на 256. Получившееся значение переменной b2 будет представлять собой изменяющуюся часть длительности импульса. Длительность импульса определяется минимально возможной длительностью для данной частоты генератора (в нашем случае при частоте 4 МГц это 10 мкс). После того как импульс будет сгенерирован, сформируем минимально необходимую паузу между импульсами в 20 мс. Затем замкнем в цикл процесс выполнения программы.

Замечание. Необходимо учитывать, что сервомотор потребляет значительно больше энергии, чем микроконтроллер. Поэтому если Вы используете общий источник питания, то он должен обладать достаточным запасом мощности. Если же у Вас разные источники, то не забудьте, что цепи “земли” обоих источников должны быть электрически соединены.

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

Теперь, я думаю, нам пора обратить внимание на другой тип индикатора - это жидкокристаллический индикатор или ЖКИ (LCD).

Пример № 6. Управление ЖКИ.

ЖКИ или ЖК монитор часто используются для вывода информации в удобной для восприятия человеком форме. На рисунке 23 представлен один из таких индикаторов.

66