Forum: Mikrocontroller und Digitale Elektronik STM32 Registermaskierung


von LBubble (Gast)


Lesenswert?

Servus

Im Rahmen eines Projektlabors an meiner FH bin ich gerade dabei mich in 
den STM32F103 einzuarbeiten, was mir schwerer fällt als gedacht.
Bis jetzt hatte ich hauptsächlich mit dem C166 zu tun, mit dem man 
Register einfach à la RegisterXYZ |= 0x0101010101 maskieren kann.
Beim STM32 spreche ich die Register über structs an, also GPIOx->ODR = 
0x010101101;.
Gibt es dafür grundsätzlich noch eine andere Methode, oder übersehe ich 
noch etwas? Bis jetzt hab ich mir damit beholfen, die unrelevanten Bits 
mit 0 oder der Reset Value zu beschreiben. Auf Dauer aber doch recht 
unschön.
In die FirmwareLib will ich mich nur ungern einarbeiten, weil die Zeit 
so schon recht knapp ist.

von PittyJ (Gast)


Lesenswert?

Kapsel das einfach mit einer Funktion und gut ist es.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

LBubble schrieb:
> mit dem man
> Register einfach à la RegisterXYZ |= 0x0101010101 maskieren kann.
> Beim STM32 spreche ich die Register über structs an, also GPIOx->ODR =
> 0x010101101;.

Hi,

allgemein:
1
GPIOx->ODR |= 0x010101101;
2
GPIOx_ODR  |= 0x010101101;
ist "das gleiche". In beiden Fällen steckt eine Adresse dahinter, nur 
die Adressbildung ist anders. Im ersten Fall berechnet der Compiler die 
Adresse aus BASE+OFFSET, im zweiten Fall hat der Vendor das im 
Headerfile selbst addiert.

Im Zuge der Standardisierung unter CMSIS wurde das für alle Cortex-M 
Devices vereinheitlicht.

Zum Einen erhöht es die Übersichtlichkeit (struct TIMER_type und 
#define-Mapping auf TIMER0,1,2,3,n), und zum Anderen ermöglicht es Tools 
mit IntelliSense Feature das automatische Einsehen der Member 
(Register).
1
/*------------------------ General Purpose and Alternate Function IO ---------*/
2
typedef struct {
3
  __IO uint32_t CRL;
4
  __IO uint32_t CRH;
5
  __IO uint32_t IDR;
6
  __IO uint32_t ODR;
7
  __IO uint32_t BSRR;
8
  __IO uint32_t BRR;
9
  __IO uint32_t LCKR;
10
} GPIO_TypeDef;
11
12
#define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)
13
#define GPIOB               ((GPIO_TypeDef *) GPIOB_BASE)
14
#define GPIOC               ((GPIO_TypeDef *) GPIOC_BASE)
15
#define GPIOD               ((GPIO_TypeDef *) GPIOD_BASE)
16
#define GPIOE               ((GPIO_TypeDef *) GPIOE_BASE)
17
#define GPIOF               ((GPIO_TypeDef *) GPIOF_BASE)
18
#define GPIOG               ((GPIO_TypeDef *) GPIOG_BASE)

STM32 speziell:
Im Gegensatz zu einigen anderen Controllern (AVR, LMI CM3, NXP) hat STM 
die PortPin-Konfigurationsmöglichkeiten in 2x 2Bits verpackt: MODE und 
CONF.
Hintergrund ist das Glitchfreie Umschalten zwischen den Modes.


VG,
/th.

von (prx) A. K. (prx)


Lesenswert?

LBubble schrieb:

> Gibt es dafür grundsätzlich noch eine andere Methode, oder übersehe ich
> noch etwas? Bis jetzt hab ich mir damit beholfen, die unrelevanten Bits
> mit 0 oder der Reset Value zu beschreiben. Auf Dauer aber doch recht
> unschön.

Bei den Portpins arbeitet man meist nicht mit dem ODR, sondern mit BSRR 
oder BRR. Manche Steuerregister anderer Komponenten besitzt ebenfalls 
separate Register, die nur Bits setzen oder löschen.

Einzelne Bits kann man via ARM Bitbanding ansprechen.

von (prx) A. K. (prx)


Lesenswert?

LBubble schrieb:

> Beim STM32 spreche ich die Register über structs an, also GPIOx->ODR =
> 0x010101101;.

Abgesehen davon, dass es optisch kaum einen Unterschied ergibt, ob man 
GPIOA_ODR oder GPIO->ODR schreibt, hat die Methode mit Strukturen den 
entscheidenden Vorteil, allgemeine Funktionen für Peripheriekomponenten 
zu ermöglichen, die mehrfach vorliegen. Wie etwa eine Funktion 
usart_init(USART1), die gleichermassen für alle USARTs einsetzbar ist 
und die Adresse der Struct zum Parameter hat.

von babbelnet (Gast)


Lesenswert?

à la Card oder was?

von LBubble (Gast)


Lesenswert?

GPIOA_ODR erzeugt bei mir einen "identifier 'GPIOA_ODR' is 
undefined"-Fehler.
Dass ich mit dem Pfeiloperator ganz normal maskieren kann wusste ich 
nicht, da ich es zuerst mit GPIOA->CRL probiert habe, und da führte es 
zu keinem funktionierenden Ergebnis, mit RCC->APB2ENR und GPIOA->ODR 
allerdings schon.
Auf jeden Fall hat mich das schon einiges weiter gebracht.
Vielen Dank an Random.. für die ausführliche Antwort und A. K für den 
Tipp mit BSRR.
Und an alle anderen für die Mühe.

Gruß

von Random .. (thorstendb) Benutzerseite


Lesenswert?

> GPIOA_ODR erzeugt bei mir einen "identifier 'GPIOA_ODR' is
> undefined"-Fehler.
Stimmt, da muss ich dem Compiler rechtgeben. Ich sagte ja, wir haben dem 
Wildwuchs ein Ende gemacht :-) Gibt im Wesentlichen nur noch
1
Peripheral->Register
für Cortex-M.

Willst du
1
Peripheral_Register
verwenden, musst du es dir selbst definieren.

> Dass ich mit dem Pfeiloperator ganz normal maskieren kann wusste ich
> nicht, da ich es zuerst mit GPIOA->CRL probiert habe, und da führte es
> zu keinem funktionierenden Ergebnis, mit RCC->APB2ENR und GPIOA->ODR
> allerdings schon.

CRL ist das Control Register Low. Die Konfiguration für die unteren 8Bit 
eines Ports sind im CRL zu 8 Portpins mal 2Bit MODE + 2Bit CONF 
organisiert, beim CRH (High) sind es gleichermaßen die Portpins 16...31


Was zum Abgucken, passend für die LEDs an Port B.8 bis B.15
1
#ifndef __GPIO_H__
2
#define __GPIO_H__
3
4
// AF enable
5
#define AFIO_EN    0  // Alternate Function Enable
6
7
// GPIO enable
8
#define IOPA_EN    2  // GPIO A enable
9
#define IOPB_EN    3  // GPIO B enable
10
#define IOPC_EN    4  // GPIO C enable
11
#define IOPD_EN    5  // GPIO D enable
12
#define IOPE_EN    6  // GPIO E enable
13
#define IOPF_EN    7  // GPIO F enable
14
#define IOPG_EN    8  // GPIO G enable
15
16
// DAC Enable
17
#define DAC_EN    29
18
19
#define GPIO_CONF_BIT(BIT)  ((BIT>7? BIT-8 : BIT) << 2)    // 4Bits per port pin
20
21
// Mode and Conf Bits
22
#define MODE0          (unsigned int)0
23
#define MODE1          (unsigned int)1
24
#define CONF0          (unsigned int)2
25
#define CONF1          (unsigned int)3
26
27
// Port Mode
28
#define GPIO_MODE_INPUT       (((unsigned int)0<<MODE0) | ((unsigned int)0<<MODE1))    // GPIO is input
29
#define GPIO_SPEED_2MHZ       (((unsigned int)0<<MODE0) | ((unsigned int)1<<MODE1))    // Max output Speed  2MHz
30
#define GPIO_SPEED_10MHZ      (((unsigned int)1<<MODE0) | ((unsigned int)0<<MODE1))    // Max output Speed 10MHz
31
#define GPIO_SPEED_50MHZ      (((unsigned int)1<<MODE0) | ((unsigned int)1<<MODE1))    // Max output Speed 50MHz
32
33
// Port Conf
34
#define GPIO_OUT_PUSH_PULL    (((unsigned int)0<<CONF0) | ((unsigned int)0<<CONF1))    // general purpose output push-pull
35
36
#define GPIO_AF_PUSHPULL      (((unsigned int)0<<CONF0) | ((unsigned int)1<<CONF1))   // alternate function push-pull
37
38
#define GPIO_IN_FLOATING      (((unsigned int)1<<CONF0) | ((unsigned int)0<<CONF1))   // input floating
39
#define GPIO_IN_ANALOG        (((unsigned int)0<<CONF0) | ((unsigned int)0<<CONF1))   // input analog
40
41
#define GPIO_IN_PULL_DOWN     (((unsigned int)0<<CONF0) | ((unsigned int)1<<CONF1))   // alternate function push-pull
42
#define GPIO_IN_PULL_UP       (((unsigned int)0<<CONF0) | ((unsigned int)1<<CONF1))   // alternate function push-pull
43
44
#endif
1
#ifndef __led_h__
2
#define __led_h__
3
4
#define LED_PORT      GPIOB->ODR
5
#define LED_PORT_MASK    0xFFFF00FF
6
#define LED_PORT_SHIFT    8
7
#define LED_PORT_SHIFT_MAX  15
8
9
int led_init(void);
10
void led_out(char out);
11
void running_light(void);
12
13
#endif
14
15
16
int ledCnt=0;
17
18
int led_init(void)
19
{  
20
  bit_on(RCC->APB2ENR, IOPB_EN);      // enable PORT B
21
  
22
  GPIOB->CRH = 
23
  ((GPIO_OUT_PUSH_PULL | GPIO_SPEED_2MHZ) << GPIO_CONF_BIT(8))  | \
24
  ((GPIO_OUT_PUSH_PULL | GPIO_SPEED_2MHZ) << GPIO_CONF_BIT(9))  | \
25
  ((GPIO_OUT_PUSH_PULL | GPIO_SPEED_2MHZ) << GPIO_CONF_BIT(10)) | \
26
  ((GPIO_OUT_PUSH_PULL | GPIO_SPEED_2MHZ) << GPIO_CONF_BIT(11)) | \
27
  ((GPIO_OUT_PUSH_PULL | GPIO_SPEED_2MHZ) << GPIO_CONF_BIT(12)) | \
28
  ((GPIO_OUT_PUSH_PULL | GPIO_SPEED_2MHZ) << GPIO_CONF_BIT(13)) | \
29
  ((GPIO_OUT_PUSH_PULL | GPIO_SPEED_2MHZ) << GPIO_CONF_BIT(14)) | \
30
  ((GPIO_OUT_PUSH_PULL | GPIO_SPEED_2MHZ) << GPIO_CONF_BIT(15));
31
32
  return(0);
33
}
34
35
void led_out(char out){
36
    LED_PORT = (LED_PORT & LED_PORT_MASK) | (out << LED_PORT_SHIFT);
37
}
38
39
void running_light(void)
40
{
41
  static int count=0;
42
  
43
  count++;
44
45
  if(count > 0xffff){
46
    count=0;
47
    led_out(1<<(ledCnt=++ledCnt<8?ledCnt:0));          // feed the running light
48
  }  
49
}

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.