ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Суббота
23 ноября
536834 Топик полностью
Adept (05.08.2014 13:02 - 13:09, просмотров: 463) ответил Codavr на Ну тогда давай так и договоримся, что для кода объемом до 8 килобайт требующего максимальной эффективности и допускающего его вылизывания пока самому не надоест асм рулит. Если ТЗ выходит за эти рамки, наступаем на горло своей песни и зовем
ну так у мну примерно в таком режиме работа и идёт :)) А лучшая оптимизация, - как известно это оптимизация алгоритма, а не кода, так что меня особо оптимизаторы не впечают. Видел не раз ассемблерный листинг  сишного кода, да, порой вполне себе оптимально (даже в "гнутом" компиляторен, не говоря уж про ИАР), но почему-то проблемы с сишным программером у нас примерно одинаковые (поиск траблов на уровне алгоритма, а не элементарных операций, ну и учитывая то, что в трёёх соснах директив и операторов ассемблера, практически не заблудишься, мне почти всегда легче что-то написать/отладить) Кстати я свой код частенько не совсем оптимально с т.зр быстродействия и размера пишу, - для лучшего понимания и универсальности, но, тем не менее особо от этого не тстрадаю, и как-то получается что не особо напрягаясь выходят довольно стройные , красивые и быстрые вещи :)) (сам себя не похвалишь - никто не похвалит :)) Кстати, по поводу понятности/универсальности/красивости кода, вот, к примеру одно из моих поделийи образцов "наскальной живописи" :)) В общем не вижу проблем перенести его, на любой другой камень, хоть на асме, хоть на Си ДЕКОДИРОВАНИЕ FSK: /* Чувствительность FSK-декодера определяется точностью работы компаратора, и к примеру, для МК ATmega88PA составляет Для Freq1/0=1/2kHz, и формулы длины бита (в периодах несущей) 4/8, соответственно. ~5mv ~5% ошибок ~10mV ~1% ошибок >20mV ~0% ошибок Аппаратные ресурсы: 1) 6 I/O выводов (в т.ч. RxD,TxD,AIN0,AIN1) 2) Модуль UART 3) 16-битный таймер (аппаратный или программно аппаратный на основе 8-битного таймера). Регистры COMPARE используются для кодирования FSK и формирования интервалов мониторинга линии TxD. Минимально необходимая разрядность регистров сравнения = 8 бит, но при других значениях BaudRate, возможно, что понадобится использование 16-разрядных регистров. В любом случае точности 8 бит достаточно, и практически любой BaudRate можно реализовать, используя предделитель таймера. Дискретность счёта - не хуже 1/4 периода самой высокой частоты FSK (можно точнее, хуже не будет, но обязательно кратно 4 :) Аналоговый компаратор (задействованы оба входа на IO ножках МК) ;------------------------------- Расход памяти - 4 байта Определения переменных в памяти: #define S_FSK_TCNTH ;старший байт аппаратно-программного FSK-таймера 1 байт #define S_FSK_TimeL ;Время, насчитанное в момент предыдущего вызова П/П FSK-декодера 2 байта #define S_FSK_TimeH ; при 16-битных слагаемых, и выбранной частоте измерений, Fmin=~0,1Гц, чтобы не вылететь за 16-битный результат #define S_FSK_flags ;байт флагов 1 байт ~~~~~~~~~~~~~~~~~~ Измерение частоты происходит следующим образом: По срабатываению компаратора (прерыванию), засекается текущее время FSK-таймера. При следующем срабатывании компаратора, определяется разница между запомненным ранее и текущем временем. Так как срабатывания компаратора - это "zero-cross" входного сигнала (предположительно FSK), то по измеренной временной разнице между срабатываниями, мы определяем какой из частот в данный момент сооветствует входной сигнал. Детектирование определяется по первому же полупериоду. Для НЧ частоты модуляции FSK, и по второму для ВЧ. Таким образом достигается равенство времён детектирований "0" и "1". Это конечно корректно работает с соотношениями частот 1:2. В соответствии с ним выставляем уровень на ножке RxD апаратного приёмника UART. Таким образом, "на лету", практически в реальном времени, происходит декодирование FSK сигнала и перенаправление декодированного битового потока на вход аппаратного UART. Далее, байтовые операции с приёмным буфером UART выполняются общепринятым образом. КОДИРОВАНИЕ FSK: ~~~~~~~~~~~~~~~~~~ Байт данных, предназначенный для отправки с FSK-кодированием помещается в передающий буфер UART, откуда, штатным образом, на запрограммированной скорости UART-BaudRate, уходит в линию TxD. Тактовый таймер FSK, с заданным интервалом "просматривая" состояние линии TxD, программирует COMPARE регистр FSK-таймера , записав в него текущее значение счётного регистра, +значение периода для частот "0" или "1" , в зависимости от состояния контролируемой линии "TxD" ГЕНЕРАЦИЯ FSK: ~~~~~~~~~~~~~~~~~~ Генерация FSK происходит по прерыванию по регистру COMPARE, FSK-таймера. по этому прерыванию, необходимо инвертировать состояние выходной ножки МК, откуда снимается сигнал. Обновление COMPARE регистра происходит по смене уровня на линии TxD, а так же по событию CompareMatch Соглашение об описании памяти: ------------------------------ В Def-файле проекта должна быть определена переменная "FSK_Memory" - начало области памяти для процедур FSK-библиотеки Последующая подключаемая библиоека должна использовать для выделения своей области памяти переменную "FSK_Memory_END". Первая доступная ячейка будет иметь адрес "FSK_Memory_END+1" */ ;#define FSK_Memory 0x... ;Определение начала области памяти зарезервированной для библиотеки FSK_Lib #define S_FSK_TCNTH FSK_Memory+1 ;старший байт аппаратно-программного FSK-таймера 1 байт #define S_FSK_TimeL FSK_Memory+2 ;Время, насчитанное в момент предыдущего вызова П/П FSK-декодера 2 байта #define S_FSK_TimeH FSK_Memory+3 ; при 16-битных слагаемых, и выбранной частоте измерений, Fmin=~0,1Гц, чтобы не вылететь за 16-битный результат #define S_FSK_flags FSK_Memory+4 ;байт флагов 1 байт #define FSK_Memory_END FSK_Memory+4 ;Определение начала области памяти зарезервированной для библиотеки FSK_Lib ;------------------------------------------------------------------------------------------------------------------------------------ ;Определения Входных/Выходных линий ;------------------------------------------- ; -- Линия TxD (UART) - выход UART битового потока, направляемого в FSK-кодер #define FSK_TxD_PIN PIND ;Регистры PIN, PORT порта контроля линии TxD и номера линии/бита #define FSK_TxD_PORT PORTD #define FSK_TxD_PinNum 1 #define FSK_TxD_PinMask bit1 ; ; -- Линия FSK_out - выход FSK генератора (синтезируемый FSK-сигнал, соответствующий битовому потоку на ножке TxD) #define FSK_out_PORT PORTB ;Регистры PIN, PORT выходной линии FSK и номера линии/бита #define FSK_out_PIN PINB #define FSK_out_DDR DDRB #define FSK_out_PinNum 3 #define FSK_out_PinMask bit3 ; ; -- Линия DATAbit_out - выход битового потока с FSK декодера (битовый поток с декодекрра FSK, подаётся на ножку RxD аппаратного UART) #define FSK_DATAbit_PORT PORTD ;Регистры PIN, PORT выходной линии FSK и номера линии/бита #define FSK_DATAbit_PIN PIND #define FSK_DATAbit_DDR DDRD #define FSK_DATAbit_PinNum 5 #define FSK_DATAbit_PinMask bit5 ; ;------------------------------------------------------------------------------------------------------------------------------------ ;Флаги регистра "S_FSK_flags" #define BitStream_bm bit7 ;флаг состояния битового потока на текущий момент (для FSK-передатчика) #define BitStream_bp 7 #define DATAbit_bm bit6 ;Бит данных на текущий момент (устанавливается и используется П/П "FSK_Detector") #define DATAbit_bp 6 #define HiFreq_HalfDetect_bm bit5 ;Флаг показывающий, что при детектировании ВЧ FSK детектирован первый полупериод, а нужно ещё и второй #define HiFreq_HalfDetect_bp 5 ; (это нужно, чтобы время детектирования для ВЧ/НЧ совпадало, так как ногу FSKout драйвим в конце детектирования ; и если не будет равенства времени детектирования, то получим разные длины для "0" и "1" (для НЧ импульс будет короче) ; ;#define ..._bm bit4 ;Reserved... ;#define ..._bp 4 ; ;#define ..._bm bit3 ;Reserved... ;#define ..._bp 3 ; ;#define ..._bm bit2 ;Reserved... ;#define ..._bp 2 ; ;#define ..._bm bit1 ;Reserved... ;#define ..._bp 1 ; ;#define ..._bm bit0 ;Reserved... ;#define ..._bp 0 ; ;------------------ ;Исходные параметры: ; !! ВНИМАНИЕ !! для корректной работы алгоритма детектирования неоходимо соблюдение двух следующих условий: ; 1) Частоты FSK для "0" и "1" должны различаться в 2 раза ; 2) Параметр FSK_BaudRate должне быть строго 1/4 самой низкой частоты FSK (4 периода на бит). Можно и 1/2, но будут ошибки декодирования. #define FSK_frequency0 2000 ;Hz частота для "0" #define FSK_frequency1 1000 ;Hz частота для "1" (она же частота несущей, перед старт-битом и после стоп-бита) #define FSK_Deviation 25 ;(1..99 dec,%) допустимое отклонение частоты при детектировании, в % (33% - это уже стык допусков для Freq0 и Freq1) #define FSK_timer_Clock 3686400/8 ;Hz частота тактирования счётного таймера FSK (для частоты 3.6864MHz это 57600kHz) ;!! ВНИМАНИЕ!! на более низкой частоте, например при предделителе 8 наблюдаются пропуски бит при генерации FSK #define FSK_CriticalFreq FSK_timer_Clock/256/2 ;Минимальная частота, c которой можно работать при данных настройках FSK-таймера. #define FSK_scope_ratio 10 ;сколько раз за полпериода максимальной FSK частоты, смотрим линию TxD (нужно для генерации FSK) ; (!) при значении параметра FSK_scope_ratio больше 20 могут наблюдаться проблемы с конкуренцией прерываний #define FSK_BaudRate 250 ;скорость потока данных - на текущий момент оптимально 1/4 в отношении самой низкой часты FSK ; (но возможно и 1/2 при некотором % ошибок) ; Статистика ошибок ; Err(2 периода) 1% ; Err(4 периода) ~0% ;#define FSK_minBitLength 4 ;Минимальная длина бита, в периодах самой низкой несущей часоты ;------------------- ;Высчитываемые из исходных параметры ;------------------------------------ ;Константы для отсчёта импульса/паузы (полпериода) генерируемой FSK частоты #define FSK_freq0_constant FSK_timer_Clock/FSK_frequency0/2 #define FSK_freq1_constant FSK_timer_Clock/FSK_frequency1/2 ;------------------- ;Константа для отсчёта периодов просмотра линии TxD для кодера FSK #if FSK_frequency0>FSK_frequency1 #define FSK_scope_constant FSK_timer_Clock/FSK_frequency0/FSK_scope_ratio #elif FSK_frequency1>FSK_frequency0 #define FSK_scope_constant FSK_timer_Clock/FSK_frequency1/FSK_scope_ratio #endif ;------------------- ;Константа для отсчёта мёртвого времени для декодера FSK (для фильтрации ошибочных срабатываний компаратора) ;Высчитываются два порога: ; DeadTime - высчитыватся как 1/4 периода (1/2 константы) для большей частоты FSK, из Freq0, Freq1 ; LostTime - высчитыватся как период для меньшей частоты FSK+допуск #if FSK_frequency0>FSK_frequency1 #define FSK_DeadTime_constant FSK_freq0_constant/2 #elif FSK_frequency1>FSK_frequency0 #define FSK_DeadTime_constant FSK_freq1_constant/2 #endif #if FSK_frequency0<FSK_frequency1 #define FSK_LostTime_constant FSK_freq0_constant+(FSK_freq0_constant/(100/FSK_Deviation)) #elif FSK_frequency1<FSK_frequency0 #define FSK_LostTime_constant FSK_freq1_constant+(FSK_freq1_constant/(100/FSK_Deviation)) #endif #message "_________________________________________________________________________" #message "FSK_frequency0 =" FSK_frequency0 #message "FSK_frequency1 =" FSK_frequency1 #message "FSK_scope_constant =" FSK_scope_constant #message "FSK_BaudRate =" FSK_BaudRate ;----------------------------------------------------------------------------------------------------------------------------- ;П/П обслуживания прерывания переполнения 8-битного таймера FSK ;INTERRUPT handler (TCNT) ;!! ВНИМАНИЕ !! при вызове этого прерывания автоматом сохраняется только контекст (SREG+TMP), ; все остальные регистры, если они нужны - сохраняем вручную здесь FSK_timer_OverFlow: S_INC S_FSK_TCNTH ret ;------------------------------- ;П/П мониторинга линии TxD UART с целью определения частоты генерации FSK (разные частоты для "0" и "1") ;INTERRUPT handler (CMPRA) ;(CompareA) - формирователь интервалов мониторинга линии TxD ;!! ВНИМАНИЕ !! при вызове этого прерывания автоматом сохраняется только контекст (SREG+TMP), ; все остальные регистры, если они нужны - сохраняем вручную здесь FSK_TxD_scope: ;Процедуры отрабатывают достаточно быстро, но они критичны ко времни исполнения, т.к реалтайм кодинг/декодинг, ; поэтому вложенные прерывания НЕ РАЗРЕШАЕМ !! push XTMP ;Сохраняем дополнительно используемые к TMP регистры ; in XTMP,OCR0A ;Считаем текущее значение CompareA регистра таймера, отвечающего за период моноринга ldi TMP,FSK_scope_constant ;константа периода мониторинга линии TxD add TMP,XTMP ;Высчитаем новое значение CompareA регистра out OCR0A,TMP ;Запишем его в CompareA регистр таймера ;----------------------------- ;непосредственно сам мониторинг линии TxD и установка флага BitStream, использующегося для генерации FSK, в регистре FSK-статуса lds TMP,S_FSK_flags ; sbic FSK_TxD_PIN,FSK_TxD_PinNum ;Установим состояние ф.BitStream в соответствие с линией TxD. rjmp SetFSK1 SetFSK0: cbr TMP,BitStream_bm ;ф.BitStream=0, если линия TxD в "0" rjmp FSK_next SetFSK1: sbr TMP,BitStream_bm ;ф.BitStream=1, если линия TxD в "1" FSK_next: sts S_FSK_flags,TMP ;Сохраним регистр флагов FSK с обновлённым флагом битового потока BitStream ;----------------- pop XTMP ret ;------------------------------- ;П/П генерации битонального сигнала FSK (разные частоты для "0" и "1") ;INTERRUPT handler (CMPRB) ;(CompareB) - регистр периода формирователя FSK-сигнала ;!! ВНИМАНИЕ !! при вызове этого прерывания автоматом сохраняется только контекст (SREG+TMP), ; все остальные регистры, если они нужны - сохраняем вручную здесь ;процедура исполняется быстро, так что вложенные прерывания не разрешаем, чтобы не нарушать процесс генерации. FSK_Gen: ;Процедуры отрабатывают достаточно быстро, но они критичны ко времни исполнения, т.к реалтайм кодинг/декодинг, ; поэтому вложенные прерывания НЕ РАЗРЕШАЕМ !! push XTMP ;---- в этой секции не портить XTMP! ---\ in XTMP,OCR0B ;Считаем текущее значение CompareB регистра таймера, отвечающего за генерацию FSK ; lds TMP,S_FSK_flags ;Анализируем ф.BitStream и идём на соответствующую ветку, для установки констант sbrc TMP,BitStream_bp ; для генерации Freq0/1 rjmp FSKfreq1 FSKfreq0:;-- генерация "0" (запись в CompareB константы для генерации "0") ldi TMP,FSK_freq0_constant ;константа генератора частоты FSK0 (для нуля) rjmp FSKfreq_SET ;Уходим, с установкой новой константы регистра периода FSK (CompareB) FSKfreq1:;-- генерация "1" (запись в CompareB константы для генерации "2") ldi TMP,FSK_freq1_constant ;константа генератора частоты FSK1 (для единицы) FSKfreq_SET: add XTMP,TMP ;Высчитаем новое значение для регистра CompareB генератора FSK out OCR0B,XTMP ;Запишем его в CompareB регистр таймера ;---------------------------------------/ ; MARKER_FLASH FSK_out_PIN,FSK_out_PORT,FSK_out_PinNum ;собственно дёргаем линию FSK ; ; (инвертирование состояния ноги при каждом исполнении макроса) pop XTMP ret ;------------------------------- ;П/П детектирования битонального сигнала FSK (разные частоты для "0" и "1") ;INTERRUPT handler (Analog Comparator) ;!! ВНИМАНИЕ !! при вызове этого прерывания автоматом сохраняется только контекст (SREG+TMP), ; все остальные регистры, если они нужны - сохраняем вручную здесь ;процедура исполняется быстро, так что вложенные прерывания не разрешаем, чтобы не нарушать процесс детектирования. ; FSK_Detector: ;Процедуры отрабатывают достаточно быстро, но они критичны ко времни исполнения, т.к реалтайм кодинг/декодинг, ; поэтому вложенные прерывания НЕ РАЗРЕШАЕМ !! push TMP2 ;Сохраним используемые в данной П/П регистры push XTMP PUSH_X PUSH_Y ; in XL,TCNT0 ;Сохраним текущие значения счётного FSK-таймера в X lds XH,S_FSK_TCNTH ; lds YL,S_FSK_TimeL ;Вспомним в Y ранее запомненные (при предыдущем вызове этого хэндлера) значения счётного FSK-таймера lds YH,S_FSK_TimeH ; sts S_FSK_TimeL,XL ;сохраним текущее время (значения счётного FSK-таймера) sts S_FSK_TimeH,XH ;-- Высчитаем модуль разницы с моментом предыдущего вызова данного хэндлера (момента срабатывания компаратора) ;-- Результат поместим в Y (фактически - это измеренный полупериод частоты FSK) sub YL,XL ;Вычислим сколько же насчитали с момента предыдущего вызова данного хэндлера (результат положим в "Y") sbc YH,XH brcc FSK_TryDetectFreq0 ;Если получился положительный результат, то идём далее, neg YL ; иначе (если результат отрицательный), то инвертируем его com YH ; ; -- Попробуем детектировать Freq0 (вычислим модуль разницы между измеренным интервалом и константой FSK_Freq0) FSK_TryDetectFreq0: ;В Y - измеренные полпериода FSK-частоты PUSH_Y ;Временно сохраним измеренный результат - полупериод FSK-частоты (на случай если ; не удасться детектировать Freq0, и придётся пробовать детектировать Freq1) LDX FSK_freq0_constant ;Константа для полупериода Freq0 sub YL,XL ;Вычислим сколько же насчитали с момента предыдущего вызова данного хэндлера (результат положим в "Y") sbc YH,XH brcc FSK_Det_Freq0 ;Если получился положительный результат, то идём далее, neg YL ; иначе (если результат отрицательный), то инвертируем его com YH ; ; -- Детектируем Freq0 (сравним измеренный интервал с константой FSK_Freq0) FSK_Det_Freq0: ;В Y - разница между измеренным интервалом и константой Freq0 LDX FSK_freq0_constant/(100/FSK_Deviation) ;Загрузим в "X" порог отклонения (допуск) от FSK_freq0_constant в % для полупериода ; в "Y" у нас на текущий момент разница измеренного периода FSK-частоты и образцовой константы cp XL,YL ;Сравниваем разницу измеренного периода FSK с порогом (допуском) Freq0 cpc XH,YH brcs FSK_TryDetectFreq1 ;Если не уложились в допуск, то значит не нашли Freq0, тогда попробуем найти Freq1, иначе ; считаем что обнаружили Freq0. ; *** Freq0_detected *** S_LDI S_AutoShutDown_Timer,AutoShutDown_Time ;взведём таймер автоотключения (переустановим его), так как обнаружили FSK ; (FSK1 есть всегда по протоколу UART, а вот FSK0 только при наличии обмена по UART-каналу) POP_Y ;подчистим стек (так как ранее, в начале детектирования Freq0, его сохраняли, а теперь он стал не нужнен. ;-------------------------------------- ;-- выравнивание времени детектирования для разных частот Freq0 и Freq1 lds YL,S_FSK_flags ;Загрузим регистр флагов для работы с флагом "HiFreq_HalfDetect" ; (Используем YL, а не TMP чтобы нечаяно не испортить его содержимое (например макросами)) #if FSK_frequency0<FSK_frequency1 ;Если Freq0 у нас НЧ, то cbi FSK_DATAbit_PORT,FSK_DATAbit_PinNum ;Сразу драйвим линию FSK_DATAbit cbr YL,HiFreq_HalfDetect_bm ; сбросим ф.детектирования первого полупериода ВЧ rjmp FSK_Det_Freq0_alignEND ; и выходим с сохранением регистра статуса. ; #else ;Иначе считаем, что Freq0 - ВЧ, и тогда будем смотреть, это 1-й или 2-й полупериод ?? sbrs YL,HiFreq_HalfDetect_bp ;Если первого периода ещё нет, rjmp SetFreq0_HalfDetect ; то установим ф.HalfDetect (продетектировали первый полупериод ВЧ) cbr YL,HiFreq_HalfDetect_bm ; Иначе считаем, что флаг уже был установлен в предыдущий вызов данного хэндлера, поэтому сбросим его cbi FSK_DATAbit_PORT,FSK_DATAbit_PinNum ; и только теперь драйвим линию FSK_DATAbit. rjmp FSK_Det_Freq0_alignEND ;Выходим с сохранением регистра статуса. SetFreq0_HalfDetect: sbr YL,HiFreq_HalfDetect_bm ;Установим флаг, что сейчас мы продетектировали первый полупериод ВЧ, и выходим. #endif FSK_Det_Freq0_alignEND: sts S_FSK_flags,YL ;Сохраним изменённый регистр статуса. ;-------------------------------------- rjmp FSK_Detector_Ret ;Уходим ;-------------------------------------------------- ; -- Попробуем детектировать Freq1 (вычислим модуль разницы между измеренным интервалом и константой FSK_Freq1) FSK_TryDetectFreq1: POP_Y ;Вспомним, что намеряли (полпериода FSK-часоты. То, что сохраняли в стеке в начале процедуры детектирования Freq0.) ; -- Вычисляем измеренный временной интервал (полпериода частоты FSK) LDX FSK_freq1_constant ;Константа для полупериода Freq1 sub YL,XL ;Вычислим сколько же насчитали с момента "0" (результат положим в "Y") sbc YH,XH brcc FSK_Det_Freq1 ;Если получился положительный результат, то идём далее, neg YL ; иначе (если результат отрицательный), то инвертируем его com YH ; FSK_Det_Freq1: ;В Y - разница между измеренным и константой Freq1 LDX FSK_freq1_constant/(100/FSK_Deviation) ;Загрузим в "X" порог отклонения (допуск) от FSK_freq1_constant в % для полупериода ; в "Y" у нас на текущий момент разница измеренного периода FSK-частоты и образцовой константы cp XL,YL cpc XH,YH brcs FSK_NotDetected ;Если не уложились в порог, то значит не нашли Freq1, т.е. и не Freq0 и не Freq1 :( ; ** Freq1_detected ;-------------------------------------- S_LDI S_AutoShutDown_Timer,AutoShutDown_Time ;взведём таймер автоотключения (переустановим его), так как обнаружили FSK ; (FSK1 есть всегда по протоколу UART, а вот FSK0 только при наличии обмена по UART-каналу) ;-- выравнивание времени детектирования для разных частот Freq0 и Freq1 lds YL,S_FSK_flags ;Загрузим регистр флагов для работы с флагом "HiFreq_HalfDetect" ; (Используем YL, а не TMP чтобы нечаяно не испортить его содержимое (например макросами)) #if FSK_frequency0>FSK_frequency1 ;Если Freq1 у нас НЧ, то sbi FSK_DATAbit_PORT,FSK_DATAbit_PinNum ;Сразу драйвим линию FSK_DATAbit cbr YL,HiFreq_HalfDetect_bm ; сбросим ф.детектирования первого полупериода ВЧ rjmp FSK_Det_Freq1_alignEND ; и выходим с сохранением регистра статуса. ; #else ;Иначе считаем, что Freq1 - ВЧ, и тогда будем смотреть, это 1-й или 2-й полупериод ?? sbrs YL,HiFreq_HalfDetect_bp ;Если первого периода ещё нет, rjmp SetFreq1_HalfDetect ; то установим ф.HalfDetect (продетектировали первый полупериод ВЧ) cbr YL,HiFreq_HalfDetect_bm ; Иначе считаем, что флаг уже был установлен в предыдущий вызов данного хэндлера, поэтому сбросим его sbi FSK_DATAbit_PORT,FSK_DATAbit_PinNum ; и только теперь драйвим линию FSK_DATAbit. rjmp FSK_Det_Freq1_alignEND ;Выходим с сохранением регистра статуса. SetFreq1_HalfDetect: sbr YL,HiFreq_HalfDetect_bm ;Установим флаг, что сейчас мы продетектировали первый полупериод ВЧ, и выходим. #endif FSK_Det_Freq1_alignEND: sts S_FSK_flags,YL ;Сохраним изменённый регистр статуса. ;-------------------------------------- rjmp FSK_Detector_Ret ;Уходим ;-------------------------------------------------- FSK_NotDetected: ;Детектирование не получилось (не нашли ни Freq0, ни Freq1), т.е. замеренный временной интервал некорректен (помеха) ; ;Сюда обычно попадаем при множественных срабатываниях компаратора в окрестности "нуля" nop #warning "Dbg FSKoutNeedle" //MARKER_nanoNEEDLE FSK_DATAbit_PIN,FSK_DATAbit_PORT,FSK_DATAbit_PinNum ;------------------------------------------- FSK_Detector_Ret: ; POP_Y ;Восстановим используемые в данной П/П регистры POP_X pop XTMP pop TMP2 ret
...делать нужно так, как нужно. А как ненужно - делать не нужно (С) Винни-Пух :)