Здравствуйте! Помогите реализовать отсчет времени с помощью TMR0 на контроллере PIC16F684. Я понимаю, что заниматься сексом с железом - это конечно круто и желательно заниматься этим самостоятельно, но сил у меня уже больше нет (трахаюсь уже 4-й день в одной и той же позе:'( ). Вот что я для примера состряпал: Код (Text): list p=pic16f684 #include <p16f684.inc> __CONFIG _IESO_OFF & _BOD_OFF & _WDT_OFF & _XT_OSC & _MCLRE_OFF & _PWRTE_ON & _CP_OFF & _FCMEN_OFF ;регистры для сохранения контекста прерываний W_temp equ 0x20 FSR_temp equ 0x21 STATUS_temp equ 0x22 ;another regs TMR0_counter equ 0x23 tmp1 equ 0x24 cbuf equ 0x25 int_flags equ 0x26 minute equ 0x27 bit_cntr equ 0x28 sec1_counter equ 0x29 ;флаги регистра int_flags sec1 equ 0x00 ms10 equ 0x01 PUSHAD_MACRO MACRO ;Макрос сохранения контекста movwf W_temp ;сохранить регистр W movf STATUS, W ;сохранить movwf STATUS_temp ;регистр STATUS movf FSR, W ;сохранить movwf FSR_temp ;регистр FSR ENDM POPAD_MACRO MACRO ;Макрос восстановления контекста movf FSR_temp, W ;Восстановить movwf FSR ;регистр FSR movf STATUS_temp, W ;Восстановить movwf STATUS_temp ;регистр STATUS movf W_temp, W ;Восстановить регистр W ENDM org 0 goto start nop nop nop ;обработчик прерываний. PUSHAD_MACRO ;сохранить контекст bcf STATUS, RP0 ;выбрать банк 0 btfsc INTCON, T0IF ;Прерывание от TMR0? goto TMR0_int ;Да btfsc PIR1, ADIF ;Нет, прерывание от АЦП? goto AD_int ;Да goto ERROR_int ;Нет, переход к процедуре восстановления при ошибке END_ISR: POPAD_MACRO retfie ;возврат с разрешением прерываний ;обработчик прервыания от ADC: AD_int: ;обработчик прерывания от TMR0: TMR0_int: ;Предделитель перед TMR0 == 64 => на частоте 4 МГц прерывание вызывается каждые (256 - 100)* 64 == 10 мсек. bcf STATUS, RP0 movlw 0x64 ; movwf TMR0 ; bcf INTCON, T0IF ;сброс флага прерывания от TMR0 incf TMR0_counter, F ;инкремент счетчика прерываний movf TMR0_counter, W ;сравнить счетчик прерываний xorlw 0x64 ;со 100d btfss STATUS,Z ;если TMR0_counter != 100d goto END_ISR ;выход clrf TMR0_counter ;сброс TMR0_counter bsf int_flags, ms10 ;устанавливается флаг сообщающий о прошествии 10 мсек incf sec1_counter, F ;инкремент и проверка movf sec1_counter, W ;на переполнение регистра sec1_counter xorlw 0x64 ;Если регистр btfss STATUS, Z ;не переполнился, goto notofl_sec1 ;то инкрементить его и выйти clrf sec1_counter ;иначе очистить его, bsf int_flags, sec1 ;сообщить, что прошла 1 секунда goto END_ISR ;иначе выход из прерывания notofl_sec1: goto END_ISR ;выход из обработчика прерываний ERROR_int: goto END_ISR org 0xDF ;Процедура преобразования hex-кода в 7-сегментный ;Перед вызовом в аккумулятор необходимо занести HEX-код ;Процедура в аккумуляторе возвращает 7-сегментный код ;Обязательно должна находиться в первой странице памяти. Макс. ;количество команд 0x20. hex_to_7seg: addwf PCL, F ;к счетчику команд прибавить смещение в таблице retlw B'00000010' ; 0 retlw B'10011110' ; 1 retlw B'00100100' ; 2 retlw B'00001100' ; 3 retlw B'10011000' ; 4 retlw B'01001000' ; 5 retlw B'01000000' ; 6 retlw B'00011110' ; 7 retlw B'00000000' ; 8 retlw B'00001000' ; 9 retlw B'00010000' ; A retlw B'11000000' ; b retlw B'01100010' ; C retlw B'10000100' ; d retlw B'01100000' ; E retlw B'01110000' ; F retlw B'11111110' ; Пустое место (код 10h) retlw B'11111100' ; Прочерк (код 11h) retlw B'10000010' ; U (код 12h) retlw B'11110010' ; I (код 13h) start: ;################## M A I N F O O ############################# ;Очистка SFR bcf STATUS, RP0 ;выбрать банк 0 movlw 0x20 ;занести в FSR movwf FSR ;адрес первого регистра GPR clr_reg: clrf INDF ;очистить регистр incf FSR, F ;инкремент FSR btfss FSR, 7 ;если FSR == 0x80 - пропуск, goto clr_reg ;иначе переход к след. итерации ;Инициализация TMR0 bcf STATUS, RP0 ;Выбрать банк 0 movlw 0x64 ;64h == 100d movwf TMR0 ;сбросить TMR0 и предделитель clrf INTCON ;Выключть прерывания, и сбросить T0IF bsf STATUS, RP0 ;Выбрать банк 1 movlw b'10000101' ;Внутренний тактовый сигнал(бит 5) ; подтягивающие резисторы отключены (бит 7) movwf OPTION_REG ;предделитель включен перед TMR0 (бит 3) bcf STATUS, RP0 ;Переход в банк 0 bsf INTCON, T0IE ;разрешить прерывание по переполнению TMR0 bsf INTCON, GIE ;разрешить все немаскированные прерывания ; ;Инициализация порта C bcf STATUS, RP0 ;выбрать банк 0 clrf PORTC ;инициализация защелок порта C movlw 0x3F ;установить RA<5:0> для цифрвого I/0 movwf CMCON0 ; bsf STATUS, RP0 ;выбрать банк 1 clrf ANSEL ;digital I/O movlw b'10000000' ;подтягивающие резисторы отключены movwf TRISC ;все биты PORTC настроены на выход ; main_loop: btfsc int_flags, sec1 ;Прошла одна секунда? call refresh_disp_ ;Да goto main_loop refresh_disp_: bcf int_flags, sec1 ; incf minute, F ; movlw 0x09 xorwf minute, W ; btfsc STATUS, Z ; clrf minute movf minute, W call hex_to_7seg xorlw 0xFF ;инверсия для индикаторов с общим катодом movwf tmp1 movlw 0x08 ; movwf bit_cntr ; refresh_disp_loop_: bsf cbuf, 0 ;установить на DATA "1" btfss tmp1, 0 ;если 0-й разряд == 0 bcf cbuf, 0 ;сбросить DATA movf cbuf, W ; movwf PORTC ;перенести значение буфера в регистр bsf cbuf, 1 ; movf cbuf, W ; movwf PORTC ;подать тактовый импульс bcf cbuf, 1 ; movf cbuf, W ; movwf PORTC ;на CLK bcf STATUS, C ;сброс флага C rrf tmp1, F ;сдвиг кода символа на 1 разряд вправо decf bit_cntr, F ;декремент счетчика btfss STATUS, Z ;Если bit_cntr обнулился - пропуск goto refresh_disp_loop_ movlw 0x00 movwf PORTC return end Что здесь не так? Ответы типа "бери AVR и ниипи моск", "PIC гамно - AVR-ы и MSP руляд" и т.п. не принимаются Также не принимается ответ вроде "У тебя бракованный проц, бери другой" (скорее у меня мозг бракованный)
а ты примеры искать не пробовал. Года 3 назад, я такой же фигней занимался, примеров находил немало, в том числе там был и таймер.
0x00786F72 Здесь отличные переводы мануалов по PIC, только я прочитав их , всё равно перешёл на AVR ))
Y_Mur, та страничка мне прекрасно знакома, но все равно спасибо 4 дня мучался из-за глупой ошибки в коде: в обработчике прерывания я дважды считал до 100, т.е. фактически вместо одной секунды он отсчитывал примерно 100 секунд На AVR, тоже собираюсь перейти, но только как закончу проект З.Ы. тему можно закрыть