|
TIMER1 в mega8, не могу заставить работать в СТС |
|
|
|
May 7 2010, 22:10
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
вот его определение Код TCCR1A= (1<<COM1A0); TCCR1B= (0<<CS02)|(0<<CS01) |(1<<CS00)|(1<<WGM12); //CTC mode, no prescaled TIMSK = (1<<TOIE0)|(1<<OCIE1A); //for counter 0 and counter 1 (1<<TICIE1)| OCR1AL= 150; //init OCR1AL for CTC mode OCR1AH= 0; хочу, чтобы счетчик досчитывал до 150, прерывался, там я инк. переменную, дальше он обнуляется и снова считает до 150... пробовал без Код TCCR1A= (1<<COM1A0); та же фигня. моя переменная, кот. должна инк. =0 постоянно вроде как ничего в коде не упустил?
Сообщение отредактировал rezident - May 8 2010, 23:53
Причина редактирования: Оформление цитаты исходника.
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 24)
|
May 8 2010, 05:36
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
т.е. поменять местами Код OCR1AL= 150; //init OCR1AL for CTC mode OCR1AH= 0; на Код OCR1AH= 0; OCR1AL= 150; //init OCR1AL for CTC mode ? это принципиально разве? Код TCCR1A= (1<<COM1A0); TCCR1B= (0<<CS02)|(0<<CS01) |(1<<CS00)|(1<<WGM12); //CTC mode, no prescaled тоже менял- результат тот же- не работатет
Сообщение отредактировал rezident - May 8 2010, 23:54
Причина редактирования: Оформление цитаты исходника.
|
|
|
|
|
May 8 2010, 06:45
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
Код char __low_level_init (void) { //this function will starts after reset AVR
UBRRL = ((OSC / 16 / RS232_BAUDRATE - 1) >> 0) & 0xFF; //for mega8 UCSRB = (1 << RXCIE) | (1<<RXEN) | (1<<TXEN); //for UART for RX & TX, enable interrupts
TCCR0 = (1<<CS02)|(0<<CS01) |(1<<CS00); //prescaler for counter 0 TCCR1B= (0<<CS02)|(0<<CS01) |(1<<CS00)|(1<<WGM12); //CTC mode, no prescaled TCCR1A= (1<<COM1A0); TIMSK = (1<<TOIE0)|(1<<OCIE1A); //for counter 0 and counter 1 (1<<TICIE1)| OCR1AH= 0; OCR1AL= koeff; //init OCR1AL for CTC mode
PORTB = (0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0); // all pins to 0 DDRB =(1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0); // all pins to out
PORTD = (0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0); // all pins to 0 DDRD =(0<<7)|(0<<6)|(0<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0); // pins 5,6,7 to in
return 1; // after return initialise memory }
#pragma vector = TIMER1_OVF_vect __interrupt void overflow_timer1(void) { CntMC++; cpl(TST); //for each ms on 24 pin } даташиту уже зачитал до дыр наверное ))) что за Код TCCR1A= (1<<COM1A0); что этот рег. делает? может по другому вектору надо ловить? по вектору сравнения какому- то?
Сообщение отредактировал rezident - May 8 2010, 23:55
Причина редактирования: Оформление цитаты исходника.
|
|
|
|
|
May 8 2010, 07:20
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
в этой таблице говорится, что если я хочу режим СТС, с вершиной OCR1, мне надо включить бит WGM12. итого, вектор прерывания должен быть другой? Код #pragma vector = TIMER1_OVF_vect скажете какой? пока читаю даташиты так а этот надо включать? Код что за TCCR1A= (1<<COM1A0);
Сообщение отредактировал rezident - May 8 2010, 23:55
Причина редактирования: Оформление цитаты исходника.
|
|
|
|
|
May 8 2010, 09:57
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Метценгерштейн @ May 8 2010, 11:20)  в этой таблице говорится, что если я хочу режим СТС, с вершиной OCR1, мне надо включить бит WGM12. В этой таблице есть графа "TOV1 Flag Set on", которая определяет условие установки флага переполнения (а, значит, и соответствующего прерывания). Из неё видно, что в этом режиме прерывание по переполнению - не подходит Цитата(Метценгерштейн @ May 8 2010, 11:20)  итого, вектор прерывания должен быть другой? Код #pragma vector = TIMER1_OVF_vect скажете какой? У этого таймера всего четыре прерывания. Одно из них - не подходит. Угадайте с трёх раз: какой вектор, если условие сброса счетчика - регистр OCR1 А. По-моему, это очевидно... Цитата(Метценгерштейн @ May 8 2010, 11:20)  так а этот надо включать? что за Код TCCR1A= (1<<COM1A0); Вам - на ноге ОС1А сигнал таймера нужен? Если - нет, не трогайте настройки, относящиеся к этому сигналу
|
|
|
|
|
May 8 2010, 17:22
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
"TOV1 Flag Set on" одного не пойму, в таблице написано что это МАХ, а ТОР это OCR1A тогда при чем здесь МАХ? думаю мне надо прерывание Код #pragma vector = TIMER1_ COMPA_vect но вот беда, ИАР ругается на такое объявление (((
Сообщение отредактировал rezident - May 8 2010, 23:56
Причина редактирования: Оформление цитаты исходника.
|
|
|
|
|
May 18 2010, 17:14
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(sigmaN @ May 9 2010, 20:57)  При использовании Си, чтобы не париться с порядком записи байтов в двухбайтовый регистр - можно просто объявить этот регистр как двухбайтовую переменную(указатель на адрес регистра) и присваивать туда сразу 16бит за один раз. При условии что эти два байта идут подряд в памяти, что не гарантировано в 100% случаев (считай никогда если пишешь универсальный модуль)... Цитата(Метценгерштейн @ May 18 2010, 18:25)  можно на примере, напрмиер, для ... mega8 Для неё как раз нельзя, т.к: Код #define UBRRL _SFR_IO8(0x09) #define UBRRH _SFR_IO8(0x20) а вообще так: Код UBRR = 0xXXXX;
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
May 18 2010, 17:36
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(Метценгерштейн @ May 18 2010, 21:20)  это понятно, имел ввиду указатель на адрес. Тут не ясно как это применять. Я же говорю, что с UBRR для mega8 это невозможно в принципе. А так: Код #define BYTE_AT(mem_addr) (*(volatile uint8_t *)(mem_addr)) #define WORD_AT(mem_addr) (*(volatile uint16_t *)(mem_addr))
#define MY_REG_L BYTE_AT(0x50) #define MY_REG_H BYTE_AT(0x51)
#define MY_REG WORD_AT(0x50) Цитата вот так, например. Не понял вопроса...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
May 21 2010, 21:18
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
думаю, надо делать на прерываниях, например вот так Код #pragma vector = TIMER1_COMPA_vect __interrupt void overflow_timer1(void) { CntMC++; } здесь я ровно каждую миллисекунду увеличиваю переменную (так настроил счетчик)
а тут
void main(void) { BOOL active = TRUE; for (;;) {
if (active) { on (LED); CntMC=0; active =FALSE; }
if (CntMC >=200) { //например, 20 мс off (LED); active =TRUE; } } вроде как должно работать, и диод будет мигать, и прога не будет тормозиться, только может есть более элегантное решение? А если надо две лампочки? т.е. в прерываниях не хотел бы ничего менять.
Сообщение отредактировал rezident - May 21 2010, 21:39
Причина редактирования: Оформление цитаты исходника.
|
|
|
|
|
May 22 2010, 18:28
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Метценгерштейн @ May 22 2010, 13:55)  Интересует как это делает народ. Идея у вас правильная, но реализация не совсем корректная. Не нужно в main-е или любой другой функции сбрасывать "тиковую" переменную, которая инкрементируется (считает тики прерывания, выраженные в единицах времени) в прерывании. Достаточно иметь в функции свою статическую (для которой выделяется постоянная память) переменную временной отметки/засечки, значение которой в свою очередь сравнивать с "тиковой" переменной беззнаковым вычитанием. Естественно обе этих переменных должны быть беззнаковыми, а "тиковая" еще глобальной с квалификаторлм volatile. Если переделать ваш вариант, то будет примерно так Код #define LED_BLINK_PERIOD 200U
volatile unsigned int CntMC;
#pragma vector = TIMER1_COMPA_vect __interrupt void overflow_timer1(void) { CntMC++; // инкремент "тиковой" переменной }
void main(void) { BOOL active = TRUE; static unsigned int timeStamp=CntMC; initTickTimer(); // инициализация таймера, выделенного под счет времени for (;;) { if (active) // устанавливаем состояние LED в соответствии с состоянием переменной active on (LED); esle off (LED); if ((CntMC-timeStamp)>=LED_BLINK_PERIOD) // проверяем окончание выделенного инетервала времени { if (active) active=FALSE; else active=TRUE; timeStamp=CntMC; // синхронизируем текущее состояние переменной временной отметки } } } Достоинство такого способа в том, что у вас в системе будет только один источник времени - "тиковая" переменная. В то же время переменных для временных засечек вы можете сделать столько, сколько вам будет нужно по количеству процессов, требующих временных отсчетов. Только следует учитывать два нюанса. 1. максимальный измеряемый временной период определяется периодом переполнения "тиковой" переменной. Если нужен сравнительно большой период, то нужна 32-х битная или даже 64-х битная переменная. Из этого следует второй нюанс. 2. если разрядность "тиковой" переменной превышает нативную разрядность архитектуры, то следует специальными методами обеспечит атомарность доступа к "тиковой" переменной. Атомарность доступа предполагает, что при копирования значения переменной по частям ее значение не может (не должно) изменяться (в прерывании, где она инкрементируется)
|
|
|
|
|
May 23 2010, 19:06
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(sigmaN @ May 23 2010, 18:54)  по-моему это вечный спор: лучше ли делать таймер глобальным или локальным, как вы советуете )) Любое измерение по сути и смыслу относительно. Измерение это сравнение (с образцом, эталоном). К измерениям времени эта характеристика тоже относится. См. сами. 100 лет назад (начало отсчета - текущий год), 1812 год (начало отсчета - рождение Христа), 3 век до н.э. (начало отсчета - наша эра, т.е. опять же рождение Христа), 5731 год от С.М.З.Х (начало отсчета - С.М.З.Х - Сотворение Мира в Звёздном Храме, согласно Славяно-Арийским Ведам заключение мира между ариями и "воинами дракона" - китайцами т.с.) ну и т.д. Независимые эталоны для каждого из измерений применять можно, но только до тех пор, пока сами измерения будут независимыми. Как только независимость измерений пропадает, то и эталон требуется единый. Например. Можно время измерять в тиках прерываний, а напряжение в единицах отсчетов АЦП, но только до тех пор, пока они используются внутри программы, исполняющейся на МК. Как только появляется какая-либо связь с "внешним миром", то оказывается, что время нужно в миллисекундах или секундах, а напряжение в миллиВольтах или Вольтах.
|
|
|
|
|
May 24 2010, 07:20
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
Спасибо за развернутый ответ. т.к. здесь использован макрос Ascold.h, то можно ещё лучше записать, чтобы лампочкой мигать с ровным меандром
void main(void) static unsigned int timeStamp=CntMC;
for (;;) { if ((CntMC-timeStamp)>=LED_BLINK_PERIOD) cpl (LED); //Ascold.h перевернуть состояние с 0 на 1 и наоборот timeStamp=CntMC; }
только не понятно, как поведет себя это дело, когда тиковая переменная приблизится к концу размера своего. Ведь наша локальная переменная будет ждать, что тиковая больше неё на 200, а тиковая дойдет до границы своего размера и обнулится и больше нашей уже никогда не станет. тут не ясный момент.
Где можно почитать про объявления переменный как простые, или как static или как volatile? Или вкратце скажите, чем они отличаются?
и как выделить мой код, чтобы он стал виден как у Вас код?
|
|
|
|
|
May 24 2010, 18:13
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Метценгерштейн @ May 24 2010, 13:20)  Ведь наша локальная переменная будет ждать, что тиковая больше неё на 200, а тиковая дойдет до границы своего размера и обнулится и больше нашей уже никогда не станет. Переменная обнулится, произойдет ее переполнение, а счет продолжится дальше. Потеряется старший разряд, но этот момент ни на что не повлияет, т.к. вычитание в сравнении беззнаковое! Для наглядности пример. Допустим CntMC и timeStamp 16-и битные переменные (макс. значение 65535 в десятичном виде или 0xFFFF в 16-иричном). Значение переменной timeStamp - 65530, CntMC - 210. Совершенно точно прошло более 200 тиков прерываний, а именно (65535-65530)+1+210=216. Беззнаковое вычитание 210-65530 даст точно такой же результат - 216. 216>200, поэтому условие в сравнении ((CntMC-timeStamp)>=200) будет истинно. Поясню откуда числа. 65535-65530 это разница в значениях счетчика до момента его переполнения. 1 - это учитываем состояние нуль. 210 - текущее значение тиковой переменной, после переполнения. Если сомневаетесь, то переведите числа в 16-тиричный вид и посчитайте сами на виндусовом калькуляторе в инженерном режиме, ограничив его разрядность 2-мя байтами . Цитата(Метценгерштейн @ May 24 2010, 13:20)  Где можно почитать про объявления переменный как простые, или как static или как volatile? Или вкратце скажите, чем они отличаются? В "букваре" языка Си. Или в стандарте Си. Вот только volatile это квалификатор, а не тип переменной, определяющий область ее распределения и видимости. Цитата(Метценгерштейн @ May 24 2010, 13:20)  и как выделить мой код, чтобы он стал виден как у Вас код? Используйте тэги [ code ] и [ codebox ] для оформления цитаты кода. Кнопочка  в редакторе вставляет первый из них. Второй, к сожалению, только вручную, редактированием сообщения.
Эскизы прикрепленных изображений
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|