Основная программа main
Данный блок соответствует приведенной ниже части программы.
;==============================================================
main ;основная программа
call initialization ;вызываем подпрограмму инициализации
main1 call indication ;вызываем подпрограмму индикации
goto pressing ;вызываем подпрограмму обработки нажатия кнопки
main2 call transfer ;вызываем подпрограмму передачи импульсов
main3 goto waiting ;вызываем подпрограмму ожидания отраженного сигнала
main4 goto reception ;вызываем подпрограмму приема отраженного сигнала
main5 call calculation ;вызываем подпрограмму вычисления расстояния
;==============================================================
В данной части используются всего два оператора перехода: оператор вызова подпрограммы call и оператор безусловного перехода goto. Для наглядности приведем блок-схему основной программы main, в которую добавлены условия и порядок взаимодействия рассматриваемых далее подпрограмм.
Блок-схема приведена на рис. 9.
Рис. 9. Блок-схема основной программы main.
Подпрограмма инициализации initialization
Данный блок соответствует приведенной ниже части программы.
;==============================================================
initialization ;подпрограмма инициализации и начальных условий
обнуляем значения используемых переменных
clrf PORTA ;очистили выходные защелки порта A
clrf NUMIMP ;обнуляем значение NUMIMP
clrf TIMER1 ;обнуляем значение TIMER1
clrf NUMCH ;обнуляем значение NUMCH
clrf TIMER2 ;обнуляем значение TIMER2
clrf LAPSE ;обнуляем значение LAPSE
clrf DIGIT1 ;обнуляем значение DIGIT1
clrf DIGIT2 ;обнуляем значение DIGIT2
clrf DIGIT3 ;обнуляем значение DIGIT3
;устанавливаем значения используемых переменных
movlw d'5' ;помещаем значение "5" для NUMIMP в аккумулятор
movwf NUMIMP ;помещаем значение из аккумулятора в NUMIMP
movlw d'100' ;помещаем значение "100" для TIMER1 в аккумулятор
movwf TIMER1 ;помещаем значение из аккумулятора в TIMER1
movlw d'100' ;помещаем значение "100" для TIMER2 в аккумулятор
movwf TIMER2 ;помещаем значение из аккумулятора в TIMER2
movlw d'57' ;помещаем значение "57" для LAPSE в аккумулятор
movwf LAPSE ;помещаем значение из аккумулятора в LAPSE
return ;возврат из подпрограммы
;==============================================================
Здесь мы обнуляем используемые переменные, и устанавливаем для них необходимые значения. Количество передаваемых импульсов NUMIMP в сигнале принимаем равным 5 (согласовано с преподавателем). И т.д.
Подпрограмма индикации indication
Данный блок соответствует приведенной ниже части программы.
;==============================================================
indication ;подпрограмма индикации измеренного расстояния
;-----------------------------------------------------устанавливаем биты подключения индикаторов
bsf DIGIT1, 6 ;устанавливаем бит 6 переменной DIGIT1 в 1
bsf DIGIT2, 7 ;устанавливаем бит 7 (точка) переменной DIGIT2 в 1
bsf DIGIT2, 5 ;устанавливаем бит 5 переменной DIGIT2 в 1
bsf DIGIT3, 4 ;устанавливаем бит 4 переменной DIGIT3 в 1
;-----------------------------------------------------выводим значение DIGIT1 на индикатор
movf DIGIT1, 0 ;помещаем значение переменной DIGIT1 в аккумулятор
movwf PORTB ;выводим значение в порт В
устанавливаем задержку отображения
clrf TMR0 ;обнуляем таймер и
bcf INTCON, TOIF ;устанавливаем в 0 флаг прерывания по его переполнению
indc1 btfss INTCON, TOIF ;проверяем флаг прерывания по переполнению таймера
goto indc1 ;если флаг равен 0 (счетчик не переполнен)-выполняем проверку
;если флаг равен 1 (счетчик переполнен) - переходим к следующему
;индикатору
;-----------------------------------------------------выводим значение DIGIT2 на индикатор
movf DIGIT2, 0 ;помещаем значение переменной DIGIT1 в аккумулятор
movwf PORTB ;выводим значение в порт В
устанавливаем задержку отображения
clrf TMR0 ;обнуляем таймер и
bcf INTCON, TOIF ;устанавливаем в 0 флаг прерывания по его переполнению
indc2 btfss INTCON, TOIF ;проверяем флаг прерывания по переполнению таймера
goto indc2 ;если флаг равен 0 (счетчик не переполнен)-выполняем проверку
если флаг равен 1 (счетчик переполнен) - переходим к следующему индикатору
;-----------------------------------------------------выводим значение DIGIT3 на индикатор
movf DIGIT3, 0 ;помещаем значение переменной DIGIT3 в аккумулятор
movwf PORTB ;выводим значение в порт В
;устанавливаем задержку отображения
clrf TMR0 ;обнуляем таймер и
bcf INTCON, TOIF ;устанавливаем в 0 флаг прерывания по его переполнению
indc3 btfss INTCON, TOIF ;проверяем флаг прерывания по переполнению таймера
goto indc3 ;если флаг равен 0 (счетчик не переполнен)-выполняем проверку
;если флаг равен 1 (счетчик переполнен)-
;---------------------------------------------------------------------------------------------------------
return ;возврат из подпрограммы
;==============================================================
В первой части подпрограммы indication мы устанавливаем «биты точки и питания» индикаторов согласно схеме. В переменной DIGIT1 будет храниться значение дециметров от 0 до 9 т.к. используемые в схеме индикаторы являются семи сегментными с дополнительным выводом для десятичного разделителя – точки, в переменной DIGIT2 – значение метров, в переменной DIGIT3 – значение декаметров соответственно. Таким образом согласно схеме для отображения цифр на индикаторах через дешифратор используется всего четыре линии порта B: RB0, RB1, RB2, RB3 для передачи битов 0, 1, 2 и 3 соответственно. Вычисленные отображаемые значения будут храниться в переменных DIGIT1…3 поразрядно, для этого используется первые четыре бита каждой переменной. Линии RB4, RB5 и RB6 порта В мы используем для поочередной подачи питания на индикаторы. Линия RB4 на индикатор декаметров (отображение значения DIGIT3), RB5 на индикатор метров (отображение значения DIGIT2), RB6 на индикатор дециметров (отображение значения DIGIT1). Для этого мы используем следующие биты переменных: бит 6 - DIGIT1, бит 5 - DIGIT2 и бит 4 - DIGIT3 согласно схеме. Линия RB7 порта В используется для подачи сигнала на десятичную точку индикатора метров (переменная DIGIT2). Таким образом используется весь порт В и мы можем, заранее установив биты в переменных посылать их на порт В поочередно, соответственно поочередно подключая индикаторы. Для наглядности ниже приведен рисунок 10.
Рис. 10. Схема индикации.
Далее выводим значение DIGIT1 на порт В. Организуем задержку отображения на индикаторе при помощи таймера TMR0 на 256 мкс. Затем эту же процедуру производим для DIGIT2 и DIGIT3 отображая их значения на индикаторах.
Подпрограмма нажатия кнопки pressing
Данный блок соответствует приведенной ниже части программы.
;==============================================================
pressing ;подпрограмма обработки нажатия кнопки
btfss PORTA, 2 ;проверяем линию RA2 порта А (кнопку s2),
goto main1 ;если не нажата возвращаемся в программу (на indication)
goto main2 ;если нажата-возврат из подпрограммы
;==============================================================
При выполнении этой подпрограммы происходит тестирование присутствия сигнала (+5В) на линии RA2 порта A. Если на линию поступает напряжение (кнопка нажата) – выполняется команда перехода в основную программу на соответствующую метку (main2). В противном случае (кнопка не нажата) переход осуществляется на другую метку основной программы (main2).
Подпрограмма передачи transfer
Данный блок соответствует приведенной ниже части программы.
;==============================================================
transfer ;подпрограмма передачи импульсов
;---------------------------------------------------------------------------------------------------------
movlw d'5' ;помещаем значение "5" для NUMIMP в аккумулятор
movwf NUMIMP ;помещаем значение из аккумулятора в NUMIMP
;-----------------------------------------------------передача сигнала
tran1 bsf PORTA, 0 ;устанавливаем в 1 линию RA0 порта А
movlw d'249' ;помещаем значение "249" для таймера в аккумулятор
movwf TMR0 ;помещаем значение из аккумулятора в таймер
bcf INTCON, TOIF ;устанавливаем в 0 флаг прерывания по переполнению таймера
tran2 btfss INTCON, TOIF ;проверяем флаг прерывания по переполнению таймера
goto tran2 ;если флаг равен 0 (счетчик не переполнен)-выполняем проверку
;если флаг равен 1 (счетчик переполнен)-
;-----------------------------------------------------задержка сигнала
bcf PORTA, 0 ;устанавливаем в 0 линию RA0 порта А
movlw d'251' ;помещаем значение "251" для таймера в аккумулятор
movwf TMR0 ;помещаем значение из аккумулятора в таймер
bcf INTCON, TOIF ;устанавливаем в 0 флаг прерывания по переполнению таймера
tran3 btfss INTCON, TOIF ;проверяем флаг прерывания по переполнению таймера
goto tran3 ;если флаг равен 0 (счетчик не переполнен)-выполняем проверку
;если флаг равен 1 (счетчик переполнен)-
;-----------------------------------------------------считаем импульсы
decfsz NUMIMP, 1 ;уменьшаем зачение NUMIMP на "1" если NUMIMP не равен "0"
;(передано<5импульсов)-
goto tran1 ;переходим в начало подпрограммы на tran1 если NUMIMP равен "0"
;-----------------------------------------------------(передано 5 импульсов)-
movlw d'3' ;помещаем значение "3" для NUMIMP в аккумулятор
movwf NUMIMP ;помещаем значение из аккумулятора в NUMIMP
;---------------------------------------------------------------------------------------------------------
return ;возврат из подпрограммы
;==============================================================
Данная подпрограмма выводит на линию RA0 порта А микроконтроллера 5 импульсов частотой 40 кГц. Учитывая, что мы не подключаем предделитель для таймера-счетчика TMR0 и в схеме используется керамический резонатор частотой 4 МГц имеем тактовую частоту микроконтроллера равную 1 МГц, т.е. одна команда выполняется за 1 мкс. Следовательно один импульс частотой 40 кГц имеет продолжительность 1/40000=25 мкс. Т.е. мы должны сформировать один импульс за 25 мкс. Блок-схема данной подпрограммы представлена на рис. 11. Значения для таймера подобраны таким образом, чтобы сформировать импульс на линии продолжительностью около 25 мкс. В конце подпрограммы устанавливается новое значение для переменной NUMIMP, т.к. оно потребуется для работы другой подпрограммы.