Jump to content
n_angelo

STM8L. Пустой бесконечный цикл тормозит тайминг.

Recommended Posts

Привет, знатоки. Написал свою первую программу для контроллера STM8L152C6T6 (STM8L-Discovery). Это, собственно, моя первая программа для контроллеров вообще. Я многого не знаю и не понимаю. Возможно ваш ответ на мой вопрос будет банален.

Используемая периферия: DAC, DMA, TIM4, CLK, GPIO

Задача у программы такая:

В EEPROM зашит один период синусоиды с дискретизацией 44100Гц. Период занимает ровно 101 байт, что по сути должно быть равно 2,29мс (1/44100*101). В коде программы только конфигурация периферии, одно прерывание на кнопке и пустой бесконечный цикл, который ничего не делает. Всю работу выполняет таймер, который настроен выдавать запрос к DMA на каждые 1/44100 (ядро тактируется 2мГц, таймер считает до 45). В свою очередь DMA забирает из EEPROM по одному байту на каждый запрос от таймера и передаёт его в DAC. Далее DAC выводит бесконечную синусоиду на ногу PF0. Прерывание на кнопке запускает весь этот механизм и зажигает светодиод.

Проблема:

Измеряя ногу PF0 осциллографом было замечено, что период синусоиды занимает около ≈4мс. Фото под катом.

Скрытый текст

DSC_0008.JPG.d3bf50618d847e1e21b7cf30ee1b20d8.JPG

Меня это расстроило. Экспериментально выяснилось, что стоит только вписать в бесконечный цикл какую-нибудь проверку, например, [если значение текущего байта синусоиды = 0xFF, то зажечь светодиод, если 0x00, то потушить], то осциллограф показывает правильный тайминг в 2(с копейками)мс. В принципе в теле цикла может быть что угодно, кроме пустоты, и тайминг налаживается.

Я не могу отдебажить дизассемблер, т.к. его не знаю. Это у меня в планах. Но я очень хочу понять, что происходит и почему пустой цикл рушит тайминг.

Спасибо.

 

 

 

 

Edited by n_angelo

Share this post


Link to post
Share on other sites
21.09.2019 в 20:10, n_angelo сказал:

что происходит и почему пустой цикл рушит тайминг

вот если ты нам расскажешь, будет очень интересно. Я бы померил, например, сколько времени занимает от входа в прерыванием до установки значения в ДАКе.


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites
5 часов назад, ruhi сказал:

вот если ты нам расскажешь, будет очень интересно. Я бы померил, например, сколько времени занимает от входа в прерыванием до установки значения в ДАКе.

К сожалению, мой осциллограф одноканальный и показывает только то, что произошло от момента триггера. А график в дебаггере показывает, что один семпл (1/44100) выводится раз в 5 секунд.

Других способов измерить я пока не придумал.

99426537_2019-09-2319_46_02.png.fe57fbaaef3751de8f53225210fa437c.png

Share this post


Link to post
Share on other sites

Вебинар «Решения Analog Devices для гальванической изоляции. Обзор технологий и новинок» (27.04.2021)

Компания «Компэл» и Analog Devices приглашают всех желающих 27/04/2021 принять участие в вебинаре, посвященном решениям Analog Devices для гальванической изоляции. В программе вебинара: технологии гальванической изоляции iCoupler, цифровые изоляторы, изолированное питание и технология isoPower, гальванически изолированные интерфейсы (RS-485, CAN, USB, I2C, LVDS) и другое.

Подробнее

19 часов назад, n_angelo сказал:

то, что произошло от момента триггера.

В коде в начале функции прерывания надо поставить инструкцию переключения уровня на любую доступную ногу процессора, перед инструкцией записи в ДАК тоже поставить переключение ноги (той же или другой - как тебе удобней) и посмотри осциллографом сигнал на этой ноге (ногах). Это вряд ли даст объяснение проблеме, но возможно наведет тебя на мысли в какую стороны копать, что еще посмотреть!


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites

Пружинные клеммники Degson - высокое качество соединения по оптимальной цене!

Пружинные клеммные блоки Degson для монтажа на печатную плату – это простое и надежное соединение, которое позволяет легко решать задачи для различных приложений за счет обширного ассортимента. Клеммники Degson доступны в двух конструктивных исполнениях (торцевой контакт и зажимная клеть), имеют различные направления ввода проводника (45°, 90°, 180°) и обладают широким диапазоном поперечных сечений (0,2…2,5 мм2).

Подробнее

32 minutes ago, ruhi said:

в начале функции прерывания

Там нет никакого прерывания, вся работа по переносу байтов происходит по DMA в фоновом режиме без участия программы. То есть процессор непрерывно крутит пустой цикл, а таймер сам по себе тикает и с каждым тиком заставляет DMA читать память и записывать в ЦАП.

On 9/21/2019 at 6:10 PM, n_angelo said:

почему пустой цикл рушит тайминг.

Без Вашего кода в студии трудно что-либо сказать.

Share this post


Link to post
Share on other sites

Новое семейство ИП от MEAN WELL мощностью 150, 300, 600 Вт с повышенной перегрузочной способностью

Компания MEAN WELL разработала семейство источников питания номинальной мощностью 150, 300 и 600 Вт с возможностью кратковременной безопасной работы при мощности в 2,5 раза выше номинальной (до 5 секунд). Данное семейство источников питания востребовано в промышленных установках с использованием электродвигателей или с емкостной нагрузкой. Применяя новые источники питания HRP/N можно получить экономический выигрыш.

Подробнее

3 часа назад, ruhi сказал:

В коде в начале функции прерывания надо поставить инструкцию переключения уровня на любую доступную ногу процессора, перед инструкцией записи в ДАК тоже поставить переключение ноги (той же или другой - как тебе удобней) и посмотри осциллографом сигнал на этой ноге (ногах). Это вряд ли даст объяснение проблеме, но возможно наведет тебя на мысли в какую стороны копать, что еще посмотреть!

Намёк понял. Буду думать.

Share this post


Link to post
Share on other sites
3 часа назад, Yurkin2015 сказал:

Там нет никакого прерывания, вся работа по переносу байтов происходит по DMA в фоновом режиме без участия программы. То есть процессор непрерывно крутит пустой цикл, а таймер сам по себе тикает и с каждым тиком заставляет DMA читать память и записывать в ЦАП.

Без Вашего кода в студии трудно что-либо сказать.

Наверное он имел ввиду самое первое прерывание, которое включает таймер.

Прилагаю код. Осциллограф выдаёт полный период за ≈4мс, хотя должен за ≈2,29мс.

main.c

Скрытый текст

#include "main.h"

#pragma vector=EXTI1_vector 
__interrupt void btnInterrupt(void) 
{
  PE_ODR |= (1<<LED); // led on
  TIM4_CR1 |= TIM4_CR1_CEN;
  EXTI_SR1 |= (0x02); //reset flag on handler exit
}

int main( void )
{
  // LED init
  PE_DDR |= (1<<LED);
  PE_CR1 |= (1<<LED);
  
  // BUTTON init
  PC_DDR &= ~(1<<BUTTON);
  PC_CR1 |= (1<<BUTTON);
  PC_CR2 |= (1<<BUTTON);
  
  // CLK init
  CLK_PCKENR1 |= CLK_TIM4;
  CLK_PCKENR1 |= CLK_DAC;
  CLK_PCKENR2 |= CLK_DMA1;
  
  // TIM4 init
  TIM4_ARR = TIM4_ARR_44100HZ;
  TIM4_DER |= TIM4_DER_EN;
  
  // DMA init
  DMA1_GCSR |= DMA1_GCSR_GEN;
  DMA1_C3CR |= DMA1_C3CR_MINCDEC;
  DMA1_C3CR |= DMA1_C3CR_CIRC;
  DMA1_C3CR |= DMA1_C3CR_DIR;
  DMA1_C3CR |= DMA1_C3CR_TCIE;
  DMA1_C3NDTR = 101;
  DMA1_C3M0ARH = 0x10; //0x1000 (10 - HBS)
  DMA1_C3M0ARL = 0x00; //0x1000 (00 - LBS)
  DMA1_C3PARH_C3M1ARH = 0x53; //0x5390 (53 - HBS)
  DMA1_C3PARH_C3M1ARL = 0x90; //0x5390 (90 - LBS)
  DMA1_C3CR |= DMA1_C3CR_EN;
  
  // DAC init
  DAC_CH1CR1 |= DAC_CH1CR1_EN;
  
  // interrupt init
  EXTI_CR1 |= (1<<BUTTON);
  asm("RIM");
  
  while(1)
  { 
  }
  
}

 

 

main.h

Скрытый текст

#define PC_IDR          *(unsigned char*)0x00500B
#define PC_DDR          *(unsigned char*)0x00500C
#define PC_CR1          *(unsigned char*)0x00500D
#define PC_CR2          *(unsigned char*)0x00500E
#define PE_ODR          *(unsigned char*)0x005014
#define PE_DDR          *(unsigned char*)0x005016
#define PE_CR1          *(unsigned char*)0x005017

#define CLK_PCKENR1     *(unsigned char*)0x0050C3
#define CLK_PCKENR2     *(unsigned char*)0x0050C4
#define CLK_TIM4        0x4
#define CLK_DAC         0x80
#define CLK_DMA1        0x10

#define TIM4_CR1        *(unsigned char*)0x0052E0
#define TIM4_ARR        *(unsigned char*)0x0052E9
#define TIM4_DER        *(unsigned char*)0x0052E3
#define TIM4_CR1_CEN    0x1
#define TIM4_ARR_44100HZ        0x2D
#define TIM4_DER_EN     0x1

#define DMA1_GCSR       *(unsigned char*)0x005070
#define DMA1_C3CR       *(unsigned char*)0x005093
#define DMA1_C3SPR      *(unsigned char*)0x005094
#define DMA1_C3NDTR     *(unsigned char*)0x005095
#define DMA1_C3M0ARH    *(unsigned char*)0x005099
#define DMA1_C3M0ARL    *(unsigned char*)0x00509A
#define DMA1_C3PARH_C3M1ARH    *(unsigned char*)0x005096
#define DMA1_C3PARH_C3M1ARL    *(unsigned char*)0x005097
#define DMA1_C3CR_MINCDEC       0x20    
#define DMA1_C3CR_CIRC          0x10
#define DMA1_C3CR_DIR           0x08
#define DMA1_C3CR_TCIE          0x02
#define DMA1_C3CR_EN            0x01
#define DMA1_GCSR_GEN           0x01

#define DAC_CH1CR1     *(unsigned char*)0x005380
#define DAC_DHR8       *(unsigned char*)0x005390 
#define DAC_CH1CR1_EN   0x01

#define EXTI_CR1        *(unsigned char*)0x0050A0
#define EXTI_SR1        *(unsigned char*)0x0050A3
#define EXTI1_vector    11

#define P0 0
#define P1 1
#define P2 2
#define P3 3
#define P4 4
#define P5 5
#define P6 6
#define P7 7
#define LED P7
#define BUTTON P1

 

Edited by n_angelo

Share this post


Link to post
Share on other sites
On 9/21/2019 at 6:10 PM, n_angelo said:

почему пустой цикл рушит тайминг.

Думается, дело в том, что DMA и ядро процессора используют одну и ту же системную шину для доступа к памяти и периферии. Когда имеем пустой цикл, то ядро ни хрена не делает, а только непрерывно занимает шину для бесконечных прыжков по памяти программ по кругу. Если заставить ядро что-нибудь делать внутри себя со своими регистрами, типа прибавлять единичку к регистру, то шина будет освобождаться на время, и в этот момент DMA будет пропихивать свои байты по свободной шине.

Ну, или установить приоритет DMA над ядром, чтобы шина освобождалась по первому же требованию DMA.

Я так думаю.

Share this post


Link to post
Share on other sites
20 минут назад, n_angelo сказал:

Наверное он имел ввиду самое первое прерывание, которое включает таймер.

Нет, я это действительно упустил, но значит надо включить прерывания таймера и поверить его период этим методом.


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites
18 минут назад, Yurkin2015 сказал:

Думается, дело в том, что DMA и ядро процессора используют одну и ту же системную шину для доступа к памяти и периферии. Когда имеем пустой цикл, то ядро ни хрена не делает, а только непрерывно занимает шину для бесконечных прыжков по памяти программ по кругу. Если заставить ядро что-нибудь делать внутри себя со своими регистрами, типа прибавлять единичку к регистру, то шина будет освобождаться на время, и в этот момент DMA будет пропихивать свои байты по свободной шине.

Ну, или установить приоритет DMA над ядром, чтобы шина освобождалась по первому же требованию DMA.

Я так думаю.

Моя благодарность! Помогло. Установил приоритет над ядром. Теперь тайминг правильный. Насколько приоритет над ядром может замедлить саму программу? Я так понимаю здесь нужно самому выбирать, либо работа в реалтайм связки (TIM->DMA->DAC) и пустить в жертву работу программы, либо никакого реалтайма в этой связке, но зато код будет работать без задержек? Насколько RTOS помогает с этим справиться?

Share this post


Link to post
Share on other sites
On 9/21/2019 at 6:10 PM, n_angelo said:

таймер считает до 45

 

3 minutes ago, n_angelo said:

может замедлить саму программу?

Ну, вот, пока таймер считает, DMA шину не трогает. То есть 1 раз из 45 тактов ядро будет подторможено, замедление составит в худшем случае 1/45, около 2%.

Share this post


Link to post
Share on other sites
1 минуту назад, Yurkin2015 сказал:

1 раз из 45 тактов ядро будет подторможено

Да, логично) Еще раз спасибо.

Share this post


Link to post
Share on other sites
23 минуты назад, n_angelo сказал:

Помогло. Установил приоритет над ядром.

Интересно! Оно же должно задерживать вывод КАЖДОГО значения в ДАК , почему же период целого синуса (правильно понимаю?) то меняется. У меня первая мысль была про это, но оно вроде на интегральный период синуса не должно влиять, джитер в периоде вывода самплов должен наблюдаться, - интересно! Хотя другого объяснения и нет!


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites

спасибо, интересное замечание. надо бы конечно собранный код посмотреть, что сгенерировал компилятор на пустой цикл... если он не пустой - работает нормально, а если пустой, то такая задержка на "аппаратные", не программные передачи данных между модулями микроконтроллера (в данном случае память->DAC)

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Сообщения

    • От этой схемы можно будет запитать два фонаря параллельно с выхода? 
    • А может вниматочно посмотришь даташит?) 
    • Уж я - то слушал. Это точно. Это ты где-то что-то пропустил, или я где-то что-то не понял?
    • Берите схему от автора, которая от руки, ПП от ДеДа, где 6 В цепь на LP, убираете индикатро разряда акб и канал АЛЛ МЕТ, потенциометры БГ и СЕНС ставите на ПП, получиться большая, но для первого раза "то что надо", динамик тоже не нужен, ствите "джек" для наушников на ПП, короче никаких проводов. Никаких допфазовращателей и режимов ПЛЯЖ, проделав это избавитесь от многих ошибок новичков. В разрыв между 4 ногой МС7 и землей установить пальчиковую батарейку. Датчик стандартный ДД или ОО на 10 кГц диаметр 22-25 см, провод 0,35-0,45мм. Делайте без разьема. Кабель желательно 5 жил каждая в своей медной оплетке без фольги. Подберите емкости с низким ТКЕ, как рекомендовал автор, найдите качественные HEF. Если, руки на месте, то получите вполне сносный прибор. 
    • Если можно дать малые обороты и чашка мелкая, тогда не понимаю, в чем трудность заточки  ф 0,5мм сверл?  Этой приспособой можно будет затачивать только стальные сверла, зажав их с небольшим выпуском, а твердосплавные  имеют утолщенных хвостовик и зажать его ближе к режущей кромке не получится. А длинная спираль сверла сразу же отломается. Хрупкие сверла нужно пальцами держать, чтобы чувствовать силу прижима.   
    • На какой  "второй"? Пищалки через 2 мкф 50 В, желательно неполярные, НЧ напрямую к усилителю. Всё.
    • Вы бы ещё сказали - именно такое число витков. Учебники, Валерий Сергеевич, на то и учебники, что дают не конкретные цифры, а общие способы достижения требуемого результата. В данном случае, не именно 3, а нечётное число. Общий, так сказать, закон. В частности, в упомянутой Вами главе есть такое    В другой книге, такое Как видите, всё это отлично  укладывается в формулу "изобретения" Комарова. То же касается и половинного числа витков внешних секций. Извините, не нашёл быстро цитаты. Да, собственно, надо ли доказывать, что в книгах пишут умное людям, этих книг не читающих? То ли, по лени, то ли, из принципа. То ли, так Василичь приказал. Если Вам угодно веровать, что это придумка Комарова - кто ж против? Принцип работает не зависимо от авторства. Реального, или приписываемого. В этих же книгах описаны и оптимальные способы намотки обмотки ООС и конструкции симметричных трансформаторов, которые, как утверждалось отдельными товарищами, на броневом сердечнике намотать невозможно. И, масса другого, не менее полезного. Я прочитал, запомнил главное и пользуюсь.
  • Similar Content

    • By RIMUS1989i
      Здравствуйте. Вопрос к гуру, на сколько будет меньше разрыв данных при посылке через SPI 16бит, если ожидание готовности написать на ассемблере? И сразу второй вопрос, как правильно её вставить?
      void sendWord(uint16_t data) { SPDR = data; while(!(SPSR & (1<<SPIF))); // это заменить на ассемблерную вставку //вот тут видно задержку SPDR = data>>8; while(!(SPSR & (1<<SPIF))); // и это заменить на ассемблерную вставку } Этот код не работает (ассемблерная вырезка из даташита). Я не соображаю...
      asm volatile( "Wait_Transmit: in r16, SPSR sbrs r16, SPIF rjmp Wait_Transmit ret" ); Пока писал сообщение, понял свой косяк, регистр r16 в строке выше у меня не соответствует data.Тогда еще вопрос, как полностью этот кусок "sendWord" написать на ассемблере?
      Заранее Спасибо!
    • By Pag
      Семейство чипов ЦАПов ES901x производства фирмы ESS Technology является довольно известным и популярным. Наибольшую известность получил 8-канальный чип ES9018 благодаря широким возможностям, наличию встроенного spdif-декодера и высокой точности преобразования цифрового сигнала в аналоговый.
      Его стерео вариант ES9018K2M, на котором построен данный ЦАП, является не менее популярным и качественным, хоть и лишен некоторых возможностей. Схема ЦАПа построена на основе известного ЦАПа Lynx Audio D48.
      Особенности ЦАПа
      1. 3 входа – USB, SPDIF и оптический.
      2. SPDIF и оптический входы используют встроенный в чип ЦАПа декодер spdif потока и поддерживают частоты 32, 44.1, 48, 88.2, 96, 176.4 и 192 КГц разрядностью 16/24 бита. Для преобразования spdif потока с сигналы TTL-уровня используются ресиверы MAX3283.
      3. USB вход реализован на модуле USB-I2S Amanero. Поддерживаются все частоты 32, 44.1, 48, 88.2, 96, 176.4 и 192, 352,8 и 384 КГц разрядностью 16/24/32 бита. Модуль Amanero работает в режиме slave, т.е. тактируется от генераторов, расположенных на плате ЦАПа
      4. USB вход поддерживает воспроизведение DSD потока – DSD64, DSD128, DSD256 (DSD не щелкает при переключении или прокрутке треков).
      5. Переключения между входами производится коротким нажатием и отпусканием на кнопку, расположенную на лицевой панели ЦАПа. Выбранный вход отображается с помощью соответствующего светодиода на лицевой панели ЦАПа.
      6. На выходе ЦАПа установлено реле отключающее выход при переключении входов и при включении ЦАПа (задержка при включении), что исключает посторонние звуки при переходных процессах при включении ЦАПа
      7. ЦАП, при работе по USB, тактируется от встроенных генераторов на 1024fs (45.1584 МГц и 49.152 МГц). При работе по оптическому и spdif входам ЦАП работает в асинхронном режиме и тактируется от встроенного генератора 100МГц.
      8. Для USB входа реализована возможность работы как в синхронном, так и в асинхронном режимах. Переключение осуществляется джампером на плате ЦАПа.
      9. На плате ЦАПа находятся 4 стабилизатора для питания микросхемы ЦАПа, а также еще 5 стабилизаторов для питания цифровой и аналоговой части ЦАПа.
      10. Аналоговая часть ЦАПа построена на операционных усилителях AD744 и AD811. Выходу ОУ в преобразователе ток-напряжение умощены транзисторным буфером на BD139.
      11. В плате блока питания использованы трансформаторы hahn elektrobau gmbh – 6
      независимых обмоток для различных частей ЦАПа. USB модуль также имеет отдельное стабилизированное питание 5В.
      12. В блоке питания установлены качественные фильтры сетевых помех EPCOS и Murata.
      13. Все электролитические конденсаторы производства YAGEO.
      14. ЦАП выполнен в пластиковом корпусе размерами 260*180*65 мм
      15. В ЦАПе используется активное охлаждение с помощью вентилятора, работающего на низких оборотах (нужно приложить ухо к корпусу чтобы услышать:) )
      В комплект поставки входят:
      1. ЦАП
      2. кабель питания
      3. USB кабель
      Я являюсь автором данного ЦАПа и предоставляю авторскою гарантию на изделие - 1 год с момента продажи!
      Цена собранного ЦАПа - 17000р
      Цена пустой платы с микроконтроллером - 1500р
      Цена пустой платы с микроконтроллером и чипом ES9018K2M - 2000р
      Доставка по России почтой России - 400р (платы 250р)












    • By kostake
      Продам ЦАП, на PCM5102, авторский. Выхлоп германиевый. Вход I2S.
      В роли транспорта подключен-Up2Stream Pro . Поддержка wifi ,bluetooth,ethernet,USB,Airplay, DLNA, UPnP. Может играть напрямую с флешки. 
      Цена : 11тыс руб. Отправка без проблем, за счет покупателя. 
    • By n_angelo
      По приходящему на ножку A1 импульсу настроено прерывание. Прерывание должно отработать один раз и должно делать следующее: пауза 7 секунд, потом на 1,5 секунды открыть реле. Во время прерывания светодиод на плате гаснет и загорается в такт секундам. Код отрабатывает верно за исключением того, что прерывание отрабатывает 2 раза. Т.е. подали импульс, заморгал светодиод в течении 7ми секунд, потом щёлкнуло реле (открылось), затем опять щёлкнуло (закрылось), потом всё повторяется еще раз (7+1,5). В режиме дебага работает нормально. Пробовал отключать реагирование на прерывания во время его отработки:
      disableInterruupts(); ... enableInterruupts(); но не помогает.
      STM8S103F3P6
      Код прерывания
      Код в main.c
       
    • Guest User1324
      By Guest User1324
      Здравствуйте, помогите подключить USB-флешку к STM32F103RCT6, нужна дополнить принципиальную схему. Если есть возможность нарисовать.
×
×
  • Create New...