Warning
This page is located in archive. Go to the latest version of this course pages. Go the latest version of this page.

01 - GPIO LED

Základní nastavení GPIO pinu na platformě STM32F401 ve variantě v jazyce C a Assembleru

Jazyk C

Následující kód způsobí blikání LED na pinu PA5 umístěnou na vývojovém kitu v daném časovém intervalu.

#include "stm32f4xx.h"
 
#define setbit(reg, bit) ((reg) |= (1U << (bit)))
#define clearbit(reg, bit) ((reg) &= (~(1U << (bit))))
#define togglebit(reg, bit) ((reg) ^= (1U << (bit)))
 
int main(void)
{
  /* klicovym slovem volatile vyradime promennou i z pripadne optimalizace */
  volatile i = 0;
 
  setbit(RCC->AHB1ENR, 0);       // aktivace hodin brany GPIOA
 
  setbit(GPIOA->MODER, 10);      // nastaveni pinu PA5 jako digital out
  clearbit(GPIOA->MODER, 11);
 
  clearbit(GPIOA->OTYPER, 5);    // nastaveni pinu PA5 jako dvoustavovy (push-pull)
 
  setbit(GPIOA->OSPEEDR, 10);    // nastaveni rychlosti brany na medium speed
  clearbit(GPIOA->OSPEEDR, 11);
 
  clearbit(GPIOA->PUPDR, 10);   // vypnuti pull-up/pull-down
  clearbit(GPIOA->PUPDR, 11);
 
  setbit(GPIOA->ODR, 5);        // nastaveni logickych urovni pinu
  clearbit(GPIOA->ODR, 5);
 
  while (1){
    togglebit(GPIOA->ODR, 5);   // prepnuti stavu LED
 
    /* smycka, co jen inkrementuje promennou, tj. ceka */
    for(i = 0; i < 500000; i++);
  }
}

Assembler

Následující kódy ukazují, jak lze nastavit piny PC0-PC7 jako výstupy (MAM shield) a jak lze blikat se spodní polovinou brány PC.

Inicializace LED

	.global leds_init
 
	.equ	rcc_reg,			0x40023800   @ adresa registru RCC
	.equ	rcc_ahb1enr_offset,		0x30         @ offset registru AHB1ENR
	.equ	rcc_gpioc_en,			0x0004       @ bit pro povoleni hodin pro GPIOC
 
	.equ 	gpio_c, 			0x40020800   @ adresa registru GPIOC
	.equ	moder_offset,			0x00         @ offset adresy registru MODER
	.equ	odr_offset,			0x14         @ offset adresy registru ODR
 
	.equ	moder_init,			0x00005555   @ inicializacni hodnota pro registr MODER (mode output)
	.equ	odr_init,			0x000000F0   @ inicializacni hodnota pro registr ODR (turn off upper 4 leds)
 
leds_init:
	push 	{R0-R3};
 
@  Enable GPIOC in  RCC->AHB1ENR
	ldr		R0, =rcc_reg;
	ldr		R1, =rcc_ahb1enr_offset;
	ldr		R2, [R0, R1];
	ldr		R3, =rcc_gpioc_en;
	orr		R2, R3;
	str		R2, [R0, R1];
 
@  Enable 8 Green leds as outputs
	ldr		R0, =gpio_c;
	ldr		R1, =moder_offset;
	ldr		R2, =moder_init;
	str		R2, [R0, R1];
 
@  Turn off upper 4 Green leds
	ldr		R1, =odr_offset;
	ldr		R2, =odr_init;
	str		R2, [R0, R1];
 
	pop 	        {R0-R3};
	bx		lr;

Blikání LED

	.global leds_blink
 
	.equ 	gpio_c, 		0x40020800   @ adresa registru GPIOC
	.equ	odr_offset,		0x14         @ offset adresy registru ODR
	.equ	odr_led_xor,		0x000000FF   @ XOR mask for bottom 8 bits (8 green leds)
 
leds_blink:
	push 	{R0-R3};
 
@  Toggle 8 Green leds
	ldr		R0, =gpio_c;
	ldr		R1, =odr_offset;
	ldr		R2, [R0, R1];
	ldr             R3, =odr_led_xor;
	eor		R2, R3
	str		R2, [R0, R1];
 
	pop 	        {R0-R3};
	bx		lr;

500ms Delay

Následující program předpokládá kmitočet procesoru 16 MHz pro zpoždění 500 ms

	.global delay_loop
 
	.equ	count_1ms,		7999  @ pocet opakovani na 1 ms
	.equ	delay,			500   @ zpozdeni 500 ms
 
delay_loop:
	push 	        {R0-R1};
	ldr		R1, =delay
 
//  Load counter for 1ms delay
load_1ms:
	ldr		R0, =count_1ms
 
 
loop:
// Loop through the counter to 1 ms
	sub 	        R0, #1
	bne		loop
 
// Loop through the number of ms (delay value)
	sub		R1, #1
	bne		load_1ms
 
	pop 	        {R0-R1};
	bx		lr;

Hlavní smyčka

Pokud se používá kombinace jazyka C a Assembleru, je třeba přejmenovat hlavní smyčku main jazyka C (pokud existuje) nebo daný soubor kompletně smazat, popřípadě přejmenovat název funkce, která se spouští po restartu mikrokontroléru. V opačném případě nastane konflikt názvů funkcí/podprogramů.

  .global main
 
  .extern leds_init
  .extern leds_blink
  .extern delay_loop
 
main:
  bl leds_init;
 
loop:
  bl leds_blink;
  bl delay_loop;
 
  b loop;

courses/b2m37mam/priklady/stm32/01-gpio.txt · Last modified: 2022/07/23 13:26 by nentvond