Ich versuche gerade, mich auf der Basis der Doku auf Registerebene durch
den STM32L100 zu kämpfen. Vermutlich gibt es sinnvollere Methoden, seine
Zeit zu verbringen; andererseits ist es mir ganz sympathisch, wenn ich
weiß, was der Rechner denn nun macht, anstatt das alles wie ein
schlechtes Schnitzel unter einem Haufen Soße (=CMSIS, StdPeriphLib) zu
ersäufen. Auf dem MSP430 bin ich auch auf Registerebene zu Potte
gekommen.
Nur den NVIC-Code habe ich geklaut, deswegen ist dort StdPeriphLib-Code
drin.
Ich habe es geschafft, die LEDs auf dem Demoboard (PORT C) blinken zu
lassen. Mäßig schöner Code:
1 | #include <stm32l1xx.h>
|
2 | #include <stdint.h>
|
3 |
|
4 | int main() {
|
5 | RCC->AHBENR |= RCC_AHBENR_GPIOCEN;
|
6 | RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
7 | GPIOC->MODER |= (0x55555555); /* General purpose output mode*/
|
8 | GPIOC->OSPEEDR |= (0x55555555); /* 2 MHz Low speed */
|
9 | static int i;
|
10 |
|
11 |
|
12 |
|
13 | TIM2->PSC = 40000; // Prescaler
|
14 | TIM2->ARR = 500; // Timer overflow value
|
15 | TIM2->EGR = 0x01; // Update generation
|
16 | TIM2->DIER |= 0x01; // Enable timer interrupt
|
17 | TIM2->CR1 |= 0x01; // Timer enabled
|
18 | RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
|
19 |
|
20 | NVIC_InitTypeDef nvicStructure;
|
21 | nvicStructure.NVIC_IRQChannel = TIM2_IRQn;
|
22 | nvicStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
23 | nvicStructure.NVIC_IRQChannelSubPriority = 1;
|
24 | nvicStructure.NVIC_IRQChannelCmd = ENABLE;
|
25 | NVIC_Init(&nvicStructure);
|
26 |
|
27 | unsigned char n = 0;
|
28 | while (1) {
|
29 | GPIOC->BSRRL = 1 << 9; /* all on */
|
30 | GPIOA->ODR = 0xFFFFFFFF;
|
31 | for (i=0; i<100000; ++i);
|
32 | GPIOC->BSRRH = 1 <<9; /* all off */
|
33 | GPIOA->ODR = 0;
|
34 | for (i=0; i<100000; ++i);
|
35 | }
|
36 | }
|
37 |
|
38 | volatile uint16_t led_status = 0;
|
39 |
|
40 | void TIM2_IRQHandler() {
|
41 | if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
|
42 | led_status = !led_status;
|
43 | TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
|
44 | if (led_status) {
|
45 | GPIOC->BSRRL = (1 << 8);
|
46 | } else {
|
47 | GPIOC->BSRRH = (1 << 8);
|
48 | }
|
49 | }
|
50 | }
|
Die Hauptschleife beackert also PC9, der Interrupt PC8. Das funktioniert
:)
Wenn ich nun versuche, den Code so zu erweitern, dass der USART1 auch
noch etwas tun darf, klappt das nicht. Checkliste:
* Peripheral Clocks für USART und für Port A einschalten
* PA9 auf Alternate Function schalten, als Alternate Function #7 =
USART1_TX nehmen
* Baudrate für USART1 setzen
* USART Enable und TX Enable setzen
* Wert ins USART Data Register schreiben
In Code gegossen (obiger Code erweitert):
1 | #include <stm32l1xx.h>
|
2 | #include <stdint.h>
|
3 |
|
4 | int main() {
|
5 | RCC->AHBENR |= RCC_AHBENR_GPIOCEN;
|
6 | RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
7 | GPIOC->MODER |= (0x55555555); /* General purpose output mode*/
|
8 | GPIOC->OSPEEDR |= (0x55555555); /* 2 MHz Low speed */
|
9 | static int i;
|
10 |
|
11 |
|
12 |
|
13 | TIM2->PSC = 40000; // Prescaler
|
14 | TIM2->ARR = 500; // Timer overflow value
|
15 | TIM2->EGR = 0x01; // Update generation
|
16 | TIM2->DIER |= 0x01; // Enable timer interrupt
|
17 | TIM2->CR1 |= 0x01; // Timer enabled
|
18 | RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
|
19 | RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
|
20 | GPIOA->MODER |= (2UL << 18) | (2UL << 20);
|
21 | GPIOA->AFR[1] |= (7UL << 4) | (7UL << 8);
|
22 | GPIOA->OSPEEDR = 0xFFFFFFFF;
|
23 | USART1->BRR = 0x341;
|
24 | USART1->CR1 |= USART_CR1_UE + USART_CR1_TE;
|
25 |
|
26 | NVIC_InitTypeDef nvicStructure;
|
27 | nvicStructure.NVIC_IRQChannel = TIM2_IRQn;
|
28 | nvicStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
29 | nvicStructure.NVIC_IRQChannelSubPriority = 1;
|
30 | nvicStructure.NVIC_IRQChannelCmd = ENABLE;
|
31 | NVIC_Init(&nvicStructure);
|
32 |
|
33 | unsigned char n = 0;
|
34 | while (1) {
|
35 | GPIOC->BSRRL = 1 << 9; /* all on */
|
36 | GPIOA->ODR = 0xFFFFFFFF;
|
37 | for (i=0; i<100000; ++i);
|
38 | GPIOC->BSRRH = 1 <<9; /* all off */
|
39 | GPIOA->ODR = 0;
|
40 | for (i=0; i<100000; ++i);
|
41 | while (!(USART1->SR & USART_SR_TXE));
|
42 | USART1->DR = n;
|
43 | n++;
|
44 | }
|
45 | }
|
46 |
|
47 | volatile uint16_t led_status = 0;
|
48 |
|
49 | void TIM2_IRQHandler() {
|
50 | if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
|
51 | led_status = !led_status;
|
52 | TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
|
53 | if (led_status) {
|
54 | GPIOC->BSRRL = (1 << 8);
|
55 | } else {
|
56 | GPIOC->BSRRH = (1 << 8);
|
57 | }
|
58 | }
|
59 | }
|
Leider tut sich exakt gar nichts, der LA sieht nur dröhnendes Schweigen
an PA9. Die LEDs blinken beide, die Abfrage while (!(USART1->SR &
USART_SR_TXE)) bleibt nicht hängen.
Jemand eine Idee, wo ich noch schrauben kann (außer die Soßenlösung
CMSIS/StdPeriphLib)?
Max