mirror of
https://github.com/rfivet/stm32bringup.git
synced 2024-12-20 15:58:44 -05:00
102 lines
3.1 KiB
HTML
102 lines
3.1 KiB
HTML
|
<!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! 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 that’s 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>
|