1
0
mirror of https://github.com/rfivet/stm32bringup.git synced 2024-12-20 15:58:44 -05:00
stm32bringup/docs/15_blink.html

102 lines
3.1 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>1.5 Blinking user LED</title>
<link type="text/css" rel="stylesheet" href="style.css">
</head>
<body>
<h1>1.5 Blinking user LED</h1>
Turning the user LED on shows that the board is alive, making it blink
shows that it has a pulse!&nbsp; A steady power LED with a pulsing user LED is
easy to interpret.
<p>
As I already manage to turn the LED on, making it blink is quite
straightforward.
<h2>Code and build</h2>
I make a copy of <b>ledon.c</b> into <b>blink.c</b> and modify it as follow:
<ul>
<li>Introduce the Output Data Register (<b>ODR</b>) of <b>GPIOB</b> peripheral
to the compiler as <b>GPIOB_ODR</b>. This is where the pin state is programmed.
<li>Modify the idle loop to toggle PB1 after a delay. The delay is coded
as an active wait loop on decrementing a counter.
</ul>
<pre>
/* Memory locations defined by linker script */
extern long __StackTop ; /* &__StackTop points after end of stack */
void Reset_Handler( void) ; /* Entry point for execution */
/* Interrupt vector table:
* 1 Stack Pointer reset value
* 15 System Exceptions
* NN Device specific Interrupts
*/
typedef void (*isr_p)( void) ;
isr_p const isr_vector[ 2] __attribute__((section(".isr_vector"))) = {
(isr_p) &__StackTop,
/* System Exceptions */
Reset_Handler
} ;
#define RCC ((volatile long *) 0x40021000)
#define RCC_AHBENR RCC[ 5]
#define RCC_AHBENR_IOPBEN 0x00040000 /* 18: I/O port B clock enable */
#define GPIOB ((volatile long *) 0x48000400)
#define GPIOB_MODER GPIOB[ 0]
#define GPIOB_ODR GPIOB[ 5]
void Reset_Handler( void) {
int delay ;
/* User LED ON */
RCC_AHBENR |= RCC_AHBENR_IOPBEN ; /* Enable IOPB periph */
GPIOB_MODER |= 1 << (1 * 2) ; /* PB1 Output [01], over default 00 */
/* OTYPER Push-Pull by default */
/* PB1 output default LOW at reset */
/* User LED blink */
for( ;;) {
for( delay = 1000000 ; delay ; delay--) ; /* delay between toggling */
GPIOB_ODR ^= 1 << 1 ; /* toggle PB1 (User LED) */
}
}
</pre>
I set the value of the delay counter at one million. By default the
internal clock is set to 8MHz at reset, which means the delay will still
be less than one second.
<pre>
$ make blink.hex
blink.elf
text data bss dec hex filename
68 0 0 68 44 blink.elf
blink.hex
rm blink.o blink.elf
</pre>
<h2>Test</h2>
As the <a href="vid/15_blink.mp4">video</a> shows, the delay is roughly
600ms. I captured three on/off transitions in this three second video, looking
through the frames gives me a better estimation.
<h2>Checkpoint</h2>
This is just a small increment on my previous step, but thats iterative
development in a nutshell. Also I didn't come with a reasonable value
for the delay counter at first, it's easy to underestimate how fast
micro-controllers are.
<p>
<a href="16_ledtick.html">Next</a>, interrupt driven blinking, because
active wait delay is just not cool.
<hr>© 2020-2024 Renaud Fivet
</body>
</html>