; набор шагов в реализации вычислителя АЦП ; нормализатора каналов АЦП с дроблением на куски ; АЦП хорошо кушает память - на каждый канал - накопитель усреднений 2 байта, буфер переноса в основной циклер 2 байта, ; буфер результата вычислителя/нормализатора 2 байта. ; Ещё пиковые значения тока и углы их появления и обработчики этого - потребуют ОЗУ. ; Однако заранее сделанная и проверенная перемещаемость АЦП модуля по банкам ОЗУ - ; позволяет легко выделить и 48 байт и больше ОЗУ. ; bra Step_0 ; bra Step_1 ; bra Step_2 ; bra Step_3 ; bra Step_4 ; bra Step_5 ; bra Step_6 ; bra Step_7 ; bra Step_8 ; bra Step_9 ; ; bra Step_10 ; Место ; bra Step_11 ; под ; bra Step_12 ; ПИД ; bra Step_13 ; регулятор ; bra Step_14 ; после ; bra Step_15 ; масштабирования ; bra Step_16 ; результатов ; bra Step_17 ; АЦП ; bra Step_18 ; ; bra Step_19 ; ; bra Step_20 ; ; bra Step_21 ; ; bra Step_22 ; ; bra Step_23 ; ; bra Step_24 ; ; bra Step_25 ; ; bra Step_26 ; ; bra Step_27 ; ; bra Step_28 ; ; bra Step_29 ; ; bra Step_30 ; ; bra Step_31 ; ; bra Step_32 ; ; bra Step_33 ; ; bra Step_34 ; ; bra Step_35 ; ; bra Step_36 ; ; bra Step_37 ; ; bra Step_38 ; ; bra Step_39 ; ; bra Step_40 ; ; bra Step_41 ; ; bra Step_42 ; ; bra Step_43 ; ; bra Step_44 ; ; bra Step_45 ; ; ; Защитные-отладочные возвраты с кодом ошибки retlw 0x01 ; RShift16_N macro A_Arg,A1A,NumShift ; Избегаем ввода повторяющегося кода local a = 0 while a < NumShift bcf _C ; На 1 команду длиннее но универсальнее rrcf A_Arg+1,F,A1A ; Три сдвига правых rrcf A_Arg+0,F,A1A ; символизируют /8 a += 1 endw endm LShift24_N macro A_Arg,A1A,NumShift ; Избегаем ввода повторяющегося кода local a = 0 while a < NumShift bcf _C ; На 1 команду длиннее но универсальнее rlcf A_Arg+0,F,A1A ; Три сдвига правых rlcf A_Arg+1,F,A1A ; символизируют /8 rlcf A_Arg+2,F,A1A ; символизируют /8 a += 1 endw endm ; Убрал из основного файла пустые обработчики Step_0; ;результат АЦП канала №0 Нога 2 Переменник/Внешний АЦП вход ; ********** Тело обработчика 1/первого/1 набора буферов АЦП ************ ; в ADC_Out+0/2/4/6 #ifdef PCPWM_Present btfss PCPWM_Flag1,6,ACCESS; Чистка флага ;6= Скорость от ADC-0 или от енкодера bra Encoder_Speed ; Прежний метод регулировки оборотов movff ADC_Out+1,WREG ; Старший байт накоплений АЦП rrcf WREG,W,ACCESS ; Делим на 2 bcf WREG,7,ACCESS ; Чистим приход с переноса addlw 0x80 ;Диапазон регулировки АЦП от середины до максимума movff WREG,PCPWM_WrkSpdBuf; Encoder_Speed #ifdef PCPWM_NoReverseKey; Yes ; Кнопа "реверс" НЕ работает - присваиваем "прямо" btfss PCPWM_Flag,4,ACCESS ;Куда крутимся - Бит прямо/реверс bra DoneForward ; movff PCPWM_SpeedReal,WREG; без смены страницы movf WREG,W,ACCESS; Выставляем флаги Z,N bnz SetFlagStpRevStart; Реальная скорость поля =0 ? bcf PCPWM_Flag,4,ACCESS ;Бит прямо/реверс - изменять только в останове bra DoneForward SetFlagStpRevStart bsf PCPWM_Flag1,4,ACCESS;4= Однократный останов-реверс-разгон на ходу DoneForward #endif #endif ;;;FXM0808SL macro ArgB,A1B,Lit8 ; Умножение знакового байта на положительную константу ;; Результат в PRODL:PRODH ; FXM0808SL Adc_Corr+3,bnk,d'13'; Умножение корректорчика на коэфф "побольше" 350-370 вольт коррекция ;; Add16L macro ArgB,A1B,Lit16; Подразумевается в памяти Младший-Старший байт идут ; Add16L PRODL,acs,0x1eff*8;максимум измерений например 495=0x1ef добавляем тетраду F ;;FXM1616U2 macro D_Arg,A1D,A_Arg,A1A,B_Arg,A1B,_Work,A1W; ; Подразумевается в памяти Младший-Старший байт идут ;;D=А*B макрос могёт в качестве операнда D принимать A (помещать в него результат 32 бита), как выгоднее. ; FXM1616U2 ADC_Work+0,bnk ,ADC_Out+0,bnk ,PRODL,acs, ADC_Work+7,bnk; ;;RShift16_N macro A_Arg,A1A,NumShift ; RShift16_N ADC_Work+2,bnk,3 ; 3 правых сдвига 2х байт ; ; movff_N ADC_Work+2,Adc_Amp+2,2; Готовый результат - в буфера для вывода ; incf ADC_Step,F,bnk ; bnK Acs BnK aCs AcS bNk Bnk retlw 0x0 Step_1;;результат АЦП канала №1 Нога 3 Термистор ; В модулях IRAMX и IRAMY разные схемы подключения термистора. ; В IRAMX АЦП вход термистора возрастает с увеличением температуры, в IRAMY уменьшается. ; Для приведения к единообразию обработчика - надо 16 бит результата АЦП от IRAMY ; вычесть из константы примерно 0xFFC0 для IRAMY #ifdef PCPWM_IRAMY; Yes; Силовой модуль IRAMY movlf 0xC0,ADC_Work+0,BANKED ; согласен, немного тупо но setf ADC_Work+1 ; на спех не могу сообразить как короче Sub16 ADC_Work+0,BANKED,ADC_Out+2,BANKED ;ArgB,A1B,ArgA,A1A ; в памяти Младший-Старший байт movff16 ADC_Work+0,ADC_Out+2 ; #endif #ifdef PCPWM_Present btfss PCPWM_Flag1,5,ACCESS;5= Контроль термистора/тока в обработчике АЦП (установлен при нормальной работе мотора) bra Done2_S1 movff Par_T,WREG ; Порог термистора в другой банке subwf ADC_Out+3,W,BANKED;ACCESS; Subtract W from f bc TempGt; Результат отрицательный ;LED0_Clear; bcf LED0_PORT,LED0_Pin,ACCESS bra Done_S1 TempGt; Превышение термистора ; LED0_Set movlw 0x5 ; Код останова=6 (инкремент в саб проге) call MotorFault ; Гасим PCPWM Done_S1 #endif FXM0808SL Adc_Corr+2, bnk, d'130' ; Умножение корректорчика на коэфф "побольше" Add16L PRODL, acs, 0x5Af*0x8;максимум измерений например 90=0x5A добавляем тетраду F FXM1616U2 ADC_Work+0, bnk, ADC_Out+2, bnk, PRODL, acs, ADC_Work+7, bnk; RShift16_N ADC_Work+2, bnk, 3 ; 3 правых сдвига 2х байт movff_N ADC_Work+2, Adc_Volt+2,2; Готовый результат - в буфера для вывода Done2_S1 ; При останове мотора не обрабатываем температуру incf ADC_Step,F,bnk ; retlw 0x0 ;-------------------------------------------------------------------- Step_2 ;;результат АЦП канала №2 нога 4 (ток общий, максимум измерения при 17 мОм и 10х усилителе ; 5V / (0.017 Ом * 10 раз) =29.4А ) ;btfss PCPWM_Flag1,5,ACCESS;5= Контроль термистора/тока в обработчике АЦП (установлен при нормальной работе мотора) ; bra Done_S2; ОверТок контролируется всегда на всяк случай #ifdef PCPWM_Present movff Par_A,WREG ; Порог тока в другой банке subwf ADC_Out+5,W,BANKED;ACCESS; Subtract W from f bc CurrentGt; Результат отрицательный ;LED0_Clear; bcf LED0_PORT,LED0_Pin,ACCESS bra Done_S2 CurrentGt; Превышение тока ; LED0_Set movlw 0x6 ; Код останова=7 (инкремент в саб проге) call MotorFault ; Гасим PCPWM Done_S2 #endif ; FXM0808SL Adc_Corr+2,bnk,d'13'; Умножение корректорчика на коэфф "побольше" ; Add16L PRODL,acs,0x1eff*0x8;максимум измерений например 495=0x1ef добавляем тетраду F ; FXM1616U2 ADC_Work+0,bnk ,ADC_Out+4,bnk ,PRODL,acs, ADC_Work+7,bnk; ; RShift16_N ADC_Work+2,bnk,3 ; 3 правых сдвига 2х байт ; movff_N ADC_Work+2,Adc_Volt+2,2; Готовый результат - в буфера для вывода FXM0808SL Adc_Corr+1, bnk, d'40' ; Умножение корректорчика на коэфф "побольше" ; Множитель "корректорчика" должен быть таким, чтоб избежать переполнения ; при сложении с нормированным максимумом измерений. ; Затея фиксированной точки в том чтоб поместилась в умножитель максимальное количество бит. ; Add16L PRODL, acs, 0x7F*0x80;максимум 7A измерений например 25=0x19 добавляем тетраду F, сдвинуть 7 раз Add16L PRODL, acs, 0xEB4B;=2048*5/0.17 Для максимума 5/0,17 умноженного на нормирующий коэфф 2048 ; получаем 60 235, коэфф умножения "корректорчика" ; 65536 - 60 235 = 5 300 / 256 = 20 раз. 20*255= 5 100, переполнения от сложения с константой множителя не ожидается. FXM1616U2 ADC_Work+0, bnk, ADC_Out+4, bnk, PRODL, acs, ADC_Work+7, bnk; RShift16_N ADC_Work+2, bnk, 7 ; 1 левый сдвиг 3х байт - быстрее 7 сдвигов 2 байт movff_N ADC_Work+2, Adc_Amp+0, 2; Готовый результат - в буфера для вывода incf ADC_Step,F,bnk ; retlw 0x0 Step_3 ;;результат АЦП канала №3 нога 5 (напряжение DC 500 вольт максимум) ; btfss PCPWM_Flag1,5,ACCESS;5= Контроль термистора/тока в обработчике АЦП (установлен при нормальной работе мотора) ; bra Done_S3 ; Овернапруга контролируется всегда на всяк случай #ifdef PCPWM_Present movff Par_V,WREG ; Порог напруги в другой банке subwf ADC_Out+7,W,BANKED;ACCESS; Subtract W from f bc VoltageGt; Результат отрицательный ; LED0_Clear; bcf LED0_PORT,LED0_Pin,ACCESS bra Done_S3 VoltageGt; Превышение тока ; LED0_Set movlw 0x7 ; Код останова=8 (инкремент в саб проге) call MotorFault ; Гасим PCPWM Done_S3 #endif FXM0808SL Adc_Corr+0, bnk, d'20' ; Умножение корректорчика на коэфф "побольше" Add16L PRODL, acs, 0x1F4F*0x4;максимум измерений например 500=0x1f4 добавляем тетраду F ; 1F4F*4=64120.-65536=1416/256=5 переполнение не ожидается FXM1616U2 ADC_Work+0, bnk, ADC_Out+6, bnk, PRODL, acs, ADC_Work+7, bnk; RShift16_N ADC_Work+2, bnk, 2 ; 2 правых сдвига 2х байт movff_N ADC_Work+2, Adc_Volt+0, 2 ; Готовый результат - в буфера для вывода incf ADC_Step,F,bnk ; retlw 0x0 Step_4;;Мощность=Напряжение*Ток, 16 бит на 16 бит=32 бита, старший и младший байты в игноре FXM1616U2 ADC_Work+0, bnk, Adc_Volt+0, bnk, Adc_Amp+0, bnk, ADC_Work+7, bnk; ;RShift16_N ADC_Work+2, bnk, 7 ; 1 левый сдвиг 3х байт - быстрее 7 сдвигов 2 байт movff_N ADC_Work+1, Adc_Watt+0, 2; Готовый результат - в буфера для вывода ; incf ADC_Step,F,bnk ; bcf ADC_Flag,1,acs; Флаг запроса времени АЦП этой веткой bcf ADC_Flag,3,acs; Прога закончена retlw 0x0 ; Обработка второго комплекта буферов ниже Step_5;;результат АЦП канала №4 (предположительно) FXM0808SL Adc_Corr+4, bnk, d'13' ; Умножение корректорчика на коэфф "побольше" Add16L PRODL, acs, 0x19f*0x80;максимум измерений например 25=0x19 добавляем тетраду F, сдвинуть 7 раз FXM1616U2 ADC_Work+0, bnk, ADC_Out+8, bnk, PRODL, acs, ADC_Work+7, bnk; RShift16_N ADC_Work+2, bnk, 7 ; 1 левый сдвиг 3х байт - быстрее 7 сдвигов 2 байт movff_N ADC_Work+2, Adc_Amp+4, 2; Готовый результат - в буфера для вывода incf ADC_Step,F,bnk ; retlw 0x0 Step_6 ; FXM0808SL Adc_Corr+5, bnk, d'13' ; Умножение корректорчика на коэфф "побольше" Add16L PRODL, acs, 0x19f*0x80 ;максимум измерений например 25=0x19 добавляем тетраду F, сдвинуть 7 раз FXM1616U2 ADC_Work+0, bnk, ADC_Out+A, bnk, PRODL, acs, ADC_Work+7, bnk; Умножение с пересылкой LShift24_N ADC_Work+1, bnk, 1 ; 1 левый сдвиг 3х байт - быстрее 7 сдвигов 2 байт movlw 0x1 ; Даже с учётом чистки andwf ADC_Work+3, bnk ; старших 7 бит movff_N ADC_Work+2, Adc_Amp+4, 2 ; Готовый результат - в буфера для вывода incf ADC_Step,F,bnk ; retlw 0x0 Step_7; FXM0808SL Adc_Corr+6, bnk, d'13' ; Умножение корректорчика на коэфф "побольше" Add16L PRODL, acs, 0x19f*0x80 ;максимум измерений например 25=0x19 добавляем тетраду F, сдвинуть 7 раз FXM1616U2 ADC_Work+0, bnk, ADC_Out+8, bnk, PRODL, acs, ADC_Work+7, bnk; LShift24_N ADC_Work+1, bnk, 1 ; 1 левый сдвиг 3х байт - быстрее 7 сдвигов 2 байт movlw 0x1 ; Даже с учётом чистки andwf ADC_Work+3, bnk ; старших 7 бит movff_N ADC_Work+2, Adc_Amp+4, 2 ; Готовый результат - в буфера для вывода incf ADC_Step,F,bnk ; retlw 0x0 Step_8 ; FXM0808SL Adc_Corr+7, bnk, d'13' ; Умножение корректорчика на коэфф "побольше" Add16L PRODL, acs, 0x19f*0x80;максимум измерений например 25=0x19 добавляем тетраду F, сдвинуть 7 раз FXM1616U2 ADC_Work+0, bnk, ADC_Out+8, bnk, PRODL, acs, ADC_Work+7, bnk; LShift24_N ADC_Work+1, bnk, 1 ; 1 левый сдвиг 3х байт - быстрее 7 сдвигов 2 байт movlw 0x1 ; Даже с учётом чистки andwf ADC_Work+3, bnk ; старших 7 бит movff_N ADC_Work+2, Adc_Amp+6, 2 ; Готовый результат - в буфера для вывода incf ADC_Step,F,bnk ; retlw 0x0 Step_9; bcf ADC_Flag,2,acs; Флаг запроса времени АЦП этой веткой bcf ADC_Flag,3,acs; Прога закончена retlw 0x0 incf ADC_Step,F,bnk ; retlw 0x0 Step_10; bcf ADC_Flag,2,acs; Флаг запроса времени АЦП этой веткой bcf ADC_Flag,3,acs; Прога закончена retlw 0x0 ;Step_10; Step_11; Step_12; Step_13; Step_14; Step_15; Step_16; Step_17; Step_18; Step_19; Step_20; Step_21 Step_22 Step_23 Step_24 Step_25 Step_26 Step_27 Step_28; Step_29 Step_30 Step_31 Step_32 Step_33 Step_34 Step_35 Step_36 Step_37 Step_38 Step_39 Step_40 Step_41 Step_42 Step_43 Step_44 Step_45 ; EndTask retlw 0x0 ; return 0