Hallo Freunde,
ich versuche mit Hilfe von CMSIS einen Timer als Funktionsparameter zu
übergeben. Der Aufruf sollte also wie folgt aussehen:
timer_einstellen(TIM17);
Kann mir bitte jemand auf die Sprünge helfen, wie man dazu die Funktion
deklariert?
In dieser Form funktioniert es leider nicht:
void timer_einstellen((TIM_TypeDef *) timer)
{
...Code
}
Mitch schrieb: > void timer_einstellen((TIM_TypeDef *) timer) Die Klammern müssen natürlich weg:
1 | void timer_einstellen(TIM_TypeDef* timer) { |
Aber ingesamt ist das mit der SPL/CMSIS leider sehr kompliziert, denn du musst ja zur Initialisierung auch den Bus kennen (APB1/APB2), den Index des Bits im RCC_APB*ENR, die Interrupt-Nummer (IRQn), ... und die kannst du nicht aus deinem "timer" Parameter berechnen, sondern musst alle seperat übergeben.
Dr. Sommer schrieb: > Die Klammern müssen natürlich weg: > void timer_einstellen(TIM_TypeDef* timer) { aaaaaaa, Danke!!! Dr. Sommer schrieb: > Aber ingesamt ist das mit der SPL/CMSIS leider sehr kompliziert, denn du > musst ja zur Initialisierung auch den Bus kennen (APB1/APB2), den Index > des Bits im RCC_APB*ENR, die Interrupt-Nummer (IRQn), ... und die kannst > du nicht aus deinem "timer" Parameter berechnen, sondern musst alle > seperat übergeben. Ich verwende den STM32F051, dieser hat zum Glück nicht so viele Möglichkeiten. Somit kann ich die UNterscheidungen in der Funktion unterbringen.
Dr. Sommer schrieb: > und die kannst > du nicht aus deinem "timer" Parameter berechnen Doch das geht, ist aber nicht grade schön:
1 | void timer_einstellen(TIM_TypeDef* timer) { |
2 | |
3 | uint32_t timerBase=(uint32_t timer); |
4 | |
5 | switch(timerBase){ |
6 | case TIMER_1_BASE: ; |
7 | //...
|
8 | |
9 | case TIMER_7_BASE: ; |
10 | }
|
11 | }
|
Die TIMER_X_Base Konstanten kann man sich aus den entsprechenden Headern rauspfriemeln.
Das ist doch ziemlich unschön: die Funktionsdeklaration suggeriert daß sie unabhängig vom konkret verwendeten Timer funktioniert. Das switch/case hinterher macht aber ziemlich das Gegenteil davon. Da sollte mindestens eine kleine Abstraktionsschicht dazwischen. Du könntest z.B. ein enum für die Timer definieren und diesen enum dann an die Funktion übergeben. Da wird dem Leser des Codes wenigstens sofort klar daß da in der Funktion irgendwo ne Unterscheidung anhand der enums gemacht wird und man das für einen anderen µC das evtl. etwas anpassen muss.
Ich habe für jede Hardware-Ressource ein struct definiert, in dem alle Parameter enthalten sind, die die entsprechende Ressource benötigt. Die wird dann der Init-Routine übergeben. Als Beispiel mal ein Uart. In dem struct werden nicht nur die zugehörigen IO-Pins definiert, sondern auch die verwendeten DMA Kanäle:
1 | typedef struct{ |
2 | USART_TypeDef* Uart; // a.e. UART4 or USART1 |
3 | |
4 | int DmaRxStreamNr; // a.e. 2 |
5 | DMA_Stream_TypeDef* DmaRxStream; // a.e. DMA1_Stream2 |
6 | uint32_t DmaRxChannel; // a.e. DMA_CHANNEL_4 |
7 | |
8 | int DmaTxStreamNr; // a.e. 2 |
9 | DMA_Stream_TypeDef* DmaTxStream; // a.e. DMA1_Stream4 |
10 | uint32_t DmaTxChannel; // a.e. DMA_CHANNEL_4 |
11 | |
12 | IRQn_Type IRQnRx; // a.e. DMA1_Stream2_IRQn |
13 | uint32_t IRQnRxPrio; // a.e. 0..15 0 = high |
14 | uint32_t IRQnRxSubPrio; // a.e. 0..15 0 = high |
15 | |
16 | IRQn_Type IRQnTx; // a.e. DMA1_Stream4_IRQn |
17 | uint32_t IRQnTxPrio; // a.e. 0..15 0 = high |
18 | uint32_t IRQnTxSubPrio; // a.e. 0..15 0 = high |
19 | |
20 | IRQn_Type IRQnTcTx; // a.e. Uart TC IRQ |
21 | uint32_t IRQnTcTxPrio; // a.e. 0..15 0 = high |
22 | uint32_t IRQnTcTxSubPrio; // a.e. 0..15 0 = high |
23 | |
24 | GPIO_TypeDef* GpioRxPort; // a.e. GPIOA |
25 | uint32_t GpioRxAfPinMapping; // a.e. GPIO_AF_UART4 |
26 | uint32_t GpioRxPin; // a.e. 1 |
27 | |
28 | GPIO_TypeDef* GpioTxPort; // a.e. GPIOA |
29 | uint32_t GpioTxAfPinMapping; // a.e. GPIO_AF_UART4 |
30 | uint32_t GpioTxPin; // a.e. 0 |
31 | |
32 | } USART_ConfigurationTypeDef; |
Diese struct lege ich für jede Hardware Komonente einmal konstant an. Gruß, Stefan
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.