реклама на сайте
подробности

 
 
> Вопрос по режиму захвата таймера Т1, ATmega8
straighter
сообщение Mar 30 2016, 14:28
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 29-06-12
Пользователь №: 72 555



Уважаемые форумчане, помогите разобраться... ATmega8 работает с кварцем 8 Мгц. На вход встроенного компаратора подаю синусоиду 20 кГц от стабильного генератора. По положительному перепаду на выходе компаратора происходит захват значения в Timer/Counter1. Возникает прерывание, значение f увеличивается на 1. Когда f достигает значения d, то PORTC.2 устанавливается в 1 на время 10мкс, а затем снова устанавливается в 0. После этого в основном цикле программы PORTC.3 устанавливается в 1 на время 10мкс, а затем снова устанавливается в 0.
Когда я задаю значение d меньше или равное 255, то все работает нормально, после каждого импульса на выходе PORTC.2 возникает импульс выходе PORTC.3, как и должно быть. Но если я задаю значение d больше или равное 256, то импульсы на выходе PORTC.3 так и продолжают идти, но не каждому из них предшествует импульс на выходе PORTC.2.
Пробовал разные частоты синусоиды - то же самое.
В чем причина?

Фрагмент кода:
CODE

unsigned int d=255; // Заданное кол-во НЧ-периодов счета (кол-во сработок компаратора)

unsigned int f; // Текущее кол-во НЧ-периодов счета (кол-во сработок компаратора)

// Timer1 input capture interrupt service routine
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
{
// Place your code here

PORTC.0=1;
delay_us(10);
PORTC.0=0;

if (f==1) {

PORTC.1=1;
delay_us(10);
PORTC.1=0;

};

if (f==(d)) {

PORTC.2=1;
delay_us(10);
PORTC.2=0;

};

f=f+1;

}

void main(void)
{

f=0;

// Global enable interrupts
#asm("sei")

while (1)
{
// Place your code here

while (f<(d+1));

#asm("cli")

PORTC.3=1;
delay_us(10);
PORTC.3=0;

delay_us(100);

PORTC.4=1;
delay_us(10);
PORTC.4=0;

f=0;

#asm("sei")

};
}


Осциллограммы :

d=255; синий цвет - вых. РС2; желт. цвет - вых. РС3; Здесь все правильно и понятно:

Прикрепленное изображение


d=256; синий цвет - вых. РС2; желт. цвет - вых. РС3; Видно, что нет импульса на РС2, а соответствующий импульс на РС3 есть:

Прикрепленное изображение


Желт. цвет - сигнал на входе компаратора; синий цвет - на вых. РС0 (смотри код программы):

Прикрепленное изображение
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 8)
aiwa
сообщение Mar 31 2016, 13:03
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



Попробуйте заменить delay_us на что-то более конкретное, чтобы убедиться, что ее реализация не разрешает прерывания.
Go to the top of the page
 
+Quote Post
straighter
сообщение Mar 31 2016, 19:10
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 29-06-12
Пользователь №: 72 555



Попробую сделать без delay_us, например так: PORTC.1=1; PORTC.1=0;
Go to the top of the page
 
+Quote Post
aiwa
сообщение Apr 1 2016, 01:26
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



Тогда осцилограммы не будет.
Если используете IAR, в нем есть удобная псевдофункция delay_cycles(const unsigned long ) - задержка на заданное количество тактов.
Либо просто пустые вложенные циклы.


Тут два возможных варианта:
Первый:
1. При выполнении оператора
while (f<(d+1));
когда значение f = 255 = [00,FF]
1. процессор загружает младший байт FF в регистр
срабатывает прерывание и увеличивает значение (f = f+1) f = 256 = [01,00]
2. процессор загружает старший байт в регистр, а теперь он уже 01, а не 00.
поэтому значение в регистах стало [01,FF] = 511, а не 256 как на самом деле.
Происходит выход из цикла while на стадии когда счетчик равен 256

Второй:
и второй вариант если delay_us разрешает прерывания, а на компараторе
происходит шумок.

Какой из них нужно судить по частоте возникновения эффекта.

Наверное быстрее переделать сравнение для первого варианта
Код
  while (1)
  {
    #asm("cli")
        unsigned int f_test=f;
    #asm("sei")
     if(f_test<(d+1)) break;
  };


Сообщение отредактировал aiwa - Apr 1 2016, 01:45
Go to the top of the page
 
+Quote Post
straighter
сообщение Apr 1 2016, 09:23
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 29-06-12
Пользователь №: 72 555



Спасибо за ответ. Только я не совсем понял, в какое место моей программы вставить приведенный фрагмент кода:

Код

    #asm("cli")
        unsigned int f_test=f;
    #asm("sei")
     if(f_test<(d+1)) break;

Go to the top of the page
 
+Quote Post
aiwa
сообщение Apr 1 2016, 09:45
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



вместо while (f<(d+1));

вставить
while(1)
{
#asm("cli")
unsigned int f_test=f;
#asm("sei")
if(f_test<(d+1)) break;
}
чтобы сделать вычитку двухбайтной переменной f "атомарной" операцией.
Go to the top of the page
 
+Quote Post
straighter
сообщение Apr 1 2016, 12:19
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 29-06-12
Пользователь №: 72 555



Сделал так и почему-то исчезли импульсы на PORTC.2 (d = 256). Но идею насчет "атомарной" операции понял. Буду думать...
Go to the top of the page
 
+Quote Post
aiwa
сообщение Apr 1 2016, 13:14
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



Цитата(straighter @ Apr 1 2016, 15:19) *
Сделал так и почему-то исчезли импульсы на PORTC.2 (d = 256). Но идею насчет "атомарной" операции понял. Буду думать...

Извините, я забыл поменять знак в теле замене цикла c '<' на '>='
Код
while(1)
{
#asm("cli")
unsigned int f_test=f;
#asm("sei")
if(f_test>=(d+1)) break;
}

Из-за этого выход из цикла происходит сразу же.
Go to the top of the page
 
+Quote Post
straighter
сообщение Apr 1 2016, 14:08
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 29-06-12
Пользователь №: 72 555



Большое спасибо, получилось!
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 08:08
Рейтинг@Mail.ru


Страница сгенерированна за 0.01435 секунд с 7
ELECTRONIX ©2004-2016