Форум РадиоКот • Просмотр темы - Расчет частоты таймера. Где-то ошибка в логике.
Сообщения без ответов | Активные темы
Страница 1 из 1
[ Сообщений: 20 ]
Автор
Сообщение
ultexplorer
Заголовок сообщения: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Вт янв 09, 2018 01:29:51
Зарегистрирован: Пн дек 25, 2017 22:14:45Сообщений: 7
Рейтинг сообщения: 0
Народ, написал программу с таймером для мигания светодиодом.
Он мигает, но не с той частотой…
Мигает где-то с частотой 3 – 4 Гц. А по моим расчетам должен мигать с частотой 0,1 Гц.
Я пользовался методикой, изложенной в книге Ревича (Практическое программирование микроконтроллеров AVR).
Вот как я считал частоту:
Микропроцессор Atmega16. Выбрал частоту 8МгЦ.
В пред-делитель прописал 8.
Значит 8000000 / 8 = 1000000 (1мГц) - это частота, с которой тикает таймер.
Далее в регистр TCNT0 записываю 250 для круглого счета:
ldi r16, 250
neg r16 ;
out TCNT0, r16
По идее прерывание должно происходить с частотой 4кГц (1000000/250 = 4000), то есть 4000 прерываний за одну сек.
Обработчик прерываний вызывает подпрограмму.
В ней я выделил в оперативной памяти переменную в 2 байта.
В нее прописал число 40000.
Переменная декрементируется прерыванием.
Когда становится равной 0, то инвертируется PortD, на 0-м пине которого я запитал светодиод.
По идее, он должен мигать с частотой 4000 / 40000, т.е. 0,1 Гц.
А он мигает с частотой 3-4 Герца…
Помогите разобраться.
Код привожу:
Код:
.include "m16def.inc" .def rK_div = r16 .def count = r17 .def Temp1 = r18 .def Temp2 = r19 .equ K_div = 250 .equ t_counter = 40000 ;Макросы--------------------------------------------------------------------- .macro mouti ldi r20, @1 out @0, r20 .endm ;---------- .dseg ram_counter: .byte 2 .cseg .ORG $000 ; (RESET) RJMP RESET .ORG $002 RETI ; (INT0) External Interrupt Request 0 .ORG $004 RETI ; (INT1) External Interrupt Request 1 .ORG $006 RETI ; (TIMER2 COMP) Timer/Counter2 Compare Match .ORG $008 RETI ; (TIMER2 OVF) Timer/Counter2 Overflow .ORG $00A RETI ; (TIMER1 CAPT) Timer/Counter1 Capture Event .ORG $00C RETI ; (TIMER1 COMPA) Timer/Counter1 Compare Match A .ORG $00E RETI ; (TIMER1 COMPB) Timer/Counter1 Compare Match B .ORG $010 RETI ; (TIMER1 OVF) Timer/Counter1 Overflow .ORG $012 RJMP timer0ovf ; (TIMER0 OVF) Timer/Counter0 Overflow .ORG $014 RETI ; (SPI,STC) Serial Transfer Complete .ORG $016 RETI ; (USART,RXC) USART, Rx Complete .ORG $018 RETI ; (USART,UDRE) USART Data Register Empty .ORG $01A RETI ; (USART,TXC) USART, Tx Complete .ORG $01C RETI ; (ADC) ADC Conversion Complete .ORG $01E RETI ; (EE_RDY) EEPROM Ready .ORG $020 RETI ; (ANA_COMP) Analog Comparator .ORG $022 RETI ; (TWI) 2-wire Serial Interface .ORG $024 RETI ; (INT2) External Interrupt Request 2 .ORG $026 RETI ; (TIMER0 COMP) Timer/Counter0 Compare Match .ORG $028 RETI ; (SPM_RDY) Store Program Memory Ready .ORG INT_VECTORS_SIZE ; Interrupts ========== timer0ovf: push Temp1 in Temp1, SREG push Temp1 push Temp2 call dec_proc pop Temp2 pop Temp1 out SREG, Temp1 pop Temp1 RETI ;---------- rjmp reset RESET: nop RAM_flash: ldi zl, low(sram_start) ldi zh,high(sram_start) clr r16 flash: st z+, r16 cpi zh,high(ramend+1) brne flash cpi zl,low (ramend+1) brne flash clr zl clr zh ldi zl, 30 clr zh dec zl st z, zh brne PC-2 nop clr Temp1 out TCNT0,Temp1 ;Инициализирую стек ---------- ldi Temp1, low(ramend) out spl, Temp1 ldi Temp1,high(ramend) out sph, Temp1 ;Инициализирую порт D для светодиода------------------------------------ mouti DDRD, 0b00000001 mouti PortD,0b11111110 ;---------- ;Записываю 40000 в переменную в ram----------------------------------- ram_var: nop ldi Temp1, low(t_counter) sts ram_counter, Temp1 ldi Temp1,high(t_counter) sts ram_counter+1, Temp1 ;---------- ;Инициализирую таймер ---------- ldi rK_div, K_div neg rK_div out TCNT0,rK_div mouti TCCR0,1<<CS01 ;предделитель 8 mouti TIMSK,1<<TOIE0 ;разрешаю прерывания таймера mouti SREG, $80 ;разрешаю все прерывания (SREG) ;---------- main: nop rjmp main ;Подпрограммы---------------------------------------------------------------- ;Декремент переменной в ram ---------- dec_proc: lds Temp1, ram_counter lds Temp2, ram_counter+1 dec_var: subi Temp1,1 sbci Temp2,0 brcc no_ziro rjmp dec_end no_ziro: sts ram_counter, Temp1 sts ram_counter+1, Temp2 rjmp dec_proc dec_end: nop ;Когда 0, инвертирую PortD ---------- cli ldi Temp1, low(t_counter) ldi Temp2,high(t_counter) sts ram_counter, Temp1 ;восстанавливаю значение переменной в ram sts ram_counter+1, Temp2 in Temp1, PortD ldi Temp2,0b00000001 eor Temp1,Temp2 out PortD, Temp1 ;---------- sei ret ;;End подпрограммы------------------------------------------------------
Вернуться наверх
Реклама
Reflector
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Вт янв 09, 2018 02:02:49
Поставщик валерьянки для Кота
Карма: 20
Рейтинг сообщений: 253
Зарегистрирован: Вс июн 19, 2016 09:32:03Сообщений: 2090
Рейтинг сообщения: 0
Далее в регистр TCNT0 записываю 250 для круглого счета: ldi r16, 250 neg r16 ; out TCNT0, r16
Neg то тут что делает?
Вернуться наверх
Реклама
akl
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Вт янв 09, 2018 05:19:29
Карма: 64
Рейтинг сообщений: 966
Зарегистрирован: Пт мар 07, 2008 06:54:43Сообщений: 4221Откуда: Ижевск
Рейтинг сообщения: 0
ultexplorer Вы должны отсчитать 250мкс и уменьшить на единицу счетчик переполнений, а программа отсчитав 250мкс 40'000 выполняет декремент счетчика, выходит из прерывания
Спойлер Код:
.include "m16def.inc" .def rK_div = r16 .def count = r17 .def Temp1 = r18 .def Temp2 = r19 .equ K_div = 250 .equ t_counter = 40000 ;Макросы--------------------------------------------------------------------- .macro mouti ldi r20, @1 out @0, r20 .endm ;---------- .dseg ram_counter: .byte 2 .cseg .ORG $000 ; (RESET) RJMP RESET ; .ORG $002 ; RETI ; (INT0) External Interrupt Request 0 ; .ORG $004 ; RETI ; (INT1) External Interrupt Request 1 ; .ORG $006 ; RETI ; (TIMER2 COMP) Timer/Counter2 Compare Match ; .ORG $008 ; RETI ; (TIMER2 OVF) Timer/Counter2 Overflow ; .ORG $00A ; RETI ; (TIMER1 CAPT) Timer/Counter1 Capture Event ; .ORG $00C ; RETI ; (TIMER1 COMPA) Timer/Counter1 Compare Match A ; .ORG $00E ; RETI ; (TIMER1 COMPB) Timer/Counter1 Compare Match B ; .ORG $010 ; RETI ; (TIMER1 OVF) Timer/Counter1 Overflow .ORG $012 SUBI XL,LOW(1) SBCI XH,HIGH(1) BRNE OUT_OVER_T0 in Temp1, PortD ldi Temp2,0b00000001 eor Temp1,Temp2 out PortD, Temp1 LDI XH,HIGH(40000) LDI XL,LOW(40000) OUT_OVER_T0: LDI R16,-250 OUT TCNT0,R16 RETI ; RJMP timer0ovf ; (TIMER0 OVF) Timer/Counter0 Overflow ; .ORG $014 ; RETI ; (SPI,STC) Serial Transfer Complete ; .ORG $016 ; RETI ; (USART,RXC) USART, Rx Complete ; .ORG $018 ; RETI ; (USART,UDRE) USART Data Register Empty ; .ORG $01A ; RETI ; (USART,TXC) USART, Tx Complete ; .ORG $01C ; RETI ; (ADC) ADC Conversion Complete ; .ORG $01E ; RETI ; (EE_RDY) EEPROM Ready ; .ORG $020 ; RETI ; (ANA_COMP) Analog Comparator ; .ORG $022 ; RETI ; (TWI) 2-wire Serial Interface ; .ORG $024 ; RETI ; (INT2) External Interrupt Request 2 ; .ORG $026 ; RETI ; (TIMER0 COMP) Timer/Counter0 Compare Match ; .ORG $028 ; RETI ; (SPM_RDY) Store Program Memory Ready ; .ORG INT_VECTORS_SIZE ; Interrupts ========== ;timer0ovf: ; push Temp1 ; in Temp1, SREG ; push Temp1 ; push Temp2 ; call dec_proc ; pop Temp2 ; pop Temp1 ; out SREG, Temp1 ; pop Temp1 ; RETI ;---------- ; rjmp reset RESET: ; nop ;RAM_flash: ; ldi zl, low(sram_start) ; ldi zh,high(sram_start) ; clr r16 ;flash: st z+, r16 ; cpi zh,high(ramend+1) ; brne flash ; cpi zl,low (ramend+1) ; brne flash ; clr zl ; clr zh ; ldi zl, 30 ; clr zh ; dec zl ; st z, zh ; brne PC-2 ; nop ; clr Temp1 ; out TCNT0,Temp1 ;Инициализирую стек ---------- ldi Temp1, low(ramend) out spl, Temp1 ldi Temp1,high(ramend) out sph, Temp1 ;Инициализирую порт D для светодиода------------------------------------ mouti DDRD, 0b00000001 mouti PortD,0b11111110 ;---------- ;Записываю 40000 в переменную в ram----------------------------------- REG_var: LDI XH,HIGH(40000) LDI XL,LOW(40000) ; nop ; ldi Temp1, low(t_counter) ; sts ram_counter, Temp1 ; ldi Temp1,high(t_counter) ; sts ram_counter+1, Temp1 LDI R16,1<<SE OUT MCUCR,R16 ;Инициализирую таймер ---------- LDI R16,-250 OUT TCNT0,R16 ; ldi rK_div, K_div ; neg rK_div ; out TCNT0,rK_div mouti TCCR0,1<<CS01 ;предделитель 8 mouti TIMSK,1<<TOIE0 ;разрешаю прерывания таймера mouti TIFR,1<<TOV0 ;сброс флага переполнения SEI ; mouti SREG, $80 ;разрешаю все прерывания (SREG) ;---------- main: SLEEP nop rjmp main ;Подпрограммы---------------------------------------------------------------- ;Декремент переменной в ram ---------- ;dec_proc: lds Temp1, ram_counter ; lds Temp2, ram_counter+1 ;dec_var: subi Temp1,1 ; sbci Temp2,0 ; brcc no_ziro ; rjmp dec_end ;no_ziro: sts ram_counter, Temp1 ; sts ram_counter+1, Temp2 ; rjmp dec_proc ;dec_end: nop ;Когда 0, инвертирую PortD ---------- ; cli ; ldi Temp1, low(t_counter) ; ldi Temp2,high(t_counter) ; sts ram_counter, Temp1 ;восстанавливаю значение переменной в ram ; sts ram_counter+1, Temp2 ; in Temp1, PortD ; ldi Temp2,0b00000001 ; eor Temp1,Temp2 ; out PortD, Temp1 ;---------- ; sei ; ret ;;End подпрограммы--------------------------- .EXIT
Вернуться наверх
Реклама
Z_h_e
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Вт янв 09, 2018 05:35:21
Собутыльник Кота
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04Сообщений: 2694Откуда: г. Чайковский
Рейтинг сообщения: 0
Медали: 1
Цитата:
dec_var: subi Temp1,1 sbci Temp2,0 brcc no_ziro rjmp dec_end
brne , я по памяти команду написал, давно на ассме ничего не делал. Ну т.е. нужно проверять флаг Z.
Еще важный момент в целом, но возможно не в этом коде. Вы зачем то разрешаете прерывания внутри обработчика прерывания, это чревато зависнуть и сорвать стек.
_________________Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Вернуться наверх
Реклама
Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Подробнее>>
akl
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Вт янв 09, 2018 06:25:36
Карма: 64
Рейтинг сообщений: 966
Зарегистрирован: Пт мар 07, 2008 06:54:43Сообщений: 4221Откуда: Ижевск
Рейтинг сообщения: 0
Код:
sei ret
Проще выходить по RETI
По мне, лучше использовать режим CTC. Отсчет времени получается гораздо точнее.
Спойлер Код:
.include "m16def.inc" .equ Fo=8000000 .def Temp1 = r18 .def Temp2 = r19 ;Макросы------------------------------------------ .macro mouti ldi r20, @1 out @0, r20 .endm ;---------- .cseg .ORG $000 RESET: RJMP START .ORG $026; (TIMER0 COMP) Timer/Counter0 Compare Match SUBI XL,LOW(1) SBCI XH,HIGH(1) BRNE OUT_OVER_T0 RET OUT_OVER_T0: RETI ; (TIMER0 COMP) Timer/Counter0 Compare Match ;************************************************* START: ;Инициализирую стек ---------- ldi Temp1, low(ramend) out spl, Temp1 ldi Temp1,high(ramend) out sph, Temp1 ;Инициализирую порт D для светодиода------------------------------------ mouti DDRD, 0b00000001 mouti PortD,0b11111110 ;Записываю 40000 в переменную в ram----------------------------------- REG_var: LDI XH,HIGH(Fo/10/250/8) LDI XL,LOW(Fo/10/250/8) ; 0,1 SEC ; LDI XH,HIGH(1*Fo/250/8) ; LDI XL,LOW(1*Fo/250/8) ; 1 SEC ; LDI XH,HIGH(10*Fo/250/8) ; LDI XL,LOW(10*Fo/250/8) ; 10 SEC LDI R16,1<<SE OUT MCUCR,R16 ;Инициализирую таймер ---------- LDI R16,250-1 OUT OCR0,R16 mouti TIMSK,1<<OCIE0 ;разрешаю прерывания таймера mouti TIFR,1<<OCF0 ;сброс флага переполнения mouti TCCR0,1<<CS01|1<<WGM01 ;Fo/8, CTC SEI ;---------- main: SLEEP BRIE MAIN RJMP REG_VAR .EXIT
Вернуться наверх
Реклама
Реклама
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Подробнее>>
ultexplorer
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Ср янв 10, 2018 14:22:39
Зарегистрирован: Пн дек 25, 2017 22:14:45Сообщений: 7
Рейтинг сообщения: 0
Далее в регистр TCNT0 записываю 250 для круглого счета: ldi r16, 250 neg r16 ; out TCNT0, r16
Neg то тут что делает?
Это 256 - 250 = 6. С 6 начинается счет, так как таймер работает по переполнени. Т.е, чтобы таймер отсчитал 250 тиков, а затем сработало прерывание, необходимо. чтобы он начинал отсчет с 6.
Вернуться наверх
Реклама
Z_h_e
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Ср янв 10, 2018 14:24:34
Собутыльник Кота
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04Сообщений: 2694Откуда: г. Чайковский
Рейтинг сообщения: 0
Медали: 1
Освойте режим CTC, как указал ak l, таймер будет считать от 0 до нужного значения и сам сбрасываться.
_________________Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Вернуться наверх
Реклама
ultexplorer
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Ср янв 10, 2018 14:50:57
Зарегистрирован: Пн дек 25, 2017 22:14:45Сообщений: 7
Рейтинг сообщения: 0
Освойте режим CTC, как указал ak l, таймер будет считать от 0 до нужного значения и сам сбрасываться.
Спасибо. Займусь этим.
В своем коде нашел ошибку.
Забыл поставить метку на выход из подпрограммы, если переменная все еще больше 0.
Вот поправил подпрограмму:
Код:
;Счетчик декремент----------------------------------------------------------- dec_proc: lds Temp1, ram_counter lds Temp2, ram_counter+1 dec_var: subi Temp1,1 sbci Temp2,0 brcc no_ziro rjmp dec_end no_ziro: sts ram_counter, Temp1 sts ram_counter+1, Temp2 rjmp end_proc dec_end: nop ;Здесь инвертируем PortD ---------- //cli ldi Temp1, low(t_counter) ldi Temp2,high(t_counter) sts ram_counter, Temp1 sts ram_counter+1, Temp2 in Temp1, PortD ldi Temp2,0b00000001 ; маска eor Temp1,Temp2 ;инвертирую out PortD, Temp1 ;---------- //sei end_proc: ret ;;End Счетчик декремент------------------------------------------------------
Вернуться наверх
Реклама
Z_h_e
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Ср янв 10, 2018 14:55:21
Собутыльник Кота
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04Сообщений: 2694Откуда: г. Чайковский
Рейтинг сообщения: 0
Медали: 1
ultexplorer писал(а):
Это 256 - 250 = 6
neg , это же не оператор препроцессора, а реальная команда, абсолютно избыточная.
Код:
ldi r16, 0-250 //neg r16 ; out TCNT0, r16
_________________Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Вернуться наверх
Реклама
ultexplorer
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Ср янв 10, 2018 15:05:43
Зарегистрирован: Пн дек 25, 2017 22:14:45Сообщений: 7
Рейтинг сообщения: 0
ultexplorer писал(а):
Это 256 - 250 = 6
neg , это же не оператор препроцессора, а реальная команда, абсолютно избыточная.
Код:
ldi r16, 0-250 //neg r16 ; out TCNT0, r16
Точно!
Не все в книгах верно...
Вернуться наверх
BOB51
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Ср янв 10, 2018 15:17:45
Друг Кота
Карма: 93
Рейтинг сообщений: 1351
Зарегистрирован: Вт мар 16, 2010 22:02:27Сообщений: 14074Откуда: ДОНЕЦК
Рейтинг сообщения: 0
Метод рассчета несколько....
Если стандартная частота генератора (внутреннего) 8МГц, то обязательно включен предделитель (фузами, ежли МК после выпуска заводом - изготовителем никто не перепрошивал "по иному").
Итогом будем иметь тактовую ядра по умолчанию в 1МГц или привычнее 0,000001 секунды/такт.
250 тиков таймера дадут прерывание в 0,000001 *250=0,000250 секунды.
Тогда чтобы получить 0,1 секунды на инверсию потребуется 0,1/0,00025=400 прерываний. А у автора АЖ 40000!
И то при инверсии состояния вывода это будет мигание не раз в 0,1 а раз в 0,2 секунды (5ГЦ).
Последний раз редактировалось BOB51 Ср янв 10, 2018 15:21:50, всего редактировалось 1 раз.
Вернуться наверх
Z_h_e
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Ср янв 10, 2018 15:21:17
Собутыльник Кота
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04Сообщений: 2694Откуда: г. Чайковский
Рейтинг сообщения: 0
Медали: 1
Я Вам уже говорил. Ваша переменная не проверяется на ноль. Вы перейдете на метку dec_end, после того как из переменной равной 0 вычтете 1. Так что можете считать что проверяется на отрицательный знак числа (хотя и это не корректное утверждение). Для Вашего кода это врядли важно, всего лишь одна итерация дополнительная, но проверки на ноль нет. З.Ы. Зачем команды nop? ---------- З.З.Ы Выкинте Ваш код, возьмите код akl . Я не предлагаю его брать как готовый текст бессмысленно, раскурите его как следует.
_________________Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Вернуться наверх
Demiurg
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Ср янв 10, 2018 21:21:48
Это не хвост, это антенна
Карма: 4
Рейтинг сообщений: 141
Зарегистрирован: Ср июн 25, 2008 15:19:44Сообщений: 1385
Рейтинг сообщения: 0
0,1 Гц - это до фига времени. Нужно делать на программных таймерах. Вкратце, аппаратный таймер настраивается на системный тик. Времянки выбираете исходя из своих задач. 1 мс, 10 мс. Пример на 1 мс при частоте кварца 16 МГц:
Спойлер Код:
//================== .equ ST_TCNT = TCNT0 .equ ST_TIMSK = TIMSK .equ ST_OCIE = OCIE0 .equ ST_OCR = OCR0 .equ ST_TCCR = TCCR0 .equ CS0 = CS00 .equ CS1 = CS01 .equ CS2 = CS02 //================== //================== .equ SYS_TICK = 1 // Период системного таймера 1 мс //================== //================== .macro Init_System_Timer clr r16 out ST_TCNT, r16 in r16, ST_TIMSK sbr r16, 1<<ST_OCIE out ST_TIMSK, r16 outi ST_OCR, (XTAL/64/1000) in r16, ST_TCCR sbr r16, 1<<CS0 | 1<<CS1 out ST_TCCR, r16 .endmacro .macro ReRun_Sys_Timer in r16,ST_OCR subi r16,-(XTAL/64/1000) out ST_OCR,r16 .endmacro //================== //================== Sys_Timer_Comp: push r16 in r16,SREG push r16 ReRun_Sys_Timer sbr FLAGS,1<<SYS_TICK_FLG pop r16 out SREG,r16 pop r16 reti //==================
Спойлер Код:
// vectors_m8535 .cseg .org 0x0000 rjmp Reset ;====== INTERRUPT VECTORS ============ .org INT0addr ; External Interrupt 0 reti .org INT1addr ; External Interrupt 1 reti .org OC2addr ; Timer/Counter2 Compare Match reti // rjmp Proc_Int_BAM // reti .org OVF2addr ; Timer/Counter2 Overflow reti .org ICP1addr ; Timer/Counter1 Capture Event reti .org OC1Aaddr ; Timer/Counter1 Compare Match A reti .org OC1Baddr ; Timer/Counter1 Compare Match B reti .org OVF1addr ; Timer/Counter1 Overflow reti .org OVF0addr ; Timer/Counter0 Overflow reti .org SPIaddr ; SPI Serial Transfer Complete reti ; rjmp SPI_Transfer_Int .org URXCaddr ; USART, RX Complete reti .org UDREaddr ; USART Data Register Empty reti .org UTXCaddr ; USART, TX Complete reti .org ADCCaddr ; ADC Conversion Complete reti // rjmp ADC_Complete .org ERDYaddr ; EEPROM Ready reti .org ACIaddr ; Analog Comparator reti .org TWIaddr ; Two-wire Serial Interface reti .org INT2addr ; External Interrupt Request 2 reti .org OC0addr ; TimerCounter0 Compare Match rjmp Sys_Timer_Comp .org SPMRaddr ; Store Program Memory Read reti ;---------- .org INT_VECTORS_SIZE ; size in words ;===================
Вернуться наверх
akl
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Чт янв 11, 2018 04:44:30
Карма: 64
Рейтинг сообщений: 966
Зарегистрирован: Пт мар 07, 2008 06:54:43Сообщений: 4221Откуда: Ижевск
Рейтинг сообщения: 0
BOB51 писал(а):
...Тогда чтобы получить 0,1 секунды...
Замечу, стартёру нужно было
ultexplorer писал(а):
По идее, он должен мигать с частотой ... 0,1 Гц.
Demiurg Код:
// outi ST_OCR, (XTAL/64/1000) outi ST_OCR, (XTAL/64/1000-1)
так будет гораздо (на 4мкс) точнее.
Вернуться наверх
Demiurg
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Чт янв 11, 2018 06:56:17
Это не хвост, это антенна
Карма: 4
Рейтинг сообщений: 141
Зарегистрирован: Ср июн 25, 2008 15:19:44Сообщений: 1385
Рейтинг сообщения: 0
akl писал(а):
так будет гораздо (на 4мкс) точнее.
Я в симуляторе AVR-Studio проверял. А вы?
Вернуться наверх
Z_h_e
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Чт янв 11, 2018 06:59:22
Собутыльник Кота
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04Сообщений: 2694Откуда: г. Чайковский
Рейтинг сообщения: 0
Медали: 1
А минус 1 это из дш
_________________Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Вернуться наверх
akl
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Чт янв 11, 2018 08:32:20
Карма: 64
Рейтинг сообщений: 966
Зарегистрирован: Пт мар 07, 2008 06:54:43Сообщений: 4221Откуда: Ижевск
Рейтинг сообщения: 0
Я в симуляторе AVR-Studio проверял. А вы?
Разумеется проверял.
с -1, т.е. на 64 такта короче
Вложения:
Комментарий к файлу: вторая и все последующие милисекунды
test_1ms_ds.PNG [14.14 KiB]
Скачиваний: 348
Комментарий к файлу: вторая и все последующие милисекунды
test_1ms_demiurg.PNG [13.12 KiB]
Скачиваний: 487
Вернуться наверх
BOB51
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Чт янв 11, 2018 08:55:51
Друг Кота
Карма: 93
Рейтинг сообщений: 1351
Зарегистрирован: Вт мар 16, 2010 22:02:27Сообщений: 14074Откуда: ДОНЕЦК
Рейтинг сообщения: 0
Так 0,1ГЦ это ж не мигание, а непрерывное горение 10 секунд с паузой в 10 секунд...
Вернуться наверх
akl
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Чт янв 11, 2018 09:08:22
Карма: 64
Рейтинг сообщений: 966
Зарегистрирован: Пт мар 07, 2008 06:54:43Сообщений: 4221Откуда: Ижевск
Рейтинг сообщения: 0
BOB51 писал(а):
Так 0,1ГЦ это ж не мигание, а непрерывное горение 10 секунд с паузой в 10 секунд...
Нет, не 0,1Гц, а 0,05Гц. Пытаюсь донести, что 0,1 секунды это не 0,1Гц. Извините.
Вернуться наверх
ultexplorer
Заголовок сообщения: Re: Расчет частоты таймера. Где-то ошибка в логике.
Добавлено: Чт янв 11, 2018 22:04:22
Зарегистрирован: Пн дек 25, 2017 22:14:45Сообщений: 7
Рейтинг сообщения: 0
Так 0,1ГЦ это ж не мигание, а непрерывное горение 10 секунд с паузой в 10 секунд...
Да. Так легче на глаз проверить, как работает собранная схема.
Я поправил код, нашел ошибки, поменял brcc на brne, заменил neg на 0-250, немного усложнил код.
Теперь 3 светодиода. Один мигает с частотой 1 Гц, второй 2 Гц, Третий 4 Гц. Собрал, все работает.
Занимаюсь дальнейшим изучением таймеров в силу свободного времени
Вот код на 3 светодиода:
Код:
.include "m16def.inc" .def rK_div = r16 .def count = r17 .def Temp1 = r18 .def Temp2 = r19 .equ K_div = 250 .equ t_counter = 4000 .equ t_counter2 = 2000 .equ t_counter3 = 1000 ;---------- .macro mouti ldi r20, @1 out @0, r20 .endm ;---------- .dseg ram_counter: .byte 2 ram_counter2: .byte 2 ram_counter3: .byte 2 .cseg .ORG $000 ; (RESET) RJMP RESET .ORG $002 RETI ; (INT0) External Interrupt Request 0 .ORG $004 RETI ; (INT1) External Interrupt Request 1 .ORG $006 RETI ; (TIMER2 COMP) Timer/Counter2 Compare Match .ORG $008 RETI ; (TIMER2 OVF) Timer/Counter2 Overflow .ORG $00A RETI ; (TIMER1 CAPT) Timer/Counter1 Capture Event .ORG $00C RETI ; (TIMER1 COMPA) Timer/Counter1 Compare Match A .ORG $00E RETI ; (TIMER1 COMPB) Timer/Counter1 Compare Match B .ORG $010 RETI ; (TIMER1 OVF) Timer/Counter1 Overflow .ORG $012 RJMP timer0ovf ; (TIMER0 OVF) Timer/Counter0 Overflow .ORG $014 RETI ; (SPI,STC) Serial Transfer Complete .ORG $016 RETI ; (USART,RXC) USART, Rx Complete .ORG $018 RETI ; (USART,UDRE) USART Data Register Empty .ORG $01A RETI ; (USART,TXC) USART, Tx Complete .ORG $01C RETI ; (ADC) ADC Conversion Complete .ORG $01E RETI ; (EE_RDY) EEPROM Ready .ORG $020 RETI ; (ANA_COMP) Analog Comparator .ORG $022 RETI ; (TWI) 2-wire Serial Interface .ORG $024 RETI ; (INT2) External Interrupt Request 2 .ORG $026 RETI ; (TIMER0 COMP) Timer/Counter0 Compare Match .ORG $028 RETI ; (SPM_RDY) Store Program Memory Ready .ORG INT_VECTORS_SIZE ; Êîíåö òàáëèöû ïðåðûâàíèé ; Interrupts ========== timer0ovf: push Temp1 in Temp1, SREG cli push Temp1 push Temp2 call dec_proc call dec_proc2 call dec_proc3 pop Temp2 pop Temp1 out SREG, Temp1 pop Temp1 RETI ;---------- rjmp reset RESET: RAM_flash: ldi zl, low(sram_start) ldi zh,high(sram_start) clr r16 flash: st z+, r16 cpi zh,high(ramend+1) brne flash cpi zl,low (ramend+1) brne flash clr zl clr zh ldi zl, 30 clr zh dec zl st z, zh brne PC-2 nop clr Temp1 out TCNT0,Temp1 ;---------- ldi Temp1, low(ramend) out spl, Temp1 ldi Temp1,high(ramend) out sph, Temp1 ;---------- mouti DDRD, 0b00000111 mouti PortD,0b11111111 ;---------- ; ram_counter----------------------------------- ram_var: ldi Temp1, low(t_counter) sts ram_counter, Temp1 ldi Temp1,high(t_counter) sts ram_counter+1, Temp1 ldi Temp1, low(t_counter2) sts ram_counter2, Temp1 ldi Temp1,high(t_counter2) sts ram_counter2+1, Temp1 ldi Temp1, low(t_counter3) sts ram_counter3, Temp1 ldi Temp1,high(t_counter3) sts ram_counter3+1, Temp1 ;---------- ;---------- //ldi rK_div, K_div //neg rK_div ldi rK_div,0-250 out TCNT0,rK_div mouti TCCR0,1<<CS01 mouti TIMSK,1<<TOIE0 mouti SREG, $80 ;---------- main: rjmp main ;---------- ;---------- dec_proc: lds Temp1, ram_counter lds Temp2, ram_counter+1 dec_var: subi Temp1,1 sbci Temp2,0 //brcc no_ziro brne no_ziro rjmp dec_end no_ziro: sts ram_counter, Temp1 sts ram_counter+1, Temp2 rjmp end_proc dec_end: ; ---------- //cli ldi Temp1, low(t_counter) ldi Temp2,high(t_counter) sts ram_counter, Temp1 sts ram_counter+1, Temp2 in Temp1, PortD ldi Temp2,0b00000001 eor Temp1,Temp2 out PortD, Temp1 ;---------- //sei end_proc: ret ;;---------- ;---------- dec_proc2: lds Temp1, ram_counter2 lds Temp2, ram_counter2+1 dec_var2: subi Temp1,1 sbci Temp2,0 //brcc no_ziro brne no_ziro2 rjmp dec_end2 no_ziro2: sts ram_counter2, Temp1 sts ram_counter2+1, Temp2 rjmp end_proc2 dec_end2: ; PortD ---------- //cli ldi Temp1, low(t_counter2) ldi Temp2,high(t_counter2) sts ram_counter2, Temp1 sts ram_counter2+1, Temp2 in Temp1, PortD ldi Temp2,0b00000010 ; ìàñêà eor Temp1,Temp2 ;èíâåðòèðóþ out PortD, Temp1 ;---------- //sei end_proc2: ret ;;---------- ;---------- dec_proc3: lds Temp1, ram_counter3 lds Temp2, ram_counter3+1 dec_var3: subi Temp1,1 sbci Temp2,0 //brcc no_ziro brne no_ziro3 rjmp dec_end3 no_ziro3: sts ram_counter3, Temp1 sts ram_counter3+1, Temp2 rjmp end_proc3 dec_end3: ;PortD ---------- //cli ldi Temp1, low(t_counter3) ldi Temp2,high(t_counter3) sts ram_counter3, Temp1 sts ram_counter3+1, Temp2 in Temp1, PortD ldi Temp2,0b00000100 eor Temp1,Temp2 out PortD, Temp1 ;---------- //sei end_proc3: ret ;;----------
Вернуться наверх
Страница 1 из 1
[ Сообщений: 20 ]
Кто сейчас на форуме
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 15
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения