Страница 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-ми разрядном таймере.
Обясните как все это прописывать в коде, с расчетом уже вроде разобрался