Файл: Учимся программировать микроконтроллеры Pic на языке PicBasicPro (В.В. Хилинский, 2007).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 17.06.2025
Просмотров: 1766
Скачиваний: 8
LED |
= |
1 |
‘ |
Включаем светодиод |
Pause |
500 |
‘ |
Пауза в 0,5 секунды |
|
LED |
= |
0 |
‘ |
Выключаем светодиод |
Pause |
500 |
‘ |
Пауза в 0,5 секунды |
|
goto main |
‘ |
Возврат на начало программы (цикл замыкается) |
||
В первой строке нашей программы выводу микроконтроллера, к которому подключен светодиод (PORTB.0), мы присваиваем символ LED. Вообще этого можно и не делать и везде, где далее в программе встречается символ LED, писать полностью название вывода. Но, согласитесь, что это будет не так наглядно. Во второй строке программы мы указываем компилятору, что мы устанавливаем все выводы PORTB на ввод информации (хотя в нашем случае это, вообще говоря, безразлично), а вывод В.0 на вывод. Как было написано ранее, регистр TRIS управляет направлением передачи информации соответствующего порта. Значение порта здесь записано в двоичной системе, об этом указывает модификатор «%». Кстати, для того, чтобы легче понимать, в какое состояние мы устанавливаем вывод порта, запомните такую подсказку 1- Input (ввод), а 0 – Output (вывод). Для того чтобы установить контакт В.0 на выход, можно было бы воспользоваться оператором OUTPUT т.е.:
OUTPUT PORTB.0
Но такая запись мне не кажется проще. Особенно, когда нам надо одновременно переключить состояние нескольких контактов порта. С помощью непосредственного управления регистром TRIS мы это можем сделать одной строкой в программе.
Втретьей строке стоит метка main, которая указывает начало нашей программы. В следующей строке мы устанавливаем на выводе PORTB.0 высокий логический уровень (1), а это означает, что светодиод начинает светиться. Затем мы выдерживаем паузу в течение 0.5 секунды для того, чтобы все успели это заметить. В шестой строчке программы мы выключаем светодиод, подавая на него низкий логический уровень (0). И затем вновь выдерживаем секундную паузу. Последняя строка нашей программы возвращает программу на начало, т.е. на метку main. Таким образом, программа будет работать циклически до тех пор, пока это Вам не надоест.
Вэтом первом примере все просто и понятно. Теперь Вы можете написать ее в редакторе MicroCode Studio и затем откомпилировать. Полученный в результате компиляции файл с расширением *.hex записать в микроконтроллер и спаять схему.
53
Рис. 18. Схема к примеру «Hello Word».
Замечание. Перед началом компиляции не забудьте в редакторе установить в отведенном для этого окне тип микроконтроллера, используемого в Вашем случае. Если же Вы собираетесь использовать кварцевый резонатор на другую частоту, то поместите в начале Вашей программы строчку:
DEFINE OSC X
Где вместо Х надо будет указать частоту Вашего кварца. По умолчанию компилятор все делает для частоты 4 МГц.
Пример № 2. Работа с несколькими светодиодами.
Этот пример в большей степени основан на предыдущем примере. Добавим в предыдущую схему еще семь светодиодов и соберем ее, так как это показано на рис. 19.
Рис. 19. Схема поочередного включения светодиодов.
54
А теперь рассмотрим следующую программу:
Define |
LOADER_USED 1 |
' Эта строка в программе необходима если Вы |
|
‘ используете интерактивную среду разработки (ICD) |
|||
LEDS |
var |
PORTB |
' Введем псевдоним для порта В – LEDS, под |
‘которым мы будем подразумевать все множество светодиодов подключенных
‘к этому порту
TRISB = %00000000 |
' Устанавливаем все выводы PORTB в состояние |
выхода |
|
LEDS = 0 |
‘ Определяем начальное состояние выводов PORTB |
Main: |
‘ Начало основной программы |
LEDS = LEDS + 1 |
‘ Увеличиваем значение переменной на 1 |
pause 500 |
‘ Задержка на 0,5 секунды |
goto main |
‘ Вернуться в начало программы |
В первой строке программы мы поместили указание компилятору на то, что мы собираемся работать в интерактивной среде разработчика или ICD. Если Вы не нуждаетесь в ней или у Вас нет возможности работать в этой среде эту строку программы можно убрать.
Далее мы вводим определение переменной LEDS, которая будет относиться к байтовому типу. Под этой переменной мы будем подразумевать все множество светодиодов подключенных к PORTB. Далее мы записываем все нули в регистр TRISB. Это приведет к тому, что все выводы PORTB будут установлены в состояние выхода. В пятой строке программы мы присваиваем начальное значение переменной LEDS. Понятно, что в двоичной форме оно будет выглядеть как
LEDS = %00000000
Это означает, что на всех выводах PORTB в начале работы программы будет логический 0. Далее начинается собственно сама программа. Об этом нам говорит метка Main:. В самом начале основной программы мы увеличиваем значение переменной LEDS на единицу. Это значит, что на выводе 0 PORTB появится логическая единица и первый светодиод зажжется. Для того чтобы заметить это следующим стоит оператор паузы, который позволит программе остановится на время 0.5 секунды. И в конце программы мы снова сталкиваемся с оператором goto возвращающим нашу программу в начало. Вернувшись в начало, программа снова увеличивает значение переменной LEDS на единицу и тогда загорается второй светодиод, а первый гаснет. Таким образом, программа, работая
55
в цикле, постоянно увеличивает значение указанной переменной на единицу. В результате этого светодиоды будут отображать значение переменной LEDS в двоичном формате. Это будет происходить до тех пор, пока значение переменной не станет равным 255 (%11111111). Затем все повторится сначала.
Теперь рассмотрим другую программу, которая будет работать с этой же схемой.
I var Byte |
' Вводим переменную цикла - I |
Symbol LEDS = PORTB |
' Введем псевдоним для PORTB, под которым мы |
‘будем подразумевать все множество светодиодов подключенных к этому
‘порту
Pause |
500 |
‘ Устанавливаем все выводы порта B в |
|
TRISB |
= %00000000 |
||
‘ состояние выхода |
|||
Loop: |
‘ Метка начала цикла |
||
LEDS = 1 |
' Устанавливаем все выводы PORTB в низкое логическое |
||
‘ состояние кроме вывода 0. |
|||
Pause |
500 |
||
For I |
= 0 To 6 |
‘ Цикл в котором происходит управление каждым |
|
‘ светодиодом
LEDS = LEDS << 1 ' При каждом проходе цикла происходит смещение ‘ горящего светодиода
Next |
Pause 500 |
' Вводим задержку на 0,5 секунд |
' Цикл продолжается пока все 8 светодиодов не мигнут |
||
GoTo |
Loop |
' Вернуться на метку Loop |
В первой строке стоит определение вводимой в программу переменной I. Размер этой переменой определяется в байт. Эта переменная позже нам понадобится для организации цикла. Вторая строка нам уже знакома по предыдущему примеру. В следующей строке программы мы вводим задержку, для того чтобы дать возможность микроконтроллеру стабилизироваться после включения питания. Далее, как и в предыдущем примере, мы непосредственно записываем в регистр TRISB все 0, это должно привести к тому, что все выводы PORTB будут находиться в состоянии выхода. Далее мы вводим метку – Loop, которая позволит нам постоянно возвращаться к этой строке в программе. Затем мы присваиваем конкретное значения псевдониму LED = 1. Это же самое мы
56
могли бы записать в двоичной системе LED = %00000001, что в данном случае, наверное, было бы наглядней. Из этой записи мы видим, что на все выводы этого порта мы подали логический 0 (все эти светодиоды не горят), но на нулевой вывод логическую единицу (светодиод подключенный к этому выводу должен загореться). Далее мы опять вводим оператор задержки длительностью в 0,5 секунды. Это сделано для того, чтобы мы успели увидеть, как этот первый светодиод горит.
В следующей строчке начинается циклический оператор FOR…NEXT. Этот оператор работает таким образом: все, что стоит между строками FOR и NEXT выполняется циклически последовательно до тех пор, пока значение переменной, меняясь от начального значения (I = 0), не станет равным ее конечному значению
(7). Причем шаг изменения определяется параметром – step. Если же этот параметр опущен, то по умолчанию этот шаг равен 1.
Далее, первым внутри цикла FOR…NEXT стоит так называемый оператор сдвига (<<), с помощью которого при каждом циклическом проходе будет происходить смещение единицы в регистре PORTB (%00000001) на один разряд влево.
I = 0 LED = %00000010
I = 1 LED = %00000100
I = 2 LED = %00001000
I = 3 LED = %00010000
I = 4 LED = %00100000
I = 5 LED = %01000000
I = 6 LED = %10000000
В результате работы оператора цикла и оператора разрядного сдвига будет происходить поочередное включение светодиодов справа налево по схеме. После оператора сдвига стоит оператор паузы, который позволяет нам видеть весь процесс с «бегущим огнем». И так будет продолжаться до тех пор, пока значение переменной I не станет равным 6. При этом блок команд, находящийся между словами FOR и NEXT, выполнится в последний раз, и наша программа выйдет из этого цикла. Выйдя из этого цикла, программа сталкивается с оператором GOTO, который возвращает программу к метке Loop. Затем весь процесс с переключением светодиодов повторяется.
В приведенной программе Вы можете изменить временные установки, чтобы сделать передвижение света быстрее или медленнее, изменяя значения в команде PAUSE. Поменяв оператор сдвига влево на оператор сдвига вправо (>>) и сделав некоторое изменение в значении, присваиваемом псевдониму LEDS в начале цикла Loop, Вы сможете добиться того чтобы «огонь бежал» слева на право.
Сделав некоторые дополнения, как в схеме, так и в программе, Вы можете сделать на основе этого примера новогоднюю гирлянду.
57
Пример № 3. Взаимодействие с кнопкой.
В предыдущих примерах мы учились, как заставить микроконтроллер выводить информацию. В этом примере мы заставим вывод PORTA.0 микроконтроллера работать как цифровой вход и считывать состояние кнопки, подключенной к этому выводу. Добавим пару элементов в предыдущую схему и получим новую – рис. 20.
Пусть наша программа будет работать следующим образом. Если вывод PORTA.0 находится в высоком логическом состоянии (кнопка не замкнута), ни один из светодиодов не горит. Если кнопку нажать, то на выводе RA0 установится низкое логическое состояние, и тогда мы зажжем один из светодиодов. Пусть это будет D1. При следующем нажатии зажжется D2 и т.д. Задача, кажется, достаточно простой? На рисунке 35. представлена принципиальная схема для этого примера.
Рис. 20. Взаимодействия микроконтроллера с кнопкой.
Атеперь текст самой программы:
‘Вначале идут основные установки и определение переменных
ADCON1 = %00000110 ' Установим все выводы PORTA как цифровые. TRISA = %00000001 ' Установим выводы RA4-RA1 как выходы, а
‘ вывод RA0 как вход.
TRISB = %00000000 ‘ Все выводы PORTB на выход
PORTB = %00000000 ' Записываем все нули в PORTB ;
‘ Здесь начинается основная программа
Main:
' *** Проверяем состояние кнопки ***
IF PORTA.0 = 0 THEN LED ' Если кнопка нажата то перейти к ‘ подпрограмме LED,
58
GOTO Main ' Иначе вернуться в начало.
LED:
'*** Подпрограмма реакции на нажатие кнопки. ***
PORTB = PORTB + 1 |
' Ведем счет нажатий переключая |
‘ светодиодов. |
|
GOTO Main |
' Вернуться к началу цикла main. |
Приведенная программа начинается, как обычно, с начальных установок и определений. Ввиду того, что выводы PORTA могут работать в трех разных режимах (цифровой вход/выход и режим АЦП), мы записываем в регистр ADON1 значение 6. Таким образом мы устанавливаем все выводы порта А как цифровые. Затем мы определяем направление работы выводов этого порта и PORTB и переходим к основной программе. В первой же строчке программы мы сталкиваемся с условным оператором IF..THEN. Здесь это единственный, еще не знакомый Вам, оператор. Согласно определению работы этого оператора он проверяет условие, стоящее после слова IF (PORTA.0 = 0), и если оно истинно, происходит переход программы на метку, стоящую после слова THEN. Если же условие ложно, то программа продолжает выполняться со следующей строки. Или говоря более подробно программа, дойдя до строки IF … THEN, анализирует состояние вывода PORTA.0. Если оно равняется 0, т.е. кнопка нажата, программа переходит на метку указанную после слова THEN. Если же состояние вывода равняется 1, то программа переходит на следующую строку. Дальше Вам все уже известно и, надеюсь, понятно.
После того как программа будет откомпилирована и записана в микроконтроллер, мы можем запустить ее и посмотреть, как она работает.
После запуска программы все происходит, так как и должно происходить, но это только до первого нажатия на кнопку. Как только мы нажмем на кнопку, увидим, что зажигается не первый светодиод, а любой из восьми светодиодов и даже, скорее всего какая либо их комбинация. В чем причина такого поведения? Причин здесь две. Первая и самая очевидная это время нажатия на кнопку. Как бы вы ни старались быстро нажать на кнопку, это время будет от нескольких десятков до сотен миллисекунд. А один цикл программы, включающий в себя опрос кнопки и переключение светодиода, займет приблизительно 10 микросекунд при указанной частоте кварца. Отсюда ясно, что пока кнопка находится в состоянии «нажато» программа успевает множество раз опросить порт, к которому она подключена, и зафиксировать это как множество последовательных нажатий. Следующей причиной этого является так называемый дребезг контактов. Более подробно о дребезге контактов написано в разделе «Команда BUTTON». Для того чтобы избавится от обоих этих явлений введите после команды переключения светодиодов (PORTB = PORTB + 1) задержку на 200 – 500 микросекунд. Для решения этой задачи можно также использовать специально предназначенную для этого команду BUTTON.
Пример:
59