Помогите с ШИМ на 100КГц

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Пн окт 05, 2009 11:12:16

Сообщение Serge_6989 »

Доброго времени суток! Стоит задача задавать управляющее напряжение для ГУН'а посредством ШИМ и интегрирующей RC-цепочки. В железе все давно собрано, сейчас дошел до программной реализации ШИМ и столкнулся с проблемой. Чтобы после RC-цепочки (10КОм, 10мкФ) не было пульсаций требуется частота выше 100КГц (если верить Proteus то идеално под 200КГц), а это у меня не получается. Аппаратно можно сделать только ~37КГц. Пробывал реализовать программно с большей частотой, но не получилось.
Может кто знает как можно решить эту проблему?
Заранее благодарен.
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 85
Зарегистрирован: Ср май 05, 2010 16:39:11

Сообщение mattheus »

Serge_6989 писал(а):Пробывал реализовать программно с большей частотой, но не получилось.
А можно подробнее, что не получалось. На таких частотах (100-200 кГц) вполне можно сделать программный ШИМ, вопрос только в его "разрешении" (т.е. дискретизации).

Код: Выделить всё

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{ // Reinitialize Timer 0 value
  TCNT0=0xb0; // 1 MHz
  // Place your code here
  static int c;
  c++; c&=0x07;
  PORTB.0=(c&0x04>>2);
}
(Код не проверялся - но должно работать). Таймер настроен на 1МГц (как вариант - без делителя от встроенных 8МГц). Счетчик c может меняться от 0 до 7 (потому что c=c&0x07). ШИМ с частотой 125 кГц (1Мгц/8) и дискретизацией 8 отсчетов на период. В примере скважность - 50% (потому что проверяется старший из 3-х значащих бит).
Конструкцию внутри функции void timer0_ovf_isr(void) стоит оптимизировать (всетаки этот код будет выполняться миллион раз в секунду), но на вид там меньше 8 тактов, так что работать должно. Нужно еще отключить сохранение переменных в стеке при вызове прерывания (для экономии времени). Тогда должно работать.

Подумал... А зачем вам прерывания? Если прерывания не нужны - то просто в главном цикле изменяем счетчик и "дергаем ножкой". В каждом цикле делаем задержку нужно длины (например, чтобы при дискретизации 8 один цикл занимал все те же 8 тактов при частоте кварца 8 МГц). Только для "точной" частоты нужно будет четко число команд за цикл посчитать (на задержку) (или ассемблере написать как вариант), а если "точная" частота не нужна - то и того проще...
Контактная информация:
Реклама
Потрогал лапой паяльник
Сообщения: 310
Зарегистрирован: Пт дек 17, 2010 14:41:25

Сообщение phenomen »

http://easyelectronics.ru/avr-uchebnyj- ... -shim.html
Почитайте про ШИМ
Вот: калькулятор для АВРок поможет с инициализацией таймеров.
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Пн окт 05, 2009 11:12:16

Сообщение Serge_6989 »

phenomen писал(а):http://easyelectronics.ru/avr-uchebnyj- ... -shim.html
Почитайте про ШИМ
Вот: калькулятор для АВРок поможет с инициализацией таймеров.
Я это читал, там ведь разбирается аппаратный ШИМ. Однако перечитав нашел интересную идею, которую завтра попробую.
mattheus писал(а):..., вопрос только в его "разрешении" (т.е. дискретизации).
В этом то и проблема. Мне нужно 8-битный ШИМ (256 отчетов на период).
Нужно еще отключить сохранение переменных в стеке при вызове прерывания (для экономии времени).
Если можно это место подробней. В CodeVision AVR я не нашел такой опции. Можно только задать размер стека.
Реклама
Эиком - электронные компоненты и радиодетали
Вымогатель припоя
Аватара пользователя
Сообщения: 672
Зарегистрирован: Вт окт 27, 2009 22:39:19
Откуда: Москва

Сообщение md5sum »

Serge_6989 писал(а):Мне нужно 8-битный ШИМ (256 отчетов на период).
256 * 100 кГц = 25,6 МГц.
Вам подойдет аппаратный ШИМ на high speed таймере - например tiny26 умеет такое с некоторыми ограничениями/оговорками.

ЗЫ: еще на вскидку: tiny45
— Не говорите мне что делать и я не скажу куда Вам идти...
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 85
Зарегистрирован: Ср май 05, 2010 16:39:11

Сообщение mattheus »

Serge_6989 писал(а):
Нужно еще отключить сохранение переменных в стеке при вызове прерывания (для экономии времени).
Если можно это место подробней. В CodeVision AVR я не нашел такой опции. Можно только задать размер стека.
Используется #pragma savereg-. Во встроенном Help CodeVisionAVR найдите раздел "The Preprocessor" и скрольтесь до #pragma.

Код: Выделить всё

The automatic saving and restoring of registers affected by the interrupt handler, can be turned on or off using the #pragma savereg directive.

Example:

/* Turn registers saving off */
#pragma savereg-

/* interrupt handler */
interrupt [1] void my_irq(void) {
/* now save only the registers that are
   affected by the routines in the interrupt
   handler, for example R30, R31 and SREG */
#asm
    push r30
    push r31
    in   r30,SREG
    push r30
#endasm

/* place the C code here */

/* now restore SREG, R31 and R30 */
#asm
    pop r30
    out SREG,r30
    pop r31
    pop r30
#endasm
}
/* re-enable register saving for the other interrupts */

#pragma savereg+

The default state is automatic saving of registers during interrupts.
The #pragma savereg directive is maintained only for compatibility with versions of the compiler prior to V1.24.1. This directive is not recommended for new projects.
Контактная информация:
Реклама
Поставщик валерьянки для Кота
Сообщения: 1957
Зарегистрирован: Пт окт 31, 2008 09:38:55
Откуда: Одесса

Сообщение clawham »

не понятно две вещи - какой камень и какова тактовая частота
например мега 8 на 16 мегагерцах и 256 дискретизацией может выдать максимум 16000000/256 = 62500 герц....

но если уменьшить битность до 7 то уже можно 125 килогерц....

нужно 100 вилогерц - 160 вариаций....

запускаете таймер в фаст PWM top on ICP = 160

Код: Выделить всё


// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: Fast PWM top=ICR1
// OC1A output: Non-Inv.
// OC1B output: Non-Inv.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0xA2;
TCCR1B=0x19;

TCNT1=0x00;

ICR1=160;

OCR1A=0x00;

OCR1B=0x00;

этот код даст Вам 100 000 герц на 160 отсчетов два выхода...задавать скважность значениями OCR1A и OCR1B 0 это ноль 160 это 100%
Что нас не убило сделало нас осторожней
Не доверяйте русским лужам - это может быть вход в метро.
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск

Сообщение Леонид Иванович »

Была похожая проблема: http://leoniv.livejournal.com/87824.html
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1957
Зарегистрирован: Пт окт 31, 2008 09:38:55
Откуда: Одесса

Сообщение clawham »

ндям...тема таки очень похожа... FPGA ... алгоритмы брезенхема...атенюаторы....
ну хотя конечно да....нужно на самом деле не RC цепочка а нормальный LoPass фильтр на операционниках...и тогда частоту можно хоть 1 килогерц...но...я бы лично увеличил резистор до 100 килоом а выход с кандера просто "повторил" бы операционником...
Что нас не убило сделало нас осторожней
Не доверяйте русским лужам - это может быть вход в метро.
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Пн окт 05, 2009 11:12:16

Сообщение Serge_6989 »

Купил ATtiny85. у нее можно тактировать таймер частотой существенно большей чем тактовая частота ядра МК. Буду делать на ней. Жалко я раньше не знал про такую возможность некоторых МК tiny :( .
Поставщик валерьянки для Кота
Сообщения: 1957
Зарегистрирован: Пт окт 31, 2008 09:38:55
Откуда: Одесса

Сообщение clawham »

ну это да....250 килогерц при 256 градациях...

Код: Выделить всё

// Timer/Counter 1 initialization
// Clock source: 64MHz PCK
// Clock value: 64000,000 kHz
// Mode: PWMA & B top=OCR1C
// OC1A output: Non-Inv., /OC1A connected
// OC1B output: Non-Inv., /OC1B connected
// Timer1 Overflow Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
// Enable the PLL
PLLCSR=0x02;
// Wait for the PLL to lock
while ((PLLCSR & 1)==0);
// Enable the 64MHz clock
PLLCSR|=0x04;

TCCR1=0x51;
GTCCR=0x50;
TCNT1=0x00;
OCR1A=0x00;
OCR1B=0x00;
OCR1C=0xFF;
Что нас не убило сделало нас осторожней
Не доверяйте русским лужам - это может быть вход в метро.
Контактная информация:
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»