Forum: Mikrocontroller und Digitale Elektronik STM32 Registermanipulation HAL


von Bert S. (kautschuck)


Lesenswert?

Hi,

Ich sehe gerade nicht wie ich ein Register manipuliere, wobei
ich nur Zugriff auf eine Instanz (htim2) habe. Was ich versucht habe 
ist:
1
htim2.Instance->EGR =(uint16_t)(1<<6) | (uint16_t)(1<<4); //Set TG=Trigger generation active and CC4G = Campture compare 4 event

Aber wenn ich EGR vor und nach diesem Codeabschnitt auslese, dann bleibt 
EGR immer Null. Wie genau manipuliere ich die Register, wenn ich nur 
Zugriff auf die Instanz habe?

von Dr. Sommer (Gast)


Lesenswert?

Bert S. schrieb:
> Aber wenn ich EGR vor und nach diesem Codeabschnitt auslese, dann bleibt
> EGR immer Null.
Normal. EGR ist ein Write-Only-Register. Da kommt beim Zurücklesen immer 
nur 0 raus.

Der Kommentar an deiner Code-Zeile ist aber verdächtig - das Register 
schaltet nichts ein oder aus, sondern löst Ereignisse aus, die 
normalerweise per Hardware ausgelöst werden. Normalerweise braucht man 
das Register eher nicht...

von Bert S. (kautschuck)


Lesenswert?

Was ich möchte ist, dass der Timer2 Channel 4 den ADC1 auslöst (über DMA 
einlesen). Beim ADC1 habe ich folgendes gesetzt:
1
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
2
 hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_CC2;

Und Timer2 Channel 4 ist im Output Compare No Output mode.

Es handelt sich um einen STM32F303K8T6:
http://www.st.com/content/ccc/resource/technical/document/reference_manual/4a/19/6e/18/9d/92/43/32/DM00043574.pdf/files/DM00043574.pdf/jcr:content/translations/en.DM00043574.pdf

: Bearbeitet durch User
von Nop (Gast)


Lesenswert?

Bert S. schrieb:

> Aber wenn ich EGR vor und nach diesem Codeabschnitt auslese, dann bleibt
> EGR immer Null.

Ist ja auch logisch, weil Du nur ein struct manipulierst, was das 
Register repräsentiert, aber nicht mit ihm identisch ist.

> Wie genau manipuliere ich die Register, wenn ich nur
> Zugriff auf die Instanz habe?

Indem Du danach eine passende API-Funktion aufrufst.

Übrigens solltest Du das direkte Rumgefummel mit Bits lassen und 
stattdessen die passenden Bitmasken-Defines verwenden, weil Dein Code 
sonst unwartbar wird.

von Dr. Sommer (Gast)


Lesenswert?

Bert S. schrieb:
> Was ich möchte ist, dass der Timer2 Channel 4 den ADC1 auslöst
> (über DMA
> einlesen).
Ah. Über EGR kannst du nur den ADC sofort auslösen. Um den Timer den 
ADC automatisch auslösen zu lassen, musst du die CCMR, CCER, CCR1 
Register sowie das MMS Feld im CR2 Register setzen und den ADC 
entsprechend konfigurieren.

Nop schrieb:
> Ist ja auch logisch, weil Du nur ein struct manipulierst, was das
> Register repräsentiert, aber nicht mit ihm identisch ist.
Naja, das struct ist mit den Bus-Adressierbaren Daten identisch. 
Allerdings enthält das EGR nur "temporäre" Signale - man schreibt z.B. 
das "UG" bit auf 1, dadurch wird der Timer auf 0 gesetzt, aber das Bit 
wird nicht als 1 gespeichert weil der Timer ja nicht ständig resettet 
werden soll, sondern nur 1x. Es wird eben eine Aktion sofort 
ausgelöst, aber nichts gespeichert.

von Bert S. (kautschuck)


Lesenswert?

Nop schrieb:
> Übrigens solltest Du das direkte Rumgefummel mit Bits lassen und
> stattdessen die passenden Bitmasken-Defines verwenden, weil Dein Code
> sonst unwartbar wird.

Das ist mir eigentlich schon klar, jedoch habe ich keine Ahnung, wie 
genau ich auf die Registernamen zugreifen kann? Ich verwende die AC6 
Toolchain und die Eclipse IDE mit den HAL Libraries.

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

Bert S. schrieb:
> Das ist mir eigentlich schon klar, jedoch habe ich keine Ahnung, wie
> genau ich auf die Registernamen zugreifen kann?
Einfach hinschreiben?
1
htim2.Instance->EGR = TIM_EGR_TG | TIM_EGR_CC4G;
Eventuell musst du noch ein
1
#include <stm32f303k8.h>
hinzufügen (oder so ähnlich, schau mal was da im Projekt ist).

Wenn du die HAL nutzt brauchst du eigentlich auch gar keine direkten 
Registerzugriffe, die HAL hat für sowas alles Funktionen.

von Dr. Sommer (Gast)


Lesenswert?

Oh, ich seh grad ich hab's sogar selbst auf dem Rechner. Es muss
1
#include <stm32f303x8.h>
sein. Da stehen so Dinge drin wie:
1
#define TIM_EGR_TG_Pos   (6U)
2
#define TIM_EGR_TG_Msk   (0x1U << TIM_EGR_TG_Pos)
3
#define TIM_EGR_TG       TIM_EGR_TG_Msk

von pegel (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Wenn du die HAL nutzt brauchst du eigentlich auch gar keine direkten
> Registerzugriffe, die HAL hat für sowas alles Funktionen.

Genau. In diesem Fall:

HAL_TIM_GenerateEvent aus der stm32f3xx_hal_tim.c

von Bert S. (kautschuck)


Angehängte Dateien:

Lesenswert?

Danke euch, ich habe das ganze jetzt mal versucht zu implementieren, 
doch leider scheint Timer2 den ADC1 immer noch nicht zu triggern. Ich 
habe das meiste in CubeMX eingestellt und dann noch die Register gemäß 
dem Datenblatt 
http://www.st.com/content/ccc/resource/technical/document/reference_manual/4a/19/6e/18/9d/92/43/32/DM00043574.pdf/files/DM00043574.pdf/jcr:content/translations/en.DM00043574.pdf 
angepasst.

1
//ADC Trigger trough Timer
2
  htim2.Instance->CR2=htim2.Instance->CR2 | (1<<TIM_CR2_MMS_0) | (1<<TIM_CR2_MMS_1) | (1<<TIM_CR2_MMS_2); 
3
  htim2.Instance->CCER=htim2.Instance->CCER |(1<<TIM_CCER_CC4E); 
4
  hadc1.Instance->CFGR=hadc1.Instance->CFGR | (1<<ADC_CFGR_EXTSEL_0) | (1<<ADC_CFGR_EXTSEL_1) | (1<<ADC_CFGR_EXTEN_0); 
5
  hadc1.Instance->CR=hadc1.Instance->CR|(1<<ADC_CR_ADSTART);
6
7
  HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);
8
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_array, ADC_SIZE);

: Bearbeitet durch User
von pegel (Gast)


Lesenswert?

Ich denke du gehst die Sache viel zu kompliziert an.
Schau einfach in das Beispiel ADC_TriggerMode in der HAL Lib.

von Bert S. (kautschuck)


Lesenswert?

pegel schrieb:
> Ich denke du gehst die Sache viel zu kompliziert an.
> Schau einfach in das Beispiel ADC_TriggerMode in der HAL Lib.

Ok, werde mir das mal ansehen, danke.

von Bert S. (kautschuck)


Lesenswert?

pegel schrieb:
> Ich denke du gehst die Sache viel zu kompliziert an.
> Schau einfach in das Beispiel ADC_TriggerMode in der HAL Lib.

Das Beispiel ist leider nur mit dem Interrupt und ohne wählen eines 
spezifischen Channels. Ich müsste aber den ADC mit DMA triggern, und nur 
wenn CH4 in der hälfte der Periode des Timers ist.

von Bert S. (kautschuck)


Angehängte Dateien:

Lesenswert?

Ok, ich glaube ich habe es fast, was ich aber noch nicht genau sehe ist, 
was der Pulse(32 bit value), siehe Bild 1, genau ist? Ist das der 
Startwert? Wenn ja, wo muss ich den Auslöser für den output compare 
setzten?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.