Страница 2 из 5

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Вт янв 29, 2013 05:41:07
ibiza11
:))) тут подсказки ТС не нужны) только протоколы, прерывания и код!

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Вт янв 29, 2013 15:20:11
dem66
Уже разобрался. Получаеся примерно такой код:

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

#define F_CPU 10000000UL

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

ISR(TIMER1_OVF_vect)
{

	TCNT1 = 64456;
	
	if( PINB & ( 1 << PB0 ) ) {
		PORTB &= ~( 1 << PB0 );
	}else {
		PORTB |= ( 1 << PB0 );
	}
}

void SetupTIMER1(void)
{
	TCCR1B = (1<<CS10);
    
	TIMSK |= (1<<TOIE1);

	//TCNT1 = 64456;
}

int main(void)
{
	DDRB = ( 1 << PB0 );
	
	SetupTIMER1();
	sei();
	
	while(1)
	{
	}
}
Теперь подскажите что делать с TCNT1? Сейчас же получается статическое значение, а если я получу новое значение по USART то как мне его туда впихнуть?

Начальное же значение указывается в функции ISR(TIMER1_OVF_vect)

И как запустить два таймера? Чтото не получается :(

ibiza11, тихо там

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Вт янв 29, 2013 22:50:58
dem66
Так всетаки как должен выглядеть код с двумя таймерами? У меня никак не поучается настроить два, перестают работать оба

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 06:21:55
ArtDen
Ты лучше объясни что вообще хочешь получить. Пока просто никто не понял как должен выглядеть твой конечный результат.

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 14:13:44
YS
Да не, ТС же писал:
Нужно получить вот такую осцилограмму
Изображение
Я тут подумал, а может ну их нафиг, контроллеры? :) Вот, два корпуса стандартной логики:

Изображение

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 15:49:23
codenamehawk
YS писал(а): Я тут подумал, а может ну их нафиг, контроллеры? :) Вот, два корпуса стандартной логики:
А перестройка частоты через уарт?

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 15:58:35
codenamehawk
TCNT1 = 64456;

замените на

TCNT1 = peremennaja_v_kotoruju_ja_budu_zadavat_znachenija_chastoty;

Для второго таймера

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

ISR(TIMER2_OVF_vect)
{

   TCNT2 = время_задержки;//это место где нет импульсов, ну или длина пачки импульсов
   
   if( пауза == 0)
 {
      TCCR1B = 0;//запретить работу первого таймера
      пауза=1;
   }else 
  {
    TCCR1B = (1<<CS10);
    пауза=0;//разрешить работу первого таймера
   }
}
как-то так

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 16:04:28
codenamehawk
codenamehawk писал(а): По уарту передаете по одному символу, загоняете в текстовую переменную нужной длины, дальше преобразование текст в целое и присвоение TCCR0
Пишите, что вам здесь непонятно, попробую помочь.

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 18:30:24
dem66
Ну на логике я бы и сам мог сделать, ну и всякие там TL494, NE555, но к сожалению такой вариант не проходит :(

Пытаюсь вручную расчитывать нужное количество тиков.

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

#define F_CPU 10000000UL
#define TCNT1_1MS (F_CPU/1024)

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

ISR(TIMER1_OVF_vect)
{

   //TCNT1 = 50000;
   TCNT1 = 0x4E2;
   
   if( PINB & ( 1 << PB0 ) ) {
      PORTB &= ~( 1 << PB0 );
   }else {
      PORTB |= ( 1 << PB0 );
   }
}

void SetupTIMER1(void)
{
   //TCCR1B = (1<<CS12);
   TCCR1B = 0x05;
    
   TCNT1 = 0x4E2;

   //TCNT1 = 64456;
   //TIMSK = (1<<TOIE1);
   TIMSK |= 1;
}

int main(void)
{
   DDRB = ( 1 << PB0 );
   
   SetupTIMER1();
   sei();
   
   while(1)
   {
   }
}
Timer0 = 10MHz/1024=15625 Гц
Частотапереполнения = 15625 / 256 = 61,0352 Гц.

10000000/1024=9765.625 Гц = 9,765Khz

Частотапереполнения = 9765.625/256 = 38.146972656 Гц.

время одного "переполнения" = 1 / 38.146972656 = 0.0262144 сек

время одного тика таймера = 0.0262144 / 65536 = 0.0000004 сек

Чтобы получить 0.0005 c (2Khz) необходимо чтобы таймер тикнул 0.0005 / 0.0000004 = 1250 раз.
1250 в 16-тиричной системе это 4E2 = 0x4E2

Чтото я не понимаю как эти данные привязать к таймеру :(

Скажите как правельно настраивать все это в таймере. Допустим сейчас пробовал сделать 2Khz но в результате не работает

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 19:12:09
zero648
Делаем частоту 2000 Гц с помощью Timer0, CLK=10.000.000 Гц:
1 - 10000000/2000=5000 ;
2 - 5000/64=78,125 ; не подходит, нужно целое число;
3 - 5000/8=625 ; уже лучше, но больше 1 байта;
4 - делаем собственный прескалер в прерывании Timer0 overflow 625/125=5, берем переменную или регистр, который не трогаем нигде, загружаем в него 5 и при каждом прерывании Timer0 уменьшаем на единицу, когда переменная станет =0, снова загружаем в переменную 5 и выполняем само прерывание. При каждом входе в прерывание обновляем TCNT0=256-125=131.

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 19:59:16
dem66
zero648 писал(а):загружаем в него 5 и при каждом прерывании Timer0 уменьшаем на единицу
Чтото непонятно :(

А как быть с TCCR0 и TIMSK??

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 20:27:31
zero648
dem66 писал(а):Чтото непонятно :(

А как быть с TCCR0 и TIMSK??
Это прописываем в инициализации:
TCCR0=0x02 - прескалер 1:8;
TIMSK=0x01 - прерывание по переполнению таймера 0

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 20:44:13
codenamehawk
dem66 писал(а): Чтобы получить 0.0005 c (2Khz) необходимо чтобы таймер тикнул 0.0005 / 0.0000004 = 1250 раз.
1250 в 16-тиричной системе это 4E2 = 0x4E2
Если подсчитали количество импульсов правильно, то необходимо от числа 0xFFFF отнять ваш результат 0x4E2 и присвоить результат TCNT1
(объясню на пальцах
как только вы присвоили TCNT1= 0x4E2 он сразу же начинает тикать с этого значения.
прерывание по переполнению наступит после 0xFFFF
сколько тиков пройдет до прерывания подсчитать можете?)


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

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 20:50:56
dem66
codenamehawk писал(а):то необходимо от числа 0xFFFF отнять ваш результат 0x4E2
извиняюсь, забыл.

zero648, сделал как вы писали и получилось 4,9Khz

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

ISR(TIMER0_OVF_vect)
{

  TCNT0 = 131;
   
   if(PINB & (1 << PB0)){
      PORTB &= ~(1 << PB0);
   }else {
      PORTB |= (1 << PB0);
   }
}

void SetupTIMER0(void)
{
   TCCR0 = 0x02;
   TCNT0 = 131;
   TIMSK = 0x01;
}
Но при работе видны какието задержки на осцилограмме, немного подтормаживает, и виртуальный осцилограф в протеусе на сразу показывает частоту.

Сейчас вот пытаюсь оптимизировать, делаю вот так:

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

int status;
int b;

ISR(TIMER0_OVF_vect)
{

  TCNT0 = 131;
   
   if(status){
      b = 0;
   }else {
      b = 1;
   }
}

void SetupTIMER0(void)
{
   TCCR0 = 0x02;   
   TCNT0 = 131;
   TIMSK = 0x01;
}

int main(void)
{
   DDRB = ( 1 << PB0 );
   
   SetupTIMER0();
   sei();
   
   while(1)
   {
	   status = (PINB & (1 << PB0));
	   
	   if(b==1){
		 PORTB |= (1 << PB0);
	   }else{
		  PORTB &= ~(1 << PB0);
	   }
   }
}
А оно вобще перестало работать.
Сейчас if(status) всегда получается FALSE

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 22:27:25
codenamehawk
Есть такое волшебное слово volatile

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Ср янв 30, 2013 22:56:47
vitalik_1984
что это за оптимизация такая? те же самые действия, только еще и используя переменную, которая может лежать вне РОН, а чаще всего так и есть.
теперь представим себе примерно ассемблер
загрузили число,
сравнили с константой,
если равно переход к метка
порт в 1
переход к метка 2
метка :порт в 0
метка 2

а в начальном варианте :
определили пин
если равно переход к метка
порт в 1
переход к метка 2
метка :порт в 0
метка 2

хорошо сэкономили?

можно вообще вот так:
PORTB ^= (1 << PB0);

в асме
загрузили в РОН
XOR константа
Поместили в порт.

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Чт янв 31, 2013 01:26:13
zero648
dem66 писал(а):zero648, сделал как вы писали и получилось 4,9Khz
Во-первых не вижу самодельного прескалера, во-вторых у Вас меняется состояние PORTB.0 каждый раз при выполнении обработчика прерывания, поэтому для полного периода в обработчик нужно зайти два раза, а значит частоту входа нужно увеличить в 2 раза, чтобы получить нужную частоту сигнала, и в третьих есть небольшой нюанс, при использовании переполнения таймера нужно учитывать время входа в обработчик, так что TCNT0=131 это как бы базовая расчетная величина и её нужно корректировать по ходу процесса.

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

ISR(TIMER0_OVF_vect)
{

  TCNT0 = 131;
   
   if(PINB & (1 << PB0)){
      PORTB &= ~(1 << PB0);
   }else {
      PORTB |= (1 << PB0);
   }
}

void SetupTIMER0(void)
{
   TCCR0 = 0x02;
   TCNT0 = 131;
   TIMSK = 0x01;
}
Теперь пересчитаем все это дело для частоты входа в обработчик 2000x2=4000Гц
10000000/4000=2500
2500=250*10, получается TCNT0 будет теперь 256-250 и плюс учтем время входа в обработчик, 11 тактов на вход плюс 1 такт на загрузку регистра TCNT0, самодельный прескалер будет 10, таймер тикает без аппаратного прескалера, т.е. 10МГц.
При таких настройках у меня все четко получается:
Изображение

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Чт янв 31, 2013 15:32:48
dem66
Прескалер это OCR0 или TCCR0?

И что это у вас за proteus такой?

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Чт янв 31, 2013 15:55:14
codenamehawk
zero648 писал(а): получается TCNT0 будет теперь 256-250 и плюс учтем время входа в обработчик, 11 тактов на вход плюс 1 такт на загрузку регистра TCNT0,
ИМХО можно не учитывать эти "11 тактов на вход плюс 1 такт на загрузку регистра TCNT0"
Прерывания и так происходят каждые 1/4000 сек , а дополнительные такты просто сместят сигнал немного правее, не меняя его ширины (длительности).

Re: Генератор на Atmega8 (микросекунды) большие погрешности

Добавлено: Чт янв 31, 2013 18:06:52
dem66
Вы меня точно запутали.
Так ктото обяснит про прескалер?

Я так понял сейчас разговор идет о 8-ми разрядном таймере.
Обясните как все это прописывать в коде, с расчетом уже вроде разобрался