stm32 - dithering pwm pres dma, dotaz...

Vojtěch Petrucha petrucha na volny.cz
Čtvrtek Leden 2 14:47:57 CET 2020


Zdravim,
 
snazil jsem se pres vanoce rozchodit dithering PWM pres DMA na HR citaci v STM32F334. Podarilo se, ale mam k tomu par dotazu, pokud by prosim nekdo vedel.
 
Cilem je mit tri DA prevodniky s rozlisenim idealne 20 bit, slouzici na generovani offsetovacich proudu ve zdroji pro triosy civkovy system s fluxgate kompenzaci..
 
Idea je popsana zde: AN4507 "PWM resolution enhancement through a dithering technique for STM32 advanced-configuration, general-purpose and lite timers"
 
https://www.st.com/content/ccc/resource/technical/document/application_note/7e/17/df/9e/5d/04/4b/72/DM00119042.pdf/files/DM00119042.pdf/jcr:content/translations/en.DM00119042.pdf
 
Jsou k tomu i zdrojaky: https://www.st.com/en/embedded-software/x-cube-pwm-dithr.html
 
Nicmene uz u te aplikacni noty jsem narazil. Zdrojak po kompilaci a nahrani do F303 Nuclea fungoval, ale po blizsim zkoumani mi prijde, ze popis v pdf je nejaky divny, nebo jsem ho nepochopil, coz je velmi dobre mozne, a ze prilozena implementace tomu pdf ne zcela odpovida..   (prepsal jsem to, funguje stejne nebo lepe, muzu poslat...)
 
Konkretne - princip by mel byt v tom, ze se v pripade rozsireni rozliseni treba o tri bity, meni postupne v osmi po sobe nasledujicich periodach pwm delka pulzu o 1.. cili by mela stacit tabulka o osmi prvcich (table[8]), ve ktere budou treba cisla 45 46 45 46 45 46 45 46 (pro kod 4 z 0-7 moznych). Pokud se budou tato cisla plnit pres (kruhove) DMA do CMP1 registru, tak po Half-transfer complete preruseni lze updatovat prvni polovinu tabulky (table[0-3]) a po transfer complete interrupt lze prepocitat druhou cast tabulky table[4-7]. V danem pdf je popsano, ze prepocet se spusti vzdy v obou prerusenich a vysledkem bude po RC filtraci trojuhelnikovy prubeh bud zubaty nebo rovny..
 
Podle me staci jedna tabulka o osmi prvcich, pdf i zdrojak zminuje dve (2*8):
 
#define DITHER_TABLE_FIRST_PART         ((uint16_t*) aDitherTable)
#define DITHER_TABLE_SECOND_PART        ((uint16_t*)(aDitherTable + 8))
#define TIMER_PERIOD ((uint32_t)63)
/* 3-bit dithering resolution implies 2x8 values table */
uint32_t aDitherTable[16];
 
ale funkce pro inicializaci DMA
TIM1_PWM_UPDATE_DMA(TIM_HandleTypeDef *htim, uint32_t *pData,uint16_t Length);
je zadana jako:
TIM1_PWM_UPDATE_DMA(&htim1, (uint32_t*) aDitherTable, 8);
cili se pracuje jen s prvnimi osmi prvky pole? pokud to neni "nejak zarizene" pres ty ruzne typy promene, (uint16_t*) aDitherTable vs. (uint32_t*) aDitherTable ?
 
Navic ve zdrojaku je jedna "updatovaci funkce" strcena do "HAL_TIM_PeriodElapsedCallback" a ne do "TIM_DMAPeriodElapsedCplt", to se snadno prehledne a pak se clovek divi, co to dela, ta funkce se podle me vubec neuplatni, protoze odkazuje na prvky z druhe poloviny tabulky o 16-ti prvcich, ktere se mozna vubec neprenasi?
 
Druha "updatovaci funkce", ktera je v "HalfTransferComplete" asi jako jedina funguje.
 
No stravil jsem asi den a pul (nachlazeny napul v posteli) snazenim se naklikat to DMA v CubeMX, no neslo to. Kupodivu po 30 minutach koukani do HRTIM_Snippets (STM32Cube_FW_F3_V1.11.0) to behalo po bezproblemu, takze doporucuju..
 
A ted ten dotaz, v me aplikaci, kde mam tabulku 16-ti prvkovou (4 bity navic), circular DMA prenasi data do komparacniho registru.. jelikoz v tomhle pripade budu hodnotu pwm menit max. cca 10-20 za sekundu, tak mi prijde zbytecne aktivovat ty transfer complete preruseni, ktere by byly radove na 65kHz, ale proste provedu ten prepocet tabulky jen pri zmene.. tak je moznost, ze se zapisem do pameti trefim zrovna do okamziku kdy se z toho mista bude chtit pres DMA cist..  predpokladam, ze si to sbernice nejak prebere a jedno nebo druhe (program nebo DMA) pocka.. a jiny problem nebude...?
 
Diky pokud nekdo docetl az sem :-)
V.P.
pro lepsi predstavu, ta tabulka pro 4 extra bity vypada takto:uint32_t xtable[16][16]={ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //0 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //1 {1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0}, //2 {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0}, //3 {1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0}, //4 {1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0}, //5 {1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0}, //6 {1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0}, //7 {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0}, //8 {1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0}, //9 {1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0}, //10 {1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,0}, //11 {1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0}, //12 {1,1,1,1,0,1,1,1,1,0,1,1,1,1,1,0}, //13 {1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0}, //14 {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}}; //15a funkce ktera ji pouzije aby updatovala to pole co se pres DMA prenasi do komparacniho registru:void UpdateDitherTable(uint32_t *pDitherTable, uint32_t Value){//Table 83. Period and Compare registers min and max values (HRTIM)//0x0060 min  0xFFDF max  uint32_t table_index;  uint32_t DitherV;  DitherV = Value;  DitherV &= 0x0000000F; //get the four last bits - the EXTRA bits  Value >>= 4; //upper 16-bits for CMP  Value &= 0xFFFF;  if(Value < 0x60){Value = 0x60;};  if(Value > 0xFFDE){Value = 0xFFDE;};  for (table_index = 0; table_index <= 15; table_index++){    if(xtable[DitherV][table_index]){      pDitherTable[table_index] = Value + 1;    }else{      pDitherTable[table_index] = Value;    }  }//for}
------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20200102/1d792735/attachment.html>


Další informace o konferenci Hw-list