|
TIMER1 в mega8, не могу заставить работать в СТС |
|
|
|
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
|
|
|