Atmega168PA, глюк с TCNT1H TCNT1L ?
-
Alex_Soroka
- Первый раз сказал Мяу!
- Сообщения: 20
- Зарегистрирован: Пт апр 15, 2016 09:39:20
Atmega168PA, глюк с TCNT1H TCNT1L ?
Atmega168PA, работаю с ним давно, но только сейчас озаботился вопросом а что с TCNT1H TCNT1L ?
почему я должен всякий раз переписывать их?
в даташите что-то не нашел ответа - может не то читаю?
Я использую Таймер1 для содания 0.5сек обработки своих событий внутри прерывания по таймеру (см.код)
Таймер не трогаю, просто при включении инициация и далее молотит 0.5сек задержки, ничего в счетчиках не меняю, не читаю их и не использую ШИМ на Таймере1.
Вот мой пример:
----- start -----
...
#include <io.h>
#include <stdlib.h>
#include <delay.h>
...
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
#asm("cli") // Global Interrupt Disable !!!
TCNT1H=0xF0;
TCNT1L=0xBE;
#asm("sei") // Global Interrupt Enable !!!
// Я вынужден эту хрень сюда писать в первые строчки !!!!!!!!!!!!!!!!!! ПОЧЕМУ ?????????????
...
}
void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
...
// -------------- Timer 1 -------------------------
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Normal
// OC1x output: Discon.
// Noise Canceler: Off
// Timer 1 Overflow Interrupt: ON
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0b00000000;
TCCR1B=0x05;
TCCR1C=0x00;
TCNT1H=0xF0; // for 8MHz
TCNT1L=0xBE;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (1<<TOIE1);
...
my code here...
...
}
--------end-----------
Вопрос:
почему я не могу ОДИН РАЗ в "майн" проинициализировать Таймер1 и потом тупо он сам молотит ?
Почему я должен какждый раз в прерывании(!) запрещать прерывание, вдувать в счетчики таймера ТО ЖЕ САМОЕ и только потом делать полезное?
Что за бред ?
....
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
#asm("cli") // Global Interrupt Disable !!!
TCNT1H=0xF0;
TCNT1L=0xBE;
#asm("sei") // Global Interrupt Enable !!!
...
}
....
вот программа ниже - НЕ работает - нет прерывания каждые 0.5сек.
В чем я не прав? Это таки глюк Атмела ?
----- start -----
...
#include <io.h>
#include <stdlib.h>
#include <delay.h>
...
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
...
my code here
...
}
void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
...
// -------------- Timer 1 -------------------------
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Normal
// OC1x output: Discon.
// Noise Canceler: Off
// Timer 1 Overflow Interrupt: ON
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0b00000000;
TCCR1B=0x05;
TCCR1C=0x00;
TCNT1H=0xF0; // for 8MHz
TCNT1L=0xBE;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (1<<TOIE1);
...
my code here...
...
}
--------end-----------
почему я должен всякий раз переписывать их?
в даташите что-то не нашел ответа - может не то читаю?
Я использую Таймер1 для содания 0.5сек обработки своих событий внутри прерывания по таймеру (см.код)
Таймер не трогаю, просто при включении инициация и далее молотит 0.5сек задержки, ничего в счетчиках не меняю, не читаю их и не использую ШИМ на Таймере1.
Вот мой пример:
----- start -----
...
#include <io.h>
#include <stdlib.h>
#include <delay.h>
...
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
#asm("cli") // Global Interrupt Disable !!!
TCNT1H=0xF0;
TCNT1L=0xBE;
#asm("sei") // Global Interrupt Enable !!!
// Я вынужден эту хрень сюда писать в первые строчки !!!!!!!!!!!!!!!!!! ПОЧЕМУ ?????????????
...
}
void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
...
// -------------- Timer 1 -------------------------
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Normal
// OC1x output: Discon.
// Noise Canceler: Off
// Timer 1 Overflow Interrupt: ON
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0b00000000;
TCCR1B=0x05;
TCCR1C=0x00;
TCNT1H=0xF0; // for 8MHz
TCNT1L=0xBE;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (1<<TOIE1);
...
my code here...
...
}
--------end-----------
Вопрос:
почему я не могу ОДИН РАЗ в "майн" проинициализировать Таймер1 и потом тупо он сам молотит ?
Почему я должен какждый раз в прерывании(!) запрещать прерывание, вдувать в счетчики таймера ТО ЖЕ САМОЕ и только потом делать полезное?
Что за бред ?
....
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
#asm("cli") // Global Interrupt Disable !!!
TCNT1H=0xF0;
TCNT1L=0xBE;
#asm("sei") // Global Interrupt Enable !!!
...
}
....
вот программа ниже - НЕ работает - нет прерывания каждые 0.5сек.
В чем я не прав? Это таки глюк Атмела ?
----- start -----
...
#include <io.h>
#include <stdlib.h>
#include <delay.h>
...
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
...
my code here
...
}
void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
...
// -------------- Timer 1 -------------------------
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Normal
// OC1x output: Discon.
// Noise Canceler: Off
// Timer 1 Overflow Interrupt: ON
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0b00000000;
TCCR1B=0x05;
TCCR1C=0x00;
TCNT1H=0xF0; // for 8MHz
TCNT1L=0xBE;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (1<<TOIE1);
...
my code here...
...
}
--------end-----------
- Реклама
-
Alkul
- Держит паяльник хвостом
- Сообщения: 933
- Зарегистрирован: Ср апр 13, 2011 11:09:20
- Откуда: Екатеринбург
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
Вы даташит на МК читали? Используйте режим CTC таймера и будет Вам счастье.Alex_Soroka писал(а): Вопрос:
почему я не могу ОДИН РАЗ в "майн" проинициализировать Таймер1 и потом тупо он сам молотит ?
Почему я должен какждый раз в прерывании(!) запрещать прерывание, вдувать в счетчики таймера ТО ЖЕ САМОЕ и только потом делать полезное?
Что за бред ?
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
Плюньте в харю тому скоту, кто посоветовал вам в обработчике прерывания запрещать прерывания! Ну и разрешать их тоже без понимания последствий в обработчике тоже не стоит.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
-
Alkul
- Держит паяльник хвостом
- Сообщения: 933
- Зарегистрирован: Ср апр 13, 2011 11:09:20
- Откуда: Екатеринбург
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
Можно даже два раза плюнуть.ARV писал(а):Плюньте в харю тому скоту, кто посоветовал вам в обработчике прерывания запрещать прерывания!
Автор, когда вызывается обработчик прерывания, бит I регистра SREG сбрасывается автоматически. А при выполнении команды RETI бит I снова устанавливается.
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
Возможно потому, что нет зелененькогоAlex_Soroka писал(а):Таймер1 для содания 0.5сек обработки своих событий внутри прерывания по таймеру (см.код)
вот программа ниже - НЕ работает - нет прерывания каждые 0.5сек.
В чем я не прав? Это таки глюк Атмела ?
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (1<<TOIE1);
...
my code here...
...
}
--------end-----------
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (1<<TOIE1);
#asm("sei") // Global Interrupt Enable !!!
Поддерживаю, т.к. нужно единожды записать в OCR1A=Clock value/256/2-1 и разрешить, соответственно, прерывание OCIE1A.Alkul писал(а):...Используйте режим CTC таймера...
- Реклама
-
Alex_Soroka
- Первый раз сказал Мяу!
- Сообщения: 20
- Зарегистрирован: Пт апр 15, 2016 09:39:20
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
а давайте без извращений ?
зачем мне "дергать ногой" процессора если есть режим "все выводы таймера отключены", НОРМАЛЬНЫЙ режим ?
зачем извращения ?
у меня на той ноге мои линии управления висят ваапще-то...
СТС не канает, да и неправильно это - извращение.
зачем мне "дергать ногой" процессора если есть режим "все выводы таймера отключены", НОРМАЛЬНЫЙ режим ?
зачем извращения ?
у меня на той ноге мои линии управления висят ваапще-то...
СТС не канает, да и неправильно это - извращение.
-
Alex_Soroka
- Первый раз сказал Мяу!
- Сообщения: 20
- Зарегистрирован: Пт апр 15, 2016 09:39:20
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
пример с запретом-разрешением прерываний взят из "рекомендуемого учебника" в Сети по АVRу...Alkul писал(а):Автор, когда вызывается обработчик прерывания, бит I регистра SREG сбрасывается автоматически. А при выполнении команды RETI бит I снова устанавливается.
вот меня и заинтересовало почему так ?
а насчет SREG - так это при любом прерывании так ?
т.е. только одно прерывание может исполняться в единицу времени и не надо думать про то "как там ежики" ?
-
Alkul
- Держит паяльник хвостом
- Сообщения: 933
- Зарегистрирован: Ср апр 13, 2011 11:09:20
- Откуда: Екатеринбург
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
Какой еще ногой Вы собираетесь дергать? Вы точно внимательно прочли даташит? Режим СТС - это прерывание по совпадению значения таймера с регистром. Есть два режима CTC - в одном содержимое таймера сравнивается с регистром OCR1A, в другом - происходит захват таймера в регистр ICP1 по внешнему сигналу. Вам нужен первый режим. Наличие генерации на выводах OC1A и OC1B определяется битами COM1A1/COM1A0 и COM1B1/COM1B0 соответственно. Обнулите эти биты и никакой "дерготни ногой" не будет. При совпадении будет вызываться обработчик прерывания TIMER1 COMPA.Alex_Soroka писал(а):зачем мне "дергать ногой" процессора если есть режим "все выводы таймера отключены", НОРМАЛЬНЫЙ режим ?
К любому материалу из сети (даже к этому моему сообщениюAlex_Soroka писал(а):пример с запретом-разрешением прерываний взят из "рекомендуемого учебника" в Сети по АVRу...
Именно так. Да, елки-палки, просто запустите программу в отладчике, вручную установите бит любого прерывания и наблюдайте, что будет с битом I регистра SREG после входа в обработчик и поcле выхода из него.Alex_Soroka писал(а):а насчет SREG - так это при любом прерывании так ?
т.е. только одно прерывание может исполняться в единицу времени
-
Alex_Soroka
- Первый раз сказал Мяу!
- Сообщения: 20
- Зарегистрирован: Пт апр 15, 2016 09:39:20
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
страница 122 даташита - Figure 16-5. Compare Match Output Unit, Schematic --- где там "можно отключить ногу" ? если DDR играться то по-любому нога на выход будет заблокирована к другим использованиям.Alkul писал(а):Какой еще ногой Вы собираетесь дергать? Вы точно внимательно прочли даташит? Режим СТС - это прерывание по совпадению значения таймера с регистром. Есть два режима CTC - в одном содержимое таймера сравнивается с регистром OCR1A, в другом - происходит захват таймера в регистр ICP1 по внешнему сигналу. Вам нужен первый режим. Наличие генерации на выводах OC1A и OC1B определяется битами COM1A1/COM1A0 и COM1B1/COM1B0 соответственно.Alex_Soroka писал(а):зачем мне "дергать ногой" процессора если есть режим "все выводы таймера отключены", НОРМАЛЬНЫЙ режим ?
кстати - в ATmega324PA - все путем, в "нормал" режиме Таймера1 ничего перезаписывать в таймер при прерывании не надо.
один раз в "майн" вначале настроил и всё.
ну так обнуление это и есть "нормальный" режимОбнулите эти биты и никакой "дерготни ногой" не будет. При совпадении будет вызываться обработчик прерывания TIMER1 COMPA.
даташит - 16.11.1 TCCR1A – Timer/Counter1 Control Register A -----------
Table 16-1. Compare Output Mode, non-PWM
... Normal port operation, OC1A/OC1B disconnected ...
я это и использую.
речь идет о том почему Таймер1 "считает один раз" ? все остальны етаймеры - вгрузил настройки, вгрузил "сколько считать"(цифра) и понеслось! считаем, прерываемся, считаемся снова сначала.
я в отладчике не отлаживаюсь.Именно так. Да, елки-палки, просто запустите программу в отладчике
были преценденты ...
предпочитаю тестировать живой контроллер.
-
Alkul
- Держит паяльник хвостом
- Сообщения: 933
- Зарегистрирован: Ср апр 13, 2011 11:09:20
- Откуда: Екатеринбург
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
Прочтите даташит полностью и (главное) поймите его.Alex_Soroka писал(а): ну так обнуление это и есть "нормальный" режим
я это и использую.
Обратите внимание на биты WGM10... WGM13. У Вас режим однократного счета получается, потому что этот режим задается нулями в этих битах, а они по умолчанию обнулены.
Вам нужен режим 4 из таблицы на странице 133.
-
Alex_Soroka
- Первый раз сказал Мяу!
- Сообщения: 20
- Зарегистрирован: Пт апр 15, 2016 09:39:20
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
я вас не понимаю.Alkul писал(а):Обратите внимание на биты WGM10... WGM13. У Вас режим однократного счета получается
Читаем:
Modes of operation supported by the Timer/Counter unit are: Normal mode (counter), Clear Timer on
Compare match (CTC) mode, and three types of Pulse Width Modulation (PWM) modes.
...
Где тут написано что "нормал" это режим "один раз запустился и стал" ????
я перечитал даташит может сотню раз - я эти контроллеры 3 года использую.
Я не вижу где явно записано что "однократный счет".
любой из таймеров это "железная пила" которая просто тупо считает, переполняется, и снова считает с нуля.
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
Все таймеры естественно работают в циклическом режиме.
Однако кто мешает по прерыванию при совпадении одновременно остановить таймер?
А затем уж сбрасывать содержимое счетчика (излишне намотанное) перед повторным запуском.

Однако кто мешает по прерыванию при совпадении одновременно остановить таймер?
А затем уж сбрасывать содержимое счетчика (излишне намотанное) перед повторным запуском.
-
Alex_Soroka
- Первый раз сказал Мяу!
- Сообщения: 20
- Зарегистрирован: Пт апр 15, 2016 09:39:20
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
да мне не надо ничего останавливать!BOB51 писал(а):Все таймеры естественно работают в циклическом режиме.
Однако кто мешает по прерыванию при совпадении одновременно остановить таймер?
А затем уж сбрасывать содержимое счетчика (излишне намотанное) перед повторным запуском.
просто тупо раз в 0.5сек надо сделать список действий и снова отпустить все в работу.
-
Alkul
- Держит паяльник хвостом
- Сообщения: 933
- Зарегистрирован: Ср апр 13, 2011 11:09:20
- Откуда: Екатеринбург
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
Может, я выразился не так. Конечно, таймер не останавливается, переполнившись в режиме normal, он генерирует прерывание и продолжает считать дальше.Alex_Soroka писал(а):Где тут написано что "нормал" это режим "один раз запустился и стал" ????
Я не вижу где явно записано что "однократный счет".
Просто в этом случае интервал между переполнениями четко определен и считается, как отношение тактовой частоты к коэффициенту предделителя, умноженное на 65536/
Но пользователю, как правило, нужен иной интервал, поэтому он вынужден перегружать таймер после каждого переполнения. Или использовать режим СТС.
-
Alex_Soroka
- Первый раз сказал Мяу!
- Сообщения: 20
- Зарегистрирован: Пт апр 15, 2016 09:39:20
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
Ура! У вас прогресс!Alkul писал(а):Конечно, таймер не останавливается, переполнившись в режиме normal, он генерирует прерывание и продолжает считать дальше.
а теперь эту вашу мысль далее подумайте - если я НИЧЕГО НЕ ДЕЛАЮ с регистрами и настройкам Таймера1 (проверил по Асмовскому коду после С) то почему такая хрень происходит???
Если написано прерываться по переполнению - прервались и???? потом считаем? нет ? почему не прерываемся ?
Почему в другом контроллере ЭТО РАБОТАЕТ?Но пользователю, как правило, нужен иной интервал, поэтому он вынужден перегружать таймер после каждого переполнения. Или использовать режим СТС.
я уже два письма в Атмел написал - в ответ какое-то жалкое блеяние, типа "поставьте другой режим и освободите ногу на выходе".
Нет чтобы признать: есть баг.
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
Потому, что где-то в программе в обозримом интервале произошел запрет прерываний - тогда хош сколько вертись - прерываний не произойдет.
Багов в типовых ситуациях больше в программном коде, чем в кристалле - сооруди простенький тест-примитив и проверь.
Тогда еще можно чегось говорить будет.
Тем более СИ не основа для проведения подобных "прикладных тестов".

Багов в типовых ситуациях больше в программном коде, чем в кристалле - сооруди простенький тест-примитив и проверь.
Тогда еще можно чегось говорить будет.
Тем более СИ не основа для проведения подобных "прикладных тестов".
-
uk8amk
- Поставщик валерьянки для Кота
- Сообщения: 2222
- Зарегистрирован: Вт ноя 27, 2007 11:32:06
- Откуда: Tashkent
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
Почему у нас всё работает на атмега48-88-168-328?
Из реального проекта:
Из реального проекта:
Код: Выделить всё
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x09;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x03;
OCR1AL=0xE7;
OCR1BH=0x00;
OCR1BL=0x00;
TIMSK1=0x02;
INTERRUPT_ENABLE();
//-----------------------------------------------------------
// TIM1_COMPA
// sound PWM update
//-----------------------------------------------------------
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
INTERRUPT_ENABLE(); // nested IRQ enable
OCR2B = sound_buf[ sound_rd_cnt++ ];
if( sound_rd_cnt == (SND_BUF_SIZE-1) )
{ // half buf2 empty
hbuf_empty_id = HBUF2;
sound_rd_cnt = 0;
}else if( sound_rd_cnt == (SND_BUF_SIZE/2-1) )
{ // hbuf1 empty
hbuf_empty_id = HBUF1;
};
}Студия разве не отлажвает живой контроллер?Alex_Soroka писал(а):я в отладчике не отлаживаюсь.были преценденты ...предпочитаю тестировать живой контроллер.
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
HEX для другого контроллера в студию.Alex_Soroka писал(а):Почему в другом контроллере ЭТО РАБОТАЕТ?
Не позорьтесь.Alex_Soroka писал(а):...я уже два письма в Атмел написал - в ответ какое-то жалкое блеяние, типа "поставьте другой режим и освободите ногу на выходе". Нет чтобы признать: есть баг.
Re: Atmega168PA, глюк с TCNT1H TCNT1L ?
Отлаживает.uk8amk писал(а): ...
Студия разве не отлажвает живой контроллер?
НО... не все аппаратные узлы в полном объеме и по-разному в разных версиях симулятора.
Для такого вида тестов надо макетку сооружать и специально прожку писать, дабы "усе грабли были абсолютно точно определены".


