|
|
  |
Синхронизация по фронтам |
|
|
|
Sep 5 2011, 06:49
|
Группа: Новичок
Сообщений: 4
Регистрация: 5-09-11
Пользователь №: 66 997

|
Здравствуйте. Есть задача. На вход поступает сигнал определенной частоты. На выходе необходимо после вычисления частоты выдать такой же сигнал синхронизированный с входящим по нарастающему и убывающему фронтам. Делаю так: - по первому прерыванию int0 включаю счетчик - по второму прерыванию int0 останавливаю счетчик и вычисляю полупериод - вычисляю задержки на вход в прерывания и по прерыванию по сравнению таймера меняю выход с 1 на 0 и наоборот. Прерывание по сравнению происходит раньше смены фронтов входящего сигнала на величину задержки. По идее должно работать, но на осциллографе частота получается равная, а вот фронты не совпадают. Подскажите, что не так. Может вообще как-то по другому надо все делать? Код ;***************************************************************************
;*************************************************************************** .include "m16def.inc" .def temp=r16; .def timeL=r17; .def timeH=r18; .def counter=r21;
.CSEG ;начало сегмента .ORG 0 ;вектор сброса rjmp init; .ORG INT0addr rjmp Ext_INT0 ; (INT0) External Interrupt Request 0 .ORG OC1Aaddr ; Timer/Counter1 Compare Match A rjmp Ext_OC1A .ORG OC1Baddr rjmp Ext_OC1B
;========================== ; Прерывания ;==========================
Ext_INT0: loop1: cpi counter,1; Захватываем начало периода по 1-му нарастающему фронту brne loop2 ldi r16,0b00000001 out TCCR1B,r16 inc counter rjmp exit loop2: cpi counter,2; Захватываем конец периода по 2-му нарастающему фронту brne loop3 ldi r16,0b00000000 out TCCR1B,r16 in timeL,TCNT1L; in timeH,TCNT1H subi timeL,3; убираем задержку вычисления периода sbci timeH,0 mov r23,timeH mov r22,timeL subi r22,51 ;устанавливаем задержку для совпадения фронта sbci r23,0 ; и заносим ее в OCR1B out OCR1BH,r23 out OCR1BL,r22 lsr timeH ;Вычисляем длительность импульса ror timeL subi timeL,16 ; убираем задержку для смены фронтов sbci timeH,0 out OCR1AH,timeH; длительность импульса в OCR1A out OCR1AL,timeL ldi r16,0 out TCNT1H,r16 out TCNT1L,r16 inc counter rjmp exit loop3: ldi r16,0 ;включаем таймер тс1в out GICR,r16 ldi r16,0b00001000 out TIMSK,r16 ldi r16,0b00000001 out TCCR1B,r16 ldi r16,0 out TCNT1H,r16 out TCNT1L,r16 exit: reti
Ext_OC1B: ldi r16,0b00010000; запускаем задержку для совпадения фронтов out TIMSK,r16 ldi r16,0 out TCNT1H,r16 out TCNT1L,r16 reti
Ext_OC1A: ; запускаем задержку для смены фронтов in r16,PortD ldi r17,0b00000001 eor r16,r17 out PortD,r16 ldi r16,0b00000000 out TCNT1H,r16 out TCNT1L,r16 reti
;========================= ; Инициализация ;========================= Init: ldi r31,LOW(RAMEND) out spl,r31 ldi r31,HIGH(RAMEND) out sph,r31
ldi r16,0b11111011; Настройка портов out DDRD,r16; ldi r16,0b00000100; out PortD,r16; ldi r16,0b00000011; out MCUCR,r16; ldi r16,0b01000000; out GICR,r16; ldi r18,100 ldi r21,1 ldi r16,0b00000101; sei; reset: ;RESET
|
|
|
|
|
Sep 5 2011, 09:58
|
Группа: Новичок
Сообщений: 4
Регистрация: 5-09-11
Пользователь №: 66 997

|
Спасибо за совет. В итоге нужно будет еще изменять ширину импульса и сдвигать выходной сигнал относительно входящего. Попробовал просто передавать сигнал - все равно есть задержка, где-то 500 нС. Код sbic PinD,2 sbi PortD,0 sbis PinD,2 cbi PortD,0
|
|
|
|
|
Sep 5 2011, 12:24
|

Гуру
     
Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106

|
Цитата(Mayak @ Sep 5 2011, 09:49)  На вход поступает сигнал определенной частоты. На выходе необходимо после вычисления частоты выдать такой же сигнал Это не возможно. Цитата(Mayak @ Sep 5 2011, 12:58)  Спасибо за совет. В итоге нужно будет еще изменять ширину импульса и сдвигать выходной сигнал относительно входящего. Попробовал просто передавать сигнал - все равно есть задержка, где-то 500 нС. Код sbic PinD,2 sbi PortD,0 sbis PinD,2 cbi PortD,0 И чему вы удивляетесь? Для выполнения любой команды процессору нужно время равное целому числу тактов входной частоты.
|
|
|
|
|
Sep 5 2011, 17:47
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
QUOTE (Mayak @ Sep 5 2011, 10:49)  Подскажите, что не так. Может вообще как-то по другому надо все делать? QUOTE (Mayak @ Sep 5 2011, 10:49)  - по первому прерыванию int0 включаю счетчик ..... и меняю выход с 1 на 0 QUOTE (Mayak @ Sep 5 2011, 10:49)  - по второму прерыванию int0 останавливаю счетчик , меняю выход наоборот и выйдя из прерывания вычисляю полупериод Для этого добавляем MAIN: -------------- вычисляю полупериод rjmp MAIN А задержку на прерывания считаем один раз - а далее считаем ее константой.
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Sep 8 2011, 08:37
|
Группа: Новичок
Сообщений: 4
Регистрация: 5-09-11
Пользователь №: 66 997

|
Спасибо за советы. Переделал программу. Теперь по прерываниям int0 я вычисляю полупериод, записываю его длительность в TC1 и по прерыванию по сравнению меняю выход с 1 на 0 и наоборот. Вроде работает, но есть небольшое дрожание фаз, как с ним бороться? Код ;***************************************************************************
;*************************************************************************** ;15.08.11 .DEVICE ATmega16 .include "m16def.inc" .def temp=r16; .def timeL=r17; .def timeH=r18; .def pause=r19; .def pause1=r20; .def counter=r21; .def tempL=r22; .def tempH=r23
.CSEG .ORG 0 rjmp init; .ORG INT0addr rjmp Ext_INT0 ; (INT0) External Interrupt Request 0 .ORG OC1Baddr rjmp Ext_OC1B
;========================== ; Прерывания ;==========================
Ext_INT0: in timeL,TCNT1L in timeH,TCNT1H inc counter in r16,MCUCR; eor r16,r22 out MCUCR,r16 ldi r16,0b00000000 out TCNT1H,r16 out TCNT1L,r16 ldi r16,0b00000001 out TCCR1B,r16 reti
Ext_OC1B: in r16,PortD eor r16,r22 out PortD,r16 reti ;========================= ; Инициализация ;========================= Init: ldi r31,LOW(RAMEND) out spl,r31 ldi r31,HIGH(RAMEND) out sph,r31
ldi r16,0b11111011; Настройка портов out DDRD,r16; ldi r16,0b00000100; out PortD,r16; ldi r16,0b00000011; out MCUCR,r16; ldi r16,0b01000000; out GICR,r16; ldi counter,1 ldi r16,0b00001000 out TIMSK,r16 ldi r22,0b00000001; sei; reset: ;RESET cpi counter,2 brne reset cli subi timeL,22 ; делаем задержку sbci timeH,0 out OCR1BH,timeH out OCR1BL,timeL dec counter; sei rjmp reset
|
|
|
|
|
Sep 8 2011, 09:03
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Mayak @ Sep 8 2011, 12:37)  есть небольшое дрожание фаз, как с ним бороться?[ "Небольшие" - это сколько? А, сколько хотите получить? Приведенная программа - это только часть будущей большой программы? Наверное, ещё добавится интерфейс управления устройством, добавятся процедуры прерываний? Судя по тому, что для Вас 500нс - большая величина, то, вероятно, Вы для решения задачи выбрали не верные средства...
|
|
|
|
|
Sep 8 2011, 09:55
|
Группа: Новичок
Сообщений: 4
Регистрация: 5-09-11
Пользователь №: 66 997

|
Наверное все-таки не тем путем я пошел. Задача такая! Начальные условия: На вход поступает сигнал от 5кГц до 80 кГц. Необходимо: На выходе получить сигнал такой же частоты, синхронизированный по фронтам. По нажатию кнопки нужно будет сдвигать этот сигнал с определенным шагом на длину импульса. По нажатию другой кнопки нужно будет регулировать длину импульса (ШИМ).
|
|
|
|
|
Sep 8 2011, 10:45
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Конкретных цифр по желаемой точности Вы так и не привели... Цитата(Mayak @ Sep 8 2011, 13:55)  На вход поступает сигнал от 5кГц до 80 кГц. 80 кГц - для программного формирования частоты на AVR - довольно "круто". Посчитайте сами: при тактировании 16МГц - на период следования импульса у Вас есть не более 200 команд МК... Цитата(Mayak @ Sep 8 2011, 13:55)  На выходе получить сигнал такой же частоты, синхронизированный по фронтам. По нажатию кнопки нужно будет сдвигать этот сигнал с определенным шагом на длину импульса. По нажатию другой кнопки нужно будет регулировать длину импульса (ШИМ). Опять же - нет конкретных цифр... Но, при "плавающей" в таком широком диапазоне частоте входных синхроимпульсов невозможно обеспечить задержку между входным и выходным импульсами менее некой величины, если это - нужно. МК не может "предсказывать" приход синхроимпульса, чтобы начать выполнение некой подпрограммы заранее. Да, и ширину импульса на высоких частотах синхроимпульсов вряд ли удастся изменять с шагом менее нескольких процентов...
|
|
|
|
|
Sep 8 2011, 22:26
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
QUOTE (Палыч @ Sep 8 2011, 14:45)  Конкретных цифр по желаемой точности Вы так и не привели...
80 кГц - для программного формирования частоты на AVR - довольно "круто". Посчитайте сами: при тактировании 16МГц - на период следования импульса у Вас есть не более 200 команд МК... так и ну его нафинг , считать программно, загнать его обратно в счётчик (16 бит) и пусть себе считает по ICP период или длительность, а во второй то что насчитал, а в память сохранять. Ну, что-то типа того,приблизительно
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|