Файл: Учимся программировать микроконтроллеры 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