Страница 1 из 5
Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Вс янв 27, 2013 23:43:55
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());
}
}
Прикрепляю прошивку
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 04:15:09
zero648
В даташите посмотрел, 10МГц для стандартного битрейта без погрешностей никакя скорость не подходит, если только подбирать чтобы была самая маленькая погрешность.
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 04:26:45
vitalik_1984
Код: Выделить всё
void sleep_us(unsigned long int us)
{
while(us--){
TCNT0 = 0;
while(TCNT0 < TIKS_1US);
}
}
сами подумайте что это у вас за бред написан?
зачем эти (us--)?
Нужно работать с прерыванием таймера, а не так деревянно так у вас получается аналогично с режимом delay_us тупит в цикле , зачем?
Рассчитайте сколько нужно поставить предделитель и сколько нужно тактов до прерывания.
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 13:59:38
dem66
vitalik_1984, в интернете нашел. Обясните тогда как правельно это сделать.
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 14:21:44
ChipKiller
А вот остался вопрос по поводу USART
... встроенного генератора (8 Мгц) вполне хватает для обмена на скорости 19200
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 15:52:55
dem66
Зачем мне встроеный? Мне и с внешним неплохо, я вот только не понимаю как реализовать прием данных в атмеге и вприхивать принятые данные в функцию генерации. Принимает же по одному символу
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 16:07:40
ploop
Принимает же по одному символу
Так придумайте протокол. Маркеры начала/конца посылки, контрольную сумму желательно. Как посылка принята и проверена - забирайте необходимые данные и работайте.
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 16:23:59
dem66
А разве нету готовых решений?

Видел что чтото с прерываниями связано
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 20:32:11
Аlex
Причём тут прерывания ? Вы хоть думаете, перед тем как пишите ? Ну или, хотя бы, погуглили бы незнакомые слова.
Вам толкуют про
протокол. Придумайте его себе сами и пользуйтесь на здоровье.
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 20:38:17
ArtDen
вообще-то таймер сам умеет выводами дергать. никаких самописных функций для задержки, которые вносят погрешность, в данном случае не надо. читайте даташит. там все написано.
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 20:40:28
dem66
Я и без вас пректрасно знаю что такое протокол
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 20:48:01
Аlex
dem66 писал(а):Я и без вас пректрасно знаю что такое протокол
Заметно :
Видел что чтото с прерываниями связано

Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 21:10:32
YS
Мой вариант Вас случайно не устроит?
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 21:37:05
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
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 23:13:15
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, там сразу куча ошибок посыпалась

Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 23:33:44
codenamehawk
Используйте два таймера.
Первый таймер в прерывании (по совпадению) сбрасываете счетчик и инвертируете нужную вам ногу.
Второй таймер в прерывании (по совпадению) сбрасываете счетчик и разрешаете-запрещаете работу первого.
(Тут не ясно что вы хотите получить из рисунка мало что понятно, какой диапазон частот ожидаете получить?)
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 23:39:26
dem66
Диапазон частот примерно 1Khz-100Khz, скважность 50%;
Если подскажите как это реализовать то буду очень благодарен.
У меня ваш код не компилируется, вываливается с ошибками на WGM01, COM00 и OCR0.
Компилирую в avr-gcc
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 23:40:18
codenamehawk
dem66 писал(а): Чтото не понял решения codenamehawk, там сразу куча ошибок посыпалась
Если прочитаете внимательно, то это прога для конкретного проца и без ошибок. Компилить надо WinAVR
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 23:41:53
dem66
уже увидел
Re: Генератор на Atmega8 (микросекунды) большие погрешности
Добавлено: Пн янв 28, 2013 23:49:49
codenamehawk
dem66 писал(а):Диапазон частот примерно 1Khz-100Khz, скважность 50%;
Если подскажите как это реализовать то буду очень благодарен.
У меня ваш код не компилируется, вываливается с ошибками на WGM01, COM00 и OCR0.
Компилирую в avr-gcc
Так мой пост перед вашим и есть подсказка, как вам еще подсказать?