; Include for: ; Filename: Interrupt_low.Asm * ; btfsc PIR1,ADIF,ACCESS ; ADC ; rcall IntAdc ; IntAdc ; Заглушка случайно возникшего прерывания ;#include ;обработка во включаемом файле. ;A11 TAD A/D Clock Period 385/1000 ns VDD = 5V/3V Page 370 ; Прерывание АЦП. Запуск бесконечной цепочки АЦП ; Сэмплировать группы по 4 канала. итого 8 входов, чередуются. ; Две группы - усредняется 64 раза ; потом меняем входы групп на альтернативные инверсией битов ADCHS. ; Итого 4 входа + 4 входа с усредняемыми 64 раза данными 146.484375 Гц ; Цикл измерения 20 ТАД , из них 11 ТАД АЦП. ; 15 ТАД * 32 ЦЛК = 480 ЦЛК на преобразование, 100 КГц от тактовой 48 МГц, ; 25 КГц прерывания с буфером х4 - можно использовать как доп источник времени задержек. ;IntCheck code 0x0100 ; btfss PIE1,ADIE,ACCESS ; Прерывания разрешены ? ; return ;#define ADC_Return retfie FAST ; ; Если последним обработчиком HiInt ;#define ADC_Return return ; возврат к опросу остальных флагов #define ADC_Return bra ExitAdcInt; Прямой переход на следующего ; bcf PIR1,ADIF,ACCESS ; Сбрасываем флаг ADC ;bcf PIE1,ADIE,ACCESS ; Прерывания в запрет - АЦП - ОТЛАДКА ЗАГЛУШКА Add16_ADC macro ArgB,A1B,ArgA,A1A ; Подразумевается в памяти Младший-Старший байт идут ; в случае переполнения ФИФО сместятся каналы. ; Результат АЦП можно читать только 1 раз, в указанном порядке: ;Note: When right justified, reading ADRESL ;increments ADPNT. When left justified, ;reading ADRESH increments ADPNT. ;Add16 macro ArgB,A1B,ArgA,A1A ; В=B+A, Подразумевается в памяти Младший-Старший байт идут movf ArgA+1,W,A1A ; начинаем со старшего байта - выравнивание вправо addwf ArgB+1,F,A1B ; и сложим старшие байты - результат в В movf ArgA,W ,A1A ; Младший байт чтение изменяет указатель буфера ФИФО ;xorwf ADC_Rnd,F,ACCESS ; Накапливаем энтропию addwf ArgB,F,A1B ; ; А + В, результат В=B+A btfsc _C ; Если в прошлом Перенос incf ArgB+1,F,A1B; Увеличим Старший БАЙТ накопителя на 1 endm Add16_ADC_Max macro ArgB,A1B,ArgA,A1A,ArgM,A1M ; Подразумевается в памяти Младший-Старший байт идут local Done ; Дополнительно - поиск максимума ; Результат АЦП можно читать только 1 раз, в указанном порядке: ;Note: When right justified, reading ADRESL ;increments ADPNT. When left justified, ;reading ADRESH increments ADPNT. ;Add16 macro ArgB,A1B,ArgA,A1A ; В=B+A, Подразумевается в памяти Младший-Старший байт идут movf ArgA+1,W,A1A ; начинаем со старшего байта - выравнивание вправо movwf ADC_Max_Buf+1,BANKED;Буфер для прерывания АЦП ;xorwf ADC_Rnd,F,ACCESS ; Накапливаем энтропию addwf ArgB+1,F,A1B ; и сложим старшие байты - результат в В movf ArgA,W ,A1A ; Младший байт чтение изменяет указатель буфера ФИФО movwf ADC_Max_Buf,BANKED;Буфер для прерывания АЦП addwf ArgB,F,A1B ; ; А + В, результат В=B+A btfsc _C ; Если в прошлом Перенос incf ArgB+1,F,A1B; Увеличим Старший БАЙТ накопителя на 1 movff16 ADC_Max_Buf,ADC_Max_Buf+2 ; Спасаем АЦП для возможного будущего присваивания ; Сравнение имеющегося максимума со спасённым мгновенным значением АЦП Sub16 ADC_Max_Buf,BANKED,ArgM,A1M ;macro ArgB,A1B,ArgA,A1A ; Подразумевается в памяти Младший-Старший байт идут ; Результат будет B=B-A, нас интересует лишь бит _С (инверсный заём Borrow) bnc Done ; либо bnc надо проверить в отладчике - этот инверсный заём всегда путает movff16 ADC_Max_Buf+2,ArgM ; Присваиваем новый максимум Done: endm Int_ADC: ;******************************************* ; 18 750 раз в секунду выполняется ;******************************************* dcfsnz WDT_ADC,F,ACCESS ; Собака для прерывания ADC bcf WDT_Flag,0,ACCESS ; Флаг Собаки прерывания ADC #ifdef PCPWM_Present ; call DelayCuriosity ; Исследование запаса по быстродействию обработчика ; Обнаружен запас по быстродействию примерно 50-55 команд, далее пропуски буферов ; После добавки засекания пиковых значений АЦП запас убавился до 20 команд, далее пропуски буферов #endif ADC_Page ; BSR for ADC Task movff ADCON1,ADCON1_Print ;,F,BANKED; ********** Отладочная анализация btfss ADCON1,BFOVFL,ACCESS ;BFEMT: Buffer Empty bit 1 = FIFO is empty bra AdcDone3 bcf ADCON0,ADON,ACCESS ;Гасим АЦП incf ADC_ERR_Counter,F,ACCESS ; ; movf ADRESL,W,ACCESS ; Чтение в пустоту ; movf ADRESL,W,ACCESS ; Чтение в пустоту ; movf ADRESL,W,ACCESS ; Чтение в пустоту ; movf ADRESL,W,ACCESS ; Чтение в пустоту ; movf ADRESL,W,ACCESS ; Чтение в пустоту movlw b'00000011' ; Общая масочка andwf ADCON1,W,ACCESS bz IgnoreBufers movf ADRESL,W,ACCESS ; Чтение в пустоту andwf ADCON1,W,ACCESS bz IgnoreBufers movf ADRESL,W,ACCESS ; Чтение в пустоту andwf ADCON1,W,ACCESS bz IgnoreBufers movf ADRESL,W,ACCESS ; Чтение в пустоту IgnoreBufers bsf ADCON0,ADON,ACCESS ;Заводим АЦП ADC_Return ; Отброс кривого буфера AdcDone3 ; Добавляю переключатель/чередователь банков АЦП btfsc ADCHS,ADCHS_TestBit,ACCESS ; Тестируем состояние указанного инвертируемого бита bra Second_ADC_Set ; Обработка второго набора из 4 каналов movlw ADC_ChannelSelect; Инвертируемые биты ADCHS: A/D CHANNEL SELECT REGISTER iorwf ADCHS,F,ACCESS ; Применяем переклюк каналов - ставим указанные биты ;******************************************* ; 9 375 раз в секунду выполняется ;******************************************* Add16_ADC_Max ADC_Buff+0,BANKED,ADRESL,ACCESS,ADC_Max+0,BANKED; Выгребаем Add16_ADC ADC_Buff+2,BANKED,ADRESL,ACCESS;,ADC_Max+2,BANKED; Буфер Add16_ADC ADC_Buff+4,BANKED,ADRESL,ACCESS;,ADC_Max+4,BANKED; ФИФО Add16_ADC ADC_Buff+6,BANKED,ADRESL,ACCESS ; шустро decfsz ADC_Counter,F,BANKED ; ADC_Return ; ;******************************************* ; 146,484375 Гц - АЦП результаты набор 1 ;******************************************* movlf .64,ADC_Counter,BANKED ; Новый счетчик накоплений movff_N ADC_Buff+0,ADC_Out+0,8 ; пересылаем и clrf_N ADC_Buff+0,BANKED,8 ; Шустро чистим накопитель ;*************************************** ; АЦП результаты набор 1 в ADC_Out+0/2/4/6 готов к обработке ;*************************************** bsf ADC_Flag,0,ACCESS ; Флаг запроса времени АЦП обработчиком ставим bsf ADC_Flag,1,ACCESS ; Флаг запроса времени АЦП веткой ставим ADC_Return; bra ExitAdcInt Second_ADC_Set ; Обработка второго набора из 4 каналов ;******************************************* ; 146,484375 Гц - АЦП результаты набор 2 ;******************************************* movlw ADC_ChannelSelect; Инвертируемые биты ADCHS: A/D CHANNEL SELECT REGISTER comf WREG,W,ACCESS ; Инверсия маски битов для сброса битов andwf ADCHS,F,ACCESS ; Применяем надёжный переклюк каналов - сброс указанных битов Add16_ADC ADC_Buff+0x8,BANKED,ADRESL,ACCESS ; Выгребаем Add16_ADC ADC_Buff+0xA,BANKED,ADRESL,ACCESS ; Буфер Add16_ADC ADC_Buff+0xC,BANKED,ADRESL,ACCESS ; ФИФО Add16_ADC ADC_Buff+0xE,BANKED,ADRESL,ACCESS ; шустро decfsz ADC_Counter2,F,BANKED ; ADC_Return ; movlf .64,ADC_Counter2,BANKED ; Новый счетчик накоплений movff_N ADC_Buff+0x8,ADC_Out+0x8,8 ; пересылаем clrf_N ADC_Buff+0x8,BANKED,8 ; Шустро чистим накопитель ;*************************************** ; АЦП результаты набор 2 в ADC_Out+8/A/C/E готов к обработке ;*************************************** bsf ADC_Flag,0,ACCESS ; Флаг запроса времени АЦП обработчиком ставим bsf ADC_Flag,2,ACCESS ; Флаг запроса времени АЦП веткой ; bsf TaskFlag1,3,ACCESS ; Флаг очистки буферов ставим ADC_Return; bra ExitAdcInt ExitAdcInt