Доброго времени суток, товарищи.. Решил сегодня продолжить изучение микроконтроллеров и надумал обучиться работе с таймером и прерыванием на простейшем контроллере.. Весь день мучался: написал простенький код в 20 машинных слов для мигания светодиодом с различимым интервалом, однако, результат совершенно не тот который я задумывал: светодиод мигает (как бы странно это ни выглядело) со случайным интервалом.. Помогите разобраться: что я делаю не так и действительно ли я написал генератор псевдослучайных чисел?
Код:
Код:
LIST P=PIC16F84A __config 0x3FF1
STATUS EQU .0003 INTCON EQU .0011 OPTION_REG EQU .0001 TMR0 EQU .0001 RP0 EQU .0005 w EQU .0000 f EQU .0001 PORTB EQU .0006 TRISB EQU .0006 Rsec EQU .0015
пару месяцев назад нашел схемку программатора на 3-х резисторах, который прошивает 84-й, поэтому и приобрел его.. сейчас, конечно, есть уже и 628-й и 887-й, однако, в них много регистров, которые пока не совсем ясны, вот и балуюсь пока на 16F84А..
Инициализацию не смотрел, а в прерывании написана какая-то глупость.
CaseBot писал(а):
Код:
main incf Rsec, f btfsc Rsec, 7 retfie
clrf Rsec comf PORTB, f retfie
Получается так, что вы инкрементируете Rsec и когда оно досчитает до 128 должно что-то выполняться. Однако получается наоборот. На каждом шаге вы уходите на clrf Rsec и дальше совсем непонятная конструкция - зачем вам комплиментарное от портаБ? Это раз.
Второе, обрабатывая прерывание вам надо снимать флаг запроса прерывания. Т.е. если прерывание вызвалось по флагу от T0IF - его надо снять внутри прерывания, иначе выйдя из прерывания прерывание снова произойдет сразу!
Ну и научитесь еще и сохранять контекст. В данном примере это не актуально, но в будущем оно будет нужно.
p.s. И еще, бросайте эту дурную затею с толпой EQU... напишите просто include "p16f84.inc" и пользуйтесь на здоровье.
Последний раз редактировалось uldemir Вс окт 13, 2013 13:29:00, всего редактировалось 1 раз.
Получается так, что вы инкрементируете Rsec и когда оно досчитает до 128 должно что-то выполняться. Однако получается наоборот. На каждом шаге вы уходите на clrf Rsec
ну с этим я разобрался, просто когда готовил код (обрезал лишнее) поспешил и перепутал, но суть не в этом, до этого совершенно иными способами прореживался интервал..
uldemir писал(а):
и дальше совсем непонятная конструкция - зачем вам комплиментарное от портаБ? Это раз.
Второе, обрабатывая прерывание вам надо снимать флаг запроса прерывания. Т.е. если прерывание вызвалось по флагу от T0IF - его надо снять внутри прерывания, иначе выйдя из прерывания прерывание снова произойдет сразу!
да, Вы правы.. я думал его необходимо снимать только для идентификации источника прерывания (чтобы узнать что вызвало прерывание)
uldemir писал(а):
Ну и научитесь еще и сохранять контекст. В данном примере это не актуально, но в будущем оно будет нужно.
Претензия за "комплиментарное" снимается. Действительно, микрочип просто инвертирует все биты (а не инвертирует и прибавляет 1).
Сохранение контекста:
Цитата:
Код:
EXAMPLE 8-1: SAVING STATUS AND W REGISTERS IN RAM PUSH MOVWF W_TEMP ; Copy W to TEMP register, SWAPF STATUS, W ; Swap status to be saved into W MOVWF STATUS_TEMP ; Save status to STATUS_TEMP register ISR : : : ; Interrupt Service Routine : ; should configure Bank as required : ; POP SWAPF STATUS_TEMP, W ; Swap nibbles in STATUS_TEMP register ; and place result into W MOVWF STATUS ; Move W into STATUS register ; (sets bank to original state) SWAPF W_TEMP, F ; Swap nibbles in W_TEMP and place result in W_TEMP SWAPF W_TEMP, W ; Swap nibbles in W_TEMP and place result into W
Эта конструкция сделает так, что при вызове прерывания можно установить любую страницу памяти, изменить значение аккумулятора, а по возвращении они восстановятся в то состояние которое было перед вызовом. Чтобы основная программа не потеряла бы данные. Это важно, если основное тело хоть чуть сложнее чем loop: goto loop.
Еще один момент.
Код:
movlw b'10100000' movwf INTCON clrf Rsec
Инициализировать Rsec следует до разрешения прерываний. иначе может быть ситуация, что прерывание уже ждёт и при разрешении сразу же вызывется. А значение переменной, которое используется в прерывании не определено. В результате возможны трудноуловимые глюки, с которыми трудно бороться.
Эта конструкция сделает так, что при вызове прерывания можно установить любую страницу памяти, изменить значение аккумулятора, а по возвращении они восстановятся в то состояние которое было перед вызовом. Чтобы основная программа не потеряла бы данные. Это важно, если основное тело хоть чуть сложнее чем loop: goto loop.
Да, про это я знаю.. Опустил для упрощения кода..
uldemir писал(а):
Инициализировать Rsec следует до разрешения прерываний. иначе может быть ситуация, что прерывание уже ждёт и при разрешении сразу же вызывется. А значение переменной, которое используется в прерывании не определено. В результате возможны трудноуловимые глюки, с которыми трудно бороться.
Про это я не подумал, буду знать.. Еще раз спасибо..
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения