роботы робототехника микроконтроллеры


 Страниц (6): [1] 2 3 4 5 6 »   

> Описание: помогите новичку
Agioso Post Id


Лейтенант


Сообщений всего: 29
Дата рег-ции: Июль 2011  



Здравствуйте! Нуждаюсь в помощи. Имею МК Atmega48, необходимо использовать его таймер, для точного подсчета промежутка времени (до 1мкс, лучше точнее) с момента запуска до выполнения определенного условия (приход '0' на вход порта). Частота кварца 16мгц, максимальный промежуток времени - 50 000 мкс, т.е 800 000 тактов. То есть я так понимаю: запускаю таймер без деления (лучше 16битный timer1), периодически проверяю выполнение условия и переполнение, при переполнении сбрасываю переполнение и увеличиваю некую переменную. После выполнения условия останавливаю таймер и считаю: переменная умножить на 65536 плюс состояние таймера.
Вот.. Програмно не могу реализовать. На atmega8 использовал 8битный timer0:

t=0; //обнуление переменной
TCCR0=1; // запуск
while(TCCR0) //пока таймер включен
{
if(условие){TCCR0=0;}
if(TIFR&0x01) // проверка переполнения
{
TIFR=0x01; // сброс переполнения
t++;
}
}
t=t*256+TCNT0;

Все работало, а в atmega48 такой функции как TIFR не оказалось (пишет ошибку), пришлось мутить с периодической проверкой состояния значения самого счетчика, что сильно ухудшило точность подсчета... А с 16битным счетчиком я вообще не смог разобраться.
Подскажите пожалуйста как у него проверять переполнение и после остановки считать с него значение, заранее СПАСИБО!

(Отредактировано автором: 29 Июля, 2011 - 14:43:17)

 
 Top
Роботов Post Id



Гуру


Сообщений всего: 1350
Дата рег-ции: Июнь 2011  



Так может не проверять каждый раз переполнение таймера, а использовать прерывание по таймеру при переполнении, и в функции прерывания увеличивать переменную?

(Отредактировано автором: 29 Июля, 2011 - 14:51:19)

 
 Top
Agioso Post Id


Лейтенант


Сообщений всего: 29
Дата рег-ции: Июль 2011  



Роботов пишет:
Так может не проверять каждый раз переполнение таймера, а использовать прерывание по таймеру при переполнении, и в функции прерывания увеличивать переменную?

вообще было бы здорово! можешь примерно черкануть как это будет выглядеть?
 
 Top
Роботов Post Id



Гуру


Сообщений всего: 1350
Дата рег-ции: Июнь 2011  



Примерно так:
CODE:

TCCR0 = 0x05; //start timer
TIMSK = 0x01; //timer interrupt sources
///////// Прерывание по таймеру 0 //////////
interrupt [TIM0_OVF] void tim0_ovf_isr(void)
{
t++;
}
///////////////////////////////////////////
 
 Top
Agioso Post Id


Лейтенант


Сообщений всего: 29
Дата рег-ции: Июль 2011  



Большое спасибо, попробую! Еще бы разобраться где находится текущее значение 16битного счетчика timer1...
 
 Top
Agioso Post Id


Лейтенант


Сообщений всего: 29
Дата рег-ции: Июль 2011  



Что то не работает...

Роботов пишет:
interrupt [TIM0_OVF] void tim0_ovf_isr(void)
{
t++;
}

это надо писать после "// Declare your global variables here"
и до "void main(void)" ?
Ошибок при компилировании нет, но прерывание запускаться не хочет. Кстати у atmega48 нет TCCR0, timer0 запускается при TCCR0B=0x05

Вот листинг программы:
...
#include <mega48.h>
// Declare your global variables here

interrupt [TIM0_OVF] void tim0_ovf_isr(void)
{
PORTD=5;
}


void main(void)
{
...
// Port D initialization
PORTD=251;
DDRD=0xFF;
...
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x05;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
...
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x01;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;
...
while (1)
{
// Place your code here
};
}
Порт D подключен к 7-сегментному индикатору, сразу наглядно видно какие изменения. Как было PORTD=251 так и остается...
Счетчик запущен, считает нормально - пробовал прописывать PORTD=TCNT0; Индикатор меняет значение с недоступной для глаза скоростью. А прерывание не работает, где ошибка?
 
 Top
Роботов Post Id



Гуру


Сообщений всего: 1350
Дата рег-ции: Июнь 2011  



Ну при беглом просмотре кода не нашел глобального разрешения прерываний
 
 Top
Agioso Post Id


Лейтенант


Сообщений всего: 29
Дата рег-ции: Июль 2011  



Роботов пишет:
Ну при беглом просмотре кода не нашел глобального разрешения прерываний

Все, спасибо, разобрался! Нужно было просто галочку поставить при создании программы - Overflow Interrupt - и все. Все настройки создаются автоматически, в том числе и глобальная переменная #asm("sei"Подмигивающий Голливудская улыбка Голливудская улыбка
 
 Top
cjA Post Id



Генерал


Сообщений всего: 3291
Дата рег-ции: Янв. 2010  



timer0 - восьмибитный же?
(Добавление)
#asm(sei) - это не глобальная переменная, а низкоуровневая инструкция, не факт что "автоматически" она вставилась там где нужно.
да и приход 0 на ножку порта тоже лучьше на прерывание посадить (если этих ножек не очень много)
 
 Top
Agioso Post Id


Лейтенант


Сообщений всего: 29
Дата рег-ции: Июль 2011  



cjA пишет:
timer0 - восьмибитный же?
(Добавление)
#asm(sei) - это не глобальная переменная, а низкоуровневая инструкция, не факт что "автоматически" она вставилась там где нужно.
да и приход 0 на ножку порта тоже лучьше на прерывание посадить (если этих ножек не очень много)

сейчас использую timer1, он 16битный, #asm(sei) автоматически вставилась куда надо, по крайней мере все заработало.
А насчет посадить приход 0 на ножку на прерывание - проверка уровня нужна не постоянно, а в определенных моментах, после запуска счетчика, следовательно и прерывание нужно только в те моменты. Сейчас у меня просто цикл:
... while(PORTC.5){}
TCCR1B=0;
...
Счет прописан в прерывании по переполнению (t++).
А если перевести ножку на прерывание, точность замера увеличится?
Как вообще такое прерывание прописать?
 
 Top
cjA Post Id



Генерал


Сообщений всего: 3291
Дата рег-ции: Янв. 2010  



все гениальное просто, нет, наверное так даже лучьше, тем более раз работает.

точность замера - всегда одинакова, это же риск процессор, один такт- одна инструкция, делители могут неправильные стоять.
еще- что на кварце написано нужно смотреть, вот те цифры которые не указаны- могут плыть от температуры (но это, так, ремарка)
кстати 65536- _17_ битное число, оно вам нужно?
 
 Top
Agioso Post Id


Лейтенант


Сообщений всего: 29
Дата рег-ции: Июль 2011  



cjA пишет:

кстати 65536- _17_ битное число, оно вам нужно?

что имеете в виду? Промежуток времени который замеряю: 50...50 000мкс, следовательно при частоте 16мгц - 800...800 000 тактов.
Итого время после остановки счетчика считаю так: t*65536+TCNT1L+TCNT1H*256

(Отредактировано автором: 05 Августа, 2011 - 15:57:26)

 
 Top
nest Администратор Post Id



Администратор


Сообщений всего: 4866
Дата рег-ции: Сент. 2009  



cjA пишет:
точность замера - всегда одинакова, это же риск процессор, один такт- одна инструкция, делители могут неправильные стоять.
еще- что на кварце написано нужно смотреть, вот те цифры которые не указаны- могут плыть от температуры (но это, так, ремарка)
кстати 65536- _17_ битное число, оно вам нужно?
что это опять за поток сознания?
Человек алгоритмически не может разобраться, а вы ему про число на кварце...
 
 Top
cjA Post Id



Генерал


Сообщений всего: 3291
Дата рег-ции: Янв. 2010  



да понял, не глухой Улыбка
раз какое-то число занимает 17 бит значит Си автоматически переведет его в 32-х разрядное и процедуры работы с этим числом- в частности умножение, будут совсем другие , нежели с 16ти битными числами. Точно нужна 32-х разрядная точность?

65536 = 2#1_0000_0000_0000_0000# в двоичной системе - 17 бит
(Добавление)
nest я же сказал что это просто ремарка, ну чиво вы придираетесь, дяденька?
(Добавление)
nest я не настолько знаю Си что бы точно знать к чему это приведет, тем более для встроеных систем, но обычно берут 65535.
(под уиндос на пеньках такие ошибки (даже не ошибки , а опечатки) приводили к очень долгому и нудному поиску "почему не работает", в Си же нет строгой типизации, он может и биллион в байт заслать, а потом ищи - где..)
А вот возьмите и помогите с алгоритмом, что критиковать то просто так?
 
 Top
nest Администратор Post Id



Администратор


Сообщений всего: 4866
Дата рег-ции: Сент. 2009  



cjA пишет:
раз какое-то число занимает 17 бит значит Си
это число "занимает" 17 бит у людей. 2^16 - это как раз 65536 СОСТОЯНИЙ. Которые как раз кладутся в 16 бит. Не морочте людям голову.
Сначала думайте, потом пишите.
 
 Top
Страниц (6): [1] 2 3 4 5 6 »
« Программирование микроконтроллеров »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 





Powered by Exclusive Bulletin Board
ExBB FM 1.0 RC1 Smiles by Fool from Foolstown
  Яндекс.Метрика   Рейтинг@Mail.ru