Någon som förstår det där med DMA i STM32?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43148
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Någon som förstår det där med DMA i STM32?

Inlägg av sodjan »

Jag skulle vara lite misstänksam till ett värde som -32768...
Kommer det överhuvud taget från en ADC?
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Någon som förstår det där med DMA i STM32?

Inlägg av DanielM »

Det är enkelt. Det är sigma delta ADC med noll referens. Enligt databladet så ger den då värden mellan -0x8000 till 0x8000.

Men sådant kan enkelt kastas om till uint16 så man får 0 till 0xFFFF.

Notera att detta är en 16-bit ADC. Väldigt noggrann.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Någon som förstår det där med DMA i STM32?

Inlägg av DanielM »

Efter några försök så har jag lyckats för första gången att programmera en STM32 med register endast. Det var att läsa databladet rätt mycket.
Det jag har gjort här är att jag sätter förstärkningen hos en SDADC. 1/2x till 32x i förstärkning. Det är bra.

Jag börjar med att kolla om SDADC är redo.

Kod: Markera allt

	/* 0: Check if SDADC is ready */
	if(hsdadc->State != HAL_SDADC_STATE_READY)
		Error_Handler();
Sedan så sätter jag init mode till 1

Kod: Markera allt

	/* 1: Enter init-mode for the control register */
	hsdadc->Instance->CR1 |= SDADC_CR1_INIT;
Skärmklipp.PNG
Sedan kollar jag på svaret jag får från registret.

Kod: Markera allt

	uint32_t tickstart = HAL_GetTick();
	bool isAtInitMode = true;
	/* Wait for INITRDY bit on SDADC_ISR */
	while ((hsdadc->Instance->ISR & SDADC_ISR_INITRDY) == (uint32_t) RESET) {
		if ((HAL_GetTick() - tickstart) > 200) {
			isAtInitMode = false;
		}
	}
Skärmklipp.PNG
Där efter om allt är OK, dvs isAtInitMode blev inte false. Då sätter jag förstärkningen. Jag hade tidigare problem med att sätta förstärkningen då jag glömde nollställa bitten. :doh:

Kod: Markera allt

	/* 2: If init mode, then set gain and offset registers */
	if(isAtInitMode){
		switch(configuration_index){
		case SDADC_CONF_INDEX_0:
			hsdadc->Instance->CONF0R &=  ~(0b111 << 20); /* Clear */
			hsdadc->Instance->CONF0R |= SDADC_gain << 20; /* Bits 22:20 GAIN0[2:0]: */
			break;
		case SDADC_CONF_INDEX_1:
			hsdadc->Instance->CONF1R &=  ~(0b111 << 20); /* Clear */
			hsdadc->Instance->CONF1R |= SDADC_gain << 20;
			break;
		case SDADC_CONF_INDEX_2:
			hsdadc->Instance->CONF1R &=  ~(0b111 << 20); /* Clear */
			hsdadc->Instance->CONF2R |= SDADC_gain << 20;
			break;
		}
	}
Skärmklipp.PNG
Sedan stänger jag ned initsaliseringen.

Kod: Markera allt

	/* 3: Leave init-mode for the control register */
	hsdadc->Instance->CR1 &= ~(SDADC_CR1_INIT);
Skärmklipp.PNG
Detta är bättre än STM32:egna HAL-funktioner för att sätta förstärkningen. Nu sätter jag endast förstärkningen, och inget annat.

Kod: Markera allt

/* Program configuration register with parameters */
      tmp = (uint32_t)((uint32_t)(hsdadc->Instance) + \
                       SDADC_CONFREG_OFFSET + \
                       (uint32_t)(ConfIndex << 2UL));
      *(__IO uint32_t *) (tmp) = (uint32_t) (ConfParamStruct->InputMode | \
                                             ConfParamStruct->Gain | \
                                             ConfParamStruct->CommonMode | \
                                             ConfParamStruct->Offset);
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
JimmyAndersson
Inlägg: 26308
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: Någon som förstår det där med DMA i STM32?

Inlägg av JimmyAndersson »

” Efter några försök så har jag lyckats för första gången att programmera en STM32 med register endast.”

Grattis! :tumupp: :)

Det tar tid i början, men efter hand så kommer man ihåg ganska mycket utantill och resten kan man snabbt hitta, eftersom man lärt sig var det finns. Så på sikt går faktiskt ”registerprogrammering” fortare för att nå från noll till färdigt.
Men det finns ju inget som säger att man måste välja *ett* sätt och enbart använda det. :)

(Sedan finns det egentligen inget som heter ”registerprogrammering, men det är en annan sak. :))
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Någon som förstår det där med DMA i STM32?

Inlägg av DanielM »

Tackar!

Jag valde registerprogrammering (LL (Low Level programmering som det egentligen kallas)) för att jag behövde skriva till enskilda register endast. STM's HAL är helt underbart, men det är väldigt grovt.

Jag måste dock säga att ST's referensmanualer var något oförklarade. Jag menar, efter man har satt hsdadc->Instance->CR1 |= 0x1 << 31 ; så måste man vänta tills hsdadc->Instance->ISR blir & (0x1 << 31) blir större än 0

Det står här inget hur länge man bör vänta. Men jag antar att detta är något som alla processorer beter sig?
Det finns ALLTID kontrollregister. Du sätter ALLTID kontroller registret först, sedan väntar du på interruptregistret?
Skärmklipp.PNG
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
JimmyAndersson
Inlägg: 26308
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: Någon som förstår det där med DMA i STM32?

Inlägg av JimmyAndersson »

Precis så. :tumupp:
Först berättar man hur man vill ha det. Sedan ber man processorn att den ska säga till när det blir ett interrupt.
Sen rullar det på och varje gång ett interrupt inträffar så hanterar man det (t.ex nollställer någon interrupt-flagga) och gör vad som ska göras när man får ett interrupt. T.ex sparar värdet från AD’n.

Jo just det ja:
Det här med timers eller interrupt:
Interrupt är lämpligast när man vill fånga något som händer exakt just när det händer. (T.ex en larm-ingång som måste hanteras med mikrosekunds reaktionstid.)
Timers är lämpligast när man med jämna mellanrum vill kolla något. (T.ex batteri-status)

Så för att läsa av en spänning löpande, som en multimeter, så hade jag valt timers istället för interrupt.
Annars lär du få interrupt när varenda liten bit ändras. Skulle man då presentera varenda förändring på en display så skulle man inte hinna läsa av något, så det vore slöseri med resurser (CPU) som kunde ha gett viktigare delar mer uppmärksamhet.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Någon som förstår det där med DMA i STM32?

Inlägg av DanielM »

JimmyAndersson skrev: 20 augusti 2021, 23:18:00 Precis så. :tumupp:
Först berättar man hur man vill ha det. Sedan ber man processorn att den ska säga till när det blir ett interrupt.
Sen rullar det på och varje gång ett interrupt inträffar så hanterar man det (t.ex nollställer någon interrupt-flagga) och gör vad som ska göras när man får ett interrupt. T.ex sparar värdet från AD’n.
Lite sent, kom hem från en god vänn, men svarar ändå.

Så alla processorer, t.ex. AVR, PIC, NPX, Infineon, Intel har detta beteende?
Jag har liksom väldigt svårt att veta vad man ska kolla efter. Troligtvis har det med att jag har bara kört STM32 och STM själva säger att dom ger inget stöd för LL programmering. Endast CubeMX och HAL. Dom verkar lyckas bra också med det då många f.d Arduino-användare använder STM32. Jag gillar verkligen STM32 för att dom är billiga jämfört vad man får tillbaka. Nuvarande STM32 är F373 processorn och den har nästan allt man kan önska sig, utom ethernet. USB har den och det fungerar bra :tumupp:

Jag skulle aldrig kunna programmera en processor igenom att kolla referensmanualen. Jag måste ha ett kodexempel först.
Jo just det ja:
Det här med timers eller interrupt:
Interrupt är lämpligast när man vill fånga något som händer exakt just när det händer. (T.ex en larm-ingång som måste hanteras med mikrosekunds reaktionstid.)
Timers är lämpligast när man med jämna mellanrum vill kolla något. (T.ex batteri-status)
Just nu håller jag på att logga mätvärden till ett SD-kort och det fungerar bra. Jag har ofta använt mig av detta logik.

Kod: Markera allt

loop_time = start - stop;
start = GetTime();

time += loop_time;

if(time>= sample_time) {

	/* Utför loggning */
	time = 0;
}
Men nu ska jag använda en interrupt trigger som aktiveras för t.ex. varje 100ms eller 1s eller 2 sekunder. Troligtvis blir det ett valbart intervall mellan 100ms till 10s.
Så för att läsa av en spänning löpande, som en multimeter, så hade jag valt timers istället för interrupt.
Annars lär du få interrupt när varenda liten bit ändras. Skulle man då presentera varenda förändring på en display så skulle man inte hinna läsa av något, så det vore slöseri med resurser (CPU) som kunde ha gett viktigare delar mer uppmärksamhet.
Jag hade valt DMA. Orsaken har med att vill man läsa värdet i realtid så krävs det ytterligare processorkraft.
Just nu använder jag DMA på Input Capture och SDADC för att varje gång jag loggar med dessa med interrupt, så stannar LCD skärmen. Men med DMA så är det fritt fram för en annan process att utföra det tråkiga :)
Skriv svar