Свежие обсуждения
Микроконтроллеры

Ликбез по программированию PIC

1 60 99

Zandy: К сожалению в си пока не секу. Циклический буфер, это и есть 8 регистров с организацией циклической записи в них?

А чего тут сечь-то? Ты читай это просто как описание алгоритма.

byte measures[8]; резервируем 8 байтов (регистров), под собственно буфер.

byte pos=255; - ещё один регистр, в нём хранится позиция в буфере. Сразу присваиваем начальное значение.

if (pos == 255) { : сравнение значения pos с числом 255. Если равно, то выполняем всё что между "{" и "}"

measures[0] = длина_интервала; - запись в 1й байт буфера значения из переменной "длина_интервала" (считаем от 0)
...
pos = 0; - запись в регистр "pos" значения 0
} конец блока "если"

measures[pos] = длина_интервала; запись в байт c номером pos+1 буфера значения из переменной "длина_интервала"

pos = pos + 1; увеличение значения регистра pos на 1
if (pos == 8) pos = 0; сравнение значения регистра pos с 8, если равен, то запись в pos 0.

ЗЫ. Я не навязываю Си, я алгоритм описываю!

 

Похоже, я всех распугал?!

 

Программу писать не дают. Заставляют графы изучать. А теперь еще и си.
picmaniac: Так что я, похоже, поспешил с расстановкой приоритетов тогда. Подумаю ещё...
Ждем-с.

 

Не, мы не из пугливых!

Zandy: Заставляют Ничуть. Лишь советую, рекомендую. Я и сам в графах не силён пока, тоже изучаю.

Вот возможный вариант алгоритма для обработчика прерываний. Рисунок большой, поэтому даю ссылку:
http://www.pic16.nm.ru/likbez1/algo4_01.gif

 

Я вот тут глянул. Предлагаю упростить алгоритм, чтобы сразу, одним махом отсекать лишние прерывания.
OLDPORTB - регистр, где хранится состояние порта в предыдущем прерывании.
TEMP и TEMP1 - служебные регистры.
итак:
movf PORTB,W
andlw B'11110000'
movwf TEMP
xorwf OLDPORTB,W
andwf TEMP,W
movwf TEMP1

movf TEMP W
movwf OLDPORTB ; запись текущего состояния

после этого побитно будем проверять четыре старших разряда TEMP1, либо сделаем swapf и организуем вычисляемый переход.
Если в каком-то разряде 1, значит был положительный фронт по этому каналу. Выполняем соответствующие действия. Если 0, ничего не делаем и проверяем дальше. Если 0000 спокойненько покидаем прерывание, ну в смысле делаем все остальное. TEMP1 можно использовать как FLAGS на вашем рисунке, только биты будут инверсные.

 

А как в этом случае быть с обнулением таймера тайм-аута? Учитывать только фронты?

 

Да, вроде нужен специальный регистр. Просто с таймаутом как-то все уж очень замороченно. Не сразу врубился. А нельзя ли как-то попроще?

 

А попробуйте, может как-то и придумаете.

 

А почему все-таки нельзя фронты учитывть?
picmaniac: А как в этом случае быть с обнулением таймера тайм-аута? Я все-таки не совсем понимаю терминологии что-ли. Что значит обнуление? Установка числа счета? Разве мы не в каждом прерывании по таймеру это делаем? Нам же всего - навсего надо определять аварийный случай отсутствия сигнала или его очень большой длительности. Ну будем в каждом прерывании смотреть, был ли фронт, т. е. сравнивать TEMP1 с его записанным значением в предыдущем прерывании по таймеру.
А если не использовать дополнительный таймер - таймер тайм аута, а делать прерывания по переполнению нашего рабочего таймера заполнения. Ну и типа, если в течении, например одного - двух прерываний, либо изменения, либо передних фронтов не проходило, считать это аварийным случаем?

 

Zandy: Что значит обнуление? Записать число 0 в регистр таймера тайм-аута.
Разве мы не в каждом прерывании по таймеру это делаем?
У нас два таймера. Физически - два разных регистра. Один - тот, который инкрементируется импульсами заполнения от тактового генератора и применяется для определения периода. Его мы не обнуляем, и прерываний от него не бывает. Он считает себе и считает по кругу, а мы только считываем данные из него в обработчике прерываний. Трогать его (изменять значение принудительно) нельзя, т.к. по его значениям определяются расчётами периоды для всех входов.
Второй - таймер тайм-аута, инкрементируется также от тактового генератора с таким расчётом, чтоб его переполнение наступало при отсутствии изменения уровня хотя бы на одном из входов в течение достаточно длительного времени (более длительности самого долгого периода в допустимом диапазоне нормальной работы). При его переполнении и происходит прерывание по тайм-ауту. Так вот, таймер тайм-аута должен быть обнулён, если импульсы на всех входах присутствуют и следуют с достаточно высокой частотой (не менее минимально допустимой по диапазону нормальной работы). Если его не обнулять - получим постоянные ложные прерывания по тайм-ауту.

Zandy, не зря ведь я старался - рисовал диаграммы на стр.56. Прикиньте по ним общую картину и то, как должен действовать контроллер. Мысленно (или в paint ) уберите импульсы (начиная со второго слева) на одном входе... на двух входах... и т.д.