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

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Аватара пользователя
Сообщения: 141
Зарегистрирован: Ср окт 26, 2011 13:38:13

Сообщение dem66 »

Доброго времени суток.
Возникла потребность собрать генератор испульсов на Atmega8.

Все работает но дело в том что слишком большие погрешости получаются.
Допустим:

Частота 6Khz
6*1000 = 6000
1/6000 = 0.000166667
0.000166667 * 1000 = 0.166667
0.166667/2 = 0.0833335
0.0833335 * 1000 = 83.3335

Полупериод = 83

Но атмега с этим не согласна и получается частота 7397Hz

Частота 3,102
1/3102 = 0.000322373
0.000322373 * 1000 = 0.322373
0.322373/2 = 0.1611865
0.1611865 * 1000 = 161.1865

Полупериод = 161

Но получается частота 3847Hz

Использую самописную функцию для милисекундных задержек, так как стандартные из <util/delay.h> весят очень много, занимают аж 10Kb.

Кварц 10Mhz

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

#define TIKS_1MS (10000000/64/1000)
#define TIKS_1US (TIKS_1MS/500)

void sleep_us(unsigned long int us)
{
	while(us--){
		TCNT0 = 0;
		while(TCNT0 < TIKS_1US);
	}
}

TCCR0 = (1<<CS02);

sleep_us(83);
На стандартной _delay_us(); погрешности почти нет
---------------------
PS: Пересобрал с опциями avr-gcc -mmcu=atmega8 -g -Os -Werror -lm -mcall-prologues -o firmware.o firmware.c и все ок, получился файлик 1,3Кб.

Теперь другой вопрос, так к нему приделать USART? чтобы можно было управлять частотой с компа.
Пример:

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

void uart_init(void)
{
  UBRRH = 0;
  //UBRRL = 52;
  //UBRRL = (10000000/(16*9600)) – 1;
  UBRRL = 65;
  UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
  UCSRB = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE);
}

unsigned char USART_Receive(void)
{
	while (!(UCSRA & (1<<RXC)));
	return UDR;
}

void USART_Transmit(unsigned char data)
{
	while (!(UCSRA & (1<<UDRE)));
	UDR = data;	        
}


int main(void){
   DDRD = 0xff;		// все выводы порта D сконфигурировать как выходы
   
  uart_init();
   
	while(1)
	{
		USART_Transmit(USART_Receive());
	}
}
Прикрепляю прошивку
Вложения
test2.h
(641 байт) 261 скачивание
test.h
(893 байт) 328 скачиваний
Это не хвост, это антенна
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

В даташите посмотрел, 10МГц для стандартного битрейта без погрешностей никакя скорость не подходит, если только подбирать чтобы была самая маленькая погрешность.
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

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

 void sleep_us(unsigned long int us)
{
   while(us--){
      TCNT0 = 0;
      while(TCNT0 < TIKS_1US);
   }
} 
сами подумайте что это у вас за бред написан?
зачем эти (us--)?
Нужно работать с прерыванием таймера, а не так деревянно так у вас получается аналогично с режимом delay_us тупит в цикле , зачем?

Рассчитайте сколько нужно поставить предделитель и сколько нужно тактов до прерывания.
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 141
Зарегистрирован: Ср окт 26, 2011 13:38:13

Сообщение dem66 »

vitalik_1984, в интернете нашел. Обясните тогда как правельно это сделать.
Последний раз редактировалось dem66 Пн янв 28, 2013 15:01:06, всего редактировалось 1 раз.
Это не хвост, это антенна
Реклама
Эиком - электронные компоненты и радиодетали
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

А вот остался вопрос по поводу USART
... встроенного генератора (8 Мгц) вполне хватает для обмена на скорости 19200
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 141
Зарегистрирован: Ср окт 26, 2011 13:38:13

Сообщение dem66 »

Зачем мне встроеный? Мне и с внешним неплохо, я вот только не понимаю как реализовать прием данных в атмеге и вприхивать принятые данные в функцию генерации. Принимает же по одному символу
Это не хвост, это антенна
Реклама
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

Принимает же по одному символу
Так придумайте протокол. Маркеры начала/конца посылки, контрольную сумму желательно. Как посылка принята и проверена - забирайте необходимые данные и работайте.
Встал на лапы
Аватара пользователя
Сообщения: 141
Зарегистрирован: Ср окт 26, 2011 13:38:13

Сообщение dem66 »

А разве нету готовых решений? :shock: Видел что чтото с прерываниями связано
Это не хвост, это антенна
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Причём тут прерывания ? Вы хоть думаете, перед тем как пишите ? Ну или, хотя бы, погуглили бы незнакомые слова.
Вам толкуют про протокол. Придумайте его себе сами и пользуйтесь на здоровье.
Мучитель микросхем
Аватара пользователя
Сообщения: 462
Зарегистрирован: Пн фев 22, 2010 09:12:34

Сообщение ArtDen »

вообще-то таймер сам умеет выводами дергать. никаких самописных функций для задержки, которые вносят погрешность, в данном случае не надо. читайте даташит. там все написано.
http://ufa-darts.ru/ - приходи играть в дартс в Уфе
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 141
Зарегистрирован: Ср окт 26, 2011 13:38:13

Сообщение dem66 »

Я и без вас пректрасно знаю что такое протокол
Это не хвост, это антенна
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

dem66 писал(а):Я и без вас пректрасно знаю что такое протокол
Заметно :
Видел что чтото с прерываниями связано
:))
YS
Друг Кота
Аватара пользователя
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05

Сообщение YS »

Мой вариант Вас случайно не устроит?
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Контактная информация:
Вымогатель припоя
Сообщения: 547
Зарегистрирован: Вт фев 09, 2010 17:52:26

Сообщение codenamehawk »

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

/*
 * main.c
 *
 *  Created on: 10.12.2011
 *      Author: Marian
 */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>

//main
int main(void)
{
	DDRB  = 1<<PB3;
	PORTB = 1<<PB3;

// Wychodnaja czastota F_OC0 = F_clkIO / (2*N*(1+OCR0))
// gdzie N prescaler (1,8,64,256,1024)
// Przyklad 12000000/2*1*(1+0) = 6000000 Hz

	TCCR0 |= 1 << CS00;							//clock/1    na wychodzie 6 000 000     Hz
//	TCCR0 |= 1 << CS01;							//clock/8    na wychodzie   750 000     Hz
//	TCCR0 |= 1 << CS01 | 1 << CS00;				//clock/64   na wychodzie    93 750     Hz
//	TCCR0 |= 1 << CS02;							//clock/256  na wychodzie    23 437.5   Hz
//	TCCR0 |= 1 << CS02 | 1 << CS00;				//clock/1024 na wychodzie     5 859.375 Hz

	TCCR0 |= 1<<WGM01 | 1<<COM00; //  CTC mode , togle wychod PB3

	OCR0   = 0;
//	OCR0   = 5; 								//OCR0   = 0x05;i dla clock/1 da na wychodzie da 1 000 000 Hz
//	OCR0   = 0x02;								//dla clock/64 da na wychodzie da 31250 Hz
//	OCR0   = 0x21;								//dla F_CPU 12MHz, clock/1, OCR0=21  da na wychodzie da 272727.2727 Hz


	sei();

	while (1)
	{
	}
}
Делал генератор на атмеге 16, кварц 12 Мн, выход на ногу PB3
По уарту передаете по одному символу, загоняете в текстовую переменную нужной длины, дальше преобразование текст в целое и присвоение TCCR0
Дальше тоже самое и с OCR0
Встал на лапы
Аватара пользователя
Сообщения: 141
Зарегистрирован: Ср окт 26, 2011 13:38:13

Сообщение dem66 »

Аlex, вы вобще внимательно читали а?
Если вы не вкурсе то принимать можно и с прерываниями

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

//Обработчик прерывания по окончанию приёма байта
ISR( USART_RXC_vect )
{
  unsigned char rxbyte = UDR;
}
И без

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

unsigned char USART_Receive(void)
{
	while (!(UCSRA & (1<<RXC)));
	return UDR;
}
YS, codenamehawk спасибо что откликнулись, буду думать.
YS а можко как то второй канал прилепить, ну он у вас как бы есть но частота у них одинкаовая, мне нужно чтобы на них можно было устанавливать разную частоту.

Нужно получить вот такую осцилограмму
Изображение

Думаю как это сделать, есть несколько вариантов:
1)генерить на две лапы и потом скрещивать дополнительной микрухой. Но какреализовать в атмеге 2 разных потока (походу два таймера с прерываниями) я пока не понял.
2)генерить на одну лапу, код типа этого:

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

int Pulse(timer1, timer2){
	int count;
	
	if(timer1>timer2){
		count = timer1/timer2;
	}else{
		count = timer2/timer1;
	}
		
		int i;
		
		for(i = 0; i<count; i++){
			PORTD |= _BV(PD3);
			_delay_us(timer2);
			PORTD &= ~_BV(PD3);
			if(i!=(count-1)){
				_delay_us(timer2);
			}
		}
	return 1;
}
int main(void){
   DDRD = 0xff;		// все выводы порта D сконфигурировать как выходы
   
   int timer1 = 238;
   int timer2 = 21;
   Pulse(timer1, timer2);
   
	while(1)
	{
		PORTD |= _BV(PD2);	// установить "1" (высокий уровень) на выводе PD1,зажечь светодиод
		
		Pulse(timer1, timer2);
		
		PORTD &= ~_BV(PD2);
		_delay_us(timer1);
	}
}
Подскажите в каком напревлении двигатся. Чтото не понял решения codenamehawk, там сразу куча ошибок посыпалась :(
Вложения
oscil.jpg
(3.24 КБ) 2923 скачивания
Это не хвост, это антенна
Вымогатель припоя
Сообщения: 547
Зарегистрирован: Вт фев 09, 2010 17:52:26

Сообщение codenamehawk »

Используйте два таймера.
Первый таймер в прерывании (по совпадению) сбрасываете счетчик и инвертируете нужную вам ногу.
Второй таймер в прерывании (по совпадению) сбрасываете счетчик и разрешаете-запрещаете работу первого.
(Тут не ясно что вы хотите получить из рисунка мало что понятно, какой диапазон частот ожидаете получить?)
Встал на лапы
Аватара пользователя
Сообщения: 141
Зарегистрирован: Ср окт 26, 2011 13:38:13

Сообщение dem66 »

Диапазон частот примерно 1Khz-100Khz, скважность 50%;

Если подскажите как это реализовать то буду очень благодарен.
У меня ваш код не компилируется, вываливается с ошибками на WGM01, COM00 и OCR0.

Компилирую в avr-gcc
Последний раз редактировалось dem66 Пн янв 28, 2013 23:40:47, всего редактировалось 1 раз.
Это не хвост, это антенна
Вымогатель припоя
Сообщения: 547
Зарегистрирован: Вт фев 09, 2010 17:52:26

Сообщение codenamehawk »

dem66 писал(а): Чтото не понял решения codenamehawk, там сразу куча ошибок посыпалась
Если прочитаете внимательно, то это прога для конкретного проца и без ошибок. Компилить надо WinAVR
Последний раз редактировалось codenamehawk Пн янв 28, 2013 23:42:34, всего редактировалось 1 раз.
Встал на лапы
Аватара пользователя
Сообщения: 141
Зарегистрирован: Ср окт 26, 2011 13:38:13

Сообщение dem66 »

уже увидел
Это не хвост, это антенна
Вымогатель припоя
Сообщения: 547
Зарегистрирован: Вт фев 09, 2010 17:52:26

Сообщение codenamehawk »

dem66 писал(а):Диапазон частот примерно 1Khz-100Khz, скважность 50%;

Если подскажите как это реализовать то буду очень благодарен.
У меня ваш код не компилируется, вываливается с ошибками на WGM01, COM00 и OCR0.

Компилирую в avr-gcc
Так мой пост перед вашим и есть подсказка, как вам еще подсказать?
Ответить

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