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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Формирование сигнала определенного вида длительностью 1,5 мкс
Sprite
сообщение Jun 6 2008, 19:07
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414



Доброго всем времени суток! Программирую atmga8535 с кварцем на 16 Мгц.
Возникла такая задача:

Имеется входной сигнал вида 1.
Нужно получить сигнал вида 2:


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


Длительность нулевых уровней сигнала 2 - строго фиксированная и составляет 1,5 мкс. Нулевой уровень сигнала 2 должен заканчивается в момент смены фронта сигнала 1.
Проблема в том, что частота сигнала 1 заранее не известна и может меняться в пределах 10-20 кГц.
Думаю, что придется использовать таймер 1 и захватывать сигнал по ICP.
Уважаемые эксперты, какой режим таймера выбрать?
Буду очень признателен за изложение алгоритма (хотя бы на словах)!
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
Flasher
сообщение Jun 6 2008, 19:26
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 374
Регистрация: 6-09-05
Из: Тирасполь, Приднестровье
Пользователь №: 8 294



Алгоритм простой- берем гадалку и пусть она говорит когда нужно начинать выдавать ноль на втором сигнале. Если гадалка правильная, то ровно через 1,5 мкс произойдет смена уровня первого сигнала.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jun 6 2008, 19:54
Сообщение #3


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Flasher @ Jun 6 2008, 23:26) *
Алгоритм простой- берем гадалку и пусть она говорит когда нужно начинать выдавать ноль на втором сигнале. Если гадалка правильная, то ровно через 1,5 мкс произойдет смена уровня первого сигнала.
Ну зря Вы так про гадалку... smile.gif Взять то ее не откудаю... smile.gif
поэтому предлагаю другой вариант, пишем(на С или асм) гадалку, которая будет "предсказывать"
когда же этот переход должен был бы произойти... smile.gif
Go to the top of the page
 
+Quote Post
Flasher
сообщение Jun 6 2008, 20:00
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 374
Регистрация: 6-09-05
Из: Тирасполь, Приднестровье
Пользователь №: 8 294



Итак в рамках темы обсуждаем как писать гадалок. Определимся с методами написанной гадалки- кофейная гуща, воск, карты таро, хрустальный шар, куриные кости. Какой из методов лучше выбрать?
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jun 6 2008, 20:09
Сообщение #5


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Flasher @ Jun 7 2008, 00:00) *
Итак в рамках темы обсуждаем как писать гадалок. Определимся с методами написанной гадалки- кофейная гуща, воск, карты таро, хрустальный шар, куриные кости. Какой из методов лучше выбрать?
Ну это Вы опять же зазря...
то что я наставил смайликов в своем сообщении еще ни к чему не обязывает...

Ну а если серьезно...

Если частота не меняеться скачкообразно... это стандартная задачка которую
приходится решать при ловле 0 для сети, там тоже иногда хочется
знать предполагаемый момент перехода через 0...
так что пока обойдемся без карт таро smile.gif
по крайней мере пока топикстартер точно не объяснит что ему нужно...
Go to the top of the page
 
+Quote Post
DRUID3
сообщение Jun 6 2008, 22:07
Сообщение #6


山伏
*****

Группа: Свой
Сообщений: 1 827
Регистрация: 3-08-06
Из: Kyyiv
Пользователь №: 19 294



По маразму задачи, я так понимаю, что это ВУЗовское задание? Ну если входной сигнал заранее не известен но стационарен то...

По внешнему прерыванию начинаем считать тики "таймера". Первый перепад ничего не делаем - просто считаем, дальше работаем - уже знаем сколько "тиков" период. Смотря какой контроллер - вычитываем из DATA SHEET - что выставлять для какого таймера, Ваш не знаю и там ничего сложного, сами разберетесь. Таймер должен сосчитать и успеть сгенерить прерывание. При приходе такого-то тика выдаем импульс длительностью столько-то (опять же, меряем таймером)...

P.S.: кстати, так сразу и не посмотрел - очень короткое время этих маленьких переключений, контроллер может и не успевать (скорее всего).


--------------------
Нас помнят пока мы мешаем другим...
//--------------------------------------------------------
Хороший блатной - мертвый...
//--------------------------------------------------------
Нет старик, это те дроиды которых я ищу...
Go to the top of the page
 
+Quote Post
domowoj
сообщение Jun 7 2008, 01:35
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 548
Регистрация: 20-12-07
Из: г.Новосибирск
Пользователь №: 33 486



Что-то подобное делал на частоте 100Гц.
В вашем случае входной сигнал - на ITNx, меряете интервал от фронта до фронта в "тиках",
вычитаете из измеренного 1,5 мкс в тиках(при тактовой 16МГц- это число 24), полученное число в
OCRx и по прерыванию от OCRx формируете на вых. импульс.
Перый импульс пропадает.


--------------------
И на камнях растут деревья!
Go to the top of the page
 
+Quote Post
rv3dll(lex)
сообщение Jun 7 2008, 04:15
Сообщение #8


Полное ничтожество
*****

Группа: Banned
Сообщений: 1 991
Регистрация: 20-03-07
Из: Коломна
Пользователь №: 26 354



на сколько я понимаю что автор не понял что говорят вокруг

если сигнал периодический пусть даже с изменением частоты -то

по входному сигналу измерять непрерывно длительность а потом исходя из дилтельности за вычетом ваших полтора отсчитывать от фронта и менять сигнал на выходе

по фронту менять обратно

- усё a14.gif
Go to the top of the page
 
+Quote Post
INT1
сообщение Jun 7 2008, 04:25
Сообщение #9


deleted
****

Группа: Свой
Сообщений: 555
Регистрация: 28-08-05
Пользователь №: 8 024



Если бы знал, где упаду(отрицательный перепад) , там соломки бы подстелил
Цитата(Sprite @ Jun 6 2008, 22:07) *
.....
Проблема в том, что частота сигнала 1 заранее не известна.....

В прошлое вернуться нельзя, можно только предсказать будущее, и то, при определенных условиях и в определенных пределах...
Go to the top of the page
 
+Quote Post
Sprite
сообщение Jun 7 2008, 04:29
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414



Цитата(domowoj @ Jun 7 2008, 08:35) *
Что-то подобное делал на частоте 100Гц.
В вашем случае входной сигнал - на ITNx, меряете интервал от фронта до фронта в "тиках",
вычитаете из измеренного 1,5 мкс в тиках(при тактовой 16МГц- это число 24), полученное число в
OCRx и по прерыванию от OCRx формируете на вых. импульс.
Перый импульс пропадает.


Действительно реальный совет! a14.gif
И к гадалкам не надо обращаться! smile.gif

Одна немаловажная поправка:
Прикрепленное изображение


В моменты времени 5-6 границы нулевого сигнала должны быть такими же(относительно полупериода входного сигнала) как и 3-4; Другими словами: границы 3-4, 5-6 измеряются один раз в период сигнала 1.
Вот что я делаю:

Код
#include "avr/io.h"
#include <avr/interrupt.h>
#include <avr/sleep.h>

#define LEFT_1  0
#define RIGHT_1 1
#define LEFT_2  2

//Массив границ нулевых импульсов сигнала 2
volatile uint16_t bound[3];
//bound[0] соответствует моменту времени 3 (на рисунке)
//bound[1] соответствует моменту времени 4 (на рисунке)
//bound[2] соответствует моменту времени 5 (на рисунке)

//Текущее, предыдущее значение тиков процессора и разница между ними
volatile uint16_t ICR_Current, ICR_Prev, ICR_Diff;

//Счетчик (для обращения к элементам массива bound)
volatile uint8_t count;
//========================================================
//========================================================

void InitPorts(void)
{
    DDRB = 0xFF;
    PORTB = 0;
    
    DDRD = _BV(5);
    PORTD = 0;
}

//========================================================
void InitTimers(void)
{
    //Таймер 1 -------------------------------------------
    TCCR1A = _BV(COM1A1)|_BV(FOC1A); //Сброс OC1A при совпадении с OCR1A, разрешаем вывод на ногу OC1A    
    TCCR1B = _BV(CS10); //Частота==16 МГц (без делителя), режим Normal
    TCCR1B|= _BV(ICES1); //Прерывание по захвату положительного фронта сигнала 1
    TIMSK =  _BV(TICIE1)|_BV(OCIE1A); //Разрешение прерывания по захвату и сравнению с OCR1A

    sei(); //Общий флаг разрешения прерываний
}

//========================================================
void InitValues(void)
{
    count = 0;
    ICR_Prev = 0;
}

//========================================================
int main (void)
{
    InitPorts();
    InitValues();
    InitTimers();

    for (;;)            
        sleep_mode();
}

//========================================================
//========================================================
ISR(TIMER1_CAPT_vect) //Прерывание по захвату сигнала 1
{
    ICR_Current = ICR1;

    if (count==4) //соответствует моменту времени 6 (на рисунке)
    {
        PORTD|= _BV(5); //Устанавливаем на выводе OC1A логическую 1
    }

    //Т.к. счетчик(TCNT1) циклично увеличивается до 65535 и сбрасывается в 0
    //нужно обработать ситуацию, когда в момент захвата значение счетчика лежит
    //в пределах [0;24]. При этом текущее значение == TCNT1, а предыдущее лежит
    //в пределах [65511; 65535](т.е. текущее значение МЕНЬШЕ предыдущего)

    ICR_Diff = (ICR_Current>ICR_Prev)? (ICR_Current-ICR_Prev) : (ICR_Prev-ICR_Current);
    ICR_Prev = ICR_Current;
    

    bound[RIGHT_1] =  ICR_Current + ICR_Diff/2;    //bound[RIGHT_1]соответствует моменту времени 4 (на рисунке)
    bound[LEFT_1]  =  bound[RIGHT_1]-24;            //bound[LEFT_1] соответствует моменту времени 3 (на рисунке)
    bound[LEFT_2]  =  ICR_Current + ICR_Diff-24;    //bound[LEFT_2] соответствует моменту времени 5 (на рисунке)
  
  
    //Установка вывода OC1A в "0" в последующем прерывании по сравнению
    TCCR1A&=~_BV(COM1A0);
    TCCR1A|=_BV(COM1A1);
    
    OCR1A = bound[LEFT_1]; //Установка первого прерывания по сравнению
    count = 1;
}


ISR(TIMER1_COMPA_vect) //Прерывание по сравнению сигнала
{
    OCR1A = bound[count];
    count++;
    
    //Режим TOGGLE (инвертирование состояния вывода OC1A в последующем прерывании по сравнению)
    TCCR1A|=_BV(COM1A0);
    TCCR1A&=~_BV(COM1A1);
}


Время между прерываниями по сравнению сигнала (3-4) ==24 такта, что очень малоsad.gif
Я не особо силен в ассемблере, и пока не знаю: успеет ли обработаться прерывание по сравнению за 24 такта? Скольким тактам процессора соответствует код в прерывании?!
Посмотрите свежим взглядом, может быть где ошибка допущена?
Заранее благодарен!
Go to the top of the page
 
+Quote Post
otrog
сообщение Jun 7 2008, 04:47
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 232
Регистрация: 22-02-06
Из: Воронеж
Пользователь №: 14 589



Для работы с временами порядка микросекунд просто необходимо писать на ассемблере, и размещать все переменные в регистрах.
Если с асмом туго, рекомендую Algorithm Builder - графический ассемблер. Осваивается буквально за часы.
Успехов.


--------------------
Истина рождается в спорах; но когда страсти кипят, истина испаряется.
Go to the top of the page
 
+Quote Post
Sprite
сообщение Jun 7 2008, 06:35
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414



Цитата(otrog @ Jun 7 2008, 11:47) *
Для работы с временами порядка микросекунд просто необходимо писать на ассемблере, и размещать все переменные в регистрах.
Если с асмом туго, рекомендую Algorithm Builder - графический ассемблер. Осваивается буквально за часы.
Успехов.


После компиляции программы посмотрел я lss-файл:
Код
ISR(TIMER1_COMPA_vect) //Прерывание по сравнению сигнала
{
190:    1f 92           push    r1
192:    0f 92           push    r0
194:    0f b6           in    r0, 0x3f; 63
196:    0f 92           push    r0
198:    11 24           eor    r1, r1
19a:    8f 93           push    r24
19c:    9f 93           push    r25
19e:    ef 93           push    r30
1a0:    ff 93           push    r31
    OCR1A = bound[count];
1a2:    e0 91 68 00     lds    r30, 0x0068
1a6:    ff 27           eor    r31, r31
1a8:    ee 0f           add    r30, r30
1aa:    ff 1f           adc    r31, r31
1ac:    e0 5a           subi    r30, 0xA0; 160
1ae:    ff 4f           sbci    r31, 0xFF; 255
1b0:    80 81           ld    r24, Z
1b2:    91 81           ldd    r25, Z+1; 0x01
1b4:    9b bd           out    0x2b, r25; 43
1b6:    8a bd           out    0x2a, r24; 42
    count++;
1b8:    80 91 68 00     lds    r24, 0x0068
1bc:    8f 5f           subi    r24, 0xFF; 255
1be:    80 93 68 00     sts    0x0068, r24
    
    //Режим TOGGLE (инвертирование состояния вывода OC1A в последующем прерывании по сравнению)
    TCCR1A|=_BV(COM1A0);
1c2:    8f b5           in    r24, 0x2f; 47
1c4:    80 64           ori    r24, 0x40; 64
1c6:    8f bd           out    0x2f, r24; 47
    TCCR1A&=~_BV(COM1A1);
1c8:    8f b5           in    r24, 0x2f; 47
1ca:    8f 77           andi    r24, 0x7F; 127
1cc:    8f bd           out    0x2f, r24; 47
1ce:    ff 91           pop    r31
1d0:    ef 91           pop    r30
1d2:    9f 91           pop    r25
1d4:    8f 91           pop    r24
1d6:    0f 90           pop    r0
1d8:    0f be           out    0x3f, r0; 63
1da:    0f 90           pop    r0
1dc:    1f 90           pop    r1
1de:    18 95           reti


И понял, что получается полная лажа sad.gif
Всего выполняется 37 asm-операций, а максимум должно быть 24. Как быть?

Может лучше такой вариант?:
1) Вызывать прерывания по захвату два раза в период (т.е. по возрастающему и ниспадающему фронтам).
2) При захвате каждого фронта определять прерывания по сравнению
3) В прерывании по сравнению делать задержку на 24 такта (т.е. 24 команды "nop")

Сообщение отредактировал Sprite - Jun 7 2008, 06:35
Go to the top of the page
 
+Quote Post
rv3dll(lex)
сообщение Jun 7 2008, 07:05
Сообщение #13


Полное ничтожество
*****

Группа: Banned
Сообщений: 1 991
Регистрация: 20-03-07
Из: Коломна
Пользователь №: 26 354



Цитата(Sprite @ Jun 7 2008, 10:35) *
После компиляции программы посмотрел я lss-файл:
[
И понял, что получается полная лажа sad.gif
Всего выполняется 37 asm-операций, а максимум должно быть 24. Как быть?

Может лучше такой вариант?:
1) Вызывать прерывания по захвату два раза в период (т.е. по возрастающему и ниспадающему фронтам).
2) При захвате каждого фронта определять прерывания по сравнению
3) В прерывании по сравнению делать задержку на 24 такта (т.е. 24 команды "nop")


вопрос ребром - вы ассемблер знаете??

си всё всегда делает через стек - посмотрите сколько времени отнимают пуш и поп
если писать на ассемблере всё (на си наверное тоже можно - но я его не смог выучить - не дано) можно выделить регистры специально под это и сохранять только необходимые вещи
Go to the top of the page
 
+Quote Post
Ledmaster
сообщение Jun 7 2008, 07:44
Сообщение #14


Частый гость
**

Группа: Свой
Сообщений: 142
Регистрация: 18-02-08
Из: Челябинск
Пользователь №: 35 141



Цитата(Sprite @ Jun 7 2008, 01:07) *
Доброго всем времени суток! Программирую atmga8535 с кварцем на 16 Мгц.
Возникла такая задача:

Имеется входной сигнал вида 1.
Нужно получить сигнал вида 2:


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


Длительность нулевых уровней сигнала 2 - строго фиксированная и составляет 1,5 мкс. Нулевой уровень сигнала 2 должен заканчивается в момент смены фронта сигнала 1.
Проблема в том, что частота сигнала 1 заранее не известна и может меняться в пределах 10-20 кГц.
Думаю, что придется использовать таймер 1 и захватывать сигнал по ICP.
Уважаемые эксперты, какой режим таймера выбрать?
Буду очень признателен за изложение алгоритма (хотя бы на словах)!

Пацаны, я конечно все понимаю, микроконтроллеры там, ассемблеры...
А что, попроще решения уже никого не устраивают? 07.gif
Задерживаете входной сигнал на 1.5 мкс и называете задержанный сигнал входным.
Для того, чтобы получить теперь сигнал вида 2, достаточно одного элемента XNOR ( например, LittleLogic от TI).
Как задержать сигнал, объяснять надо? rolleyes.gif
Go to the top of the page
 
+Quote Post
Sprite
сообщение Jun 7 2008, 07:50
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414



Цитата(rv3dll(lex) @ Jun 7 2008, 14:05) *
вопрос ребром - вы ассемблер знаете??

си всё всегда делает через стек - посмотрите сколько времени отнимают пуш и поп
если писать на ассемблере всё (на си наверное тоже можно - но я его не смог выучить - не дано) можно выделить регистры специально под это и сохранять только необходимые вещи


Спасибо за совет! Ассемблер я не знаю, но чувствую, что без него здесь не обойтись, постараюсь переписать прерывание на asm'e - скажу что получится.
Go to the top of the page
 
+Quote Post
rv3dll(lex)
сообщение Jun 7 2008, 08:12
Сообщение #16


Полное ничтожество
*****

Группа: Banned
Сообщений: 1 991
Регистрация: 20-03-07
Из: Коломна
Пользователь №: 26 354



Цитата(Ledmaster @ Jun 7 2008, 11:44) *
Пацаны, я конечно все понимаю, микроконтроллеры там, ассемблеры...
А что, попроще решения уже никого не устраивают? 07.gif
Задерживаете входной сигнал на 1.5 мкс и называете задержанный сигнал входным.
Для того, чтобы получить теперь сигнал вида 2, достаточно одного элемента XNOR ( например, LittleLogic от TI).
Как задержать сигнал, объяснять надо? rolleyes.gif


я бы тоже на плисине сделал на самой дохлой тока задача судя по всему про контроллер
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Jun 7 2008, 08:44
Сообщение #17


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Я знаю как надо поступить.

1. засекаем входной период (таймером, через ICP или как его там)
2. вычисляем 2 константы - время установки вых. сигнала и время сброса (в тиках таймера).
3. таймер работает в непрерывном режиме
4. заносим наши константы в регистры сравнения А и В.
5. настраиваем так чтобы по 1-му совпадению сигнал на выходе устанавливался, а по 2-му - сбрасывался.
6. это всё непрерывно в цикле.
7. вуаля!


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Ledmaster
сообщение Jun 7 2008, 09:40
Сообщение #18


Частый гость
**

Группа: Свой
Сообщений: 142
Регистрация: 18-02-08
Из: Челябинск
Пользователь №: 35 141



Цитата(rv3dll(lex) @ Jun 7 2008, 14:12) *
я бы тоже на плисине сделал на самой дохлой тока задача судя по всему про контроллер

Ну, ради бога, пусть на контроллере, принцип тот же самый: формируем задержанный сигнал, который далее считаем входным. Для этого падаем в прерывание по фронту/спаду, тупо формируем там импульс 1.5мкс без всяких таймеров, просто по времени выполнения последовательности команд типа

OutPort1 = 0
NOP
NOP
...
OutPort1 = 1

затем формируем задержанную копию входного сигнала

OutPort2 = InPort1


Естественно, такой подход неприменим, если требуется реакция на опережение в реальном времени
Go to the top of the page
 
+Quote Post
Sprite
сообщение Jun 9 2008, 14:35
Сообщение #19


Частый гость
**

Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414



Цитата(MrYuran @ Jun 7 2008, 15:44) *
Я знаю как надо поступить.

1. засекаем входной период (таймером, через ICP или как его там)
2. вычисляем 2 константы - время установки вых. сигнала и время сброса (в тиках таймера).
3. таймер работает в непрерывном режиме
4. заносим наши константы в регистры сравнения А и В.
5. настраиваем так чтобы по 1-му совпадению сигнал на выходе устанавливался, а по 2-му - сбрасывался.
6. это всё непрерывно в цикле.
7. вуаля!


Вот оно! то, что надо!
Сделал как вы посоветовали - проблема решилась!
Респект!
a14.gif a14.gif a14.gif
Go to the top of the page
 
+Quote Post

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

 


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


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