Генератор с длительностью импульсов 20us с частотой 80Khz

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25327
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение КРАМ »

[uquote="Reflector",url="/forum/viewtopic.php?p=3982580#p3982580"]Если нужно каждые 72 такта обновлять ARR таймера...[/uquote]
А откуда взялись 72 такта? Синтезировать фиксированную частоту - нет никаких проблем. Проблема создать СЕТКУ частот. То есть нужно считать каждое следующее переполнение таймера. А это - деление с нахождением остатка. И совершенно не факт, что времени на это хватит. Зависит от синтезируемой частоты.

Добавлено after 2 minutes 21 second:
[uquote="Dimon456",url="/forum/viewtopic.php?p=3982584#p3982584"]Вообще разгоняется не только таймер но и ЦПУ[/uquote]
Нудануда, разгоняешь-разгоняешь, а на выходе все в почти полсотни раз медленнее... :tea:
Намекаю, в PIC18FxxQ43 частота накачки NCO может быть 64 МГц, то есть от осциллятора МК. Там смешно о джиттере вообще говорить. Не всякий анализатор спектра покажет такой джиттер.
Реклама
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Dimon456 »

Нету там PIC18FxxQ43, есть PIC18F4620 и его серия. Лучше уж AD9833.
КРАМ писал(а):Нудануда, разгоняешь-разгоняешь, а на выходе все в почти полсотни раз медленнее...
Каждому свое.
Реклама
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Reflector »

[uquote="КРАМ",url="/forum/viewtopic.php?p=3982599#p3982599"]А откуда взялись 72 такта?[/uquote]
72 MHz тактовая, таймер генерит меандр частотой 500 KHz.
Синтезировать фиксированную частоту - нет никаких проблем. Проблема создать СЕТКУ частот. То есть нужно считать каждое следующее переполнение таймера. А это - деление с нахождением остатка. И совершенно не факт, что времени на это хватит. Зависит от синтезируемой частоты.
Допустим хочется 9750 Гц меандр, тогда нужно инвертить выход таймера каждые 72M / 9750 / 2 = 3692.3076 такта. 3692 - это базовое значение для ARR, а 0.3076 переводится в число с фиксированной точкой и на каждой итерации суммируется, затем целая часть прибавляется к 3692 . Учитывая, что в цикле рассчитываются сразу сотня значений и все константы из памяти загрузятся в регистры всего один раз, я бы ожидал тактов 10 на итерацию.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Dimon456 »

Чип stm32f030f4p6 разогнан до 72МГц прерывание таймера 1МГц.
При 48МГц - таймер получается 500кГц.
Вот код разгона
Спойлер

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

	// Внешний кварцевый HSE генератор
void Overclocking(void) // Разгон микроконтроллера.
{
	  FLASH->ACR|=  FLASH_ACR_PRFTBE;        //Включить буфер предварительной выборки
	  FLASH->ACR&= ~FLASH_ACR_LATENCY;       //Очистить FLASH_ACR_LATENCY
	  FLASH->ACR |= FLASH_ACR_LATENCY;     //Пропускать 1 такт

	  RCC_HSEConfig(RCC_HSE_ON); // Включаем  HSE генератор.
	  //RCC->CR |= ((uint32_t)RCC_CR_HSEON); // Включаем HSE
	  while(!(RCC->CR & RCC_CR_HSERDY));  //ожидание готовности HSE

  RCC->CFGR2 = RCC_CFGR2_PREDIV1_DIV1;  // предделитель для PLL 
  RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE); // Выбираем источником такторования HSE генератор.
  RCC_PLLCmd(DISABLE); // Выключаем умножитель частоты.
  RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_CFGR_PLLMULL9); // На сколько будем умножать частоту. 8*9 - 72MHz
  RCC_PLLCmd(ENABLE); // Включаем умножитель частоты.
  while ((RCC->CR & RCC_CR_PLLRDY) == 0);     // Ждем запуска умножителя частоты.
  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // Выбираем источником такторования умножитель частоты.



  SystemCoreClockUpdate(); // Вычисление тактовой частоты ядра.
}
Код настройки таймера
Спойлер

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

void timer_init (void) {
	  RCC -> APB1ENR |= RCC_APB1ENR_TIM14EN; //TIM14 Timer clock enable

	  TIM14->CR1;   //Bit 0 CEN: Counter enable

	  TIM14->PSC = 0;//
	  TIM14->ARR = 71;	// 1MHz
	  NVIC_EnableIRQ (TIM14_IRQn); //разрешить прерывания от таймера

	  TIM14->DIER |= TIM_DIER_UIE; //Bit 0 UIE: Update interrupt enable
	  TIM14->CR1 |= TIM_CR1_CEN;   //Bit 0 CEN: Counter enable
}
Reflector, все верно?
Код прерывания
Спойлер

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

volatile uint16_t n_counter = 62967; // 480404Hz

void TIM14_IRQHandler(void) {
	static uint32_t gen_counter = 0;
	TIM14->SR &= ~TIM_SR_UIF;//очистить флаг прерывания
	gen_counter += n_counter;
		if (gen_counter > 65535) {
			gen_counter -= 65536;
			GPIOB->ODR ^= GPIO_Pin_1;
		}
}
Ну, что я могу сказать, на осциллографе видно, DM90A показывает процент заполнения 51,6% - не чистый меандр.
Одним словом 1МГц мало. Фотки надо? Могу выложить, но только завтра.
Реклама
Эиком - электронные компоненты и радиодетали
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Reflector »

Таймер должен работать в режиме Toggle и сам при переполнении дергать пином, а в прерывании, раз уж ты с ним пока сделал, нужно периодически корректировать значение ARR причем опять же в момент переполнения, для чего нужно включить для ARR буферизацию.
72M / 480404 / 2 = 74.9369, суммируя дробную часть и периодически прибавляя единичку у тебя должно получаться 74 или 75, т.е. период таймера будет постоянно слегка меняться. Примерно 15-16 полупериодов частота будет 486486 Hz, потом один полупериод - 480000 Hz, в среднем это должно давать твои 480404. Если нацело не делится, то джиттер будет в любом случае, но чем больше частота таймера, тем он меньше, а больше она точно не на пиках :) Можно, конечно, еще взять STM32 с HRTIM, есть у некоторых F3/G4, он ведет себя так будто работает на частоте 5.44 GHz :)
Реклама
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Dimon456 »

Reflector писал(а):Таймер должен работать в режиме Toggle и сам при переполнении дергать пином
Вот если бы таймер смог работать в режиме сумматора, а не в режиме счетчика, и при переполнении дергать пином - вот тогда да.
Reflector писал(а):72M / 480404 / 2 = 74.9369, суммируя дробную часть и периодически прибавляя единичку у тебя должно получаться 74 или 75
Вот только в какой момент времени эту единичку прибавлять я так и не смог рассчитать, на разных частотах по разному.
Я пытался на Атмега168 на двух таймерах в режиме Toggle, с одного на другой подавал, весь ексель в табличках изрисовал, но делитель он и есть делитель. Не получите вы частоты с шагом, допустим 10Гц.

В данном примере у меня получается шаг 7,629394531Гц, 2^16, 2 часа ночи было, думаю без ущерба коду можно 2^24 получить, я не пробовал. Можно путем изменения частоты таймера подогнать что бы ровно было на 2^16 7Гц.
Жалко DAC нет, придется пошимить малость, синусоиду получить охота, таблицу на килобайт в оперативке, и опустить частоту таймера, что бы ровно шаг 5Гц был, чисто ради эксперимента.
Reflector писал(а):то джиттер будет в любом случае, но чем больше частота таймера, тем он меньше,
Джиттер наблюдается на любом частотном участке, вот это число 62967 (480404Гц) не делится нацело, на некоторых частотах джиттер половину импульса занимает, я весь диапазон не исследовал, так по диагонали прошелся.
Реклама
Аватара пользователя
oleg110592
Друг Кота
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение oleg110592 »

До кучи, в тему, сразу 3 DDS Чена на STM32F303K8
http://elm-chan.org/junk/mdds_ipol/report.html
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Reflector »

[uquote="Dimon456",url="/forum/viewtopic.php?p=3982885#p3982885"][Вот если бы таймер смог работать в режиме сумматора, а не в режиме счетчика, и при переполнении дергать пином - вот тогда да.[/uquote]
Это полезно только для меандра, для табличной синусоиды все равно придется или DMA использовать, тогда суммировать и самому можно, или медленные прерывания.
Вот только в какой момент времени эту единичку прибавлять я так и не смог рассчитать, на разных частотах по разному.
Что там рассчитывать? В качестве начального значения дробной части можно 0.5 взять, первый раз добавляешь 0.9369, получаешь 1.4369, значит единичку добавляем, остается 0.4369. В следующий раз будет 0.4369 + 0.9369 = 1.3738, снова добавляем...
Джиттер наблюдается на любом частотном участке, вот это число 62967 (480404Гц) не делится нацело, на некоторых частотах джиттер половину импульса занимает, я весь диапазон не исследовал, так по диагонали прошелся.
Чтобы получить 500KHz нужно 72MHz / 72, а если хочется чуть меньше, то можно разве что 72МHz / 73, но это уже сразу 493'150 Hz. NCO тут не поможет, даже с таймером на 5.44 GHz будет шаг 100 Hz... А если генерить синусоиду, то для любого дробного значения можно получить достаточно точное значение синуса именно в данной точке, там все упирается в величину таблиц или разрядность DAC/ШИМа.
Sergi
Мучитель микросхем
Сообщения: 412
Зарегистрирован: Ср янв 04, 2012 11:57:40
Откуда: Алчевск

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Sergi »

Вот например без прерываний и оптимизации на STM32F030

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

while(1)		
		{
			while(~(TIM1->SR & TIM_SR_UIF)) {};
			TIM1->SR &=~ TIM_SR_UIF; 
			a = a + df;
			TIM14->CCMR1 = tab[a>>21];
		};
компилится вот в такое

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

    52:                         while(~(TIM1->SR & TIM_SR_UIF)) {}; 
0x080003E8 BF00      NOP      
0x080003EA 4810      LDR      r0,[pc,#64]  ; @0x0800042C
0x080003EC 6900      LDR      r0,[r0,#0x10]
0x080003EE 07C0      LSLS     r0,r0,#31
0x080003F0 0FC0      LSRS     r0,r0,#31
0x080003F2 43C0      MVNS     r0,r0
0x080003F4 2800      CMP      r0,#0x00
0x080003F6 D1F8      BNE      0x080003EA
    53:                         TIM1->SR &=~ TIM_SR_UIF;  
0x080003F8 480C      LDR      r0,[pc,#48]  ; @0x0800042C
0x080003FA 6900      LDR      r0,[r0,#0x10]
0x080003FC 0840      LSRS     r0,r0,#1
0x080003FE 0040      LSLS     r0,r0,#1
0x08000400 490A      LDR      r1,[pc,#40]  ; @0x0800042C
0x08000402 6108      STR      r0,[r1,#0x10]
    54:                         a = a + df; 
0x08000404 480A      LDR      r0,[pc,#40]  ; @0x08000430
0x08000406 6800      LDR      r0,[r0,#0x00]
0x08000408 490A      LDR      r1,[pc,#40]  ; @0x08000434
0x0800040A 6809      LDR      r1,[r1,#0x00]
0x0800040C 1840      ADDS     r0,r0,r1
0x0800040E 4908      LDR      r1,[pc,#32]  ; @0x08000430
0x08000410 6008      STR      r0,[r1,#0x00]
    55:                         TIM14->CCMR1 = tab[a>>21]; 
0x08000412 4608      MOV      r0,r1
0x08000414 6800      LDR      r0,[r0,#0x00]
0x08000416 0D00      LSRS     r0,r0,#21
0x08000418 0040      LSLS     r0,r0,#1
0x0800041A 4907      LDR      r1,[pc,#28]  ; @0x08000438
0x0800041C 5A08      LDRH     r0,[r1,r0]
0x0800041E 4907      LDR      r1,[pc,#28]  ; @0x0800043C
0x08000420 6188      STR      r0,[r1,#0x18]
    50:                 while(1)                 
0x08000422 E7E1      B        0x080003E8
TIM14 выход ШИМ - типа ЦАП. TIM1 - таймер синхронизации выборок. tab - таблица сигнала, df - приращение фазы
В железе не проверил,оптимизацию не включал,всего 30 АСМ команд. Задавая частоту работы TIM1 можно определить максимальную скорость загрузки.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Dimon456 »

С чего же начать, начнем с Чена.
oleg110592, я сравнивал звучание wav файла с ШИМ и DAC на слух разница ощутима.
У меня есть F100 с DAC, но гонится всего до 56МГц.
Как бы мы не старались, как бы мы не хотели, с DMA без DMA, мы даже близко не приблизимся к накачке сумматора хотя бы 16МГц, увы программно есть программно, а аппаратный модуль есть аппаратный модуль.
КРАМ писал(а):Намекаю, в PIC18FxxQ43 частота накачки NCO может быть 64 МГц, то есть от осциллятора МК. Там смешно о джиттере вообще говорить. Не всякий анализатор спектра покажет такой джиттер.
Sergi, оставим цикл while пользователю, иначе тут метод "конечных автоматов" придется реализовывать.
Reflector писал(а):Чтобы получить 500KHz нужно 72MHz / 72, а если хочется чуть меньше, то можно разве что 72МHz / 73, но это уже сразу 493'150 Hz. NCO тут не поможет, даже с таймером на 5.44 GHz будет шаг 100 Hz
Я бы так не согласился, вот табличка: зависимость разрядности сумматора от частоты накачки таймера
СпойлерИзображение
Это единица, шаг сумматора. Смотрите формулу NCO модуля PIC.
В таблице представлены значения поделенные на 2, как для выходной частоты "меандр" моего примера на stm32f030
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Reflector »

[uquote="Dimon456",url="/forum/viewtopic.php?p=3983113#p3983113"]Я бы так не согласился, вот табличка[/uquote]
Еще раз... На входе 16MHz, нужно получить при помощи NCO 500KHz, следовательно сумматор должен переполняться каждый 16 тактов и получим 16M / 16 = 1MHz. А чтобы получить переполнение сумматора каждые 16 тактов нужно прибавлять 65536: 16М / (2**20 / 65536) = 1MHz. Теперь если поменять 65536 на 65537, то получим 1000015.26 Hz, т.е. шаг в 15 Hz о котором пишет сам Microchip. Но это все в среднем, невозможно 16М поделить на (2**20 / 65537) = 15.9998, делить все равно придется на 16 или 15, потому с NCO будет ровно то же самое, что и без него: 16М / int(2**20 / 65537) = 1066666.7 Hz. Джитер будет одинаковый, а стабильность частоты на большом интервале будет выше на STM32, потому что там я могу для дробной части выделить 32 бита и увеличить точность на 3 порядка.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Dimon456 »

Ошибка будет всегда, но она напрямую зависит от тика таймера (тик сумматора).
В проекте на Атмега168 тактовая 16Мгц сумматор качается 200кГц (я прерывание на asm переписал) на частоте 9512 ошибка составляла то 50мкс то 56мкс, один тик таймера 6,25мкс, я же писал про это. Я считаю чем этот тик меньше тем и ошибка будет меньше.

Кому интересно, картинки для сравнения
Спойлерstm32f030 72МГц 1МГц
Изображение
Частота 350кГц
Изображение
Частота 225,125кГц
Изображение
Частота 250кГц
Изображение
Частота 125кГц
Изображение
Частота 51,410кГц
Изображение
Частота 3,404кГц
Изображение
Частота 210Гц
Изображение

Сравнивайте хоть на Атмеге хоть на реальном NCO модуле, хоть на AD9833
Sergi
Мучитель микросхем
Сообщения: 412
Зарегистрирован: Ср янв 04, 2012 11:57:40
Откуда: Алчевск

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Sergi »

Превел как пример. Максимальная частота выборки из таблицы на STM вряд ли сильно превысит 2 МГц при тактовой 64-72. И это без обработки кнопок и проч. На AVR с работой в прерывании была частота выборки 500 кГц при тактовой 19,5 , но и таблица покороче.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Dimon456 »

И так, синус.
Код ШИМ
Спойлер

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

void chim_init (void)
{
	// Тактирование  GPIOB , TIM3, альтернативных функций порта
    RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; //TIM3 Timer clock enable
    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;

    //--------- Настройка выводов для ШИМ ----------------------
    //    PB1  --> TIM3_CH4

    // Initialize GPIO pin
    // настройка вывода на режим альтернативной функции с активным выходом
    GPIOB->MODER &= ~GPIO_MODER_MODER1;
    GPIOB->MODER |= GPIO_MODER_MODER1_1;	
    GPIOB->OTYPER &= ~GPIO_OTYPER_OT_1;         
    GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR1;		
    GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR1;

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_1); // PB1 это выход таймера TIM 3.

			//делитель
			TIM3->PSC = 0;
			//значение перезагрузки
			TIM3->ARR = 256;
			//коэф. заполнения
			TIM3->CCR4 = 127;
			//настроим на выход канал 4, активный уровень низкий
			TIM3->CCER |= TIM_CCER_CC4E;
			//разрешим использовать выводы таймера как выходы
			TIM3->BDTR |= TIM_BDTR_MOE;
			//PWM mode 1, прямой ШИМ 4 канал
			TIM3->CCMR2 |= TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1;
			//считаем вверх
			TIM3->CR1 &= ~TIM_CR1_DIR;
			//выравнивание по фронту, Fast PWM
			TIM3->CR1 &= ~TIM_CR1_CMS;
			//включаем счётчик
			TIM3->CR1 |= TIM_CR1_CEN;

}
От 72МГц ШИМ получился 281.2kHz разрешение 8бит
Код таймера
Спойлер

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

void TIM14_IRQHandler(void) {
	static uint32_t gen_counter = 0;
	TIM14->SR &= ~TIM_SR_UIF;//очистить флаг прерывания
	gen_counter += n_counter;
		// 2^24
		if (gen_counter > (0x1000000-1)) {
			gen_counter -= 0x1000000;
		}
	TIM3->CCR4 = (uint8_t)WfmSin[(gen_counter>>16)];	// 16 бит на 256 таблицу
	//TIM3->CCR4 = (uint8_t)WfmSin[(gen_counter>>14)];		// 14 бит на 1024 таблицу
}
Таблицу синуса не привожу, картинок то же не будет.
Вменяемый синус получается где-то до 25кГц, замена таблицы на 1024 отсчетов результата не дала, те же до 25кГц.
Может разрешение 8 бит ШИМ мало.
Sergi писал(а): Максимальная частота выборки из таблицы на STM вряд ли сильно превысит 2 МГц при тактовой 64-72.
Для синуса в этом точно нет смысла.

Reflector, а для генерации меандра пошел бы вот такой вариант
Спойлер

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

void TIM14_IRQHandler(void) {	//1MGz
	static uint32_t gen_counter = 0;
	TIM14->SR &= ~TIM_SR_UIF;//очистить флаг прерывания
	gen_counter += n_counter;
		if (gen_counter > (500000-1)) {
			gen_counter -= 500000;
			GPIOB->ODR ^= GPIO_Pin_1;
		}
}
Шаг 1Гц.
Вывод из всего этого: AD9833 и подобные.
Sergi
Мучитель микросхем
Сообщения: 412
Зарегистрирован: Ср янв 04, 2012 11:57:40
Откуда: Алчевск

Re: Генератор с длительностью импульсов 20us с частотой 80Kh

Сообщение Sergi »

Все верно, выше писал что приемлемая форма - до 1/8 таблицы, 256/8=32 кГц. И это с фильтром второго порядка. А 260р за модуль 9833 - копейки.
Ответить

Вернуться в «AVR»