6.7.1. Постановка задачи и алгоритм ее решения
Возьмем для примера следующую, достаточно часто встречающуюся на практике, задачу, в которой необходимо измерить временной интервал между двумя импульсами в сигнале, поступающем от датчика и выдать полученный результат в виде параллельных двоичных кодов в порт ввода/вывода. Причем, входные импульсные сигналы имеют следующие параметры:
где - длительность цикла выполнения команды микроконтроллера.
Для решения поставленной задачи выберем микроконтроллер PIC 16C84(16F84) с многократно электрически перепрограммируемыми пользователем ППЗУ программ и данных-констант а также имеющим возможность работы с прерываниями. Причем, в данном микроконтроллере прерывание возникает по целому ряду причин и, в том числе, при переполнении счетчика-таймера TMRO (RTCC).
Основываясь на знании особенностей архитектуры и функционирования микроконтроллера PIC 16C84(16F84) можно предложить один из возможных вариантов алгоритма решения поставленной задачи. Последовательность действий при этом должна быть следующей:
1. Организовать процедуру ожидания поступления первого импульса, например, на вывод микроконтроллера RA1 (стандартная процедура «Ожидания события»).
2. После обнаружения переднего фронта первого импульса запустить внутренний таймер/счетчик TMRO.
3. Организовать процедуру ожидания поступления второго импульса на тот же вывод RA1.
4. После обнаружения переднего фронта второго импульса остановить таймер/счетчик.
5. Полученный в регистре таймера/счетчика параллельный двоичный код выдать в порт В в сопровождении стробирующего сигнала, свидетельствующего о готовности данных на выходе микроконтроллера. Стробирующий сигнал выдается, например, на вывод RA0.
6.7.2. Написание исходного текста программы
Написание исходного текста программы осуществляется с помощью редактора Editor Only, имеющегося в составе интегрированной среды MPLAB 3.30. Для того, чтобы войти в оболочку редактора, необходимо выполнить следующие действия:
1. Осуществить запуск основного пакета программ (выбрав в главном меню интегрированной среды иконку с надписью MPLAB);
2. Выбрать в меню пользователя пакетом MPLAB 3.30 пункт Option;
3. Выбрать в меню Option опцию Development Mode ... и в ней задать режим «Editor Only» а также тип процессора PIC 16C84(16F84);
4. Нажать кнопку с надписью RESET (что позволит запомнить наше изменение);
5. Выбрать в меню пользователя пакетом MPLAB пункт File;
6. Выбрать в меню File опцию New Source.
После этого можно приступить к написанию исходного текста программы. Причем, в исходном тексте программы сознательно сделаем некоторые ошибки, которые необходимо будет выявить и устранить на этапах трансляции и отладки программы с помощью Ассемблера MPASM и симулятора MPLAB-SIM.
Исходный текст программы в этом случае имеет следующий вид:
LIST P=PIC16C84
; Секция заголовка
TMR0 EQU 01H
STATUS EQU 03H
PORTA EQU 05H
PORTB EQU 06H
INTCON EQU 0BH
TRISA EQU 05H
TRISB EQU 06H
; Описание битов регистра STATUS
C EQU 00H
DC EQU 01H
Z EQU 02H
PD EQU 03H
TO EQU 04H
RP0 EQU 05H
RP1 EQU 06H
IRP EQU 07H
; Описание битов регистра INTCON
RBIF EQU 00H
INTF EQU 01H
TOIF EQU 02H
RBIE EQU 03H
INTE EQU 04H
TOIE EQU 05H
EEIE EQU 06H
GIE EQU 07H
; Описание битов порта В
RB0 EQU 00H
RB1 EQU 01H
RB2 EQU 02H
RB3 EQU 03H
RB4 EQU 04H
RB5 EQU 05H
RB6 EQU 06H
RB7 EQU 07H
; Описание битов порта А
RA0 EQU 00H
RA1 EQU 01H
RA2 EQU 02H
RA3 EQU 03H
RA4 EQU 04H
; Рабочая секция
; Начало исполняемой части рабочей программы
ORG 00H ; Следующая команда будет рас-
; положена по адресу 00H
GOTO BEGIN
ORG 004H ; Указываем адрес ячейки памяти
; программ 004Н, куда осуществляется переход при возникновении преры-
; вания. В нашем случае это прерывание при переполнении счетчика
; таймера tmr0
INCF TMR1,1 ; Инкрементируем счетчик TMR1
; при возникновении каждого очередного прерывания от TMR0. В резуль-
; тате таких действий получим двухбайтное число, хранящееся в регистрах
; tmr0 и tmr1. Причём старшая часть числа находится в регистре
; tmr1,а младшая - в регистре tmr0. Данное число соответствует коли-
; честву тактов нашего микроконтроллера прошедших между импульсами.
CLRF TMR0 ; Сбрасываем значение регистра
; tmr0
BCF INTCON,TOIF ; Сбрасываем флаг TOIF, указы-
; вающий на то, что было преры-
; вание по переполнению счетчи-
; ка таймера tmr0
RETFIE ; Выходим из процедуры обра-
; ботки прерывания от таймера с разрешением прерываний. То есть, уста-
; навливаем бит gie в регистре intcon. Это выполняется автоматически
; по команде retfie.
; Далее располагается текст основной программы
BEGIB ; Метка BEGIN
CALL INIT ; Вызываем процедуру для ини-
; циализации портов и прерыва
; ний
POVTOR BTFSC PORTA,PA1 ; Ждем начало импульса, то есть
; передний фронт импульса
GOTO POVTOR
BCF INTCON,TOIF ; Сбрасываем флаг прерыва-
; ния от таймера
BSF INTCON,TOIE ; Разрешаем прерывание по
; факту переполнения счётчика
; таймера
POVTOR_1 BTFSS PORTA,PA1 ; Ждем задний фронт первого
; импульса, то есть конец перво
; го импульса
GOTO POVTOR
POVTOR_2 BTFSC PORTA,PA1 ; Ждем передний фронт второго
; импульса (т.е. его начало)
GOTO POVTOR_2
BCF INTCON,TOIE ; Запрещаем прерывание по
; факту переполнения счетчи-
; ка таймера
CALL PERED ; Вызываем процедуру передачи
; информации
GOTO POVTOR ; Повторяем измерение
PERED MOVF TMR0,0 ; Передаём в порт В значение ре-
; гистра TMR0
MOVWF PORTB
BSF PORTA,PA0 ; Устанавливаем флаг передачи
NOP ; Организуем задержку
NOP
NOP
BCF PORTA,PA0 ; Сбрасываем флаг передачи
MOVF TMR1,0 ; Передаём в порт В значение
; регистра tmr1
MOVWF PORTB
BSF PORTA,PA0 ; Устанавливаем флаг передачи
NOP ; Организуем задержку
NOP
NOP
BCF PORTA,PA0 ; Сбрасываем флаг передачи
; Выход из процедуры передачи
INIT BSF STATUS,RP0 ; Устанавливаем активной
вторую страницу памяти
MOVLW B'00000010' ; Устанавливаем направления
; работы выводов порта А. В
; данном случае вывод ra1 бу-
; дет работать на ввод , а осталь-
; ные на вывод
MOVWF TRISA
MOVLW B'00000000' ; Устанавливаем направления
; работы выводов порта В.Все
; выводы порта работают в дан-
; ном случае на вывод информа-
; ции
MOVWF TRISB
BSF 1,5 ; Устанавливаем выходы генера-
; тора и предделителя на таймер
BCF STATUS,RP0 ; Cнова делаем активной пер-
; вую страницу
BCF PORTA,PA0 ; Устанавливаем на выводе ra1
; нулевой уровень
RETURN ; Конец процедуры инициализа-
; ции
END
; Конец всей нашей программы
После написания программы сохраняем её под любым именем. Для этого необходимо выбрать меню FILE и выбрать подменю SAVE AS..., после чего Вас попросят ввести имя файла с расширением. По умолчанию (если нет расширения) система автоматически добавит расширение ASM. Сохраним наш файл, например, с именем OUR.ASM
6.7.3. Преобразование исходного текста программы
в объектный код
Теперь начнём создавать объектный код (модуль) нашей программы. Для этого войдём в меню PROJECT и выберем подменю NEW PROJECT.После єтого у Вас попросят ввести следующую информацию:
· PROJECT PATH AND NAME - указать путь к поиску объекта
и его имя.
Пишем: C:MPLABOUR.PJT
· DEFAULT TOOLBAR - выбрать внешний вид оболочки.
Оставляем без изменений.
· DEFAULT KEY MAPPING - указать файл переназначения
функций клавиш.
Оставляем без изменений.
· DEVELOPMENT MODE - выбрать среду (режим) для
отладки программы.
Выбираем MPLAB-SIM SIMULATOR и нажимаем кнопку OK.
После этих действий перед Вами появится окно EDIT PROJECT где от Вас требуется выбрать файл программы вошедшей в данный проект. В нашем примере берём из списка NON-PROJECT FILES файл с именем OUR.ASM, выбираем кнопку <=ADD и нажимаем кнопку ОК.
Теперь выбираем в меню PROJECT подменю BUILD ALL. После чего начинается компиляция нашей программы.
После этих действий мы увидим окно с именем MPASM v02.00, в котором содержится следующая информация:
* Вверху первая строка указывает есть ли ошибки. В нашем случае
они есть, поэтому появляется следующее сообщение:
- ERRORS FOUND и красная линия 100%;
· Количество ошибок - ERRORS: 12;
· Количество описок - WARNINGS:
- REPORTED: 1;
- SUPPRESSED: 0;
· Количество сообщений:
- REPORTED: 0;
- SUPPRESSED: 0;
· Всего строк - (LINE ASSEMBLED): 132.
Затемпоявится окно с именемCOMPILE STATUS, содержащее следующую информацию:
STATUS: THERE ARE ERRORS
COMMAND LINE:
MPASMWIN /e /l /ainhx8m /q c:mplabour.asm
Это окноинформирует были ли ошибки при компиляции. В нашем случаи они были.
Выбираем кнопку OK.
Так как были ошибки, то система автоматически открывает окно с файлом ошибок, который генерирует MPASM. Теперь, последовательно анализируя сообщения в файле ошибок, будем исправлять ошибки в исходном тексте программы:
1. Warning[207] C:MPLABOUR.ASM 36: Found label after column 1. (RB7).
В этом сообщении об ошибке сказано следующее (см.п.2.5.2.):ПРЕДУПРЕЖДЕНИЕ, [код ошибки-207], путь к файлу (место расположения и имя программы)- C:MPLABOUR.ASM, номер строки (в которой обнаружена)- 36: комментарий к ошибке (то есть, в чем заключается ошибка ) - НАЙДЕНА МЕТКА ПОСЛЕ СТРОКИ 1.(RB7).
Обращаемся к строке №36:
RB7 EQU 07H
Данная ошибка связанна с пробелами в начале строки, так как ассемблер не знает команды RB7.
Наши действия: Убираем пробелы в начале строки.
2. Error[113] C:MPLABOUR.ASM 47: Symbol not previously defined (BEGIN)
В этой ошибке говорится: СИМВОЛ НЕОПРЕДЕЛЁН (BEGIN)
Смотрим в нашей программе строку №47:
GOTO BEGIN ; Переход на метку
Итак, мы определили метку BEGIN, но почему же ошибка? Просматривая программу, мы увидим, что в строке №69 написано:
BEGIB ; МЕТКА BEGIN
То есть, мы написали вместо BEGIN -> BEGIB.
Значит необходимо исправить єту описку.
3. Error[113] C:MPLABOUR.ASM 52: Symbol not previously defined (TMR1).
В этой ошибке говорится: СИМВОЛ НЕОПРЕДЕЛЁН (TMR1).
Проверяем описание регистров в секции заголовка. При этом выясняется, что там вообще нет описания регистров памяти данных (ОЗУ).
Поєтому в секцию заголовка добавим описание регистра TMR1 расположив его, например, по адресу 0CH в памяти данных:
TMR1 EQU 0CH
4. Error[113] C:MPLABOUR.ASM 73: Symbol not previously defined (PA1).
В этой ошибке говорится: СИМВОЛ НЕОПРЕДЕЛЁН (PA1).
Проверяем описание регистров в секции заголовка и увидим, что биты порта А определены под именами RA0,RA1,RA2,RA3,RA4, а в программе используем имена РА0,РА1,PA2,PA3,PA4.
Делаем соответствующие изменения в программе.
5. Error[113] C:MPLABOUR.ASM 81: Symbol not previously defined (PA1).
В этой ошибке говорится: СИМВОЛ НЕОПРЕДЕЛЁН (PA1), поэтому выполняем такие же действия, как и в п.4.
6. Error[113] C:MPLABOUR.ASM 85: Symbol not previously defined (PA1).
В этой ошибке говорится: СИМВОЛ НЕОПРЕДЕЛЁН (PA1), поэтому выполняем такие же действия, как и в п.4.
7. Error[113] C:MPLABOUR.ASM 97: Symbol not previously defined (PA0).
В этой ошибке говорится СИМВОЛ НЕОПРЕДЕЛЁН (PA0), поэтому выполняем такие же действия, как и в п.4.
8. Error[113] C:MPLABOUR.ASM 101: Symbol not previously defined (PA0).
В этой ошибке говорится СИМВОЛ НЕОПРЕДЕЛЁН (PA0), поэтому выполняем такие же действия, как и в п.4.
9. Error[113] C:MPLABOUR.ASM 102: Symbol not previously defined (TMR1).
В этой ошибке говорится СИМВОЛ НЕОПРЕДЕЛЁН (TMR1). Эта ошибка уже исправлена в п.3.
10. Error[113] C:MPLABOUR.ASM 105: Symbol not previously defined (PA0).
В этой ошибке говорится: СИМВОЛ НЕОПРЕДЕЛЁН (PA0), поэтому выполняем такие же действия, как и в п.4.
11. Error[113] C:MPLABOUR.ASM 109: Symbol not previously defined (PA0).
В этой ошибке говорится: СИМВОЛ НЕОПРЕДЕЛЁН (PA0), поэтому выполняем такие же действия, как и в п.4.
12. Error[122] C:MPLABOUR.ASM 112: Illegal opcode (ВТОРУЮ).
В этой ошибке говорится: НЕИЗВЕСТНАЯ КОМАНДА (ВТОРУЮ).
Смотрим на строку №114:
INIT BSF STATUS,RP0 ; Устанавливаем активной
вторую страницу памяти
Оказывается, что мы забыли поставить знак комментария (;) в начале 115 строки.
Делаем соответствующие изменения в исходном тексте программы.
13. Error[113] C:MPLABOUR.ASM 127: Symbol not previously defined (PA0).
В этой ошибке говорится: СИМВОЛ НЕОПРЕДЕЛЁН (PA0), поэтому выполняем такие же действия, как и в п.4.
Теперь, когда вроде бы исправили все ошибки, запускаем откорректированную программу на компиляцию снова.
Теперь всё откомпилировалось без ошибок. После этого, в принципе, можно было бы записать откомпилированную программу в ППЗУ микроконтроллера. Однако, более целесообразно вначале промоделировать и отладить работу программы с помощью, например, программного симулятора MPLAB-SIM, имеющегося в составе интегрированной среды MPLAB 3.30.
6.7.4. Отладка программы
Для использования симулятора необходимо проделать следующие операции:
- Выбрать в главном меню пункт OPTION;
- Выбрать опцию DEVELOPMENT MODE;
- Выбрать MPLAB-SIM Simulator и тип микроконтроллера PIC16C84;
- Выбрать кнопку RESET , после чего Вас попросят сохранить наш проект и загрузится симулятор.
После этого осуществляем следующие действия:
- Выбираем в меню PROJECT и загружаем наш проект;
- Выбираем в меню DEBUG-RUN-RESET;
- Выбираем в меню DEBUG-RUN-STEP для пошагового выполнения нашей программы.
Теперь наша программа как-то выполняется, но для окончательной отладки нужно задать уровни сигналов на выводах микроконтроллера. Для этого воспользуемся текстовым редактором (любым) и создадим следующий файл стимула (файл для эмуляции уровней сигналов на выводах микроконтроллера):
OUR.STI
STEP RA0
25 0
30 1
100 0
105 1
115 0
В этом файле STEP- значение счетчика циклов в симуляторе, а RA0- вывод порта нашего микроконтроллера.
Запускаем на выполнение программу следующим образом:
- Выбираем в меню DEBUG-RUN-RESET;
- Выбираем в меню DEBUG-SIMULATOR STIMULUS-PIN STIMULUS-ENABLE;
- Вводим имя нашего файла OUR.STI;
- Выбираем в меню DEBUG-RUN-STEP для пошагового выполнения нашей программы.
Для наблюдения значений регистров воспользуемся функцией WATCH. Для этого выбираем WINDOW NEW WATCH и вводим имена интересующих нас регистров:
TMR0,TMR1,PORTA,PORTB,TRISA,TRISB.
Теперь, пошагово выполняя нашу программу, проверяем логику её работы и обнаружим следующие ошибки:
- в строке 83 имя метки, куда необходимо переходить, должно быть POVTOR_1;
- в строке 112 пропущена инструкция RETURN.
6.7.5. Листинг отлаженной программы
Итак, наша программа работает и окончательный вид её следующий:
LIST P=PIC16C84
; Секция заголовка
TMR0 EQU 01H
STATUS EQU 03H
PORTA EQU 05H
PORTB EQU 06H
INTCON EQU 0BH
TRISA EQU 05H
TRISB EQU 06H
; Описание битов регистра STATUS
C EQU 00H
DC EQU 01H
Z EQU 02H
PD EQU 03H
TO EQU 04H
RP0 EQU 05H
RP1 EQU 06H
IRP EQU 07H
; Описание битов регистра INTCON
RBIF EQU 00H
INTF EQU 01H
TOIF EQU 02H
RBIE EQU 03H
INTE EQU 04H
TOIE EQU 05H
EEIE EQU 06H
GIE EQU 07H
; Описание битов порта В
RB0 EQU 00H
RB1 EQU 01H
RB2 EQU 02H
RB3 EQU 03H
RB4 EQU 04H
RB5 EQU 05H
RB6 EQU 06H
RB7 EQU 07H
; Описание битов порта А
RA0 EQU 00H
RA1 EQU 01H
RA2 EQU 02H
RA3 EQU 03H
RA4 EQU 04H
; Описание регистров памяти данных (ОЗУ)
TMR1 EQU 0CH
;
; Рабочая секция
; Начало исполняемой части рабочей программы
ORG 00H ; Следующая команда будет рас-
; положена по адресу 00H
GOTO BEGIN
ORG 004H ; Указываем адрес ячейки памяти
; программ 004Н, куда осуществляется переход при возникновении прерывания. В нашем случае это прерывание при переполнении счетчика
; таймера tmr0
INCF TMR1,1 ; Инкрементируем счетчик TMR1
; при возникновении каждого очередного прерывания от TMR0.В резуль-
; тате таких действий получим двухбайтное число, хранящееся в регистрах
; tmr0 и tmr1. Причём старшая часть числа находится в регистре
; tmr1, а младшая - в регистре tmr0. Данное число соответствует коли-
; честву тактов нашего микроконтроллера прошедших между импульсами.
CLRF TMR0 ; Сбрасываем значение регистра
; tmr0
BCF INTCON,TOIF ; Сбрасываем флаг TOIF, указы-
; вающий на то, что было преры-
; вание по переполнению счетчи-
; ка таймера tmr0
RETFIE ; Выходим из процедуры обра-
; ботки прерывания таймера с разрешением прерываний. То есть, устанав-
; ливаем бит gie в регистре intcon. Это выполняется автоматически по
; команде retfie.
; Далее располагается текст основной программы
BEGIN ; Метка BEGIN
CALL INIT ; Вызываем процедуру для ини-
; циализации портов и прерыва
; ний
POVTOR BTFSC PORTA,RA1 ; Ждем начало импульса, то есть
; передний фронт импульса
GOTO POVTOR
BCF INTCON,TOIF ; Сбрасываем флаг прерыва
; ния от таймера
BSF INTCON,TOIE ; Разрешаем прерывание по
; факту переполнения счётчика
; таймера
POVTOR_1 BTFSS PORTA,RA1 ; Ждем задний фронт первого
; импульса, то есть конец перво-
; го импульса
GOTO POVTOR
POVTOR_2 BTFSC PORTA,RA1 ; Ждем передний фронт второго
; импульса (т.е. его начало)
GOTO POVTOR_2
BCF INTCON,TOIE ; Запрещаем прерывание по
; факту переполнения счетчи-
; ка таймера
CALL PERED ; Вызываем процедуру передачи
; информации
GOTO POVTOR ; Повторяем измерение
PERED MOVF TMR0,0 ; Передаём в порт В значение ре-
; гистра TMR0
MOVWF PORTB
BSF PORTA,RA0 ; Устанавливаем флаг передачи
NOP ; Организуем задержку
NOP
NOP
BCF PORTA,RA0 ; Сбрасываем флаг передачи
MOVF TMR1,0 ; Передаём в порт В значение
; регистра tmr1
MOVWF PORTB
BSF PORTA,RA0 ; Устанавливаем флаг передачи
NOP ; Организуем задержку
NOP
NOP
BCF PORTA,RA0 ; Сбрасываем флаг передачи
; Выход из процедуры передачи
INIT BSF STATUS,RP0 ; Устанавливаем активной вто
; рую страницу памяти
MOVLW B'00000010' ; Устанавливаем направления
; работы выводов порта А. В
; данном случае вывод ra1 бу-
; дет работать на ввод , а осталь-
; ные на вывод
MOVWF TRISA
MOVLW B'00000000 ; Устанавливаем направления
; работы выводов порта В. В
; данном случае все выводы пор-
; та работают на вывод информа;
; ции
MOVWF TRISB
BSF 1,5 ; Устанавливаем выходы генера-
; тора и предделителя на таймер
BCF STATUS,RP0 ; Снова делаем активной пер-
; вую страницу
BCF PORTA,RA0 ; Устанавливаем на выводе ra1
; нулевой уровень
RETURN ; Конец процедуры инициализа-
; ции
END
; Конец всей нашей программы
6.7.6. Запись программы в ППЗУ микроконтроллера PIC 16F84(16С84)
Для записи отлаженной программы в ППЗУ микроконтроллера PIC 16F84 необходимо снова осуществить ее компиляцию, выбрать файл с именем OUR.HEX и передать его в программатор.
При наличии подключенного к IBM PC программатора PICSTART запись отлаженной программы в микроконтроллер можно осуществить не выходя из оболочки пакета MPLAB 3.30. Для этого необходимо воспользоваться опцией Picstart Plus в меню основного пакета программ.
При отсутствии PICSTARTa можно воспользоваться любым из следующих типов программаторов: COMPIC, PROPIC, PICLAB-16, LEAPER-6 или PROMATE. Для этого необходимо выйти из оболочки интегрированного пакета и запустить соответствующую программу (драйвер), поддерживающую имеющийся в наличии у разработчика программатор.
Все указанные выше программаторы имеют различные по сложности схемы и функциональные возможности. Но, все они рассчитаны на использование ПЭВМ типа IBM PC и подключаются с помощью последовательных интерфейсов типа I2C и RS-232C, либо через параллельный принтерный порт с помощью интерфейса Centronics.