Справочник по программированию «Bascom-AVR» (М.Л. Кулиш)
.pdf
===================================== Справочник по программированию «Bascom-AVR» ==
' |
----------------------------------------------------------- |
|
|
|
|
'ШЕСТНАДЦАТИРИЧНЫЕ ЦИФРЫ |
|
|
|
|||||
Tabseg0: |
|
|
|
|
|
|
||||||||
&HC0 |
|
, &HF9 |
|
|
|
' 0 , 1 |
-d0 - |
|
||||||
|
Data |
|
|
|
|
I |
||||||||
|
Data |
&HA4 |
|
, &HB0 |
|
|
|
' 2 , 3 I |
|
|||||
|
Data |
&H99 |
|
, &H92 |
|
|
|
' 4 , 5 D5 |
D1 |
|||||
|
Data |
&H82 |
|
, &HF8 |
|
|
|
' 6 , 7 I |
-d6 - |
I |
||||
|
Data |
&H80 |
|
, &H90 |
|
|
|
' 8 , 9 |
I |
|||||
|
Data |
&H88 |
|
, &H83 |
|
|
|
' A , B I |
|
|||||
|
Data |
&HC6 |
|
, &HA1 |
|
|
|
' C , D D4 |
D2 |
|||||
|
Data |
&H86 |
|
, &H8E |
|
|
|
' E , F I |
-D3- |
I |
||||
' |
|
|
|
|
|
|
|
|
|
' |
|
|
[D7] |
|
---------------------------------------------------------------------------------- |
|
|
|
программы клавиатуры |
|
|
|
|
||||||
' |
|
|
|
|
|
|
|
|
||||||
'--------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
' --------------------------------------- |
| |
|
|
|
|
AVR-WATCH |
|
|
|
| |
|
|
||
' |
|
|
|
|
|
|
|
|
|
|||||
' --------------------------------- |
| |
| |
--- |
|
|
--- |
|
--- |
|
--- |
| |
| |
|
|
' |
| |
| |
| |
| |
| |
| |
|
|
||||||
' |
| | | |
| |
| |
| |
| | |
|
|
|||||||
' |
| |
| |
--- |
| |
| |
--- |
| |
--- |
| |
--- |
| |
| |
|
|
' |
| | | |
| |
| |
| |
| | |
|
|
|||||||
' |
| |
| |
--- |
|
[] |
--- [] |
|
--- [] |
|
--- [] | |
| |
|
|
|
' --------------------------------- |
| |
|
1 |
|
|
2 |
|
3 |
|
4 |
|
| |
|
|
' |
| |
|
|
|
|
|
|
| |
|
|
||||
' |
| |
|
_ |
|
|
_ |
|
_ |
|
_ |
|
| |
|
|
' |
| |
|
|_| |
|
|
|_| |
|
|_| |
|
|_| |
|
| |
|
|
' |
| |
|
Reset |
|
+ |
|
+ |
|
- |
|
| |
|
|
|
' |
| |
|
|
|
|
|
| |
|
|
|||||
' |
| |
|
Min |
|
|
Hour |
|
Min |
|
Min |
|
| |
|
|
' --------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'выполнение программ обработки кнопок - основной список
'0: пустой переход из-за того, что кнопки нумеруются с 1-й, а не с 0-й
'1: Сбросить минуты 2: Добавить час 3: Добавить минуту 4: Убавить минуту
'---------------------------------------------------------
Программа обНазначение кнопок выбрано произвольно. Для перехода к программам обработки кнопок работки кнопок используется специальная функция On – Goto с индексированием списка меток. Дает быстрый и экономичный код. Применение функции Select Case не рекомендуется, так как не по-
зволяет вкладывать объемные конструкции.
W_klb:
On Buf_kl Goto Kn , Km1 , Km2 , Km3 , Km4
'обработать нажатие кнопки |
|
'--------- |
|
Km1: |
'сбросить минуты |
Rmin = 0 |
|
If Rmin > 30 Then |
'при необходимости округления |
Goto Km2 |
'скорректировать счетчик минут |
End If |
|
Km1_1: |
'поставить признак обновления индикации |
Ddat = 255 |
|
Kn: |
|
Return |
|
'--------- |
|
Km2: |
'плюс час |
Incr Rhour |
|
If Rhour > 23 Then |
'при необходимости |
Rhour = 0 |
'скорректировать счетчик часов |
End If |
|
Goto Km1_1 |
|
'--------- |
|
Km3: |
'плюс минута |
Incr Rmin |
|
If Rmin > 59 Then |
'при необходимости |
Rmin = 0 |
'скорректировать счетчик минут |
End If |
|
Goto Km1_1 |
|
'--------- |
|
Km4: |
'минус минута |
Decr Rmin |
|
If Rmin = 255 Then |
'при необходимости |
Rmin = 59 |
'скорректировать счетчик минут |
End If |
|
Goto Km1_1 |
|
'---------------------------------------------------------------------------------- |
|
============================================================================= 11
===================================== Справочник по программированию «Bascom-AVR» ==
Первая версия программы готова, она полностью работоспособна, но функционально бедна. Структура программы во всех компонентах открыта для расширения функциональных возможностей. Определив набор добавляемых функций, следует выбрать путь реализации новых задач. Существует несколько подходов:
-простое добавление новых функций по имеющимся правилам работы программы. Этот путь пригоден для небольших добавлений, похожих на уже имеющиеся;
-добавление новых функций по другим правилам построения программы. Необходимость в этом возникает при создании многофункциональных систем и обычно решается создание других разделов с собственной структурой ГЦ;
-добавление сложных функций в виде отдельных модулей, содержащих все необходимые компоненты ввода и отображения данных. Это приемлемый вариант реализации небольшого количества функций при некритичном времени реагирования на внешние воздействия. Примером таких функций могут быть программы тестирования, сохранения данных, обработка протокола установления связи;
-создание новых функций посредством специальных инструментов – утилит. Утилиты – специальные программы, облегчающие реализацию часто повторяющихся операций. Использование утилит для расширения системы наиболее эффективно при реализации большого количества несложных и похожих функций. Рассмотрим примеры построения и применения утилит.
Этап 5. «Создание утилит для расширения функциональных возможностей». Задача этапа – создание набора стандартных программных модулей для выполнения элементарных операций.
Требуемый для расширения набор утилит определяется составом добавляемых функций. Выберем, например, следующий набор расширяемых режимов:
-выбор с помощью меню;
-многофункциональная клавиатура;
-отображение текстовых сообщений.
Для этого нам понадобятся следующие утилиты:
-вывод указанного текстового сообщения на индикатор, например, с помощью индекса;
-останов на фиксированное время с ожиданием нажатия кнопки.
При добавлении этих утилит прошлось расширить список используемых переменных и функций прерывания реального времени. Все изменения в программе можно наблюдать в полном измененном тексте, который будет приведен дальше.
Этап 6. «Расширение функциональных возможностей с помощью утилит».
В программу версии 2 добавлено:
-несколько новых переменных для обеспечения работы новых систем;
-расширена функция программы прерывания таймера 0. Добавлена ветка формирования временных интервалов 64 мс и проверка запрета звукового сигнала;
-расширена функция программы формирования изображения;
-добавлен и выделен отдельно раздел утилит (вспомогательных универсальных программ формирования изображения и управления). Там же расположены расширенные таблицы кодов сегментов и сообщений;
-добавлено начальное сообщение;
-изменены и добавлены функции клавиатуры. Функции, конечно, надуманные, но это демонстрационная программа. Показан один из основных механизмов создания многофункциональной клавиатуры;
-добавлены программы коррекции монтажа индикатора и клавиатуры (при отклонении фактической разводки от теоретической модели.
И так, программа работает и обеспечивает все требуемые режимы работы. Однако работа не закончена. Необходимо привести ее в порядок. Имеется в виду введение последних непринципиальных улучшений и подготовка исходного текста к дальнейшей модернизации, возможно даже, через продолжительное время. Все это можно назвать этапом оптимизации.
Этап 7. «Оптимизация программы».
Прагматичный (лишь бы работало) стиль программирования часто оказывается, безответственным. Практика показывает, что встроенное программное обеспечение часто подвергается доработке в процессе производства и даже эксплуатации. Законченный программный проект в той или иной степени должен удовлетворять возможности дальнейшей доработки или, в крайней случае, должен быть пригоден для заимствования его частей для других проектов. Что нужно для этого сделать? Следующее:
-просмотреть текст программы и одинаковые участки, даже если это всего одна строка, попытаться оформить в качестве отдельной подпрограммы. В приведенной программе такие примеры имеются;
-попробовать свести к одной подпрограмме похожие участки программы, сделав, например, несколько входов с различными параметрами и промежуточное преобразование;
-устранить слишком длинные участки программ, оформив их как функционально законченную подпрограмму. В первую очередь это относится к вычислительным программам;
============================================================================= 12
===================================== Справочник по программированию «Bascom-AVR» ==
-провести подробное комментирование программы. Особенно тщательно описывая, протоколы, форматы данных, условия принятия решение, обязательно применительно к тем физическим процессам, с которыми взаимодействует программа;
-в максимальной степени представить применяемые цифровые константы в символьном виде. Их определение вынести в заголовки и указать их назначение;
-обязательно указать номер версии продукта, разницу в версиях (историю доработок), дату создания (компиляции), версию и тип компилятора.
После оптимизации (и в процессе тоже) необходимо провести повторную компиляцию и проверку функционирования.
ПРОГРАММА 4
Вторая версия программы Содержит все добавления.
'------------------------------------------
' Программа "AVR-WATCH" (версия 2)
'------------------------------------------ |
|
типа ATMEGA8 |
|
' Микроконтроллер |
|||
'------------------------------------------ |
|
Fuses: |
|
' Программируемые |
- низкочастотный кварцевый резонатор |
||
' CKSEL3... |
CKSEL0 |
= 1001 |
|
'CKOPT=0 - внутренние конденсаторы подключены к кварцевому резонатору
'RSTDISBL=1 - порт PC6 используется как сброс
'WDTON=1 - сторожевой таймер разрешен
'SPIEN=0 - последовательное программирование разрешено
'BOOTSZ1,BOOTSZ0 = 00, BOOTRST=1 - параметры загрузчика
'EESAVE = 1 - НЕ ОЧИЩАТЬ EEPROM при программировании
'BODLEVEL=1, BODEN=1 - ПАРАМЕТРЫ СБРОСА
'SUT1=1,SUT1=0 - ВРЕМЯ СТАРТА
'------------------------------------------
'Ресурсы:
'Генератор RC - внутренний 1 МГц, а к TOSC1 and TOSC2 подключен кристалл 32768 Гц
'На выходе PB3 (OC2) импульсы длительностью 1 с (0.5 Гц)
'На выходе PB1 (OC1A) звуковой сигнал
'Порт Portd выход сегментов
' Portc0... |
Portc3 - код знакоместа (позиционный) он же порт сканирования клавиатуры |
|
' Четыре кнопки: Port0... |
Portc3 - код сканирования клавиатуры, Portc4 - линия возврата клавиатуры |
|
'------------------------------------------ |
|
'определить тип микроконтроллера |
$regfile = "m8def.dat" |
||
'------------------------------------------ |
|
'признак "обновить данные" |
Dim Ndat As Byte |
||
Dim Ddat As Byte |
'признак "обновить индикатор" |
|
'--------------------- |
|
'режим отображения: 0 - ЧЧММ, 1 - ММСС, 2 - погашен |
Dim Mdisp As Byte |
||
Dim Msnd As Byte |
'режим звука: 0 - включен, <>0 - выключен |
|
'--------------------- |
|
'программный счетчик времени |
Dim S_tim As Byte |
||
Dim W_tim As Byte |
'счетчик времени задержек |
|
Dim R_btim As Byte |
'счетчик времени звонка |
|
'--------------------- |
|
'счетчик секунд |
Dim Rsec As Byte |
||
Dim Rmin As Byte |
'счетчик минут |
|
Dim Rhour As Byte |
'счетчик часов |
|
'--------------------- |
|
'код нажатой кнопки |
Dim Buf_kl As Byte |
||
Dim Buf_pkl As Byte |
'предварительный код нажатой кнопки |
|
Dim R_ckl As Byte |
'счетчик удержания клавиатуры |
|
'--------------------- |
|
'буфер индикации (копия сегментов) |
Dim Buf_dis(4) As Byte |
||
Dim Cnt_dis As Byte |
'счетчик индикации |
|
Dim Tmpb As Byte |
'временное значение |
|
Dim Index As Byte |
'временное значение |
|
Dim Value As Byte |
'временное значение |
|
'--------------------- |
|
'текстовая строка |
Dim Bufr As String * 10 |
||
'------------------------------------------ |
|
'генератор 1 МГц, необходим компилятору для правильного |
$crystal = 1000000 |
||
' |
|
' вычисления задержек и других временных параметров |
|
|
|
'назначение векторов прерывания.
On Timer0 Timer0_int Nosave |
'вектор прерывания |
от |
таймера 0 |
On Timer2 Timer2_int Nosave |
'вектор прерывания |
от |
таймера 2 |
'------------------------------------------ |
'режим IDLE - разрешить |
||
Mcucr = &B10000000 |
|||
============================================================================= 13
===================================== Справочник по программированию «Bascom-AVR» ==
'ТАЙМЕРЫ
Tccr0 = &B00000011 |
'режим таймера 0: Fкв/64 - часы реального времени |
|||
' |
--------------------- |
|
'режим таймера 1: |
|
Tccr1a |
= &B01000000 |
|||
'генератор звука 2 кГц с выходом на PB1 (OC1A) |
||||
Tccr1b |
= &B00001000 |
'делитель Fкв / 1 и с выходам Oc1a |
||
Ocr1ah |
= 0 : Ocr1al = 250 |
'и коэффициетном Fкв/250*2 |
||
' |
--------------------- |
|
'режим таймера 2: генератор секундых импульсов |
|
Assr.3 |
= 1 : Wait 1 |
|||
'включить НЧ-генератор AS2 и подождать стабилизации амплитуды |
||||
Tcnt2 = 0 : Waitms 10 |
'очистить счетчик и подождать пока значение |
|||
Ocr2 = |
128 : Waitms 10 |
'перепишется из временного буфера |
||
'установить значение сравнения |
||||
Tccr2 = &B00010101 |
'установить коэффициент деления прескалера К=128 |
|||
'и выход секундных импульсов на PB3 (OC2) |
||||
' |
---------------------ПОРТЫ |
|
||
' |
'направление линий порта B: 1 - на вывод |
|||
|
Ddrb = &B00001010 |
|||
Portb = &B11111111 |
'исходное состояние линий B: hhhh1h1h |
|||
' |
Ddrc---------------------= &B00001111 |
'направление линий порта C: 1 - на вывод |
||
Portc = &B11111111 |
'исходное состояние линий C: hhhh1111 |
|||
' |
Ddrd---------------------= &B00000000 |
'направление линий порта D: 1 - на вывод |
||
Portd = &B11111111 |
'исходное состояние линий D: hhhhhhhh |
|||
' |
|
|
'* h - высокий уровень, подтянутый через резистор |
|
---------------------прерывания. |
|
|||
' |
|
|||
Timsk = &B010000001 |
'разрешить прерывание от переполнения таймера 0 |
|||
Enable |
Timer0 |
|||
Enable |
Timer2 |
'разрешить прерывание от переполнения таймера 2 |
||
Enable |
Interrupts |
'разрешить прерывания. |
||
' |
---------------------Index = 1 : Gosub Dis_tr |
'ВЫВОД СООБЩЕНИЯ СООБЩЕНИЯ (НОМЕР ВЕРСИИ) |
||
|
Wait 1 |
'подождать |
||
'ГЛАВНЫЙ ЦИКЛ |
|
|||
Mc: |
Ndat <> 0 Then |
|
||
|
If |
'очистить "обновить данные" |
||
|
|
Ndat = 0 |
||
|
|
Gosub New_data |
'обработать данные |
|
|
|
Goto Mc |
|
|
|
End If |
|
||
|
If |
Ddat <> 0 Then |
'очистить "обновить индикатор" |
|
|
|
Ddat = 0 |
||
|
|
Gosub New_led |
'обновить индикатор |
|
|
|
Goto Mc |
|
|
|
End If |
|
||
|
If |
Buf_kl <> 0 Then |
|
|
'следующая строка добавляется при необходимости |
||||
' |
|
Gosub Tr_klb |
'скорректировать номер кнопок |
|
|
|
Gosub W_klb |
'обработать нажатие |
|
|
|
Buf_kl = 0 |
'очистить оработанное нажатие |
|
|
|
Goto Mc |
|
|
End If Idle
Goto Mc '----------------------------------------------------------------------------------
'ОБРАБОТКА ПРОГРАММ ГЛАВНОГО ЦИКЛА
'---------------------
'обработать данные времени по истечении секунды
New_data:
Incr Rsec |
59 Then |
'плюс секунда |
|
If Rsec > |
'при необходимости |
||
Rsec = |
0 |
: Goto Ndata1 |
'скорректировать счетчик секунд |
End If |
|
|
|
Goto Ndata3 |
|
|
|
Ndata1: |
|
|
'плюс минута |
Incr Rmin |
59 Then |
||
If Rmin > |
'при необходимости |
||
Rmin = |
0 |
: Goto Ndata2 |
'скорректировать счетчик минут |
End If |
|
|
|
Goto Ndata3 |
|
|
|
Ndata2: |
|
|
'плюс час |
Incr Rhour |
|
|
|
If Rhour > 23 Then |
'при необходимости |
||
Rhour = 0 |
|
'скорректировать счетчик часов |
|
End If |
|
|
|
Ndata3: |
|
|
'поставить признак обновления индикации |
Ddat = 255 |
|
|
|
============================================================================= 14
===================================== Справочник по программированию «Bascom-AVR» ==
Return '----------------------------------------------------------------------------------
Здесь проведена оптимизация Подпрограммы Add_vtmpb и Add_sz появились в результате оптимизации исходно текста
'обновить индикатор по завершению одной из операций в соответствии с текущим состоянием
New_led: |
|
|
|
|
|
|
|
'очистить строку |
||||
|
Bufr = "" |
|
|
|
|
|
|
|||||
|
If Mdisp = 1 Then |
|
|
|
|
|
'выбрать вариант обработки индикатора |
|||||
|
|
Goto Nled2 |
|
|
|
|
|
|
'на формирования отображения ММСС |
|||
|
Elseif Mdisp = 2 Then |
|
|
|
|
'на гашение |
||||||
|
|
Goto Nled3 |
|
|
|
|
|
|
||||
|
End If |
|
|
|
|
|
|
|
|
|
||
'сформировать символьное изображение времени в виде ЧЧММ |
||||||||||||
|
Tmpb = Rhour : Gosub Add_vtmpb |
|
'добавить значение часов |
|||||||||
' |
Tmpb = Rmin : Gosub Add_vtmpb |
|
|
'добавить значение минут |
||||||||
--------- |
|
|
|
|
|
|
|
|
|
|
||
Nled1: |
|
|
|
|
|
|
|
|
'получить код первого знакоместа |
|||
' |
Gosub Asc_seg : Buf_dis(1) = Tmpb |
|
||||||||||
Gosub Asc_seg2 : Buf_dis(2) = Tmpb |
'получить код второго знакоместа |
|||||||||||
' |
||||||||||||
Gosub Asc_seg2 : Buf_dis(3) = Tmpb |
'получить код третьего знакоместа |
|||||||||||
' |
||||||||||||
Gosub Asc_seg2 : Buf_dis(4) = Tmpb |
'получить код четвертого знакоместа |
|||||||||||
|
||||||||||||
Return |
|
|
|
|
|
|
|
|
|
|
||
'--------- |
|
|
|
|
|
|
|
|
|
|
|
|
'сформировать символьное изображение времени в виде ММСС |
||||||||||||
Nled2: |
|
|
|
|
|
|
|
|
'добавить значение минут |
|||
|
Tmpb = Rmin : Gosub Add_vtmpb |
|
|
|||||||||
|
Tmpb = Rsec : Gosub Add_vtmpb |
|
|
'добавить значение секунд |
||||||||
' |
Goto Nled1 |
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
||
'погасить индикатор |
|
|
|
|
|
|
|
|||||
Nled3: |
|
|
|
|
|
|
|
|
'погасить все сегменты |
|||
|
Buf _ dis(1) = 255 |
|
|
|
|
|
||||||
|
Buf _ dis(2) = &HFF |
|
|
|
|
|
|
|
||||
|
Buf _ dis(3) = &B11111111 |
|
|
|
|
|||||||
|
Buf _ dis(4) = 255 |
|
|
|
|
|
|
|
||||
Return |
|
|
|
|
|
|
|
|
|
|
||
'--------- |
|
|
|
|
|
|
|
|
|
|
|
|
'п/п результат оптимизации |
|
|
|
|
|
|||||||
Add_vtmpb: |
|
|
|
|
|
|
|
'если значение выражается одной цифрой |
||||
|
If Tmpb < 10 Then |
|
|
|
|
|
||||||
|
|
Gosub Add_sz |
|
|
|
|
|
'добавить символ лидирующего нуля |
||||
|
End If |
|
|
|
|
|
|
|
'добавить значение |
|||
|
Bufr = Bufr + Str(tmpb) |
|
|
|||||||||
Return |
|
|
|
|
|
|
|
|
|
|
||
'--------- |
|
|
|
|
|
|
|
|
|
|
|
|
Add_sz: |
|
|
|
|
|
|
|
|
'добавить символ лидирующего нуля |
|||
|
Bufr = Bufr + "0" |
|
|
|
|
|
||||||
Return |
|
|
|
|
|
|
|
|
|
|
||
'---------------------------------------------------------------------------------- |
|
|
|
программы клавиатуры |
|
|
|
|||||
' |
|
|
|
|
|
|
||||||
'--------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
|
' --------------------------------------- |
| |
|
|
AVR-WATCH |
|
|
|
| |
||||
' |
|
|
|
|
|
|||||||
' --------------------------------- |
| |
| |
--- |
--- |
|
|
--- |
--- |
|
| |
| |
|
' |
| |
| |
| |
| |
| |
|||||||
' |
| | | |
| |
| |
| |
| |
| | |
||||||
' |
| |
| |
--- |
--- |
| |
| |
--- |
--- |
| |
| |
| |
|
' |
| | | |
| |
| |
| |
| |
| | |
||||||
' |
| |
| |
--- [] |
--- [] |
|
--- [] |
--- [] | |
| |
||||
' --------------------------------- |
| |
|
1 |
2 |
|
|
3 |
4 |
|
|
| |
|
' |
| |
|
|
|
|
|
| |
|||||
' |
| |
|
_ |
_ |
|
|
_ |
_ |
|
|
| |
|
' |
| |
|
|_| |
|_| |
|
|
|_| |
|_| |
|
|
| |
|
' |
| |
Reset |
+ |
|
|
+ |
Shift |
|
| |
|||
' |
| |
|
|
|
| |
|||||||
' |
| |
|
Min |
Hour |
|
Min |
|
|
|
| |
||
' --------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
|
'выполнение программ обработки кнопок - основной список
'0: пустой переход из-за того, что кнопки нумеруются с 1-й, а не с 0-й
'1: Сбросить минуты 2: Добавить час 3: Добавить минуту 4: Второе назначение
' |
| |
_ |
_ |
_ |
_ |
| |
' |
| |
|_| |
|_| |
|_| |
|_| |
| |
============================================================================= 15
===================================== Справочник по программированию «Bascom-AVR» ==
' |
| |
ЧЧММ |
ММСС |
ON/OFF |
ON/OFF |
| |
' |
| |
| |
||||
' |
| |
Формат |
врем. |
Sound |
Disp |
| |
'---------------------------------------
'выполнение программ обработки кнопок - дополнительный список
'0: пустой переход из-за того, что кнопки нумеруются с 1-й, а не с 0-й
'1: Отображать ЧЧММ 2: Отображать ММСС 3: Вкл.Выкл. Звук 4: Вкл.Выкл. Индикацию
'---------------------------------------------------------
W_klb:
On Buf_kl Goto Kn , Km1 , Km2 , Km3 , Km4 '----------------------------------------------
W_skl:
On Buf_kl Goto Km1_1 , Ks1 , Ks2 , Ks3 , Ks4 '---------
Km1:
Rsec = 0 : Rmin = 0 |
'сбросить секунды и минуты |
If Rmin > 30 Then |
'при необходимости округления |
Goto Km2 |
'скорректировать счетчик минут |
End If |
|
Km1_1: |
'поставить признак обновления индикации |
Ddat = 255 |
|
Kn: |
|
Return |
|
'--------- |
|
Km2: |
'плюс час |
Incr Rhour |
|
If Rhour > 23 Then |
'при необходимости |
Rhour = 0 |
'скорректировать счетчик часов |
End If |
|
Goto Km1_1 |
|
'--------- |
|
Km3: |
'плюс минута |
Incr Rmin |
|
If Rmin > 59 Then |
'при необходимости |
Rmin = 0 |
'скорректировать счетчик минут |
End If |
|
Goto Km1_1 |
|
'---------
' переключить режим второго назначения кнопок
Km4: |
'выдать приглашение " SH " |
Index = 2 : Gosub Dis_tr |
|
Gosub Waitklc |
'ожидание нажатий 2.5 с |
If Buf_kl <> 0 Then |
'есть нажания кнопки? |
Goto W_skl |
'да - переходим к обработке списка |
End If |
'на обновление индикации |
Goto Km1_1 |
|
'--------- |
|
Ks1: |
'установить режим отображения ЧЧММ |
Mdisp = 0 |
|
Goto Km1_1 |
'на обновление индикации |
'--------- |
|
Ks2: |
'установить режим отображения ММСС |
Mdisp = 1 |
|
Goto Km1_1 |
'на обновление индикации |
'---------
Совет |
Необходимо выбирать такие способы обработки управляющих переменных, чтобы ложные значения |
|
не могли создаваться, а при появлении исключались автоматически. Пример тому обработка пере- |
|
менной Msnd. Избыточности кода при этом не происходит. |
Ks3: |
'изменить режим звука на противоположенный |
If Msnd <> 0 Then |
|
Msnd = 0 |
|
Else |
|
Msnd = 255 |
|
End If |
'на обновление индикации |
Goto Km1_1 |
|
'--------- |
|
Ks4: |
'изменить режим гашения на противоположенный |
If Mdisp <> 2 Then |
|
Mdisp = 2 |
'установить режим гашения |
Else |
'снять режим гашения |
Mdisp = 0 |
|
End If |
'на обновление индикации |
Goto Km1_1 |
|
'---------------------------------------------------------------------------------- |
|
'обработка прерывания таймера 0 |
|
============================================================================= 16
===================================== Справочник по программированию «Bascom-AVR» ==
'используется как часы реального времени с частотой 244 Гц (4 мс)
'для этого нужно организовать схему деления 1 МГц/64/64 = 0,000244140625 МГц
Timer0_int: |
|
$asm |
'сохраним регистры |
Push R31 |
|
In R31 , Sreg |
|
Push R31 |
|
Push R30 |
|
'----- |
'переустановим счетчик |
Ldi R31 , 192 |
|
Out Tcnt0 , R31 |
|
'--------------------- |
'вывод в индикатор |
Rcall Led_out |
|
Rcall In_kl |
'опрос клавиатуры |
'--------------------- |
|
'обработка счетчика времени |
'считать счетчик |
Lds R31 , {s_tim} |
|
Dec R31 |
'уменьшить |
Sts {s_tim} , R31 |
'сохранить |
Andi R31 , &h0f |
'маска |
Brne Intt2_4 |
'каждое 16 прерывание (64 мс) обрабатываем еще два счетчика |
'--------------------- |
|
'обработка счетчика переменных временных интервалов |
|
Lds R31 , {w_tim} |
'считать счетчик |
Dec R31 |
'может уменьшаться только от 127 до нуля. |
Brmi Intt2_1 |
|
Sts {w_tim} , R31 |
|
'--------------------- |
|
'обработка счетчика времени звонка |
|
Intt2_1: |
'проверим, а звонок разрешен? |
Lds R31 , {Msnd} |
|
And R31 , R31 |
'если не равен 0 - переход на отключение |
Brne Intt2_2 |
|
'разрешен |
'считаем счетчик времени звонка |
Lds R31 , {r_btim} |
|
And R31 , R31 |
'если он равен 0 - переход |
Breq Intt2_2 |
|
Dec R31 |
'уменьшить |
Sts {r_btim} , R31 |
'и разрешить пищать |
Ldi R31 , &B00001001 |
|
Rjmp Intt2_3 |
|
Intt2_2: |
'запретить пищать |
Ldi R31 , &B00001000 |
|
Intt2_3: |
'в регистр управления таймером 2 |
Out Tccr2 , R31 |
|
'----- |
|
Intt2_4: |
'восстановим регистры |
Pop R30 |
|
Pop R31 |
|
Out Sreg , R31 |
|
Pop R31 |
|
$end Asm |
|
Return |
|
'----------------------------------------------
'обработка прерывания таймера 2. Происходит 1 раз в секунду
Timer2_int: |
|
||
$asm |
push R31 |
'сохраним регистры |
|
' |
|||
In R31 , Sreg |
|
||
' |
Push R31 |
|
|
'----- |
ldi R31 , 255 |
|
|
' |
Sts {ndat} , R31 |
|
|
Pop R31 |
'восстановим регистры |
||
' |
|||
' |
Out Sreg , R31 |
|
|
|
Pop R31 |
|
|
|
Reti |
|
|
$end Asm Return
'----------------------------------------------------------------------------------
'ВВОД ДАННЫХ С КЛАВИАТУРЫ
'клавиатура опрашивается при выводе очередного знакоместа на индикатор
'код кнопки совпадает с номером знакоместа. Осуществляется подавление дребезга
'срабатывание фиксируется при удержании более 6 циклов опроса
In_kl: |
|
|
$asm |
,{Buf_kl} |
'пока буфер клавиатуры не опустеет |
Lds R31 |
||
And R31 |
, R31 |
|
============================================================================= 17
===================================== Справочник по программированию «Bascom-AVR» ==
Breq Inkl |
|
'сканирование не проводится |
||
Ret |
|
|
|
|
'--------- |
|
|
|
|
' НАЧИНАЕМ |
|
|
||
Inkl: |
R31 |
, |
{r_ckl} |
'подготовим счетчика нажатий к обработке |
Lds |
||||
Sbic Pinc |
, 4 |
'считать состояние линии опроса кнопки |
||
Rjmp N_st |
|
'нет нажатия - переход |
||
'--------- |
|
ЕСТЬ |
|
|
' НАЖАТИЯ |
|
|||
Y_st: |
R31 |
, |
6 |
'если равен 6 - нажатие уже было зафиксировано |
Cpi |
||||
Breq Y_st1 |
|
'на выход без запоминания. |
||
Inc |
R31 |
|
|
'иначе нужен инкремент |
Sts |
{r_ckl} , R31 |
'и сохранить |
||
Cpi |
R31 |
, |
6 |
'меньше 6 - тоже выход без действий |
Brne y_st1 |
|
|||
'--------- |
|
ЗАФИКСИРОВАТЬ |
|
|
' НАЖАТИЕ |
'звонить 60 мс |
|||
Ldi |
R31 |
, |
3 |
|
Sts |
{r_btim} , R31 |
'преобразуем код знакоместа (от 0 до 3) |
||
Lds |
R31 |
, |
{Cnt_dis} |
|
Inc |
R31 |
|
|
'в код кнопки (от 1 до 4) |
Sts |
{Buf_kl} , R31 |
|
||
Y_st1: |
|
|
|
|
Ret |
|
|
|
|
'--------- |
|
НЕТ |
|
|
' НАЖАТИЯ |
|
|||
N_st: |
R31 |
, |
R31 |
'проверим счетчик "удержания" |
And |
||||
Breq N_st1 |
|
'не равен нулю |
||
Dec |
R31 |
|
|
'декремент |
Sts |
{r_ckl} , R31 |
'и сохранить |
||
N_st1: |
|
|
|
|
Ret |
|
|
|
|
$end Asm |
|
|
|
|
'---------------------------------------------------------------------------------- |
||||
'данные |
константы позволяют учесть и скорректированит "нерегулярность" монтажа индикатора |
|||
Const N_scn = |
&B11110000 |
' МАСКА СКАНИРОВАНИЯ ДЛЯ ИНДИКАТОРА С ОА |
||
Const N_sc1 = |
&B11111110 |
' МАСКА ДЛЯ ПОДСВЕТКИ 1-ГО ЗНАКОМЕСТА |
||
Const N_sc2 = |
&B01111101 |
' МАСКА ДЛЯ ПОДСВЕТКИ 2-ГО ЗНАКОМЕСТА |
||
Const N_sc3 = |
&B11111011 |
' МАСКА ДЛЯ ПОДСВЕТКИ 3-ГО ЗНАКОМЕСТА |
||
Const N_sc4 = |
&B11110111 |
' МАСКА ДЛЯ ПОДСВЕТКИ 4-ГО ЗНАКОМЕСТА |
||
'----------------------------- |
|
|||
'обслуживание |
светодиодного 7-сегментного индикатора |
|||
Led_out: |
|
|
|
|
$asm |
R31 |
, |
{Cnt_dis} |
'считать значение счетчика сканирования |
Lds |
||||
Inc |
R31 |
|
|
|
Andi R31 , 3 |
'и сохранить |
|||
Sts |
{Cnt_dis} , R31 |
|||
'--------- |
, |
1 |
|
|
Cpi |
R31 |
|
||
Breq Led_1 |
|
|
||
'--------- |
, |
2 |
|
|
Cpi |
R31 |
|
||
Breq Led_2 |
|
|
||
'--------- |
, |
3 |
|
|
Cpi |
R31 |
|
||
Breq Led_3 |
|
|
||
Led_0: |
|
|
|
|
'--------- |
, |
{buf_dis} |
|
|
Lds |
R30 |
' ЗНАЧЕНИЕ ДЛЯ ПОДСВЕТКИ 1-ГО ЗНАКОМЕСТА |
||
Ldi |
R31 |
, |
N_sc1 |
|
Rjmp Led_e |
|
|
||
'--------- |
|
|
|
|
Led_1: |
R30 |
, |
{buf_dis+1} |
|
Lds |
' ЗНАЧЕНИЕ ДЛЯ ПОДСВЕТКИ 2-ГО ЗНАКОМЕСТА |
|||
Ldi |
R31 |
, |
N_sc2 |
|
Rjmp Led_e |
|
|
||
'--------- |
|
|
|
|
Led_2: |
R30 |
, |
{buf_dis+2} |
|
Lds |
' ЗНАЧЕНИЕ ДЛЯ ПОДСВЕТКИ 3-ГО ЗНАКОМЕСТА |
|||
Ldi |
R31 |
, |
N_sc3 |
|
Rjmp Led_e |
|
|
||
'--------- |
|
|
|
|
Led_3: |
R30 |
, |
{buf_dis+3} |
|
Lds |
' ЗНАЧЕНИЕ ДЛЯ ПОДСВЕТКИ 4-ГО ЗНАКОМЕСТА |
|||
Ldi |
R31 |
, |
N_sc4 |
|
============================================================================= 18
===================================== Справочник по программированию «Bascom-AVR» ==
Led_e: |
Portd , R30 |
|
Out |
|
|
In R30 , Portc |
' МАСКА СКАНИРОВАНИЯ |
|
Ori |
R30 , N_scn |
|
And |
R30 , R31 |
|
Out |
Portc , R30 |
|
Ret |
|
|
$end Asm |
|
|
'---------------------------------------------------------------------------------- |
|
УТИЛИТЫ |
' |
|
|
'---------------------------------------------------------------------------------- |
|
|
'ВЫВОД СООБЩЕНИЯ СООБЩЕНИЯ, НОМЕР КОТОРОГО УКАЗАН Index |
||
Dis_tr: |
Value = 1 To 4 |
'определим число считываемых символов |
For |
||
|
Tmpb = Index * 4 |
'вычислить индекс, указывающих на начало сообщения |
|
Tmpb = Tmpb + Value |
'вычислить индекс, указывающих на текущий символ |
|
Decr Tmpb |
'коррекция индекса |
|
Tmpb = Lookup(tmpb , Tr_led) |
'считать из таблицы код символа |
|
Gosub Pos_seg |
'преобразовать в код сегментов |
|
Buf_dis(index) = Tmpb |
'записать в буфер индикации |
Next Index |
|
|
Return |
|
|
'---------------------------------------------------------------------------------- |
|
|
'П/П ВЫБОРА ИЗ ТАБЛИЦЫ КОДА ЧИСЛА В 7-СЕГМЕНТНОМ КОДЕ ИЗ ASCII (ВТОРОГО СИМВОЛА) |
||
Asc_seg2: |
'сдвинуть строку влево на одну позицию |
|
Bufr = Mid(bufr , 2) |
||
'---------
'П/П ВЫБОРА ИЗ ТАБЛИЦЫ КОДА ЧИСЛА В 7-СЕГМЕНТНОМ КОДЕ ИЗ ASCII
Asc_seg: |
|
|
|
|
'считать первый символ строки |
||||
|
Tmpb = Asc(bufr) |
|
|
|
|||||
' |
Tmpb = Tmpb - &H30 |
|
|
|
'преобразовать ASCII в число |
||||
--------- |
|
|
|
|
7-СЕГМЕНТНЫЙ КОД |
|
|||
'П/П ПРЕОБРАЗОВАНИЯ ПОЗИЦИОННОГО КОДА В |
|
||||||||
Pos_seg: |
|
|
|
|
'считать из таблицы, используя число как смещение |
||||
|
Tmpb = Lookup(tmpb , Tabseg0) |
|
|||||||
'при необходимости подключить следующую |
строчку |
|
|
||||||
' |
Gosub Tr_seg |
|
|
|
'исправить монтаж сегментов индикатора |
||||
Return |
|
|
|
|
|
|
|
|
|
'--------- |
|
|
|
|
|
ДЛЯ КОРРЕКЦИИ "НЕПРАВИЛЬНОГО" МОНТАЖА |
|||
'П/П ПЕРЕСЫПКИ БИТОВ 7-СЕГМЕНТНОГО КОДА |
|||||||||
Tr_seg: |
|
|
|
|
: Value.2 = Tmpb.5 |
'например "отзеркалить" |
|||
|
Value.0 = Tmpb.7 : Value.1 = Tmpb.6 |
||||||||
|
Value.3 = Tmpb.4 : Value.4 = Tmpb.3 |
: Value.5 = Tmpb.2 : Value.6 = Tmpb.1 : Value.7 = Tmpb.0 |
|||||||
' |
Tmpb = Value : Return |
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
'ТАБЛИЦА РАСПОЛОЖЕНИЯ СЕГМЕНТОВ ИНДИКАТОРА - ПРОТОТИПА |
|
||||||||
'--------- |
|
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
' |
|
||||||||
' |
|
¦-----------------------------------------------h1 |
g1 |
f1 |
e1 |
d1 |
c1 |
b1 |
a1 |
'BUF_DIS(4) |
|||||||||
'BUF_DIS(3) |
¦ h2 |
g2 |
f2 |
e2 |
d2 |
c2 |
b2 |
a2 |
|
'BUF_DIS(2) |
¦ h3 |
g3 |
f3 |
e3 |
d3 |
c3 |
b3 |
a3 |
|
'BUF_DIS(1) |
¦ h4 |
g4 |
f4 |
e4 |
d4 |
c4 |
b4 |
a4 |
|
'------------------------------------------- |
|
|
|
|
|
|
|
|
|
'РАСПОЛОЖЕНИЕ СЕГМЕНТОВ НА ПОЛЕ ИНДИКАТОРА
'===============================================
' ¦ |
-a4- |
|
-a3- |
|
-a2- |
|
-a1- |
|
¦ |
|
' ¦ |
I |
I |
I |
I |
¦ |
|
||||
' ¦ I |
I |
I |
I |
¦ |
|
|||||
' ¦ |
f4 |
b4 |
f3 |
b3 |
f2 |
b2 |
f1 |
b1 |
¦ |
|
' ¦ I |
I |
I |
I |
I |
I |
I |
I |
¦ |
|
|
' ¦ |
-g4- |
I |
-g3- |
I |
-g2- |
I |
-g1- |
I |
¦ |
|
' ¦ I |
I |
I |
I |
¦ |
|
|||||
' ¦ |
e4 |
c4 |
e3 |
c3 |
e2 |
c2 |
e1 |
c1 |
¦ |
|
' ¦ I |
I |
I |
I |
I |
I |
I |
I |
¦ |
|
|
' ¦ |
-d4- |
[h4] |
-d3- |
|
-d2- |
[h2] |
-d1- |
|
¦ |
|
' ¦ |
|
|
[h3] |
|
[h1]¦ |
|
||||
' ¦ |
|
|
|
|
|
|
|
|
¦ |
|
' |
=============================================== |
|
||||||||
'----------------------------------------------------------- |
|
|
|
|
, СВЕЧЕНИЕ "0" |
|
|
|
||
' ТАБЛИЦА КОДОВ СЕГМЕНТОВ |
|
|
|
|||||||
'----------------------------------------------------------- |
|
|
'ШЕСТНАДЦАТИРИЧНЫЕ ЦИФРЫ ОТ |
0(00h) ДО 15(0Fh) |
||||||
Tabseg0: |
|
|||||||||
|
|
|
|
|
' 0 , |
1 |
-d0 - |
|
||
|
Data &HC0 , &HF9 |
|
|
|
I |
|||||
|
Data &HA4 , &HB0 |
|
|
|
' 2 , |
3 |
I |
|||
|
Data &H99 , &H92 |
|
|
|
' 4 , |
5 |
D5 |
D1 |
||
|
Data &H82 , &HF8 |
|
|
|
' 6 , |
7 |
I |
I |
||
|
Data &H80 , &H90 |
|
|
|
' 8 , |
9 |
-d6 - |
|
||
============================================================================= 19
===================================== Справочник по программированию «Bascom-AVR» ==
|
Data |
&H88 |
, &H83 |
' A |
, B I |
I |
|
|
Data |
&HC6 |
, &HA1 |
' C |
, D D4 |
D2 |
|
|
Data |
&H86 |
, &H8E |
' E |
, F I |
I |
|
' |
|
|
|
' |
|
-D3- |
[D7] |
|
|
'ДРУГИЕ СИМВОЛЫ (УСЛОВНАЯ |
НУМЕРАЦИЯ) |
|
|||
|
Data |
&HAF |
|
||||
|
|
' R |
*(16) |
|
|||
|
Data |
&HE3 |
|
' U |
*(17) |
|
|
|
Data |
&HC7 |
|
' L(18) |
|
|
|
|
Data |
&HFF |
|
' ПРОБЕЛ(19) |
|
||
|
Data |
&H0B |
|
' H |
*(20) |
|
|
|
Data |
&HB7 |
|
' =(21) |
|
|
|
|
Data |
&HF7 |
|
' _(22) |
|
|
|
|
Data |
&HC3 |
|
' ЛЕВАЯ ЧАСТЬ БУКВЫ "W"(23) |
|||
|
Data |
&HE1 |
|
' ПРАВАЯ ЧАСТЬ БУКВЫ "W"(24) |
|||
|
Data |
&H0C |
|
' P(25) |
|
|
|
|
Data |
&HFB |
|
' I |
*(26) |
|
|
|
Data |
&H07 |
|
' T |
*(27) |
|
|
|
Data |
&HAB |
|
' П |
*(28) |
|
|
|
Data |
&HA3 |
|
' O |
*(29) |
|
|
|
Data |
&HE7 |
|
' L |
*(30) |
|
|
|
Data |
&H09 |
|
' H(31) |
|
|
|
|
Data |
&H9C |
|
' ГРАДУС(32) |
|
||
|
Data |
&HAF |
|
' ФРОНТ -(33) |
|
||
|
Data |
&HBB |
|
' СПАД ¬(34) |
|
||
|
Data |
&HBF |
|
' МИНУС -(35) |
|
||
'ПРИМЕЧАНИЕ. * - МАЛЫЕ СИМВОЛЫ |
|
|
|
|
|||
'----------------------------------------------------------- |
|
|
|
|
символов таблицы Tabseg0 |
||
'сообщения индикатора, записанные в номерах |
|||||||
Tr_led: |
17 , |
22 , 1 , 2 |
' "v_12" (0) |
|
|||
|
Data |
|
|||||
|
Data |
19 , |
5 , 31 , 19 |
' " |
SH " (1) |
|
|
|
Data |
14 , |
16 , 12 , 5 |
' "ErCS" (2) |
|
||
|
Data |
19 , |
0 , 15 , 15 |
' " |
OFF" (3) |
|
|
|
Data |
19 , |
0 , 18 , 19 |
' " |
OL " (4) |
|
|
|
Data |
19 , |
18 , 0 , 19 |
' " |
LO |
" (5) |
|
' |
Data |
19 , |
23 , 24 , 19 |
' " |
W |
" (6) |
|
|
|
|
|
|
|
|
|
'ожидание нажатий 2.5 с |
|
|
|
|
|||
Waitklc: |
|
|
'задать время ожидания 2500=64 мс * 40 |
||||
|
W_tim = 40 |
|
|||||
|
Buf_kl = 0 |
|
'очистим регистр клавиатуры от кода предыдущего нажати |
||||
'цикл ожидания нажатий |
|
|
|
|
|||
Do |
If Buf_kl |
<> 0 Then |
'есть нажания кнопки? |
||||
|
Goto Wtklend |
'да |
- на выход |
|
|||
|
End If |
|
|
|
|
|
|
|
Idle |
|
|
'или истечения разрешенного времени 2.5 с |
|||
Loop Until W_tim = 0 |
|||||||
Wtklend: |
|
|
|
|
|
|
|
'следующая строка добавляется при необходимости |
|
|
|||||
' |
Gosub Tr_klb |
'скорректировать номер кнопокReturn |
|||||
'--------- |
|
|
|
|
|
|
|
'П/П ПЕРЕСЫПКИ НОМЕРОВ КНОПОК - ПЕРЕХОД ОТ ФИЗИЧЕСКИХ НОМЕРОВ К ЛОГИЧЕСКИМ |
|||||||
Tr_klb: |
|
|
|
|
|
|
|
|
Buf_kl = Lookup(Buf_kl , tklb) : Return |
|
|
|
|||
Tklb: |
0 , 4 , 3 , 2 , 1 |
|
'таблица перекодировки, например, наоборот |
||||
' |
Data |
|
|||||
|
|
|
|
|
|
|
|
============================================================================= 20
