Страница 43 из 72
Re: Таймеры/счётчики в AVR
Добавлено: Ср ноя 08, 2017 06:24:36
7seg
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;
}
Re: Таймеры/счётчики в AVR
Добавлено: Ср ноя 08, 2017 06:52:50
Dimon456
7seg писал(а):Столкнулся только с одной проблемой при испытаниях кода переменная 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;
}
if ((TIMER.Channel[Number].TimeCountingOFF == TIMER.MS) && (TIMER.Channel[Number].FlagTimersON==1)) {
TIMER.Channel[Number].FlagTimersOFF = 1;
TIMER.Channel[Number].FlagTimersON = 0;
}
}
}
А в основном цикле
Спойлер
Код: Выделить всё
if (TIMER.Channel[0].FlagTimersON == 1) {
PORTC |= (1<<1);
} else PORTC &= ~(1<<1);
if (TIMER.Channel[1].FlagTimersON == 1) {
PORTC |= (1<<2);
} else PORTC &= ~(1<<2);
if (TIMER.Channel[2].FlagTimersON == 1) {
PORTC |= (1<<3);
} else PORTC &= ~(1<<3);
Re: Таймеры/счётчики в AVR
Добавлено: Ср ноя 08, 2017 08:58:57
7seg
На самом деле при использование uint32_t это незначительно.
Есть вот такой код в функции Algoritm(); которая вызывается в цикле while();
Код: Выделить всё
R01TOP=OnAfterTimeMS(1200,1,R01TOP);
R01TOP=OFFAfterTimeMS(1300,2,R01TOP);
Соответственно он работает не совсем правильно каждый момент включения на 100ms увеличиваеться еще на 100ms
т.е 100/200/300 итд.
При использование кода:
Код: Выделить всё
void Algoritm()
{
if (R01TOP==0)
{
R01TOP=OnAfterTimeMS(1200,1,R01TOP);
}
R01TOP=OFFAfterTimeMS(1300,2,R01TOP);
}
Все работает как и задумывалось включение каждые 1300ms на 100ms.
Как думаете Можно ли поправить функции ON/OFF Чтобы избавиться от дополнительных проверок вне функции ?.
Код:
Спойлер
Код: Выделить всё
#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#define SPI_PORT PORTB
#define SPI_DDR DDRB
#define SPI_MISO PB4
#define SPI_MOSI PB3
#define SPI_SCK PB5
#define SPI_SS PB2
struct UnionBits
{
unsigned DO0: 1;
unsigned DO1: 1;
unsigned DO2: 1;
unsigned DO3: 1;
unsigned DO4: 1;
unsigned DO5: 1;
unsigned DO6: 1;
unsigned DO7: 1;
};
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;
#define AMOUNT_TIMERS 6 //Количество используемых таймеров
typedef struct
{
uint8_t FlagTimersON; //Флаг работы таймера
uint8_t FlagTimersOFF;
volatile uint32_t TimeCountingON; //Переменная фиксирующая время старта
volatile uint32_t TimeCountingOFF;
}TimerStruct;
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;
}
void StartInitIO()
{
OneOUT.ByteRegister=0x00;
TwoOUT.ByteRegister=0x00;
ThreeOUT.ByteRegister=0x00;
OneIN.ByteRegister=0x00;
TwoIN.ByteRegister=0x00;
ThreeIN.ByteRegister=0x00;
FourIN.ByteRegister=0x00;
FifthIN.ByteRegister=0x00;
}
/*инициализация SPI модуля в режиме master*/
void SPI_Init(void)
{
/*настройка портов ввода-вывода
все выводы, кроме MISO выходы*/
SPI_DDR |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO);
SPI_PORT |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO);
SPCR = (1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(0<<SPR1)|(1<<SPR0);
SPSR = (0<<SPI2X);
}
uint8_t SPI_UpdataByte(uint8_t data)
{
uint8_t report;
SPDR = data;
while(!(SPSR & (1<<SPIF)));
report = SPDR;
return report;
}
void SpiOutRegister()
{
SPI_PORT &= ~(1<<SPI_SS);
OneIN.ByteRegister=SPI_UpdataByte(0);
TwoIN.ByteRegister=SPI_UpdataByte(0);
ThreeIN.ByteRegister=SPI_UpdataByte(ThreeOUT.ByteRegister);
FourIN.ByteRegister=SPI_UpdataByte(TwoOUT.ByteRegister);
FifthIN.ByteRegister=SPI_UpdataByte(OneOUT.ByteRegister);
SPI_PORT |= (1<<SPI_SS);
}
/*Описание распределителей*/
#define R01TOP OneOUT.Register.DO0
#define R01DOWN OneOUT.Register.DO1
#define R02RO3 OneOUT.Register.DO2
#define R04 OneOUT.Register.DO3
#define R05 OneOUT.Register.DO4
#define R06RO7 OneOUT.Register.DO5
#define R08 OneOUT.Register.DO6
#define RO9 OneOUT.Register.DO7
#define R10 TwoOUT.Register.DO0
#define R11 TwoOUT.Register.DO1
#define R12 TwoOUT.Register.DO2
#define R13 TwoOUT.Register.DO3
#define R14 TwoOUT.Register.DO4
#define R15 TwoOUT.Register.DO5
#define R16 TwoOUT.Register.DO6
#define K1 TwoOUT.Register.DO7
#define K2 ThreeOUT.Register.DO1
/*Описание датчиков*/
#define D01 OneIN.Register.DO0
#define D02 OneIN.Register.DO1
#define D03 OneIN.Register.DO2
//#define D33 OneIN.Register.DO2
void Algoritm()
{
R01TOP=OnAfterTimeMS(1200,1,R01TOP);
R01TOP=OFFAfterTimeMS(1300,2,R01TOP);
}
int main(void)
{
SPI_Init();
StartInitIO();
InitTimers();
DDRD=0xff;// Настраиваем порт D на выход
TCCR0=(1<<CS01)|(1<<CS00); //Настраиваем пред делитель 64
TIMSK=(1<<TOIE0); // Запускаем таймер
TCNT0=131;
//TIMER.MS=MAX_UINT32-9000;
sei();
while(1)
{
SpiOutRegister();
Algoritm();
}
return 0;
}
Re: Таймеры/счётчики в AVR
Добавлено: Ср ноя 08, 2017 09:01:49
ARV
не перестаю удивляться тому, как простые вещи можно сделать сложными...
Re: Таймеры/счётчики в AVR
Добавлено: Ср ноя 08, 2017 09:12:51
7seg
Просто проще на самом деле не получается (
Re: Таймеры/счётчики в AVR
Добавлено: Ср ноя 08, 2017 09:14:50
ARV
[uquote="7seg",url="/forum/viewtopic.php?p=3227070#p3227070"]Просто проще на самом деле не получается ([/uquote]
если вы будете решать частный случай, будет просто. а решение "в общем случае" всегда избыточно, и потому сложно. и, главное, никому никогда на практике не нужно, т.к. вся жизнь состоит из частных случаев...
Re: Таймеры/счётчики в AVR
Добавлено: Ср ноя 08, 2017 11:16:24
viiv
[uquote="7seg",url="/forum/viewtopic.php?p=3226996#p3226996"]По поводу CurrentFlag функция включения планируется использоваться если CurrentFlag изначально имеет флаг FALSE.
И Соответственно как видно в теле функции она будет возвращать CurrentFlag до тех пор пока не выполниться условия (TimerToStart>=TimeVar)[/uquote]
Ну не понять мне. CurrentFlag - всегда признак, что таймер не истек? Так функция "знает" об этом признаке и без CurrentFlag.
Зачем смешивать в кучу? У Вас есть абстракция - таймер. Так? Так введите простой и понятный интерфейс:
1) включение таймера (timer_arm ())
2) если необходимо, проверку, что таймер включен (timer_armed ())
3) проверку, что таймер истек timer_expired ()
Спойлер
Код: Выделить всё
typedef struct _soft_timer_t {
uint32_t start;
uint32_t timeout;
} soft_timer_t;
/*
* Включение таймера
* ~~~~~~~~~~~~~~~~~
* ВНИМАНИЕ! Если таймер включен, он перезапускается
*/
void soft_timer_arm (soft_timer_t *t, uint32_t timeout)
{
t->timeout = timeout;
if (timeout)
t->start = get_current_tick ();
}
bool_t soft_timer_armed (soft_timer_t *t)
{
return (t->timeout != 0);
}
bool_t soft_timer_expired (soft_timer_t *t)
{
uint32_t now;
if (! soft_timer_armed (t))
return 0; /* таймер не запущен, соответственно истекшим быть не может */
now = get_current_tick ();
return (now - t->start) >= t->timeout;
}
Все, теперь "наворачивайте" свою логику
[uquote="7seg",url="/forum/viewtopic.php?p=3226996#p3226996"]А по поводу 4294967295UL то есть если к нему прибавить +1, он как я понял обнулится ?[/uquote]
В си переполнения никак не контролируются. Т.е. то, что Вы написали выше - верно.
[uquote="7seg",url="/forum/viewtopic.php?p=3226996#p3226996"]Столкнулся только с одной проблемой при испытаниях кода переменная TIMER.MS была == uint16_t.
Если зафиксируем время допустим в 65530 TIMER.MS а TimeVar установим больше 5 то TIMER.MS обнулялся раньше чем выполниться условия (TimerToSTOP >= TimeVar) и соответственно происходил сбой в работе.[/uquote]
Как и писал выше, в си переполнение никак не контролируется.
Код: Выделить всё
uint16_t TimeCountingON = 65530; // тик начала работы таймера
uint16_t MS = 0; // текущий тик (было переполнение)
// разница между текущим тиком и тиком начала работы таймера
uint16_t ticks_passed = MS - TimeCountingON; // ticks_passed будет 6!!!
Добавлено after 1 hour 13 minutes 3 seconds:
[uquote="7seg",url="/forum/viewtopic.php?p=3227070#p3227070"]Просто проще на самом деле не получается ([/uquote]
Все работает как и задумывалось включение каждые 1300ms на 100ms.
Код: Выделить всё
/* включает/выключает что надо :-) */
void on_off (bool_t on)
{
.....
}
static soft_timer_t on_off_timer;
static bool_t on;
/*включение каждые 1300ms на 100ms*/
void Algoritm()
{
soft_timer_t *t = &on_off_timer;
if (soft_timer_expired (t)) { /* таймер истек */
/* переключаем */
on ^= 1; on_off (on);
/* и перезапускаем таймер */
soft_timer_arm (t, on ? 100 : 1200);
}
}
Код: Выделить всё
/* выключаем и стартуем таймер */
on_off (on = 0);
soft_timer_arm (&on_off_timer, 1200);
while(1)
{
SpiOutRegister();
Algoritm();
}
Так не проще?
Re: Таймеры/счётчики в AVR
Добавлено: Ср ноя 08, 2017 14:18:16
Dimon456
viiv писал(а):Все работает как и задумывалось включение каждые 1300ms на 100ms.
Так не проще?
Нет, не проще.
Не даром у него забабахано
Код: Выделить всё
#define AMOUNT_TIMERS 6 //Количество используемых таймеров
Скорее всего он имел ввиду так
Спойлер
Использовал три таймера:
1- каждые 800мс на 300мс
2- каждые 400мс на 500мс
3- каждые 1300мс на 100мсПлохо что мы невидим полностью поставленную задачу.
Re: Таймеры/счётчики в AVR
Добавлено: Ср ноя 08, 2017 14:40:42
7seg
Полностью поставленную задачу пока не могу описать(. на данном этапе реализовал нужное количество IO и работу с таймерами(которых пока не известное количество ) сейчас принялся вкуривать как организовать управление по ModBus.
Так как хочу управлять всем с панели :
http://systemcontrol.ru/magazin/aon/kin ... /mt4532tte
Если со слейвом все просто так как есть уже готовые либы, то с мастер придется писать ручками ( пока что пред пологаю для управления использовать доп МК на котором будет реализован Master Modbas и слейв i2c.
Re: Таймеры/счётчики в AVR
Добавлено: Ср ноя 08, 2017 15:11:18
ARV
когда-то давно мне тоже приспичило сделать "много гибких таймеров"... я сделал примерно так:
Код: Выделить всё
// установка очередного таймера. если успешно, возвращает номер таймера, если не успешно, возвращает TIMER_ERROR
uint8_t set_timer(timer_t t);
// проверка указанного таймера. Если истек, возвращает 1, если не истек, возвращает 0, если номер не корректный - возвращает TIMER_ERROR
uint8_t timeout(uint8_t timer_id);
typedef uint16_t timer_t;
static timer_t timers[TIMER_CNT];
ISR(TIMER0_OVF_vect){
for(uint8_t i=0; i<TIMER_CNT; i++){
if(timers[i] != TIMER_FREE){
if(timers[i]) timers[i]--;
}
}
}
uint8_t set_timer(timer_t t){
if(t > TIMER_MAX) return TIMER_ERROR;
for(uint8_t i=0; i<TIMER_CNT; i++){
ATOMIC_BLOCK(ATOMICK_RESTORE_STATE){
if(timers[i] == TIMER_FREE){
timers[i] = t;
return i;
}
}
}
return TIMER_ERROR;
}
uint8_t timeout(uint8_t timer_id){
if(timer_id >= TIMER_CNT) return TIMER_ERROR;
ATOMIC_BLOCK(ATOMICK_RESTORE_STATE){
if(timers[timer_id] == TIMER_FREE) return TIMER_ERROR;
if(timers[timer_id] != 0) return 0;
else {
timers[timer_id] = TIMER_FREE;
return 1;
}
}
}
лишнее я выкинул - определение констант всяких и т.п.... по-моему, мой вариант гораздо проще и понять, и работать с ним.
установили таймер, получили его номер. потом проверяем по этому номеру, когда истечет и принимаем меры.
Re: Таймеры/счётчики в AVR
Добавлено: Чт ноя 09, 2017 03:00:05
7seg
а в чем разница между обычным выполнением и ATOMIC_BLOCK(ATOMICK_RESTORE_STATE) ?
Re: Таймеры/счётчики в AVR
Добавлено: Чт ноя 09, 2017 07:02:43
ARV
ATOMIC_BLOCK обеспечивает атомарное выполнение операций в своем блоке. в отличие от традиционного запрета-разрешения прерываний ATOMIC_BLOCK не портит текущий контекст разрешения прерываний, т.е. не разрешит их, если до этого они были запрещены.
Re: Таймеры/счётчики в AVR
Добавлено: Чт ноя 09, 2017 07:35:15
Dimon456
Вот 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 мс
Re: Таймеры/счётчики в AVR
Добавлено: Пт ноя 10, 2017 10:11:05
mishan4uk
Доброго времени суток.
Подскажите что делаю не так?
Хочу настроить таймер0 микроконтролера атмега8 на приривание по переполнению но ничево не получается.
Использую програму codevisionavr и симулятор Proteus.
Код: Выделить всё
/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.0 Evaluation
Automatic Program Generator
© Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
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
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out
// State6=T State5=T State4=T State3=T State2=T State1=T State0=0
PORTC=0x00;
DDRC=0xff;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x07;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;
// USART initialization
// USART disabled
UCSRB=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// ADC initialization
// ADC disabled
ADCSRA=0x00;
// SPI initialization
// SPI disabled
SPCR=0x00;
// TWI initialization
// TWI disabled
TWCR=0x00;
// Global enable interrupts
#asm("sei")
while (1)
{
// Place your code here
}
}
Заметил что когда ставить делитель на 128 в регистре TCCR0=0x05 то преривание работает, а если ставить 256 и 1024 то не работает.В чем может быть проблема?
Зарание спасибо за помощь.
Re: Таймеры/счётчики в AVR
Добавлено: Пт ноя 10, 2017 10:26:06
akl
External clock source on T0 pin. Clock on rising edge. Подайте частоту на PD4/T0
Re: Таймеры/счётчики в AVR
Добавлено: Пт ноя 10, 2017 10:41:21
mishan4uk
[uquote="akl",url="/forum/viewtopic.php?p=3228937#p3228937"]
External clock source on T0 pin. Clock on rising edge. Подайте частоту на PD4/T0[/uquote]
А как настроить от внутреннего генератора?
Re: Таймеры/счётчики в AVR
Добавлено: Пт ноя 10, 2017 10:54:15
akl
Спойлер

выбираете нужный предделитель и всё. Лучше всё таки пользоваться
DS на ATmega8
Re: Таймеры/счётчики в AVR
Добавлено: Пт ноя 10, 2017 11:57:38
mishan4uk
Спасибо разобрался

))))
У меня просто рускоязычный перевод даташита и там была неточность. Вчера весь вечер не мог понять в чем дело)))
Так что нужно учить английский

Re: Таймеры/счётчики в AVR
Добавлено: Вт дек 05, 2017 17:57:11
jeka101
Всем добрый день.
Вопросик есть, мне нужен таймер, с 2мя каналами на atmega8 или 328, к сожалению программную среду атмег я почти не знаю. Тем не менее хочу спросить может кто поможет.
Суть, нужно что-бы канал работал допустим 10ч а потом был выключен 14ч, 2й так-же но независимо от первого, и фоторезистор который не останавливает таймеры но блокирует работу обоих каналов, то есть если я посветил светом, канал отключиться но когда наступит темнота если время рабочего состояния на таймере еще не истекло он включит канал.
Я поискал на просторах интернета и нашел некоторые схемы и прошивки к ним но они все с дисплеями и ручными настройками, я ищу вариант без дисплея где у меня есть 1 кнопка RESET которая коротким нажатием запускает таймер одного канала и начинает его отсчет а последующим коротким нажатием запускает таймер второго канала и начинает его счет, а долгим нажатием сбрасывает оба, настройка интервалов таймеров через исходники.
Схему вроде собрать могу а вот программную часть не знаю как реализовать...
Re: Таймеры/счётчики в AVR
Добавлено: Вс янв 14, 2018 14:08:22
Feruz
Привет! Кто сталкивался с такой проблемой?
Очищаю и запускаю таймер вот так:
Спойлер
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. Шо за БАГ? Может неправильная последовательность запуска и очистки? До выполнения приведенного кода таймер использовался в другом режиме с другим делителем.