viiv, Спасибо за правки. По поводу CurrentFlag функция включения планируется использоваться если CurrentFlag изначально имеет флаг FALSE. И Соответственно как видно в теле функции она будет возвращать CurrentFlag до тех пор пока не выполниться условия (TimerToStart>=TimeVar)
Добавлено after 2 minutes 2 seconds: А по поводу 4294967295UL то есть если к нему прибавить +1, он как я понял обнулится ?
Добавлено after 6 minutes 26 seconds: Столкнулся только с одной проблемой при испытаниях кода переменная TIMER.MS была == uint16_t. Если зафиксируем время допустим в 65530 TIMER.MS а TimeVar установим больше 5 то TIMER.MS обнулялся раньше чем выполниться условия (TimerToSTOP >= TimeVar) и соответственно происходил сбой в работе.
Добавлено after 28 minutes 25 seconds: Как я понимаю надо делать проверку на подобие ((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)>TimeVar) и если она не выполнилась использовать еще одну переменную для подсчета ?
Добавлено after 6 minutes 12 seconds: Без доп переменной пришла такая идея, правда не знаю насколько она правильная.
Код:
Код:
uint8_t OnAfterTimeMS(uint32_t TimeVar,uint8_t Number,uint8_t CurrentFlag) { cli(); uint8_t OutFlag=0; //Переменная отвечает за RETURN f(). TIMER.TimeCurrent=TIMER.MS; //Присваиваем текущие значение МС if (TIMER.Channel[Number].FlagTimersON==0) //Условия для захвата времени вызова функции и установки флага работы { TIMER.Channel[Number].TimeCountingON=TIMER.MS; TIMER.Channel[Number].FlagTimersON=1; } uint32_t TimerToStart = TIMER.TimeCurrent-TIMER.Channel[Number].TimeCountingON; if ((TimerToStart >= TimeVar)&((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)>TimeVar)) //Если время до старта == TimeVar, то OutFlag=1 и обнуляем Флаг работы. { OutFlag=1; TIMER.Channel[Number].FlagTimersON=0; TIMER.TimeCurrent=0; TIMER.Channel[Number].TimeCountingON=0; TimerToStart=0; } else { OutFlag=CurrentFlag; if (((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)<TimeVar)) { TIMER.MS=0; TIMER.Channel[Number].TimeCountingON=0; } } sei(); return OutFlag; }
Столкнулся только с одной проблемой при испытаниях кода переменная TIMER.MS была == uint16_t. Если зафиксируем время допустим в 65530 TIMER.MS а TimeVar установим больше 5 то TIMER.MS обнулялся раньше чем выполниться условия (TimerToSTOP >= TimeVar) и соответственно происходил сбой в работе.
Это происходит потому что условие проверок надо делать в прерывании ISR (TIMER0_OVF_vect). Тогда условие будет контролировать каждый тик таймера. А в основном цикле проверять флаги работы таймера. К примеру так Спойлер
Код:
ISR (TIMER0_OVF_vect) { uint8_t Number=0; TCNT0=0x83; //значение для T0_0VF переполнения 1 раз в MS TIMER.MS++; //Подсчет MS
for (Number=0;Number<AMOUNT_TIMERS;Number++) { if ((TIMER.Channel[Number].TimeCountingON == TIMER.MS) && (TIMER.Channel[Number].FlagTimersOFF==0)) { TIMER.Channel[Number].FlagTimersON = 1; }
Соответственно он работает не совсем правильно каждый момент включения на 100ms увеличиваеться еще на 100ms т.е 100/200/300 итд. При использование кода:
Код:
void Algoritm() { if (R01TOP==0) { R01TOP=OnAfterTimeMS(1200,1,R01TOP); } R01TOP=OFFAfterTimeMS(1300,2,R01TOP); }
Все работает как и задумывалось включение каждые 1300ms на 100ms. Как думаете Можно ли поправить функции ON/OFF Чтобы избавиться от дополнительных проверок вне функции ?. Код: Спойлер
union Byte { uint8_t ByteRegister; struct UnionBits Register; };
union Byte OneOUT; union Byte TwoOUT; union Byte ThreeOUT; union Byte OneIN; union Byte TwoIN; union Byte ThreeIN; union Byte FourIN; union Byte FifthIN;
typedef struct { TimerStruct Channel[AMOUNT_TIMERS]; volatile uint32_t MS; volatile uint32_t TimeCurrent; //Текущие время }SoftTimers; SoftTimers TIMER; /*Функция инициализации таймеров (установка всех значений в 0 )*/ void InitTimers() { TIMER.TimeCurrent=0; TIMER.MS=0; for(uint8_t i=0;i<AMOUNT_TIMERS;i++) { TIMER.Channel[i].FlagTimersON=0; TIMER.Channel[i].FlagTimersOFF=0; TIMER.Channel[i].TimeCountingON=0; } } #define MAX_UINT32 4294967295UL ISR (TIMER0_OVF_vect) { TCNT0=131; //значение для T0_0VF переполнения 1 раз в MS TIMER.MS++; //Подсчет MS if (TIMER.MS == MAX_UINT32) { TIMER.MS=0; } } /*Функция вернет TRUE через время TimeVar,Иначе возвращает CurrentFlag */ uint8_t OnAfterTimeMS(uint32_t TimeVar,uint8_t Number,uint8_t CurrentFlag) { cli(); uint8_t OutFlag=CurrentFlag; //Переменная отвечает за RETURN f(). TIMER.TimeCurrent=TIMER.MS; //Присваиваем текущие значение МС if (TIMER.Channel[Number].FlagTimersON==0) //Условия для захвата времени вызова функции, и установки флага работы { TIMER.Channel[Number].TimeCountingON=TIMER.MS; TIMER.Channel[Number].FlagTimersON=1; } volatile uint32_t TimerToStart = TIMER.TimeCurrent-TIMER.Channel[Number].TimeCountingON; //Если (время до старта == TimeVar) и (условия по переполнению MAX_UINT32 выполняеться), //то OutFlag=1 и обнуляем Флаг работы if ((TimerToStart >= TimeVar)&&((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)>TimeVar)) { OutFlag=1; TIMER.Channel[Number].FlagTimersON=0; TIMER.Channel[Number].TimeCountingON=0; TimerToStart=0; } else { OutFlag=CurrentFlag; //Если MAX_UINT32 переполниться быстрей чем досчитает TimeVar то обнулим таймер if (((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)<TimeVar)) { TIMER.MS=0; TIMER.Channel[Number].TimeCountingON=0; } } sei(); return OutFlag; }
uint8_t OFFAfterTimeMS(uint32_t TimeVar,uint8_t Number,uint8_t CurrentFlag) { cli(); uint8_t OutFlag=CurrentFlag; //Переменная отвечает за RETURN f(). TIMER.TimeCurrent=TIMER.MS; //Присваиваем текущие значение МС if (TIMER.Channel[Number].FlagTimersOFF==0) //Условия для захвата времени вызова функции и установки флага работы { TIMER.Channel[Number].TimeCountingOFF=TIMER.MS; TIMER.Channel[Number].FlagTimersOFF=1; } volatile uint32_t TimerToSTOP = TIMER.TimeCurrent-TIMER.Channel[Number].TimeCountingOFF; //Если (время до старта == TimeVar) и (условия по переполнению MAX_UINT32 выполняеться), //то OutFlag=0 и обнуляем Флаг работы if ((TimerToSTOP >= TimeVar)&&((MAX_UINT32-TIMER.Channel[Number].TimeCountingOFF)>TimeVar)) { OutFlag=0; TIMER.Channel[Number].FlagTimersOFF=0; TIMER.Channel[Number].TimeCountingOFF=0; TimerToSTOP=0; } else { OutFlag=CurrentFlag; //Если MAX_UINT32 переполниться быстрей чем досчитает TimeVar то обнулим таймер if (((MAX_UINT32-TIMER.Channel[Number].TimeCountingOFF)<TimeVar)) { TIMER.MS=0; TIMER.Channel[Number].TimeCountingOFF=0; } } sei(); return OutFlag; }
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
если вы будете решать частный случай, будет просто. а решение "в общем случае" всегда избыточно, и потому сложно. и, главное, никому никогда на практике не нужно, т.к. вся жизнь состоит из частных случаев...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
По поводу CurrentFlag функция включения планируется использоваться если CurrentFlag изначально имеет флаг FALSE. И Соответственно как видно в теле функции она будет возвращать CurrentFlag до тех пор пока не выполниться условия (TimerToStart>=TimeVar)
Ну не понять мне. CurrentFlag - всегда признак, что таймер не истек? Так функция "знает" об этом признаке и без CurrentFlag. Зачем смешивать в кучу? У Вас есть абстракция - таймер. Так? Так введите простой и понятный интерфейс: 1) включение таймера (timer_arm ()) 2) если необходимо, проверку, что таймер включен (timer_armed ()) 3) проверку, что таймер истек timer_expired () Спойлер
Столкнулся только с одной проблемой при испытаниях кода переменная TIMER.MS была == uint16_t. Если зафиксируем время допустим в 65530 TIMER.MS а TimeVar установим больше 5 то TIMER.MS обнулялся раньше чем выполниться условия (TimerToSTOP >= TimeVar) и соответственно происходил сбой в работе.
Как и писал выше, в си переполнение никак не контролируется.
Код:
uint16_t TimeCountingON = 65530; // тик начала работы таймера uint16_t MS = 0; // текущий тик (было переполнение) // разница между текущим тиком и тиком начала работы таймера uint16_t ticks_passed = MS - TimeCountingON; // ticks_passed будет 6!!!
Скорее всего он имел ввиду такСпойлерИспользовал три таймера: 1- каждые 800мс на 300мс 2- каждые 400мс на 500мс 3- каждые 1300мс на 100мсПлохо что мы невидим полностью поставленную задачу.
Полностью поставленную задачу пока не могу описать(. на данном этапе реализовал нужное количество IO и работу с таймерами(которых пока не известное количество ) сейчас принялся вкуривать как организовать управление по ModBus. Так как хочу управлять всем с панели : http://systemcontrol.ru/magazin/aon/kin ... /mt4532tte Если со слейвом все просто так как есть уже готовые либы, то с мастер придется писать ручками ( пока что пред пологаю для управления использовать доп МК на котором будет реализован Master Modbas и слейв i2c.
когда-то давно мне тоже приспичило сделать "много гибких таймеров"... я сделал примерно так:
Код:
// установка очередного таймера. если успешно, возвращает номер таймера, если не успешно, возвращает TIMER_ERROR uint8_t set_timer(timer_t t); // проверка указанного таймера. Если истек, возвращает 1, если не истек, возвращает 0, если номер не корректный - возвращает TIMER_ERROR uint8_t timeout(uint8_t timer_id);
ATOMIC_BLOCK обеспечивает атомарное выполнение операций в своем блоке. в отличие от традиционного запрета-разрешения прерываний ATOMIC_BLOCK не портит текущий контекст разрешения прерываний, т.е. не разрешит их, если до этого они были запрещены.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Вот 16 таймеров. Хватит?Спойлер 1- каждые 800мс на 300мс 2- каждые 400 мс на 500 мс 3- каждые 1300 мс на 100 мс 4- каждые 1500 мс на 200 мс 5- каждые 200 мс на 100 мс 6- каждые 300 мс на 300 мс 7- каждые 400 мс на 400 мс 8- каждые 500 мс на 500 мс 9- каждые 100 мс на 100 мс 10- каждые 50 мс на 50 мс 11- каждые 5 мс на 5 мс 12- каждые 500 мс на 100 мс 13- каждые 500 мс на 200 мс 14- каждые 1000 мс на 1000 мс 15- каждые 300 мс на 300 мс 16- каждые 300 мс на 300 мс
Зарегистрирован: Вс май 14, 2017 09:29:28 Сообщений: 5
Рейтинг сообщения:0
Доброго времени суток. Подскажите что делаю не так? Хочу настроить таймер0 микроконтролера атмега8 на приривание по переполнению но ничево не получается. Использую програму codevisionavr и симулятор Proteus.
Project : Version : Date : 10.11.2017 Author : Freeware, for evaluation and non-commercial use only Company : Comments:
Chip type : ATmega8 Program type : Application AVR Core Clock frequency: 8,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 256 *****************************************************/
#include <mega8.h>
// Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // Place your code here PORTC.0=1; }
// Declare your global variables here
void main(void) { // Declare your local variables here
Заметил что когда ставить делитель на 128 в регистре TCCR0=0x05 то преривание работает, а если ставить 256 и 1024 то не работает.В чем может быть проблема? Зарание спасибо за помощь.
Зарегистрирован: Вс май 14, 2017 09:29:28 Сообщений: 5
Рейтинг сообщения:0
Спасибо разобрался )))) У меня просто рускоязычный перевод даташита и там была неточность. Вчера весь вечер не мог понять в чем дело))) Так что нужно учить английский
Зарегистрирован: Чт май 04, 2017 23:57:33 Сообщений: 13
Рейтинг сообщения:0
Всем добрый день. Вопросик есть, мне нужен таймер, с 2мя каналами на atmega8 или 328, к сожалению программную среду атмег я почти не знаю. Тем не менее хочу спросить может кто поможет. Суть, нужно что-бы канал работал допустим 10ч а потом был выключен 14ч, 2й так-же но независимо от первого, и фоторезистор который не останавливает таймеры но блокирует работу обоих каналов, то есть если я посветил светом, канал отключиться но когда наступит темнота если время рабочего состояния на таймере еще не истекло он включит канал.
Я поискал на просторах интернета и нашел некоторые схемы и прошивки к ним но они все с дисплеями и ручными настройками, я ищу вариант без дисплея где у меня есть 1 кнопка RESET которая коротким нажатием запускает таймер одного канала и начинает его отсчет а последующим коротким нажатием запускает таймер второго канала и начинает его счет, а долгим нажатием сбрасывает оба, настройка интервалов таймеров через исходники. Схему вроде собрать могу а вот программную часть не знаю как реализовать...
Очищаю и запускаю таймер вот так: Спойлерldi temp, (0<<WGM02)|(0<<CS02)|(0<<CS01)|(0<<CS00) //Стоп таймер out TCCR0B, temp
ldi temp, (1<<OCF0A) //Очищаем прерывание out TIFR0, temp
ldi temp, 0 //Очищаем таймер out TCNT0, temp
ldi temp, (0<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(0<<WGM00) //Режим CTC, без дрыгания ногой out TCCR0A, temp
ldi temp, 124 //Сравниваем с 124 (дает 1 секунду при делителе 1024 и 128 кГц тактовой) out OCR0A, temp
ldi temp, (1<<OCIE0A) //Включаем прерывание по OCIE0A out TIMSK0, temp
ldi temp, (0<<WGM02)|(1<<CS02)|(0<<CS01)|(1<<CS00) //Запускаем делитель 1024 out TCCR0B, temp По идее таймер должен запуститься, досчитать до 124 и вылететь в прерывание. В симуляторе 4й студии так и есть. А вот в протеусе (в версиях 7.1 и 8.6) прерывание вылетает как только счетчик сделает один тик, т.е. когда TCNT0 меняет свое значение с 0 на 1. Шо за БАГ? Может неправильная последовательность запуска и очистки? До выполнения приведенного кода таймер использовался в другом режиме с другим делителем.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 31
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения