Таймеры/счётчики в AVR
Re: Таймеры/счётчики в AVR
akl, спасибо!
Насколько я понял, вы советуете этот подход для энергосбережения?
У меня вопрос с потреблением пока не стоит, питается от сети. Я хочу просто поработать с внешним кварцем.
Насколько я понял, вы советуете этот подход для энергосбережения?
У меня вопрос с потреблением пока не стоит, питается от сети. Я хочу просто поработать с внешним кварцем.
Re: Таймеры/счётчики в AVR
Нет, у меня на первом месте стоит точность. Конечно, очень хорошо, когда удается совместить и точность и потребление. В качестве примера формирование интервала 100'000мкс для малоподходящей частоты кварца. Работа в SLEEP'е привлекательна не только малым потреблением, а тем, что ядро стоит, т.е. конвейер, в отличие от опроса флагов в цикле, не работает.
Re: Таймеры/счётчики в AVR
Ага, спасибо за идею! Я её попробую позже, когда дойду до спящего режима.
Вчерашние эксперименты показали что дело в этом опросе флагов, прерывания по таймерам его сильно замедляют и получаются пропуски отсчёта. Для эксперимента перенёс подсчёт времени в обработчик прерывания часового таймера, в итоге отставание получилось около секунды на 15 минут.
Вопрос 1. Я правильно понимаю, что т.к. прерывание самое приоритетное да ещё и тактируется от собственного кварца остальные прерывания и т.п. НЕ могут его замедлить и это уже погрешность самого кварца?
Вопрос 2. Нигде в даташите не указана паразитная ёмкость ножек XTAL1 и XTAL2, где её взять? В интернетах нашёл что её берут 3 пФ, но откуда это значение не сказано, кроме того сказано что оно может быть другое - " If you suspect your stray capacitance is higher, add the additional stray capacitance ..."
Вопрос 3. Если для тактирования МК используется внутрненний осцилятор 8 МГц (CKSEL 0010), подключаются ли внутренние конденсаторы на 18 и 8 пФ к ножкам XTAL1 и XTAL2? Или они подключаются только если вырать фьюзами Low Frequency Crystal Oscillator?
Вчерашние эксперименты показали что дело в этом опросе флагов, прерывания по таймерам его сильно замедляют и получаются пропуски отсчёта. Для эксперимента перенёс подсчёт времени в обработчик прерывания часового таймера, в итоге отставание получилось около секунды на 15 минут.
Вопрос 1. Я правильно понимаю, что т.к. прерывание самое приоритетное да ещё и тактируется от собственного кварца остальные прерывания и т.п. НЕ могут его замедлить и это уже погрешность самого кварца?
Вопрос 2. Нигде в даташите не указана паразитная ёмкость ножек XTAL1 и XTAL2, где её взять? В интернетах нашёл что её берут 3 пФ, но откуда это значение не сказано, кроме того сказано что оно может быть другое - " If you suspect your stray capacitance is higher, add the additional stray capacitance ..."
Вопрос 3. Если для тактирования МК используется внутрненний осцилятор 8 МГц (CKSEL 0010), подключаются ли внутренние конденсаторы на 18 и 8 пФ к ножкам XTAL1 и XTAL2? Или они подключаются только если вырать фьюзами Low Frequency Crystal Oscillator?
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Таймеры/счётчики в AVR
Эээ... Чего? Если помимо этого прерывания есть и другие, то могут запросто.alexan9er писал(а):т.к. прерывание самое приоритетное да ещё и тактируется от собственного кварца остальные прерывания и т.п. НЕ могут его замедлить и это уже погрешность самого кварца?
2. Да какая разница? Они сами предлагают брать кондёры в диапазоне 12...22 пФ.
3. Только фьюзами для низкочастотного кварца.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Re: Таймеры/счётчики в AVR
1. Этот момент я не понимаю. Допустим прерывание 1 с высшим приоритетом, 2 с более низким. В какой ситуации обработчик прерывания 1 будет ждать выполнения прерывания 2? К тому же у меня прерывание 1 тактируется от собственного часового кварца, я читал что в этом случае все команды также выполняются по его тактам и основной генератор тут вообще не задействован. Как же на него может повлиять другое прерывание?
2. Я читал что влияет, и на практике у меня получается что влияет и довольно сильно. Хотя также читал мнение что кварц довольно устойчив к вариациям нагрузочных кондёров
3. Спасибо
2. Я читал что влияет, и на практике у меня получается что влияет и довольно сильно. Хотя также читал мнение что кварц довольно устойчив к вариациям нагрузочных кондёров
3. Спасибо
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Таймеры/счётчики в AVR
Вы для начала даташит или другую литературу прочитайте про прерывания у АВР.alexan9er писал(а):1. Этот момент я не понимаю. Допустим прерывание 1 с высшим приоритетом, 2 с более низким...
В небольшом диапазоне подстроить можно.alexan9er писал(а):2. Я читал что влияет
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Re: Таймеры/счётчики в AVR
ОК, спасибо.
Про прерывания прочитал, теперь ясно. Получается что если мне нужен точный отсчёт времени то другие прерывания использовать нельзя... Как же это обходят на практике? Очень уж хочется использовать прерывания и от часового кварца, и от внутрненнего.
Про прерывания прочитал, теперь ясно. Получается что если мне нужен точный отсчёт времени то другие прерывания использовать нельзя... Как же это обходят на практике? Очень уж хочется использовать прерывания и от часового кварца, и от внутрненнего.
Re: Таймеры/счётчики в AVR
Убрал все прерывания кроме часового.
Всё равно отстаёт на 15 сек в минуту
Визуально первые 5 сек считает норм, потом замедляется.
Можете подсказать что-нибудь по коду?
В коде стоит заглушка чтобы минута считалась за секунду - для отладки.
И цифры выводит HEX.
Всё равно отстаёт на 15 сек в минуту
Визуально первые 5 сек считает норм, потом замедляется.
Можете подсказать что-нибудь по коду?
В коде стоит заглушка чтобы минута считалась за секунду - для отладки.
И цифры выводит HEX.
Спойлер
Код: Выделить всё
/*
* clocks.asm
*
* Created: 03.12.2014 1:18:40
* Author: Alexander
*/
.device ATMEGA328P
.include "m328Pdef.inc"
; Пороговые значения обработки кнопок
.equ CNTBUTTONPUSHED = 30; пороговое значение счётчика для констатации нажатия клавиши
.equ CNTBUTTONLONGPUSHED = 90; пороговое значение счётчика для констатации длинного нажатия клавиши
.dseg
bD1: .byte 1 ; байт первой цифры
bD2: .byte 1 ; байт второй цифры
bDD: .byte 1 ; байт символа точки
bD3: .byte 1 ; байт третьей цифры
bD4: .byte 1 ; байт четвёртой цифры
bIdx: .byte 1 ; позиция отображаемого разряда
bHrs: .byte 1 ; байт часов
bMin: .byte 1 ; байт минут
bSec: .byte 1 ; байт секунд
bDot: .byte 1 ; байт состояния точки
bIsEven: .byte 1 ; флаг чётного срабатывания часового кварца
bIsRenew: .byte 1 ; флаг установки цифр индикатора
bCntBtnScanDelay: .byte 1 ; счётчик паузы сканирования кнопок
bIsIncHrs: .byte 1 ; флаг инкремента часов
bIsIncMin: .byte 1 ; флаг инкремента минут
bCntBtnHrs: .byte 1 ; счётчик периодов нажатого состояния кнопки установки часов
bCntBtnMin: .byte 1 ; счётчик периодов нажатого состояния кнопки установки минут
.cseg
.org 0
; векторы прерываний
.org 0x000 rjmp RESET ; Reset Handler
.org 0x002 reti ; IRQ0 Handler
.org 0x004 reti ; IRQ1 Handler
.org 0x006 reti ; PCINT0 Handler
.org 0x008 reti ; PCINT1 Handler
.org 0x00A reti ; PCINT2 Handler
.org 0x00C reti ; Watchdog Timer Handler
.org 0x00E reti ; Timer2 Compare A Handler
.org 0x010 reti ; Timer2 Compare B Handler
.org 0x012 rjmp TIMER2OVF ; Timer2 Overflow Handler
.org 0x014 reti ; Timer1 Capture Handler
.org 0x016 reti ; Timer1 Compare A Handler
.org 0x018 reti ; Timer1 Compare B Handler
.org 0x01A reti ; Timer1 Overflow Handler
.org 0x01C reti ; Timer0 Compare A Handler
.org 0x01E reti ; Timer0 Compare B Handler
.org 0x020 reti ; Timer0 Overflow Handler
.org 0x022 reti ; SPI Transfer Complete Handler
.org 0x024 reti ; USART, RX Complete Handler
.org 0x026 reti ; USART, UDR Empty Handler
.org 0x028 reti ; USART, TX Complete Handler
.org 0x02A reti ; ADC Conversion Complete Handler
.org 0x02C reti ; EEPROM Ready Handler
.org 0x02E reti ; Analog Comparator Handler
.org 0x030 reti ; 2-wire Serial Interface Handler
.org 0x032 reti ; Store Program Memory Ready Handler
; ----------
; Вектор RESET HANDLER
RESET:
cli
; установка указателя стека
ldi R16, high(RAMEND)
out SPH, R16
ldi R16, low(RAMEND)
out SPL, R16
; отключаем WD
wdr
in R16, MCUSR
andi R16, ( 0xff & ( 0 << WDRF ) )
out MCUSR, R16
lds R16, WDTCSR
ori R16, ( 1 << WDCE ) | ( 1 << WDE )
sts WDTCSR, R16
ldi R16, ( 0 << WDE )
sts WDTCSR, R16
; начальное состояние порта B
; PB0 вход кнопки
; PB1 вход кнопки
ldi R16, ( 0 << PB1 ) | ( 0 << PB0 )
out DDRB, R16
ldi R16, ( 1 << PB1 ) | ( 1 << PB0 )
out PORTB, R16
; начальное состояние порта C
; порт C управляет анодами индикаторов
ldi R16, 0b11111111
out DDRC, R16
; начальное состояние порта D
; порт D управляет катодами индикаторов
ldi R16, 0b11111111
out DDRD, R16
; выдерживаем паузу для раскачки внешнего часового кварца
; ему нужна пауза примерно в 1 сек
; счётчик 0x001F40 при частоте 8 МГц даст задержку в ~ 1 сек
ldi R16, 0x40
ldi R17, 0x1F
ldi R18, 0x02
WAITQUARTZ:
subi R18, 1
sbci R17, 0
sbci R16, 0
brcc WAITQUARTZ
; таймер 2
; асинхронный режим
; внешний генератор часовой кварц 32768 Гц
; делитель частоты 64
; прерывание по переполнению - MAX = 255 период 2 Гц
ldi R16, ( 0 << OCIE2B ) | ( 0 << OCIE2A ) | ( 0 << TOIE2 )
sts TIMSK2, R16
ldi R16, ( 0 << EXCLK ) | ( 1 << AS2 )
sts ASSR, R16
ldi R16, ( 0 << COM2A1 ) | ( 0 << COM2A0 ) | ( 0 << COM2B1 ) | ( 0 << COM2B0 ) | ( 0 << WGM21 ) | ( 0 << WGM20 )
sts TCCR2A, R16
ldi R16, ( 0 << FOC2A ) | ( 0 << FOC2B ) | ( 0 << WGM22 ) | ( 1 << CS22 ) | ( 0 << CS21 ) | ( 0 << CS20 )
sts TCCR2B, R16
WAITASSR:
lds R16, ASSR ; ждём пока кварц инициализируется
cpi R16, ( 0 << EXCLK ) | ( 1 << AS2 ) | ( 0 << OCR2AUB ) | ( 0 << OCR2BUB ) | ( 0 << TCR2AUB ) | ( 0 << TCR2BUB ) ; флаги должны быть сброшены
brne WAITASSR
ldi R16, ( 1 << OCF2B ) | ( 1 << OCF2A ) | ( 1 << TOV2 )
out TIFR2, R16
ldi R16, ( 0 << OCIE2B ) | ( 0 << OCIE2A ) | ( 1 << TOIE2 )
sts TIMSK2, R16
clr R16
sts TCNT2, R16
; задание начальных значений
ldi R16, 0
sts bD1, R16
ldi R16, 0
sts bD2, R16
ldi R16, 0
sts bDD, R16
ldi R16, 0
sts bD3, R16
ldi R16, 0
sts bD4, R16
ldi R16, 1
sts bIdx, R16
ldi R16, 0
sts bHrs, R16
ldi R16, 0
sts bMin, R16
ldi R16, 0
sts bSec, R16
ldi R16, 1
sts bDot, R16
ldi R16, 1
sts bIsEven, R16
ldi R16, 1
sts bIsRenew, R16
ldi R16, 0
sts bCntBtnScanDelay, R16
ldi R16, 0
sts bIsIncHrs, R16
ldi R16, 0
sts bIsIncMin, R16
ldi R16, 0
sts bCntBtnHrs, R16
ldi R16, 0
sts bCntBtnMin, R16
sei
jmp BEGIN
; ----------
; Подпрограмма раскодировки цифры для отображения на 7-ми сегментном индикаторе
; in R16 - байт младшие 4 бита цифра
; out R16 - бинарный код цифры
DECODE:
push R17
andi R16, 0b00001111
ldi ZL, low( dbDigits * 2 )
ldi ZH, high( dbDigits * 2 )
ldi R17, 0
add ZL, R16
adc ZH, R17
lpm
mov R16, R0
pop R17
ret
; массив байтов с бинарными кодами цифр на 7-ми сегментном индикаторе
dbDigits:
.db 0b11000000, 0b11111001 ; 0 1
.db 0b10100100, 0b10110000 ; 2 3
.db 0b10011001, 0b10010010 ; 4 5
.db 0b10000010, 0b11111000 ; 6 7
.db 0b10000000, 0b10010000 ; 8 9
.db 0b10001000, 0b10000011 ; A B
.db 0b11000110, 0b10100001 ; C D
.db 0b10000110, 0b10001110 ; E F
; ----------
; Подпрограмма отображения символов на 4-х символьном 7-ми сегментном индикаторе
; Также отображается состояние точки между 2м и 3м символами
; Динамическая индикация
DISPLAY:
push R16
push R17
lds R17, bIdx
cpi R17, 1
breq DISPLAY1ST
cpi R17, 2
breq DISPLAY2ND
cpi R17, 3
breq DISPLAY3RD
cpi R17, 4
breq DISPLAY4TH
cpi R17, 5
breq DISPLAY5TH
; 1-ая позиция индикатора
; отображаем символ
DISPLAY1ST:
ldi R16, 0b00000000
out PORTC, R16
lds R16, bD1
call DECODE
out PORTD, R16
ldi R16, 0b00000001
out PORTC, R16
rjmp INCIDX
; 2-ая позиция индикатора
; отображаем символ
DISPLAY2ND:
ldi R16, 0b00000000
out PORTC, R16
lds R16, bD2
call DECODE
out PORTD, R16
ldi R16, 0b00000010
out PORTC, R16
rjmp INCIDX
; 3-я позиция индикатора
; отображаем точку
DISPLAY3RD:
ldi R16, 0b00000000
out PORTC, R16
lds R16, bDD
swap R16 ; состояние точки в 0-м бите
lsl R16 ; точкой на индикаторе управляет PD7
lsl R16 ; поэтому сдвигаем на 7 битов влево
lsl R16
ori R16, 0b01111111 ; а остальные биты устанавливаем всегда чтобы не засвечивать лишние сегменты
out PORTD, R16
ldi R16, 0b00000100
out PORTC, R16
rjmp INCIDX
; 4-ая позиция индикатора
; отображаем символ
DISPLAY4TH:
ldi R16, 0b00000000
out PORTC, R16
lds R16, bD3
call DECODE
out PORTD, R16
ldi R16, 0b00000100
out PORTC, R16
rjmp INCIDX
; 5-ая позиция индикатора
; отображаем символ
DISPLAY5TH:
ldi R16, 0b00000000
out PORTC, R16
lds R16, bD4
call DECODE
out PORTD, R16
ldi R16, 0b00001000
out PORTC, R16
rjmp INCIDX
INCIDX:
inc R17
cpi R17, 6 ; если показали последнюю позицию индикатора
brne IDXSET ; устанавливаем указатель обратно на первую
ldi R17, 1
IDXSET:
sts bIdx, R17
pop R17
pop R16
ret
; ----------
; Подпрограмма сканирования кнопок
; Выставляет флаги нажатия
; Распознаёт одиночное нажатие и факт длительного зажатия кнопки
; С защитой от дребезга контактов
SCANBUTTONS:
push R16
; сканирование осуществляем только каждую 256-ю итерацию
lds R16, bCntBtnScanDelay
inc R16
sts bCntBtnScanDelay, R16
cpi R16, 0
brne ENDSCANBUTTONS
; обрабатываем состояние кнопки часов
in R16, PINB
sbrs R16, PB1
rjmp BTNHPUSHED
rjmp BTNHRELEASED
BTNHPUSHED:
lds R16, bCntBtnHrs
inc R16
sts bCntBtnHrs, R16
cpi R16, CNTBUTTONLONGPUSHED
brlo BTNHANALYZED
ldi R16, CNTBUTTONPUSHED
sts bCntBtnHrs, R16
ldi R16, 1
sts bIsIncHrs, R16
rjmp BTNHANALYZED
BTNHRELEASED:
lds R16, bCntBtnHrs
cpi R16, CNTBUTTONPUSHED
brlo CLEARCNTBTNH
ldi R16, 1
sts bIsIncHrs, R16
CLEARCNTBTNH:
clr R16
sts bCntBtnHrs, R16
BTNHANALYZED:
nop
; обрабатываем состояние кнопки минут
in R16, PINB
sbrs R16, PB0
rjmp BTNMPUSHED
rjmp BTNMRELEASED
BTNMPUSHED:
lds R16, bCntBtnMin
inc R16
sts bCntBtnMin, R16
cpi R16, CNTBUTTONLONGPUSHED
brlo BTNMANALYZED
ldi R16, CNTBUTTONPUSHED
sts bCntBtnMin, R16
ldi R16, 1
sts bIsIncMin, R16
rjmp BTNMANALYZED
BTNMRELEASED:
lds R16, bCntBtnMin
cpi R16, CNTBUTTONPUSHED
brlo CLEARCNTBTNM
ldi R16, 1
sts bIsIncMin, R16
CLEARCNTBTNM:
clr R16
sts bCntBtnMin, R16
BTNMANALYZED:
nop
ENDSCANBUTTONS:
pop R16
ret
; ----------
; Вектор TIMER2 OVERFLOW HANDLER
; Отсчитывает время
TIMER2OVF:
push R16
in R16, SREG
push R16
lds R16, bIsEven ; инвертируем флаг чётности
ldi R17, 0b00000001
eor R16, R17
sts bIsEven, R16
sts bDot, R16 ; точка переключается каждую итерацию
ldi R16, 1
lds R16, bIsEven ; если чётная итерация значит отсчитали секунду
cpi R16, 1
brne EVENANALYZED
call COUNTSECOND
EVENANALYZED:
ldi R16, 1
sts bIsRenew, R16
pop R16
out SREG, R16
pop R16
reti
; ----------
; Подпрограмма отсчёта секунды
COUNTSECOND:
push R16
push R17
push R18
lds R16, bSec
lds R17, bMin
lds R18, bHrs
ldi R16, 59 ; ЗАГЛУШКА
inc R16
cpi R16, 60
brne CLOCKED
clr R16
inc R17
cpi R17, 60
brne CLOCKED
clr R17
inc R18
cpi R18, 24
brne CLOCKED
clr R18
CLOCKED:
sts bSec, R16
sts bMin, R17
sts bHrs, R18
pop R18
pop R17
pop R16
ret
; ----------
; Подпрограмма установки отображаемых символов индикатора
SETDIGITS:
push R16
lds R16, bIsRenew ; отрабатываем только если установлен флаг
cpi R16, 1
brne ENDSETDIGITS
lds R16, bMin
andi R16, 0b00001111
sts bD1, R16
lds R16, bMin
andi R16, 0b11110000
swap R16
sts bD2, R16
lds R16, bDot
sts bDD, R16
lds R16, bHrs
andi R16, 0b00001111
sts bD3, R16
lds R16, bHrs
andi R16, 0b11110000
swap R16
sts bD4, R16
clr R16
sts bIsRenew, R16
ENDSETDIGITS:
pop R16
ret
; ----------
; Основной цикл
BEGIN:
; ВНИМАНИЕ
; флаги обрабатываются по одному за итерацию
; для того чтобы не задерживать цикл
; если флагов нет то сканируем кнопки
; обрабатываем флаг инкремента часов
lds R16, bIsIncHrs
cpi R16, 1
brne NOINCHRS
clr R16
sts bIsIncHrs, R16
lds R16, bHrs
inc R16
cpi R16, 24 ; при переполнении начинаем прокручивать сначала
brne HRSSET
clr R16
HRSSET:
sts bHrs, R16
ldi R16, 1
sts bIsRenew, R16
jmp MAINROUTINES
NOINCHRS:
nop
; обрабатываем флаг инкремента минут
lds R16, bIsIncMin
cpi R16, 1
brne NOINCMIN
clr R16
sts bIsIncMin, R16
sts bSec, R16 ; очищаем секунды
lds R16, bMin
inc R16
cpi R16, 60 ; при переполнении начинаем прокручивать сначала
brne MINSET
clr R16
MINSET:
sts bMin, R16
ldi R16, 1
sts bIsRenew, R16
jmp MAINROUTINES
NOINCMIN:
nop
call SCANBUTTONS ; сканируем кнопки
MAINROUTINES:
call SETDIGITS ; устанавливаем отображаемые символы
call DISPLAY ; отображаем символы на индикаторе
rjmp BEGIN
END:
Re: Таймеры/счётчики в AVR
По мне, ну очень тяжёлая для понимания программа. Разбирался 2 часа, не смог. Скидал свою. Работа только от таймера Т2 в режиме CTC. Для проверки в студии подал на вход 32768*64.
Спойлер
Код: Выделить всё
.include "m328Pdef.inc"
; Пороговые значения обработки кнопок
.equ Fo=32768*64
;.equ Fo=8000000
.def DC=R18
.def _FF =R2 ;FF
.def R_SEC=R25
.def R_MIN=R24
.def R_HOUR=R23
.cseg
.org 0
; векторы прерываний
.org 0x000
RESET:
CLR ZH
LDI R16,0b10000111
OUT DDRB,R16
out PORTB, R16
out DDRB,ZH
rjmp START ; Reset Handler
; массив байтов с бинарными кодами цифр на 7-ми сегментном индикаторе
TB_DIG:
.db 0b11000000, 0b11111001 ; 0 1
.db 0b10100100, 0b10110000 ; 2 3
.db 0b10011001, 0b10010010 ; 4 5
.db 0b10000010, 0b11111000 ; 6 7
.db 0b10000000, 0b10010000 ; 8 9
TB_DC:
;десятки часов единицы часов
.db 0b00001000, 0b00000100
;десятки минут единицы минут
.db 0b00000010, 0b00000001
.org 0x00E
TIMER2_COMPA:
OUT PORTC,ZH ; принудительное гашение всех сегментов
OUT PORTD,_FF ; обратной полярностью
;*************************************************
LDI ZL,LOW(TB_DC*2)
ADD ZL,DC
LPM
LDI ZL,5 ; загрузить в ZH,ZL адрес R5
ADD ZL,DC
LD R16,Z ; содержимое текущего регистра R5...R10 в R16
POINT:
OUT PORTC,R0
OUT PORTD,R16 ; вывод на индикацию
IND:
; подготовиться к индикации следующего знака
INC DC
ANDI DC,$03
SCAN:
SBIW YL,1
BRMI SEC_OUT
RETI
SEC_OUT:
SET ; период 1'000'000us окончен
RET
; ----------
START:
; начальное состояние порта C
; порт C управляет анодами индикаторов
ldi R16, 0b11111111
out DDRC, R16
; начальное состояние порта D
; порт D управляет катодами индикаторов
out DDRD, R16
OUT PORTD,R16
;*************************************************
RJMP TIME_BEGIN
GO:
CLR ZH
LDI R16,0b11111111
MOV _FF,R16
CLR DC
LDI YH,HIGH(4*128-1)
LDI YL,LOW(4*128-1) ;число сравнений компаратора
LDI R16,(Fo/64/512-1)
STS OCR2A,R16
LDI R16,1<<SE
OUT SMCR,R16 ; SLEEP IDLE ENABLE
CLT
SBI DDRB,7
SBI PORTB,7 ; конец импульса 1 секунда
LDI R16,(1 <<WGM21)
sts TCCR2A, R16
ldi R16,(1 <<CS22)
sts TCCR2B, R16
ldi R16,(1<<OCF2A)
sts TIMSK2, R16
out TIFR2, R16
SEI ; разрешение глобальных прерываний
WAIT:
SLEEP
BRTC WAIT
CLT
;**********************************************************
CBI PORTB,7 ; начало импульса 1 секунда
;EXT_POWER:
; SBIS PINB,3
; RJMP INC_TIME ; работа от батареи с блокировкой кнопок
KEY_MIN:
SBIC PINB,1
RJMP KEY_HOUR ; проверка нажатия часов MIN
INC R_MIN ; нажата MIN
CPI R_MIN,60
BRLO MIN_60
CLR R_MIN
MIN_60:
KEY_HOUR:
SBIC PINB,0 ; проверка нажатия часов HOUR
RJMP KEY_PAUSE
INC R_HOUR
CPI R_HOUR,24
BRLO KEY_PAUSE
CLR R_HOUR
KEY_PAUSE:
SBIC PINB,2
RJMP INC_TIME
RJMP GO_TIME_PAUSE ; нажата кнопка ПАУЗА
INC_TIME:
INC R_SEC
INC_TIME1:
CPI R_SEC,60
BRLO GO_TIME
CLR R_SEC
INC_MIN:
INC R_MIN
CPI R_MIN,60
BRLO GO_TIME
CLR R_MIN
INC_HOUR:
INC R_HOUR
CPI R_HOUR,24
BRLO GO_TIME
TIME_BEGIN:
CLR R_HOUR
CLR R_MIN
GO_TIME_PAUSE:
CLR R_SEC
GO_TIME:
RCALL DIG_HOUR
RCALL DIG_MIN
; RCALL DIG_SEC
RJMP GO
;**********************************************************
DIG_HOUR:
MOV R17,R_HOUR
RCALL BIN8_BCD3
LDI ZL,LOW(TB_DIG*2)
ADD ZL,R27
LPM R5,Z
LDI ZL,LOW(TB_DIG*2)
ADD ZL,R28
LPM R6,Z
RET
;*************************************************
DIG_MIN:
MOV R17,R_MIN
RCALL BIN8_BCD3
LDI ZL,LOW(TB_DIG*2)
ADD ZL,R27
LPM R7,Z
LDI ZL,LOW(TB_DIG*2)
ADD ZL,R28
LPM R8,Z
RET
;*************************************************
;DIG_SEC:
; MOV R17,R_SEC
; RCALL BIN8_BCD3
; LDI ZL,LOW(TB_DIG*2)
; ADD ZL,R27
; LPM R9,Z
; LDI ZL,LOW(TB_DIG*2)
; ADD ZL,R28
; LPM R10,Z
; RET
;*************************************************
BIN8_BCD3:
CLR R27 ; BCD OUT 10,1
LDI R28,8
PR:
subi r27,-0x33 ;add 0x33
sbrs r27, 3 ;if carry to bit 3
subi r27, 3 ;subtract 3
sbrs r27, 7 ;if carry to bit 7
subi r27, 0x30 ;subtract 0x30
LSL R17 ;shift input*/
ROL R27
dec R28 ;\n"
brne PR ;repeat for all bits*/
MOV R28,R27
ANDI R28,$0F
SWAP R27
ANDI R27,$0F
RET
.EXIT
Re: Таймеры/счётчики в AVR
Спасибо, значит буду смотреть вашу 
У вас МК тактируется от часового кварца?
У вас МК тактируется от часового кварца?
Re: Таймеры/счётчики в AVR
Для проверки в студии задавал тактирование Fo=32768*64 и Т2 в синхронном режиме.
Re: Таймеры/счётчики в AVR
Кстати, а почему если ядро стоит а не крутит цикл то это предпочтительнее с т.з. точности прерываний асинхронного таймера? Прерывание же останавливает основной цикл и выполняется, по идее основной цикл его не замедляет ...
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Таймеры/счётчики в AVR
Кто сказал?alexan9er писал(а):Кстати, а почему если ядро стоит а не крутит цикл то это предпочтительнее с т.з. точности прерываний асинхронного таймера?
Есть команды которые выполняются больше чем за 1 такт. И пока команда не выполнится, прерывания не произойдёт.alexan9er писал(а):Прерывание же останавливает основной цикл и выполняется, по идее основной цикл его не замедляет ...
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Re: Таймеры/счётчики в AVR
ЯGudd-Head писал(а): Кто сказал?
Поэтому не накапливается, хоть и небольшая, но погрешность.akl писал(а):Работа в SLEEP'е привлекательна не только малым потреблением, а тем, что ядро стоит, т.е. конвейер, в отличие от опроса флагов в цикле, не работает.
Gudd-Head писал(а): Есть команды которые выполняются больше чем за 1 такт. И пока команда не выполнится, прерывания не произойдёт.
Re: Таймеры/счётчики в AVR
Понятненько, спасибо!
Кстати эксперименты показали что кварц то отстаёт, то догоняет и обгоняет, но в среднем мне удалось выставить порог в режиме CTC таймера чтобы время шло более менее точно.
Засекал отклонение за 5 часов.
Очень интересное поведение
Кстати эксперименты показали что кварц то отстаёт, то догоняет и обгоняет, но в среднем мне удалось выставить порог в режиме CTC таймера чтобы время шло более менее точно.
Засекал отклонение за 5 часов.
Очень интересное поведение
- c2n
- Сверлит текстолит когтями
- Сообщения: 1193
- Зарегистрирован: Ср июл 25, 2012 21:40:09
- Откуда: Самара
- Контактная информация:
Re: Таймеры/счётчики в AVR
Думается мне.... мозги оно конопатит из-за перепадов питания.
Отмониторьте напряжение питания и ток потребления, и сравните с динамикой рахождений.
По идее если используется внешний кварц, то проблем не должно быть.
Попробуйте поменяйте конденсаторы в обвязе....
К стати, если есть хороший осциллоскоп, проверьте, на сколько равномерно происходит тактирование.
Отмониторьте напряжение питания и ток потребления, и сравните с динамикой рахождений.
По идее если используется внешний кварц, то проблем не должно быть.
Попробуйте поменяйте конденсаторы в обвязе....
К стати, если есть хороший осциллоскоп, проверьте, на сколько равномерно происходит тактирование.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Таймеры/счётчики в AVR
люди, которые утверждают, что может накапливаться ошибка счета времени из-за того, что разные команды основного цикла могут иметь разное кол-во тактов, ответьте на вопрос: как ошибка в 1 или 2 такта может накапливать ошибку, а пробуждение из SLEEP-а, которое длится десятки и даже сотни тактов, не накапливает этой ошибки?!
неужели не понятно, что если между прерываниями будет промежуток больше, чем внесенная по любым причинам задержка, никакого искажения хода часов не будет?
вот простой пример: запустим метроном, чтобы стукал 1 раз в минуту - это будет аналог запроса прерывания. а вы будете ядром процессора, и по каждому тику метронома будете обрабатывать прерывание таким образом: встаете со стула, обходите его кругом и снова садитесь. если вам 15 лет, вы среагируете на щелчок мгновенно, и отработаете прерывание за 10 секунд. если вам 70 лет, то среагируете вы на щелчок за 5 секунд, и еще 40 уйдет на обработку, но ведь каждый запрос будет обработан своевременно, ни один пропущен не будет!!! откуда же возьмется погрешность у реального ядра микроконтроллера?!
неужели не понятно, что если между прерываниями будет промежуток больше, чем внесенная по любым причинам задержка, никакого искажения хода часов не будет?
вот простой пример: запустим метроном, чтобы стукал 1 раз в минуту - это будет аналог запроса прерывания. а вы будете ядром процессора, и по каждому тику метронома будете обрабатывать прерывание таким образом: встаете со стула, обходите его кругом и снова садитесь. если вам 15 лет, вы среагируете на щелчок мгновенно, и отработаете прерывание за 10 секунд. если вам 70 лет, то среагируете вы на щелчок за 5 секунд, и еще 40 уйдет на обработку, но ведь каждый запрос будет обработан своевременно, ни один пропущен не будет!!! откуда же возьмется погрешность у реального ядра микроконтроллера?!
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Таймеры/счётчики в AVR
На аналогию наложено ещё одно условие - отсчёт события проводится когда глаза открыты.
- SLEEP IDLE глаза открыты всегда, т.е. мгновенная реакция на событие
- непрерывно моргаем, находясь в цикле и реакция на событие будет разная, в зависимости от того открыты глаза или моргнули в момент наступления события.
Проверяется простым примером. SLEEP IDLE даёт постоянный отсчет ...201,201,201..., а без слипа в цикле чередующийся интервал ...200-202-200-202...
- SLEEP IDLE глаза открыты всегда, т.е. мгновенная реакция на событие
- непрерывно моргаем, находясь в цикле и реакция на событие будет разная, в зависимости от того открыты глаза или моргнули в момент наступления события.
Проверяется простым примером. SLEEP IDLE даёт постоянный отсчет ...201,201,201..., а без слипа в цикле чередующийся интервал ...200-202-200-202...
Спойлер
Код: Выделить всё
.include "tn13def.inc"
.cseg
.org 0
RESET:
RJMP GO
.org 6
TIMER0_COMP1A:
SET
RET
;***********************************
GO:
LDI R22,1<<SE
OUT MCUCR,R22 ;SLEEP IDLE
LDI R22,1<<WGM01
OUT TCCR0A,R22 ; режим CTC T0
LDI R22,200
OUT OCR0A,R22 ; число сравнения
LDI R22,1<<OCIE0A
OUT TIMSK0,R22 ; режим прерывания по сравнению
OUT TIFR0,R22 ; сброс соответствующего флага
LDI R22,1<<CS00
OUT TCCR0B,R22
CLT
SEI
WAIT:
; SLEEP
BRTC WAIT
RJMP GO
.EXITRe: Таймеры/счётчики в AVR
Приветствую!
Подскажите, есть ли возможность настроить ШИМ в Attiny13 с пониженной разрядностью?
Так, чтобы была возможность 2 такта держать лапку в 1, затем 8 тактов на лапке 0 и возврат к началу счета.
Вроде это режим Fast PWM top=OCR0A...
Но такая настройка от CodeVision не работает:
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 9600,000 kHz
// Mode: Fast PWM top=OCR0A
// OC0A output: Non-Inverted PWM
// OC0B output: Disconnected
TCCR0A=0x83;
TCCR0B=0x09;
TCNT0=0x02;
OCR0A=0x0A;
OCR0B=0x00;
Подскажите, есть ли возможность настроить ШИМ в Attiny13 с пониженной разрядностью?
Так, чтобы была возможность 2 такта держать лапку в 1, затем 8 тактов на лапке 0 и возврат к началу счета.
Вроде это режим Fast PWM top=OCR0A...
Но такая настройка от CodeVision не работает:
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 9600,000 kHz
// Mode: Fast PWM top=OCR0A
// OC0A output: Non-Inverted PWM
// OC0B output: Disconnected
TCCR0A=0x83;
TCCR0B=0x09;
TCNT0=0x02;
OCR0A=0x0A;
OCR0B=0x00;
- Pink-Pank
- Опытный кот
- Сообщения: 721
- Зарегистрирован: Ср июн 11, 2014 09:43:13
- Откуда: США
- Контактная информация:
Re: Таймеры/счётчики в AVR
такое количество тактов можно только программно эмулировать. на ассемблере. При этом ничего другого контроллер делать не сможет. Аппаратно Вы такое не сделаете. Единственный вариант - поднять частоту тактирования. Тогда можно выдать нужную Вам частоту аппаратно.
Fucking static initialization order fiasco