Генератор на Atmega8 (микросекунды) большие погрешности
Ставим плюсы: )
- Реклама
- Сообщения: 141
- Зарегистрирован: Ср окт 26, 2011 13:38:13
Уже разобрался. Получаеся примерно такой код:
Теперь подскажите что делать с TCNT1? Сейчас же получается статическое значение, а если я получу новое значение по USART то как мне его туда впихнуть?
Начальное же значение указывается в функции ISR(TIMER1_OVF_vect)
И как запустить два таймера? Чтото не получается
ibiza11, тихо там
Код: Выделить всё
#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)
{
}
}
Начальное же значение указывается в функции ISR(TIMER1_OVF_vect)
И как запустить два таймера? Чтото не получается
ibiza11, тихо там
Это не хвост, это антенна
- Сообщения: 141
- Зарегистрирован: Ср окт 26, 2011 13:38:13
Так всетаки как должен выглядеть код с двумя таймерами? У меня никак не поучается настроить два, перестают работать оба
Это не хвост, это антенна
- Сообщения: 462
- Зарегистрирован: Пн фев 22, 2010 09:12:34
Ты лучше объясни что вообще хочешь получить. Пока просто никто не понял как должен выглядеть твой конечный результат.
http://ufa-darts.ru/ - приходи играть в дартс в Уфе
- Сообщения: 7518
- Зарегистрирован: Вс мар 29, 2009 22:09:05
Да не, ТС же писал:
Вот, два корпуса стандартной логики:

Я тут подумал, а может ну их нафиг, контроллеры?Нужно получить вот такую осцилограмму
![]()

Разница между теорией и практикой на практике гораздо больше, чем в теории.
- Реклама
- Сообщения: 547
- Зарегистрирован: Вт фев 09, 2010 17:52:26
А перестройка частоты через уарт?YS писал(а): Я тут подумал, а может ну их нафиг, контроллеры?Вот, два корпуса стандартной логики:
- Сообщения: 547
- Зарегистрирован: Вт фев 09, 2010 17:52:26
TCNT1 = 64456;
замените на
TCNT1 = peremennaja_v_kotoruju_ja_budu_zadavat_znachenija_chastoty;
Для второго таймера
как-то так
замените на
TCNT1 = peremennaja_v_kotoruju_ja_budu_zadavat_znachenija_chastoty;
Для второго таймера
Код: Выделить всё
ISR(TIMER2_OVF_vect)
{
TCNT2 = время_задержки;//это место где нет импульсов, ну или длина пачки импульсов
if( пауза == 0)
{
TCCR1B = 0;//запретить работу первого таймера
пауза=1;
}else
{
TCCR1B = (1<<CS10);
пауза=0;//разрешить работу первого таймера
}
}
Последний раз редактировалось codenamehawk Ср янв 30, 2013 16:41:50, всего редактировалось 1 раз.
- Сообщения: 547
- Зарегистрирован: Вт фев 09, 2010 17:52:26
Пишите, что вам здесь непонятно, попробую помочь.codenamehawk писал(а): По уарту передаете по одному символу, загоняете в текстовую переменную нужной длины, дальше преобразование текст в целое и присвоение TCCR0
- Сообщения: 141
- Зарегистрирован: Ср окт 26, 2011 13:38:13
Ну на логике я бы и сам мог сделать, ну и всякие там TL494, NE555, но к сожалению такой вариант не проходит
Пытаюсь вручную расчитывать нужное количество тиков.
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 но в результате не работает
Пытаюсь вручную расчитывать нужное количество тиков.
Код: Выделить всё
#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)
{
}
}
Частотапереполнения = 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 но в результате не работает
Это не хвост, это антенна
Делаем частоту 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.
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.
- Сообщения: 141
- Зарегистрирован: Ср окт 26, 2011 13:38:13
Чтото непонятноzero648 писал(а):загружаем в него 5 и при каждом прерывании Timer0 уменьшаем на единицу
А как быть с TCCR0 и TIMSK??
Это не хвост, это антенна
Это прописываем в инициализации:dem66 писал(а):Чтото непонятно![]()
А как быть с TCCR0 и TIMSK??
TCCR0=0x02 - прескалер 1:8;
TIMSK=0x01 - прерывание по переполнению таймера 0
- Сообщения: 547
- Зарегистрирован: Вт фев 09, 2010 17:52:26
Если подсчитали количество импульсов правильно, то необходимо от числа 0xFFFF отнять ваш результат 0x4E2 и присвоить результат TCNT1dem66 писал(а): Чтобы получить 0.0005 c (2Khz) необходимо чтобы таймер тикнул 0.0005 / 0.0000004 = 1250 раз.
1250 в 16-тиричной системе это 4E2 = 0x4E2
(объясню на пальцах
как только вы присвоили TCNT1= 0x4E2 он сразу же начинает тикать с этого значения.
прерывание по переполнению наступит после 0xFFFF
сколько тиков пройдет до прерывания подсчитать можете?)
Вы бы почитали о других возможных режимах прерываний(про тот что я советовал), обошлись бы без такого геморроя.
- Сообщения: 141
- Зарегистрирован: Ср окт 26, 2011 13:38:13
извиняюсь, забыл.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
Это не хвост, это антенна
- Сообщения: 547
- Зарегистрирован: Вт фев 09, 2010 17:52:26
что это за оптимизация такая? те же самые действия, только еще и используя переменную, которая может лежать вне РОН, а чаще всего так и есть.
теперь представим себе примерно ассемблер
загрузили число,
сравнили с константой,
если равно переход к метка
порт в 1
переход к метка 2
метка :порт в 0
метка 2
а в начальном варианте :
определили пин
если равно переход к метка
порт в 1
переход к метка 2
метка :порт в 0
метка 2
хорошо сэкономили?
можно вообще вот так:
PORTB ^= (1 << PB0);
в асме
загрузили в РОН
XOR константа
Поместили в порт.
теперь представим себе примерно ассемблер
загрузили число,
сравнили с константой,
если равно переход к метка
порт в 1
переход к метка 2
метка :порт в 0
метка 2
а в начальном варианте :
определили пин
если равно переход к метка
порт в 1
переход к метка 2
метка :порт в 0
метка 2
хорошо сэкономили?
можно вообще вот так:
PORTB ^= (1 << PB0);
в асме
загрузили в РОН
XOR константа
Поместили в порт.
Последний раз редактировалось vitalik_1984 Чт янв 31, 2013 19:31:30, всего редактировалось 1 раз.
Во-первых не вижу самодельного прескалера, во-вторых у Вас меняется состояние PORTB.0 каждый раз при выполнении обработчика прерывания, поэтому для полного периода в обработчик нужно зайти два раза, а значит частоту входа нужно увеличить в 2 раза, чтобы получить нужную частоту сигнала, и в третьих есть небольшой нюанс, при использовании переполнения таймера нужно учитывать время входа в обработчик, так что TCNT0=131 это как бы базовая расчетная величина и её нужно корректировать по ходу процесса.dem66 писал(а):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;
}
10000000/4000=2500
2500=250*10, получается TCNT0 будет теперь 256-250 и плюс учтем время входа в обработчик, 11 тактов на вход плюс 1 такт на загрузку регистра TCNT0, самодельный прескалер будет 10, таймер тикает без аппаратного прескалера, т.е. 10МГц.
При таких настройках у меня все четко получается:
- Сообщения: 141
- Зарегистрирован: Ср окт 26, 2011 13:38:13
Прескалер это OCR0 или TCCR0?
И что это у вас за proteus такой?
И что это у вас за proteus такой?
Это не хвост, это антенна
- Сообщения: 547
- Зарегистрирован: Вт фев 09, 2010 17:52:26
ИМХО можно не учитывать эти "11 тактов на вход плюс 1 такт на загрузку регистра TCNT0"zero648 писал(а): получается TCNT0 будет теперь 256-250 и плюс учтем время входа в обработчик, 11 тактов на вход плюс 1 такт на загрузку регистра TCNT0,
Прерывания и так происходят каждые 1/4000 сек , а дополнительные такты просто сместят сигнал немного правее, не меняя его ширины (длительности).
- Сообщения: 141
- Зарегистрирован: Ср окт 26, 2011 13:38:13
Вы меня точно запутали.
Так ктото обяснит про прескалер?
Я так понял сейчас разговор идет о 8-ми разрядном таймере.
Обясните как все это прописывать в коде, с расчетом уже вроде разобрался
Так ктото обяснит про прескалер?
Я так понял сейчас разговор идет о 8-ми разрядном таймере.
Обясните как все это прописывать в коде, с расчетом уже вроде разобрался
Это не хвост, это антенна


