Нужна помощь: таймер TIM0, AtTiny24

Обсуждаем контроллеры компании Atmel.
Ответить
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 36
Зарегистрирован: Чт июн 25, 2015 20:53:36

Сообщение Browny »

Уважаемые коты, мяу!
Прошу помощи и совета.
AtTiny24, 8MHz, тактирование от внутреннего генератора.
Делаю таймер TIM0 с обработкой переполнения. Цель - отсчёт интервалов 1 мсек.
Размышляю так: 8000000 тиков в секунду, 8000 тиков в мсек. Значит, если поставить делитель на 64, получим 125 тиков таймера. Смещаем стартовое значение таймера на 131, чтобы таймер сделал до переполнения именно 125 тиков.
Ставлю делитель на 64. При этом получаю контрольный интервал примерно в 8 раз позже ожидаемого значения.
Ставлю делитель на 8 - и (грубо считая секундомером) получаю правильное срабатывание (оцениваю интервал 20 тыс мсек).
Что-то делаю не так? Влияет ли фьюз CKDIV8 на первоначальную частоту таймера?

Спасибо за ваши советы и ответы.
Прилагаю тестовый пример (AVR Studio 4.19)

Код: Выделить всё

#define F_CPU 8000000UL
#include <avr/interrupt.h>
#include <util/delay.h>  

volatile uint32_t CNT32 = 0;

uint32_t millis(void){
	unsigned long m;
	uint8_t oldSREG = SREG;
	cli();
	m = CNT32;
	SREG = oldSREG;
    return m;
}

void StartTimer0()
{	
       cli();
	   TIMSK0 &= ~(1<<TOIE0); // выключить обработку по переполнению
       TCNT0  = 131;
       //TCCR0B = (1 << CS01) | (1 << CS00); //Делитель = 64; 8000000 Hz / 64 = 125 000 Hz; 125 000 Hz / 1000 = 125 ticks
	   TCCR0B = (1 << CS01); //Делитель = 8;
       TIMSK0|= (1 << TOIE0); // включить обработку по переполнению
	   sei();
}

ISR(TIM0_OVF_vect)
{
  CNT32++;
  TCNT0 = 131; // смещаем значение счётчика так, чтобы счётчику осталось сделать 125 тиков (256 - 125) до нового переполнения
  TIMSK0|= (1<<TOIE0);	//Продолжить отсчет, (разрешить прерывания по таймеру1)
};

void setup() 
{ 
  DDRA|= 0B00000010;
  PORTA&= 0B11111101; 
  StartTimer0();
}


void main() {
 setup();
 while (1) {
	if (millis() > 20000) PORTA |= 0B00000010;
 };
 return;
};
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Browny писал(а): Влияет ли фьюз CKDIV8 на первоначальную частоту таймера?
Однозначно.
Browny писал(а):Смещаем стартовое значение таймера на 131, чтобы таймер сделал до переполнения именно 125 тиков.
Лучше использовать один из режимов таймера, при котором происходит прерывание при значении таймера 125 и автоматический его сброс. Так будет точнее и короче обработчик прерывания.
Ставлю делитель на 8
Может наоборот выключаете? С фузами легко запутаться.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 36
Зарегистрирован: Чт июн 25, 2015 20:53:36

Сообщение Browny »

Z_h_e, спасибо, и - да, режим, про который говорите - не CTC? Когда для TOP значение задаётся в OCRA? (таблица Waveform Generation Mode Bit Description в даташите).
Фьюзы, в данном случае, насколько я понял, инверсные (в студии). В противном случае, снятый RSTDSBL и установленный SPIEN стали бы для меня проблемой :)
Extended = 0xFF
High = 0xDF
Low = 0x62

Значит, получается, что мне надо "плясать" от частоты ядра, делённой на 8.... ок.
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Новые МК идут с запрограммированным фьюзом CKDIV8. Поэтому, всегда при первом программировании МК ставим у программатора низкую частоту, выставляем фьюзы как требуется. В студии фьюзы показываются как есть. Но так как у AVR установленный фьюз это сброшенный бит, то в стороннем программном обеспечении нужно учитывать что биты инверсные. Возможно уже и есть программы, которые показывают фьюзы как есть, но я при программировании МК никогда не пользовался самопальными, сторонними программаторами и соответствующими программами. Только фирменными программаторами и только в AVR-Studio.

Пример настройки таймера на 1 мс.

Код: Выделить всё

//==================
#pragma vector = TIMER0_COMP_vect
__interrupt void Timer0Comp(void)
{
   ST_OCR += 250;
   sys_tick++;
}
//==================

//==================
void init_soft_timers (void)
{
   sys_tick = 0;
   ST_TCNT = 0;
   ST_OCR = 250;
   ST_TCCR |= ((1<<CS0) | (1<<CS1));
   set_bit (ST_TIMSK, ST_OCIE);
}
При 16 МГц 250, при 8 Мгц 125. Это самая точная настройка. Эти настройки и кварцы я использую уже несколько лет. Если требуется UART и соответствующие кварцы (7,3728 к примеру), то точная дискретность уже получается 10 мс.
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Чтобы не париться насчет фьюза CKDIV8, просто пишите в инициализации:

Код: Выделить всё

C:
	CLKPR=(1<<CLKPCE)
	CLKPR=0

ASM:
	LDI	R16,(1<<CLKPCE)
	OUT	CLKPR,R16
	LDI	R16,0
	OUT	CLKPR,R16

Это программно сбросит делитель, независимо от значения CKDIV8. Справедливо для всех контроллеров в регистром CLKPR.
Неправильно собранная из неисправных деталей схема нуждается в отладке и сразу не работает... (С)
Реклама
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Engineer_Keen писал(а):Это программно сбросит делитель, независимо от значения CKDIV8. Справедливо для всех контроллеров в регистром CLKPR.
Причем здесь регистр CLKPR и фьюз CKDIV8?
Контактная информация:
Реклама
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 36
Зарегистрирован: Чт июн 25, 2015 20:53:36

Сообщение Browny »

Engineer_Keen, Demiurg - меня пока вполне устраивает частота 8Mhz / 8. Я ставлю делитель счётчика ещё на 8 и выхожу как раз на 125 тиков в 1 мсек.
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Browny писал(а):Engineer_Keen, Demiurg - меня пока вполне устраивает частота 8Mhz / 8. Я ставлю делитель счётчика ещё на 8 и выхожу как раз на 125 тиков в 1 мсек.
И? Вы намеренно замедлили мк, да еще прерывания каждые 125*8. По сути мк работает на 1 мгц. Смысл?
Контактная информация:
akl
Друг Кота
Сообщения: 4462
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Для более точного отсчета времени, производитель рекомендует заносить в OCRx значение на единицу меньше требуемого. Например, выдержка 1мс.
Спойлер

Код: Выделить всё

	.INCLUDE "tn24def.inc"

.equ	Fo=8000000
;.equ	Fo=16000000

.CSEG
.ORG 0x0000
	RJMP	START
;*************************************************
.ORG 0x0009
T0_COMPA:
	RETI
;*************************************************
;*************************************************
;*************************************************
;*************************************************
;*************************************************
START:
	SBI	ACSR,ACD

	LDI	R20,1<<SE
	OUT	MCUCR,R20
GO:
	SBI	DDRB,0

	LDI	R16,Fo/1000/64-1
	OUT	OCR0A,R16

	LDI	R16,1<<OCIE0A
	OUT	TIMSK0,R16
	OUT	TIFR0,R16

	LDI	R16,1<<WGM01
	OUT	TCCR0A,R16		; режим CTC

	LDI	R16,1<<CS01|1<<CS00
	OUT	TCCR0B,R16		; Fo/64
	CLT
	SEI
;********************
WAIT:
	SLEEP
	SBI		PINB,0	; переключатель 1 мс
	RJMP	WAIT
.EXIT
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

akl писал(а):...
Точные отмерения времени всегда подбираются исходя из условий. Ваши -1 верны для одного случая и не верны для другого. Точность зависит от частоты кварца, режима таймера, делителя, условий реакции прерывания и так далее.
Контактная информация:
akl
Друг Кота
Сообщения: 4462
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Бред!!!
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

akl писал(а):Бред!!!
Это вы мне? Если да, в каком месте бред? Предлагаю вам прежде чем высказываться, обкатывать утверждения хотя бы в симуляторе студии.
Контактная информация:
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 36
Зарегистрирован: Чт июн 25, 2015 20:53:36

Сообщение Browny »

Demiurg, фьюз CKDIV8 уже был установлен. Пока для моей задачи мне хватает частоты 1МГц, если будут проблемы - или уберу фьюз, или программно поменяю делитель, как советовал Engineer_Keen. А прерывание 1 раз в 1 мсек мне нужно для обратной совместимости с настройками внешних событий, которые заданы как раз в мсек. И - да, обработка TIM0_COMP_vect будет ли более производительной, чем TIM0_OVF_vect со смещением в TCNT0?
И - да, в даташите на attiny24 написано, что OCR у TMR0 таки два, так что обработчик, думаю, TIM0_COMPA или TIM0_COMPB.
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Я регистром CLKPR никогда не пользовался. Также всегда сбрасывал фьюз CKDIV8.

CKDIV8 у вас уже установлен. Если он установлен, то дальше уже зависимость значения в CLKPR от CKDIV8. Также нужно точно убедиться, как тактируется таймер. Вполне возможно, что он тактируется помимо CLKPR.
Балуясь при CKDIV8 с регистром CLKPR можно попасть в ситуацию, что программатор не сможет перепрограммировать МК. Так как частота ядра окажется слишком маленькой.

Поэтому, если у вас не стоит задача энергосбережения, предлагаю не экспериментировать с CKDIV8 и CLKPR. Если все же зачесалось, тогда курите даташит и досконально разбирайтесь, как это все работает. Потому что лично мне такие извращения не нужны были, и я не разбирался что такое регистр CLKPR и как он работает. Товарищ, который вам его посоветовал, походу тоже не разобрался и советует кому ни попадя.
Контактная информация:
akl
Друг Кота
Сообщения: 4462
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Demiurg писал(а):
akl писал(а):Бред!!!
Это вы мне? Если да, в каком месте бред? Предлагаю вам прежде чем высказываться, обкатывать утверждения хотя бы в симуляторе студии.
ИзображениеИзображение
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Повторяю еще раз: ваши -1 верны для: делитель 64, режим, частота кварца. Для 10 МГц уже нужно сидеть, экспериментировать, чтобы получить эти же 1 мс. Наиболее точно можно получить только на 16 битном таймере. На UART кварцах вообще точность можно получить только для 10 мс. 7372800:1024=7200. Грузим в регистр сравнения 72, получаем 10 мс.
Опять же, вы не ответили, где бред. Я же не говорил вам, что вы не правы со своими -1.
И кстати, при вашем примере, если прогнать 100 раз, какова будет точность?
При моем примере всегда стабильный результат. Строго 1 мс, +- несколько тактов. Притом, если убежит в сторону на эти несколько тактов при одном прерывании, то при следующем прерывании разница убирается. И при 100 разах будет строго 100 мс +- несколько тактов.

Пример: на 50 мс было строго 50 мс. на 51 выбег на несколько тактов. Судя по всему был запрет прерывания или команда на несколько тактов.

Изображение
Контактная информация:
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 36
Зарегистрирован: Чт июн 25, 2015 20:53:36

Сообщение Browny »

Demiurg, относительно тактирования TMR0 в разрезе AtTiny24 (выдержки из даташита):

страница 24: Figure 6-1. Clock Distribution: Crystal oscillator->Clock multiplexer->System clock prescaler->AVR Clock Control Unit
На выходе AVR Clock Control Unit идёт clkI/O

страница 116: Figure 13-2. Prescaler for Timer/Counter0: на входе у "10bit prescaler" clkI/O, на выходе мультиплексора clkT0

страница 30: касательно регистра CLKPR: "....it will affect the clock frequency of the CPU and all synchronous peripherals. clkI/O, clkADC, clkCPU, and clkFLASH".

Видимо, тактирование TMR0 для attiny24 учитывает CLKPR. Но вариант убрать фьюз, конечно, проще :)
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Demiurg писал(а):Я регистром CLKPR никогда не пользовался. Также всегда сбрасывал фьюз CKDIV8.
Часто новички, особенно при повторе чужих устройств, по неопытности меняют фьюзы так, что контроллер лочится (меняют SPIEN или RSTDSBL, или шьют без предварительного чтения), хотя в большинстве случаев автор требует всего-лишь убрать делитель на 8. Чтобы лишний раз не трогать фьюзы, проще один раз в программе сделать сброс делителя, и тогда эта программа залитая на новый МК будет работать на нужной частоте.
Demiurg писал(а):CKDIV8 у вас уже установлен. Если он установлен, то дальше уже зависимость значения в CLKPR от CKDIV8.
CLKPR просто при запуске устанавливается в то значение, которое прописано в CKDIV8. (т.е. либо /1, либо /8) Кстати программно можно поставить и другие делители!
Demiurg писал(а):Также нужно точно убедиться, как тактируется таймер. Вполне возможно, что он тактируется помимо CLKPR.
Вся цепочка тактирования: встроенный RC/кварц/генератор -> CLKPR -> CLKPS таймера, CLKPR тут никуда не денется, кроме случая тактирования от внешнего источника Tn.
Demiurg писал(а):Балуясь при CKDIV8 с регистром CLKPR можно попасть в ситуацию, что программатор не сможет перепрограммировать МК. Так как частота ядра окажется слишком маленькой.
Меняя CKDIV8 да, можно, либо поставив CKDIV8 в паре с каким-либо низкочастотным источником тактирования, либо просто при ошибочной записи других бит в этот фьюз. А вот при изменении CLKPR ничего страшного не случится - данные в него загружаются после сброса при старте программы, а при введении в режим программирования программа не начинает работу по определению.
Demiurg писал(а):Если все же зачесалось, тогда курите даташит и досконально разбирайтесь, как это все работает.
Вот вот, и сами заодно его покурите, прежде чем (см. ниже)...
Demiurg писал(а): Потому что лично мне такие извращения не нужны были, и я не разбирался что такое регистр CLKPR и как он работает. Товарищ, который вам его посоветовал, походу тоже не разобрался и советует кому ни попадя.
Browny писал(а):Видимо, тактирование TMR0 для attiny24 учитывает CLKPR. Но вариант убрать фьюз, конечно, проще :)
Все верно. Если нужно менять еще какие-либо фьюзы (например BOD или EESAVE), то да имеет смысл поменять фьюз, а если нужен только CKDIV8, то ИМХО проще программно, один раз.
Последний раз редактировалось Engineer_Keen Чт апр 28, 2016 13:44:23, всего редактировалось 1 раз.
Неправильно собранная из неисправных деталей схема нуждается в отладке и сразу не работает... (С)
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Demiurg писал(а):Причем здесь регистр CLKPR и фьюз CKDIV8?
The CKDIV8 Fuse determines the initial value of the CLKPS bits. If CKDIV8 is unprogrammed,
the CLKPS bits will be reset to “0000”. If CKDIV8 is programmed, CLKPS bits are reset to
“0011”, giving a division factor of eight at start up.
Browny писал(а):режим, про который говорите - не CTC?
Он. Но можно использовать FAST PWM 7ой режим. Тогда еще от этого же таймера можно ШИМ задействовать, если конечно частота ШИМ будет устраивать.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Engineer_Keen писал(а):Вот вот, и сами заодно его покурите, прежде чем (см. ниже)...
Если вы посмотрите историю моих сообщений, вы не увидите от меня вопросов, которые касаются азов. Прежде чем использовать что-то, что я до этого не использовал, я всегда предварительно изучу тему. Буду читать даташиты, различные материалы.
Если вы хотели ткнуть меня носом, то позвольте заметить, использовать фьюз делитель на 8, чтобы добиться 1 мс, это уже извращение. А ваш совет использовать регистр не сбрасывая фьюз - извращение вдвойне.
Если кто-то хочет экспериментировать, то пусть это делает не компостируя другим мозги.
В случае с ТС нет никаких моментов, которые вынуждали бы его использовать как делитель на 8 так и регистр.
Контактная информация:
Ответить

Вернуться в «AVR»