stm32f4 v2
stm32f4 v2
Ihsen SAAD
Ihsen.saad@enit.rnu.tn
Glossary
STM32 F4 series:
Most powerful Cortex-M
Key Features :
STM32F4 versus competitors
(Coremark)
STM32F4 features :
MCU DSP
Harvard architecture
Ease of use of C
Single-cycle MAC
programming Cortex-M4
Interrupt handling Barrel shifter
Ultra-low power
Audio architecture
HW crypto/hash
PWMs @
Ethernet 168
withMHz
2 USB
andOTG
coprocessor
IEEE 1588v2
2 full2.4
ADC duplex
andMSPS I²S
<1 µA RTC
1
Hardware block diagram
DMA : Direct Memory Access
Memories :
Two 5V pin.
The STM32F4 embeds three I²C bus interfaces that can operate
MOSI
MOSI:Master Output data, Slave Input data.
MISO
MISO: Master Input data, Slave Output data.
SS
SS:Slave Select
Board audio capability
Temperature Sensor
The temperature sensor has to generate a voltage that varies
Consumer
Medical
Communication
STM32F4
System Structure
STM32F4 Discovery schematic
The CooCox IDE also relies on the GNU GCC compiler which device support
is constantly being updated. The IDE itself is also Eclipse based and it
integrates nicely with many different programmer and debugger adapters, fx the
ST-Link.
The CooCox IDE were released, adding support for the STM32F4 family. This
makes it a great compiler suite for use with the STM32F4-DISCOVERY board.
To use them in CooCox you should simply create a new project with the
booting files and then add all of the sources, including the libraries from lower
level folders. Finally you should remember to add the include paths and
symbols/definitions and you should be good to go.
The CooCox IDE requires the GNU GCC to be installed as a seperate package.
On Windows this is a bit more complicated, though GNU GCC has already
been crosscompiled by many different people.
Download:
http://www.labsud.org/stm32_discovery_coocox_gnuc_arm_codesourcery_decouverte_test/
One time installation and configuration
CoIDE environment
1. Project explorer view: the project explorer view gives you a view of your current
project.
2. Editor: the editor window your code is displayed and can be edited.
3. Panel pane: in the panel pane extra panels can be stored, normally the Help and
Outline pane can be viewed here.
4. Console and problems view: The console and show status information on
compiling and debugging.
GPIO on the STM32F4 Discovery
Each pin has several qualities that are defined by setting bits in their
corresponding registers:
Mode: input, output, analog or alternate function (SPI, USB, Timer,
etc.)
Output type: push-pull or open-drain.
Output speed: 2MHz, 25MHz, 50MHz or 100MHz.
Pull-up or pull-down: none, pull-up or pull-down.
Alternate function low: sets the alternate function for pins 0 – 7.
Alternate function high: sets the alternate function for pins 8 – 15.
The reset (default) values for most pins are: input, push-pull, 2MHz, no pull-up/down,
AF0. See RM0090 6.4.11 (p.153) for the few exceptions. Good coding practice would
involve resetting the GPIO channel if subsequent code expects the reset values.
Note: Analog pins are not 5V tolerant.
GPIO on the STM32F4 Discovery
Each pin can be used with one of the 15 possible alternate functions
shown in RM0090 Figure 14 (p.141):
GPIO Configuration
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO Configuration
From the figure above, the namesake of “open-drain” is
obvious to anyone who is familiar with MOSFETs. A MOSFET
has three terminals called: gate, source, and drain. In an open-
drain configuration, the source is grounded, the gate is driven
internally, and the drain is open (i.e. not connected to anything).
An open-drain output can only sink current. Its two states are
low and high-impedance. When M1 is on, the output is set to
0V. When M1 is off, the output is not driven high nor low. Most
applications, including I2C buses, use an external pull-up
resistor on any open-drain outputs. Another useful application
for open-drain outputs is having multiple external devices drive
a single, active-low interrupt pin on a microcontroller.
GPIO Configuration
The GPIO’s clock can be anything of the following:
GPIO_Speed_2MHz
GPIO_Speed_25MHz
GPIO_Speed_50MHz
GPIO_Speed_100MHz
On the STM32F4 the GPIO can have up to 4 modes (check the datasheet for which modes
are available for which pin):
GPIO_Mode_OUT for digital output
GPIO_Mode_IN for digital input
GPIO_Mode_AN for analog input
GPIO_Mode_AF for the alternate functions (like SPI, I²C, USART, …)
The type indicates the hardware configuration of the pin which can be:
GPIO_OType_PP, a push-pull is driving the output
GPIO_OType_OD, the output is open-drain
Next we can configure pull up, pull down resistors or nothing at all for each pin:
GPIO_PuPd_NOPULL, no resistor connected
GPIO_PuPd_UP, pin is connected to a pull up resistor
GPIO_PuPd_DOWN, pin is connect to a pull down resistor
GPIO Configuration
Example :
Let us assume that we would like to configure pins 11 and 12 of PortD
as digital outputs at full speed, with a push-pull and no pull up or pull
down:
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure);
The CooCox GPIO peripheral is a great library for easy setup. The GPIO_InitTypeDef is a
structure defined in the ST’s library and it contains all the properties you can configure on the
corresponding peripheral: Speed, Mode, Type and Pull up/pull down resistors.
In our first project we’ll create a small program that is capable to blink the
four leds on the discovery board and we’ll demonstrate
semihosting. Semihosting is a mechanism that enables code running on
an ARM target to communicate and use the I/O facilities on a host
computer that is running a debugger. In other words send data back over
the ST-LINK back to your computer.
Selected Peripherals
Now to get the clock running at desired speed all of this code needs to be called
before the main program starts. This done by editing the startup_stm32f4xx.c file
and uncommenting the SystemInit prototype first:
/*----------Function prototypes-----------------------------------------------*/
extern int main(void); /*!< The entry point for the application. */
extern void SystemInit(void); /*!< Setup the microcontroller system(CMSIS) */
void Default_Reset_Handler(void); /*!< Default reset handler */
static void Default_Handler(void); /*!< Default exception handler */
#ifdef __FPU_USED
/* Enable FPU.*/
__asm(" LDR.W R0, =0xE000ED88\n"
" LDR R1, [R0]\n"
" ORR R1, R1, #(0xF << 20)\n"
" STR R1, [R0]");
#endif
Now your code should run at full speed, this is the first step for every project
you create. Next we want to use the semihosting to send data back over the
debugger to the PC, to achieve this, we must rewrite printf or more concrete its
PrintChar method. Open the printf.c file and edit the PrintChar method and
add a call to SH_SendChar just before the method’s closing bracket (remember
to include the semihosting.h!):
9 #include "semihosting/semihosting.h"
1
0 /**
1 * @brief Transmit a char, if you want to use printf(),
1 * you need implement this function
1 *
2 * @param pStr Storage string.
1 * @param c Character to write.
3 */
1 void PrintChar(char c)
4 {
1 /* Send a char like: To enable the semihosting over the
5 while(Transfer not completed);
1 Transmit a char; debugger, right click your project and
6 */ select ‘Configure’, got to the ‘Debugger’
1 SH_SendChar(c);
tab and enable the check box for
7 }
‘Semihosting Enable’.
printf("Hello World!\r\n");
while (1) {
static int count = 0;
static int i;
Description:
This example describes how to toggle the GPIO pins connected on AHB bus.
PD12, PD13, PD14 and PD15 (configured in output pushpull mode) toggles in a
forever loop.
Set PD12, PD13, PD14 and PD15 by setting corresponding bits in BSRRL register
Reset PD12, PD13, PD14 and PD15 by setting corresponding bits in BSRRH
register
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h«
Example for GPIO
GPIO_InitTypeDef GPIO_InitStructure;
void Delay(__IO uint32_t nCount);
int main(void)
{
SystemInit();
/* GPIOD Periph clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
/* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
Description:
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure);
This example describes how to toggle the GPIO pins connected on AHB bus.
while(1)
PD12,
{ PD13, PD14 and PD15 (configured in output pushpull mode) toggles in a
/* PD12 to be toggled */
forever loop.
GPIO_SetBits(GPIOD, GPIO_Pin_12); Delay(0x3FFFFF);
Set /* PD13 to be toggled
PD12, PD13, */ PD14 and PD15 by setting corresponding bits in BSRRL register
GPIO_SetBits(GPIOD, GPIO_Pin_13); Delay(0x3FFFFF);
Reset /* PD14PD12, PD13,
to be toggled */ PD14 and PD15 by setting corresponding bits in BSRRH
GPIO_SetBits(GPIOD, GPIO_Pin_14); Delay(0x3FFFFF);
register
/* PD15 to be toggled */
GPIO_SetBits(GPIOD, GPIO_Pin_15); Delay(0x7FFFFF);
GPIO_ResetBits(GPIOD, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
Delay(0xFFFFFF);
}
}
In order to debug we need some code from the Simple GPIO example:
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
int main()
{
// Initialise the peripheral clock.
RCC->AHB1ENR |= RCC_AHB1Periph_GPIOD; Starting the debugger (Ctrl-F5)
// Initialise the GPIO port. changes the IDE context and presents
GPIOD->MODER |= GPIO_Mode_OUT; the debugging interface with the
GPIOD->OSPEEDR |= GPIO_Speed_25MHz; application stopped at the first line of
GPIOD->OTYPER |= GPIO_OType_PP;
GPIOD->PUPDR |= GPIO_PuPd_NOPULL; code:
Initialize_Button(); Main
while(1)
{
if (GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_0)!=0)
{
GPIO_SetBits(GPIOD, GPIO_Pin_12); Delay(1000);
}
else
{
GPIO_ResetBits(GPIOD, GPIO_Pin_12); Delay(1000);
}
}
Réf : HC-SR04
2cm<distance<4m
Example : Robot with ultrasonic sensor (2/2)
void pulse(void){
functions developeds GPIO_WriteBit(GPIOA,GPIO_Pin_8,Bit_SET);
Wait(15);
GPIO_WriteBit(GPIOA,GPIO_Pin_8,Bit_RESET);
Ultrason.c : }
if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3) == Bit_SET )
{
TIM_Cmd(TIM2,ENABLE);
}
if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3) == Bit_RESET )
{
TIM_Cmd(TIM2,DISABLE);
TmpCapteur=TIM_GetCounter(TIM2);
TIM_SetCounter(TIM2,0);
newvalue = TRUE;
}
}
lcd_init();
lcd_set_xy(0,0);
lcd_out("Hello World !!");
lcd_set_xy(3,1);
lcd_out("Ihsen SAAD");
Analog--to
Analog to--digital converters (ADCs)
ADC
CHN 1&2 3
# PORT
Three 12-bit analog- 0 PA0 PA0
to-digital converters 1 PA1 PA1
are embedded and 2 PA2 PA2
each ADC shares 3 PA3 PA3
up to 16 external 4 PA4 PF6
channels, 5 PA5 PF7
performing 6 PA6 PF8
conversions in the 7 PA7 PF9
single-shot or scan 8 PB0
mode. In scan 9 PB1 PF3
mode, automatic 10 PC0 PC0
11 PC1 PC1
conversion is
12 PC2 PC2
performed on a
13 PC3 PC3
selected group of 14 PC4 PF4
analog inputs. 15 PC5 PF5
Example: ADC input
AHB1
three 12-bit ADCs
ADC
CHN 1&2 3
# PORT
0 PA0 PA0
1 PA1 PA1
2 PA2 PA2
3 PA3 PA3
4 PA4 PF6
5 PA5 PF7
6 PA6 PF8
APB2
7 PA7 PF9
8 PB0
9 PB1 PF3
10 PC0 PC0
11 PC1 PC1
12 PC2 PC2
13 PC3 PC3
14 PC4 PF4
15 PC5 PF5
Configuration
ADC_InitTypeDef ADC_init_structure; //Structure for adc confguration
GPIO_InitTypeDef GPIO_initStructre; //Structure for analog input pin
//Clock configuration
//The ADC1 is connected the APB2 peripheral bus thus we will use its clock source
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
//Clock for the ADC port!! Do not forget about this one ;)
RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_GPIOCEN,ENABLE);
int adc_convert(){
ADC_SoftwareStartConv(ADC1);//Start the conversion
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));//Processing the conversion
return ADC_GetConversionValue(ADC1); //Return the converted data
}
Universal synchronous/asynchronous
receiver transmitters (USART)
int main(void)
{
Usart3_Config();
char a;
while(1)
{
a=getchar(USART3);
putchar(USART3,a);
}
}
Nested vectored interrupt controller (NVIC)
Interrupts are important in microcontrollers. With them you are able to stop executing
main program and jump to some predefined area if there is something important.
There is an interrupt called each time data arrive to MCU. Different peripheral can
trigger interrupt, like data come to USART, ADC finished conversion, timer overflow,
and more. NVIC is used to dynamically tell which interrupt is more important and for
enabling or disabling interrupts. It supports up to 256 different interrupt vectors.
There are four Data Fields in the InitStructure to set up:
NVIC_IRQChannel
NVIC_IRQChannelPreemptionPriority
NVIC_IRQChannelSubPriority
NVIC_IRQChannelCmd
Priority can be a value between 0 and 15. A lower value means higher priority. Please
refer to the above mentioned programming manual (DM00046982.PDF, Page
40) for information about Preemption- and SubPriority.
The Stdperiph manual provides a channel list. Timer 1 has four different channels. To
generate an update interrupt we need to use the channel TIM1_UP_TIM10_IRQn.
Priorities are not important because we are not generating more than one interrupt.
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);
//This will handle ALL interrupts which are enabled for USART1
void USART1_IRQHandler(void) {
//Check if interrupt was because data is received
if (USART_GetITStatus(USART1, USART_IT_RXNE)) {
//Do your stuff here
if(incomingByte == cmdL) {
GPIO_WriteBit(GPIOD,GPIO_Pin_14,Bit_SET);
GPIO_WriteBit(GPIOD,GPIO_Pin_12,Bit_RESET);// current command
}
else if(incomingByte == cmdR) {
GPIO_WriteBit(GPIOD,GPIO_Pin_14,Bit_RESET);
GPIO_WriteBit(GPIOD,GPIO_Pin_12,Bit_SET);
}
}
}
STM32F4 External interrupts tutorial(1/4)
Each STM32F4 device has 23 external interrupt or event sources. They are split into 2
sections. First interrupt section is for external pins (P0 to P15) on each port, and other section
is for other events, like RTC interrupt, Ethernet interrupt, USB interrupt and so on.
EXTI
GPIOA GPIOB GPIOC GPIOD GPIOE GPIOF GPIOG GPIOH GPIOI GPIOJ GPIOK
LINE
LINE 0 PA0 PB0 PC0 PD0 PE0 PF0 PG0 PH0 PI0 PJ0 PK0
LINE 1 PA1 PB1 PC1 PD1 PE1 PF1 PG1 PH1 PI1 PJ1 PK1
LINE 2 PA2 PB2 PC2 PD2 PE2 PF2 PG2 PH2 PI2 PJ2 PK2
LINE 3 PA3 PB3 PC3 PD3 PE3 PF3 PG3 PH3 PI3 PJ3 PK3
LINE 4 PA4 PB4 PC4 PD4 PE4 PF4 PG4 PH4 PI4 PJ4 PK4
LINE 5 PA5 PB5 PC5 PD5 PE5 PF5 PG5 PH5 PI5 PJ5 PK5
LINE 6 PA6 PB6 PC6 PD6 PE6 PF6 PG6 PH6 PI6 PJ6 PK6
LINE 7 PA7 PB7 PC7 PD7 PE7 PF7 PG7 PH7 PI7 PJ7 PK7
LINE 8 PA8 PB8 PC8 PD8 PE8 PF8 PG8 PH8 PI8 PJ8 PK8
LINE 9 PA9 PB9 PC9 PD9 PE9 PF9 PG9 PH9 PI9 PJ9 PK9
LINE 10 PA10 PB10 PC10 PD10 PE10 PF10 PG10 PH10 PI10 PJ10 PK10
LINE 11 PA11 PB11 PC11 PD11 PE11 PF11 PG11 PH11 PI11 PJ11 PK11
LINE 12 PA12 PB12 PC12 PD12 PE12 PF12 PG12 PH12 PI12 PJ12 PK12
LINE 13 PA13 PB13 PC13 PD13 PE13 PF13 PG13 PH13 PI13 PJ13 PK13
LINE 14 PA14 PB14 PC14 PD14 PE14 PF14 PG14 PH14 PI14 PJ14 PK14
LINE 15 PA15 PB15 PC15 PD15 PE15 PF15 PG15 PH15 PI15 PJ15 PK15
This table show you which IRQ you have to set for NVIC (first column) and function
names to handle your interrupts (second column). You have probably also figured, that
only lines 0 to 4 have own IRQ handler. Yes, lines 5-9 have the same interrupt handler
and this is also for lines 10 to 15.
After you set settings for EXTI, you have to add them into NVIC.
Timer peripherals
Timer peripherals
We can easily configure the timer to generate pulse signal on another channel. The
period will have to be the same, however the compare value can be different:
Research area
Balancing robot with STM32F4
Web server