Таймеры/счётчики в AVR

Обсуждаем контроллеры компании Atmel.
Ответить
Мучитель микросхем
Аватара пользователя
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Сообщение Грендайзер »

Здравствуйте, товарищи. Никак не могу заставить Timer/Counter1 Atmega16A работать в режиме fast PWM. Что уже только не делал... Он ведь как дойдёт до значения TOP должен сразу обнулиться, а он зараза такая доходит до значения 0x3FF (не обращая внимание на TOP) и начинает считать в обратную сторону :evil:

Код: Выделить всё

#include "avr/io.h" 
#include<avr/interrupt.h>
#include<avr/boot.h>

#define F_CPU 1000000UL // 1MHz
#include <util/delay.h>


ISR(TIMER1_COMPA_vect) // вектор прерывания (хрен знает зачем, может поможет)
{
	//reti();
	sei();
}

int main(void)
{
	sei(); // устанавливаем флаг глоб. прерывания
	DDRA = 0; // Порт A на ввод
	DDRB = 0; // Порт B на ввод
	PORTA = 0xFF; // Включить внутренние резисторы порта А
	PORTB = 0xFF; // Включить внутренние резисторы порта В

	ACSR = 0x80; // Отключить компаратор
	ADCSRA = 0x80; // Отключить АЦП

	DDRC = 0xFF; // Порт С на вывод
	PORTC = 1; // выдать на порт С лог. "1"	

	DDRD = 0xFF; // Порт D на вывод для генерации ШИМ на ногах OC1В и ОС1А (PD4 и PD5)
	PORTD = 0; // выдать на порт D лог. "0" 

	// Нога OC1B должна работать в неинверсном режиме, а нога OC1А в инверсном
	// Для этого записываем в в соотв. разряды регистра TCCR1A соотв. уровни
	TCCR1A |= _BV(COM1A1);
	TCCR1A |= _BV(COM1A0);

	// Нога OC1B должна работать в неинверсном режиме, а нога OC1А в инверсном
	// Для этого записываем в в соотв. разряды регистра TCCR1A соотв. уровни
	TCCR1A |= _BV(COM1B1);
	TCCR1A &= ~_BV(COM1B0);	

	// Значение TOP должно храниться в регистре OCR1A, для этого разряды WGM13:10
	// должны быть равны 1
	TCCR1A |= _BV(WGM11);
	TCCR1A |= _BV(WGM10);

	// Значение TOP должно храниться в регистре OCR1A, для этого разряды WGM13:10
	// должны быть равны 1
	TCCR1B |= _BV(WGM13);
	TCCR1B |= _BV(WGM12);

	// Записываем значение TOP в OCR1A = 500, а в ICR1 = 500/2 = 250 (скважность ШИМ = 2)
	OCR1A = 500;//000;
	ICR1  = 250;//000;
	//OCR1B = 50;//000;

	TIMSK |= _BV(OCIE1A); // Устанавливаем маску прерывания (хрен знает зачем, может поможет)

        TCNT1 = 0; // Обнуляем счётный регистр (хрен знает зачем, может поможет) 

	// Запускаем счётчик выбрав источник тактового сигнала (напрямую от внутреннего генератора
        // без использования предделителя )
	TCCR1B |= 1;

		while(1)
		{		
			PORTC = ~PORTC;
		}
}
Реклама
Друг Кота
Аватара пользователя
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение Gudd-Head »

Грендайзер писал(а):и начинает считать в обратную сторону
Дык, это вроде Phase Correct PWM Mode?
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Реклама
Мучитель микросхем
Аватара пользователя
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Сообщение Грендайзер »

Дык, это вроде Phase Correct PWM Mode?
Ну делал то я фаст пвм... а вот работает то он как то не так...
Правда нашёл тут на форуме ссылочку на другой форум, там товарищ почти с таким косяком столкнулся... так вроде пишет что железка нормально фурычит, что мол косяк симмулятора студии... Вчера не успел в железе посмотреть, сегодня вечером попробую...
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

Подтверждаю, АВР студии есть косяк с симуляцией режимов ШИМ
Ставим плюсы: )
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение Gudd-Head »

Грендайзер писал(а):что мол косяк симмулятора студии...
Для этого открываем Хэлп в студии, ищем Known Issues на симулятор, смотрим:
General Simulator Issues
The issues in this section apply to all AVR devices.
...
Timer/Counters
16-bit Timer/Counters on all devices have several problems with PWM, prescaler and output compare. Output compare registers are not buffered properly.
The Asynchronous Status Register (ASSR) is not supported in timers with asynchronous mode. This is due to lack of a generic external clock implementation.
...
Плюс ещё есть смысл глянуть на Device specific issues
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Реклама
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

народ можно ли реализовать таймер на включение порта врубился он на минут 5 и выключился на час при этом не мешая работае основной программе тоесть чтобы программа не прекращалла работать.
есть у меня часы счётчик на 1000000 мгц атмега48
Спойлер

Код: Выделить всё

ISR(TIMER0_OVF_vect) {

time++;

   if (time==488)     {asm("wdr");time=0;seconds++;}
   if (seconds==60)   {seconds=0; minutes++;  }
   if (minutes==60)   {minutes=0; hours++;    }
 }
делал так

Код: Выделить всё


#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <string.h>
#include <string.h>
#include <util/delay.h>

#define PORT 3
#define PORT_ON PORTC|=1<<PORT
#define PORT_OFF PORTC&=~(1<<PORT)

void ON(){
TIMSK1=0x00;
код
TCNT1H=0x00;
TCNT1L=0xFF;
TCCR1A=0x00;
TCCR1B=0x03;
TIMSK1=0x01;
}

ISR(TIMER1_OVF_vect) {
TIMSK1=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
sei();
PORT_ON;
_delay_ms(100000); 
PORT_OFF;

 }

int main(void)
{
// Input/Output Ports initialization
PORTB=0xFF;
DDRB=0x00;

// Port C initialization
PORTC=0xFF;
DDRC=0x00;

// Port D initialization
PORTD=0xFF;
DDRD=0x00;

DDRC|=(1<<3); PORT_OFF;

// External Interrupt(s) initialization
// INT0: On
EICRA=0x00;
EIMSK=0x00;
EIFR=0x00;
PCICR=0x00;


// Clock value: 31.250 kHz
TCCR0A=0x00;
TCCR0B=0x02;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;


 // Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x01;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;


// Analog Comparator: Off
ACSR=0x80;
ADCSRB=0x00;

sei();

while (1){
ON();
  }
}
но при этом когда вызывается таймер на открытие порта основной код висит до завершения вызова таймера на открытие порта.
сможет кто нибудь помочь?
Реклама
Мучитель микросхем
Аватара пользователя
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Сообщение Грендайзер »

Вчера зашил в железку... Результат - 0. Не работает. Что ж за ерунда :evil: Может кто нить поделится кодиком 100% рабочим, а то уже и не знаючто за ерунда. Попробую ещё в последней студии всё это сделать....
Мучитель микросхем
Аватара пользователя
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Сообщение Грендайзер »

Gudd-Head писал(а): ...
Timer/Counters
16-bit Timer/Counters on all devices have several problems with PWM, prescaler and output compare. Output compare registers are not buffered properly.
The Asynchronous Status Register (ASSR) is not supported in timers with asynchronous mode. This is due to lack of a generic external clock implementation.
...
Не ну нормально!! И чё теперь?! Зря мы на этих капиталюг бомбу ядрёную не сбросили :twisted:
Мучитель микросхем
Аватара пользователя
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Сообщение Грендайзер »

значение WGM10 заменил на "0". Т.е. тот же фаст пвм, только максимальное значение лежит в другом регистре - вроде железка заработала. Заставить счётчик работать в 15 - ом режиме (WGM13:0 = 15) так и не вышло... чудеса :dont_know: Походу не только наш брат но и за бугром инженеры косячат :)))
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

Вопрос отпадает, сделал так

Код: Выделить всё

ISR(TIMER0_OVF_vect) {

time++;

   if (time==488)     {asm("wdr");time=0;seconds++;}
   if (seconds==60)   {seconds=0; minutes++;  }
   if (minutes==60)   {minutes=0; hours++;    }
  
   if(minutes==1){
PORT_ON;
}
if(minutes==2){
PORT_OFF;
}
   
 }
через каждый час врубается и вырубается на 2 минуте.
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

Грендайзер писал(а):Заставить счётчик работать в 15 - ом режиме (WGM13:0 = 15) так и не вышло... чудеса :dont_know: Походу не только наш брат но и за бугром инженеры косячат :)))
Читайте внимательно DS. Этот режим скорее не для ШИМ, а для частотной модуляции. Режим дергания ножками в данном случае можно установить как "поменять на противоположное". Получите меандр. Изменяя OCR1A можно менять частоту.

Код: Выделить всё

int main(void)
{
  DDRD = _BV(PD5);
  TCCR1A = _BV(COM1A0) | _BV(WGM11) | _BV(WGM10);
  TCCR1B = _BV(CS10) | _BV(WGM13) | _BV(WGM12);
  OCR1A = 1000;
  while(1);
}
Изображение
Мучитель микросхем
Аватара пользователя
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Сообщение Грендайзер »

Изменяя OCR1A можно менять частоту.
Это здорово конечно... Но что делать, если на ноге то физически нет сигнала, что там не меняй? :dont_know:
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

Залейте вышеприведенный пример в МК и увидите сигнал на ножке с частотой fcpu/1000/2. ;)
Не устанавливайте COM1A1 или COM1B1 в единицу. См. замечание к таблице 45 DS. Единственный вариант дергать ножкой в этом случае - "поменять на противоположное". Получите меандр.
Мучитель микросхем
Аватара пользователя
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Сообщение Грендайзер »

a_skr, действительно. Ваш код заработал. На ноге OC1A появился меандр со скважностью 2. И хотя я так и не понял про какую таблицу Вы писали, всё же данный вид работы, это не совсем то, о чём говорится в даташите :dont_know: Конечно можно поиграться с прерываниями, но тем не менее это не совсем то, что я ожидал от пвм контроллера. Да и подобный сигнал можно и в режиме CTC сгенерить :dont_know:
Родился
Сообщения: 11
Зарегистрирован: Вт апр 08, 2014 18:20:56

Сообщение Mr.Noiro »

Предлагаю детально разобрать нюансы работы с таймерами-счетчиками микроконтроллеров задавая вопросы и давая ответы.
И вот, первый вопрос по коду:
ldi r16,0x05
out TCCR1B,r16
ldi r16,0x02
out TCCR1A,r16
ldi r16,high(pause)
ldi r17,low(pause)
out OCR1AH,r16
out OCR1AL,r17

записав командой out OCR1AH,r16 - значение в регистре появляется. Но после следующей команды - пропадает.
В регистре OCR1AL - сохраняется и не исчезает, МК tiny2313, avrstudio 4. В чем может быть причина?
Друг Кота
Аватара пользователя
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Сообщение Ser60 »

Поменяйте местами 2 последние строчки кода.
Мудрый кот
Аватара пользователя
Сообщения: 1802
Зарегистрирован: Ср сен 07, 2011 21:40:30

Сообщение Flasher »

зачем менять? Пишем старший, потом младший.
Друг Кота
Аватара пользователя
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Сообщение Ser60 »

Да. Вы правы - это у меня переклинило что-то.
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

А как Вы, простите, узнали, что пропадает? Это симулятор показал? Или Вы потом командами считали значение и вывели в порт?
Мучитель микросхем
Сообщения: 494
Зарегистрирован: Пн авг 12, 2013 19:07:47
Откуда: башкирия мелеуз

Сообщение pavel1979 »

запись идет со сдвигом
записали предустановку,оно сначала в младшем,потом программа сдвигает на 8 разрядов,получается старший,в даташите написано
в меге8 все пишется как захочешь
Ответить

Вернуться в «AVR»