Forum: Mikrocontroller und Digitale Elektronik STM32F100xx Bitmanipulation ohne Header Datei


von Justin S. (justin76200)


Lesenswert?

Hey ich möchte einen Stm32 Microcontroller programmieren und das 
funktioniert eigtl alles ganz gut. Der Code funktioniert zwar(LEDS 
blinken), aber ich möchte die Makros der Header Datei mit pointern die 
auf das Register zeigen ersetzten:
Hier mal der Code.

#include "stm32f10x.h"



int main() {
  RCC->APB2ENR |= (1<<4);

  GPIOC->CRL |= (  (1<<16)  |  (1<<17)  );

  GPIOC->CRL &= ~(  (1<<18) |  (1<<19));

  GPIOC->CRL |= (  (1<<20)  |  (1<<21)  );

  GPIOC->CRL &= ~(  (1<<22)  |  (1<<23)  );

  GPIOC->CRL |= (  (1<<24)  |  (1<<25)  );

  GPIOC->CRL &= ~(  (1<<26)  |  (1<<27)  );

  while(1){
    int i = 0;

    GPIOC->BSRR = (1<<5);

    GPIOC->ODR |= (1<<4);

    //GPIOC->ODR = 1<<(

    while(i < 2000000){
      i++;
    }
    GPIOC->BSRR = (1<<21);
    GPIOC->ODR &= ~(1<<4);
    //GPIOC->ODR =
    i = 0;
    while(i < 2000000){
      i++;
    }



  }

}

RCC-APB2ENR soll zum Beispiel mit einem Pointer ersetzt werden, der auf 
diese Adresse zeigt. Ich habe mal im Datenblatt nachgeschaut nur versteh 
ich nicht auf welcher Adresse der Bus liegt.
Hier noch der Link zum Datenblatt:

https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwiG3qv-nervAhVE9IUKHSZ2AJEQFjABegQIAxAD&url=https%3A%2F%2Fwww.st.com%2Fresource%2Fen%2Freference_manual%2Fcd00246267-stm32f100xx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf&usg=AOvVaw2GsY3qPMGEaY6As6a7xMbJ

Ich hoffe ihr könnt mir helfen.

von Stefan F. (Gast)


Lesenswert?

Guck doch einfach von den CMSIS headern ab, z.B. der Datei 
stm32f100xb.h:

Die Basisadresse von RCC ergibt sich aus:
1
#define PERIPH_BASE         0x40000000U
2
#define AHBPERIPH_BASE      (PERIPH_BASE + 0x00020000U)
3
#define RCC_BASE            (AHBPERIPH_BASE + 0x00001000U)
4
#define RCC                 ((RCC_TypeDef *)RCC_BASE)

0x40000000 + 0x00020000 + 0x00001000 = 40021000

Dazu addierst du die Adresse des Registers innerhalb der Struktur:
1
typedef struct
2
{
3
  __IO uint32_t CR;
4
  __IO uint32_t CFGR;
5
  __IO uint32_t CIR;
6
  __IO uint32_t APB2RSTR;
7
  __IO uint32_t APB1RSTR;
8
  __IO uint32_t AHBENR;
9
  __IO uint32_t APB2ENR;
10
  __IO uint32_t APB1ENR;
11
  __IO uint32_t BDCR;
12
  __IO uint32_t CSR;
13
14
15
  uint32_t RESERVED0;
16
  __IO uint32_t CFGR2;
17
} RCC_TypeDef;

APB2ENR ist das siebte 32 bit Register innerhalb der Struktur, also 
addierst dazu 6 mal 4 Bytes.

40021000 + 6 * 4 = 0x40021018

Das müsste die Adresse von dem Register RCC->APB2ENR sein, falls ich 
mich jetzt nicht verrechnet habe.

Gibt es einen vernünftigen Grund, auf die CMSIS header zu verzichten?

von Bauform B. (bauformb)


Lesenswert?

Stefan ⛄ F. schrieb:
> Gibt es einen vernünftigen Grund, auf die CMSIS header zu verzichten?

Die Lizenz? War mal BSD, jetzt ist es nur noch ein Link auf eine bunte 
Seite irgendwo im Internet.

von Stefan F. (Gast)



Lesenswert?

Bauform B. schrieb:
> Die Lizenz? War mal BSD, jetzt ist es nur noch ein Link auf eine bunte
> Seite irgendwo im Internet.

Das ist die Lizenz direkt aus dem Paket. Ist sehe darin nichts 
hinderliches.

von Bauform B. (bauformb)


Angehängte Dateien:

Lesenswert?

Stefan ⛄ F. schrieb:
> 0x40000000 + 0x00020000 + 0x00001000 = 40021000

diese 40021000 steht auch direkt im Handbuch (RM0041), s.o.

> Dazu addierst du die Adresse des Registers innerhalb der Struktur:

Das muss wohl sein, wenn man die struct nicht benutzen will. Das wäre 
mir dann doch zu umständlich.

Ich mache einen Kompromiss und benutze zwar eine ähnliche struct, aber 
keine CMSIS-#defines. Also zeigt der Pointer auf die 40021000 aus dem 
Manual und der GPIO-Takt wird so eingeschaltet:
1
RCC->IOPCEN = 1;
APB2ENR usw. schreibe ich nicht mit, das ist ja in der struct definiert, 
genau wie das Bit IOPCEN. Deshalb muss ich mir nicht merken, dass der 
Takt mit 1<<4 eingeschaltet wird und kann APB1 und AHB2 usw. nicht 
leicht verwechseln.

: Bearbeitet durch User
von PittyJ (Gast)


Lesenswert?

Ist das wirklich so kryptisch bei den F100er Prozessoren?
Ich habe einen H7, und da schreibe ich so etwas wie

  HAL_GPIO_WritePin(GPIOC, ui_PinBitmask, GPIO_PIN_SET);

oder zum Abfragen

       State = HAL_GPIO_ReadPin(GPIOC,ui_PinBitmask);


Finde ich über sichtlicher als

    GPIOC->ODR &= ~(1<<4);

Warum gibt es für die F100 nicht so wtwas wie HAL.

Letztendlich optimiert der Compiler ja eh auf den gleichen Code.

von Nop (Gast)


Lesenswert?

PittyJ schrieb:

> Warum gibt es für die F100 nicht so wtwas wie HAL.

Erstens benutzt die HAL natürlich die CMSIS-Definitionen, und 
zweitens...

> Letztendlich optimiert der Compiler ja eh auf den gleichen Code.

... tut er das nicht. Die HAL gibt deutlich größeren und langsameren 
Code, und abgesehen davon nagelt sie Dich auch auf STM32 fest, weil 
dieser vendor lock-in der eigentliche Sinn dahinter ist.

von Stefan F. (Gast)


Lesenswert?

In der CMSIS gibt es auch hilfreiche Makros wie
1
SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN);
2
CLEAR_BIT(RCC->CR, RCC_CR_PLLON);
3
WRITE_REG(GPIOA->BSRR, GPIO_BSRR_BS5);
4
MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_HSI);

von Bauform B. (bauformb)


Lesenswert?

PittyJ schrieb:
> Ist das wirklich so kryptisch bei den F100er Prozessoren?
> Ich habe einen H7, und da schreibe ich so etwas wie
>   HAL_GPIO_WritePin(GPIOC, ui_PinBitmask, GPIO_PIN_SET);

> Finde ich über sichtlicher als
>     GPIOC->ODR &= ~(1<<4);

Das kannst du doch schreiben wie du willst, bei jedem Prozessor. Nur 
weil der Justin das oben so geschrieben hat, musst du das doch nicht 
nachmachen. Ersetze mal das 1<<4 durch etwas wie deine ui_PinBitmask. 
Schon besser. Im nächsten Schritt ersetze das noch durch einen Namen wie 
led_motor.

Schon kann das jeder lesen, auch wenn er HAL nicht kennt. Und wenn er 
nicht sicher ist, was ODR genau ist, kann er das in dem selben Manual 
nachlesen, das er sowieso täglich benutzt.

von PittyJ (Gast)


Lesenswert?

Bauform B. schrieb:
> PittyJ schrieb:
>> Ist das wirklich so kryptisch bei den F100er Prozessoren?
>> Ich habe einen H7, und da schreibe ich so etwas wie
>>   HAL_GPIO_WritePin(GPIOC, ui_PinBitmask, GPIO_PIN_SET);
>
>> Finde ich über sichtlicher als
>>     GPIOC->ODR &= ~(1<<4);
>
> Das kannst du doch schreiben wie du willst, bei jedem Prozessor. Nur
> weil der Justin das oben so geschrieben hat, musst du das doch nicht
> nachmachen. Ersetze mal das 1<<4 durch etwas wie deine ui_PinBitmask.
> Schon besser. Im nächsten Schritt ersetze das noch durch einen Namen wie
> led_motor.
>
> Schon kann das jeder lesen, auch wenn er HAL nicht kennt. Und wenn er
> nicht sicher ist, was ODR genau ist, kann er das in dem selben Manual
> nachlesen, das er sowieso täglich benutzt.

Für mich ist nur nur so: Wenn man nach 5 Jahren wieder in seinen 
Source-Code schauen muss, weil ein Fehler festgestellt wird, dann weiss 
man bei HAL_GPIO_WritePin() sofort was dort passiert. Bei ODR muss man 
dann noch das Handbuch aufmachen und nachlesen, was war jetzt ODR. Also 
sucht man erst mal das Handbuch, dann nach dem Register .....

Und bei mir kommt es öfters vor, dass ich in uralten Projekten noch 
Änderungen vornehmen muss. Da freut man sich über jeden Kommentar und 
sinnvolle Benamung.

von Bauform B. (bauformb)


Lesenswert?

PittyJ schrieb:
> Und bei mir kommt es öfters vor, dass ich in uralten Projekten noch
> Änderungen vornehmen muss. Da freut man sich über jeden Kommentar und
> sinnvolle Benamung.

Meine Rede! Für die ältesten Funktionen könnte ich ein H-Kennzeichen 
beantragen, die sind in gutem Originalzustand ;) Nur bei der Suche nach 
ODR vs HAL_GPIO_WritePin() geht es mir genau umgekehrt wie dir.

von Stefan F. (Gast)


Lesenswert?

PittyJ schrieb:
> Für mich ist nur nur so: Wenn man nach 5 Jahren wieder in seinen
> Source-Code schauen muss, weil ein Fehler festgestellt wird, dann weiss
> man bei HAL_GPIO_WritePin() sofort was dort passiert. Bei ODR muss man
> dann noch das Handbuch aufmachen und nachlesen, was war jetzt ODR.

Absolut richtig. Deswegen sollte man diese Aufrufe in eine Funktion 
kapseln, die z.B. Pumpe_an() und Pumpe_aus() heißt.

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.