@par Example Description
How to use the ADC3 and DMA to transfer continuously converted data from ADC3 to memory.
The ADC3 is configured to convert continuously ADC_CHANNEL_8.
Each time an end of conversion occurs the DMA transfers, in circular mode, the converted data from ADC3 DR register to the uhADCxConvertedValue variable.
The uhADCxConvertedValue read value is coded on 12 bits, the Vref+ reference voltage is connected on the board to VDD (+3.3V), the Vref- reference voltage is connected on the board to the ground.
To convert the read value in volts, here is the equation to apply :
Voltage = uhADCxConvertedValue * (Vref+ - Vref-) / (2^12) = uhADCxConvertedValue * 3.3 / 4096
In this example, the system clock is 216MHz, APB2 = 108MHz and ADC clock = APB2/4.
Since ADC3 clock is 27 MHz and sampling time is set to 3 cycles, the conversion
time to 12bit data is 12 cycles so the total conversion time is (12+3)/27 = 0.56us(1.57Msps).
User can vary the ADC_CHANNEL_8 voltage by applying an input voltage on pin PF10 connected to Arduino CN5 pin A1.
STM32 Eval board's LEDs can be used to monitor the transfer status:
- LED1 is ON when the conversion is complete.
- LED1 blinks when error occurs in initialization.
@par Keywords
Analog, ADC, Analog to Digital Converter, Regular Conversion, DMA, Continuous Conversion
@Note If the user code size exceeds the DTCM-RAM size or starts from internal cacheable memories (SRAM1 and SRAM2),that is shared between several processors,
then it is highly recommended to enable the CPU cache and maintain its coherence at application level.
The address and the size of cacheable buffers (shared between CPU and other masters) must be properly updated to be aligned to cache line size (32 bytes).
@Note It is recommended to enable the cache and maintain its coherence, but depending on the use case
It is also possible to configure the MPU as "Write through", to guarantee the write access coherence.
In that case, the MPU must be configured as Cacheable/Bufferable/Not Shareable.
Even though the user must manage the cache coherence for read accesses.
Please refer to the AN4838 “Managing memory protection unit (MPU) in STM32 MCUs”
Please refer to the AN4839 “Level 1 cache on STM32F7 Series”
@par Directory contents
- ADC/ADC_RegularConversion_DMA/Inc/stm32f7xx_hal_conf.h HAL configuration file
- ADC/ADC_RegularConversion_DMA/Inc/stm32f7xx_it.h DMA interrupt handlers header file
- ADC/ADC_RegularConversion_DMA/Inc/main.h Header for main.c module
- ADC/ADC_RegularConversion_DMA/Src/stm32f7xx_it.c DMA interrupt handlers
- ADC/ADC_RegularConversion_DMA/Src/main.c Main program
- ADC/ADC_RegularConversion_DMA/Src/stm32f7xx_hal_msp.c HAL MSP file
- ADC/ADC_RegularConversion_DMA/Src/system_stm32f7xx.c STM32F7xx system source file
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/** @addtogroup STM32F7xx_HAL_Examples
* @{
*/
/** @addtogroup ADC_RegularConversion_DMA
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* ADC handler declaration */
ADC_HandleTypeDef AdcHandle;
/* Variable used to get converted value */
__IO uint16_t uhADCxConvertedValue = 0;
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void Error_Handler(void);
static void CPU_CACHE_Enable(void);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
ADC_ChannelConfTypeDef sConfig;
/* Enable the CPU Cache */
CPU_CACHE_Enable();
/* STM32F7xx HAL library initialization:
- Configure the Flash prefetch
- Systick timer is configured by default as source of time base, but user
can eventually implement his proper time base source (a general purpose
timer for example or other time source), keeping in mind that Time base
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis.
- Set NVIC Group Priority to 4
- Low Level Initialization
*/
HAL_Init();
/* Configure the system clock to 216 MHz */
SystemClock_Config();
/* Configure LED1 */
BSP_LED_Init(LED1);
/*##-1- Configure the ADC peripheral #######################################*/
AdcHandle.Instance = ADCx;
AdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
AdcHandle.Init.Resolution = ADC_RESOLUTION_12B;
AdcHandle.Init.ScanConvMode = DISABLE; /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
AdcHandle.Init.ContinuousConvMode = ENABLE; /* Continuous mode enabled to have continuous conversion */
AdcHandle.Init.DiscontinuousConvMode = DISABLE; /* Parameter discarded because sequencer is disabled */
AdcHandle.Init.NbrOfDiscConversion = 0;
AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Conversion start trigged at each external event */
AdcHandle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
AdcHandle.Init.NbrOfConversion = 1;
AdcHandle.Init.DMAContinuousRequests = ENABLE;
AdcHandle.Init.EOCSelection = DISABLE;
if (HAL_ADC_Init(&AdcHandle) != HAL_OK)
{
/* ADC initialization Error */
Error_Handler();
}
/*##-2- Configure ADC regular channel ######################################*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
{
/* Channel Configuration Error */
Error_Handler();
}
/*##-3- Start the conversion process #######################################*/
if(HAL_ADC_Start_DMA(&AdcHandle, (uint32_t*)&uhADCxConvertedValue, 1) != HAL_OK)
{
/* Start Conversation Error */
Error_Handler();
}
/* Infinite loop */
while (1)
{
}
}
/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 216000000
* HCLK(Hz) = 216000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSE Frequency(Hz) = 25000000
* PLL_M = 25
* PLL_N = 432
* PLL_P = 2
* PLL_Q = 9
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 7
* @param None
* @retval None
*/
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
HAL_StatusTypeDef ret = HAL_OK;
/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 432;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 9;
ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Activate the OverDrive to reach the 216 MHz Frequency */
ret = HAL_PWREx_EnableOverDrive();
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);
if(ret != HAL_OK)
{
while(1) { ; }
}
}
/**
* @brief This function is executed in case of error occurrence.
* @param None
* @retval None
*/
static void Error_Handler(void)
{
while (1)
{
/* LED1 blinks */
BSP_LED_Toggle(LED1);
HAL_Delay(20);
}
}
/**
* @brief Conversion complete callback in non blocking mode
* @param AdcHandle : AdcHandle handle
* @note This example shows a simple way to report end of conversion, and
* you can add your own implementation.
* @retval None
*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/* Turn LED1 on: Transfer process is correct */
BSP_LED_On(LED1);
}
/**
* @brief CPU L1-Cache enable.
* @param None
* @retval None
*/
static void CPU_CACHE_Enable(void)
{
/* Enable I-Cache */
SCB_EnableICache();
/* Enable D-Cache */
SCB_EnableDCache();
}
Showing posts with label stm32 tutorial. Show all posts
Showing posts with label stm32 tutorial. Show all posts
Sunday, April 12, 2020
Thursday, April 9, 2020
$3- DAC_SignalsGeneration | STM32F7 Tutorial | Example code with HAL

@par Example Description
How to use the DAC peripheral to generate several signals using the DMA controller.
For each press on User push-button, a signal has been selected and can be monitored on
the DAC channel one:
- Triangle waveform (Channel 1).
- Escalator waveform (Channel 1) using DMA transfer.
STM32746G-DISCOVERY board's LED can be used to monitor the process status:
- LED1 is slowly blinking (1 sec. period) and example is stopped (using infinite loop)
when there is an error during process.
@note Care must be taken when using HAL_Delay(), this function provides accurate delay (in milliseconds)
based on variable incremented in SysTick ISR. This implies that if HAL_Delay() is called from
a peripheral ISR process, then the SysTick interrupt must have higher priority (numerically lower)
than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
To change the SysTick interrupt priority you have to use HAL_NVIC_SetPriority() function.
@note The application need to ensure that the SysTick time base is always set to 1 millisecond
to have correct HAL operation.
@par Keywords
Analog, DAC, Signals generation, DMA, Triangle, Escalator, Waveform, Amplitude
@Note If the user code size exceeds the DTCM-RAM size or starts from internal cacheable memories (SRAM1 and SRAM2),that is shared between several processors,
then it is highly recommended to enable the CPU cache and maintain its coherence at application level.
The address and the size of cacheable buffers (shared between CPU and other masters) must be properly updated to be aligned to cache line size (32 bytes).
@Note It is recommended to enable the cache and maintain its coherence, but depending on the use case
It is also possible to configure the MPU as "Write through", to guarantee the write access coherence.
In that case, the MPU must be configured as Cacheable/Bufferable/Not Shareable.
Even though the user must manage the cache coherence for read accesses.
Please refer to the AN4838 “Managing memory protection unit (MPU) in STM32 MCUs”
Please refer to the AN4839 “Level 1 cache on STM32F7 Series”
1. main.h
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f7xx_hal.h"
#include "stm32746g_discovery.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* User can use this section to tailor DACx instance used and associated resources */
/* Definition for DACx clock resources */
#define DACx DAC
#define DACx_CHANNEL_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define DMAx_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE()
#define DACx_CLK_ENABLE() __HAL_RCC_DAC_CLK_ENABLE()
#define DACx_FORCE_RESET() __HAL_RCC_DAC_FORCE_RESET()
#define DACx_RELEASE_RESET() __HAL_RCC_DAC_RELEASE_RESET()
/* Definition for DACx Channel Pin */
#define DACx_CHANNEL_PIN GPIO_PIN_4
#define DACx_CHANNEL_GPIO_PORT GPIOA
/* Definition for DACx's Channel */
#define DACx_DMA_CHANNEL DMA_CHANNEL_7
#define DACx_CHANNEL DAC_CHANNEL_1
/* Definition for DACx's DMA_STREAM */
#define DACx_DMA_INSTANCE DMA1_Stream5
/* Definition for DACx's NVIC */
#define DACx_DMA_IRQn DMA1_Stream5_IRQn
#define DACx_DMA_IRQHandler DMA1_Stream5_IRQHandler
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#endif /* __MAIN_H */
2.main.c
DAC_HandleTypeDef DacHandle;
static DAC_ChannelConfTypeDef sConfig;
const uint8_t aEscalator8bit[6] = {0x0, 0x33, 0x66, 0x99, 0xCC, 0xFF};
__IO uint8_t ubSelectedWavesForm = 1;
__IO uint8_t ubKeyPressed = SET;
/* Private function prototypes -----------------------------------------------*/
static void DAC_Ch1_TriangleConfig(void);
static void DAC_Ch1_EscalatorConfig(void);
static void TIM6_Config(void);
void SystemClock_Config(void);
static void Error_Handler(void);
static void CPU_CACHE_Enable(void);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
/* Enable the CPU Cache */
CPU_CACHE_Enable();
/* STM32F7xx HAL library initialization:
- Configure the Flash prefetch
- Systick timer is configured by default as source of time base, but user
can eventually implement his proper time base source (a general purpose
timer for example or other time source), keeping in mind that Time base
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis.
- Set NVIC Group Priority to 4
- Low Level Initialization
*/
HAL_Init();
/* Configure the system clock to 216 MHz */
SystemClock_Config();
/* Configure LED1 */
BSP_LED_Init(LED1);
/* Configures User push-button */
BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_EXTI);
/*##-1- Configure the DAC peripheral #######################################*/
DacHandle.Instance = DACx;
/*##-2- Configure the TIM peripheral #######################################*/
TIM6_Config();
/* Infinite loop */
while (1)
{
/* If the Key is pressed */
if (ubKeyPressed != RESET)
{
HAL_DAC_DeInit(&DacHandle);
/* select waves forms according to the User push-button status */
if (ubSelectedWavesForm == 1)
{
/* The triangle wave has been selected */
/* Triangle Wave generator -------------------------------------------*/
DAC_Ch1_TriangleConfig();
}
else
{
/* The escalator wave has been selected */
/* Escalator Wave generator -------------------------------------------*/
DAC_Ch1_EscalatorConfig();
}
ubKeyPressed = RESET;
}
}
}
/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 216000000
* HCLK(Hz) = 216000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSE Frequency(Hz) = 25000000
* PLL_M = 25
* PLL_N = 432
* PLL_P = 2
* PLL_Q = 9
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 7
* @param None
* @retval None
*/
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
HAL_StatusTypeDef ret = HAL_OK;
/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 432;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 9;
ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Activate the OverDrive to reach the 216 MHz Frequency */
ret = HAL_PWREx_EnableOverDrive();
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);
if(ret != HAL_OK)
{
while(1) { ; }
}
}
/**
* @brief This function is executed in case of error occurrence.
* @param None
* @retval None
*/
static void Error_Handler(void)
{
/* Error if LED1 is slowly blinking (1 sec. period) */
while(1)
{
BSP_LED_Toggle(LED1);
HAL_Delay(1000);
}
}
static void DAC_Ch1_EscalatorConfig(void)
{
/*##-1- Initialize the DAC peripheral ######################################*/
if (HAL_DAC_Init(&DacHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/*##-1- DAC channel1 Configuration #########################################*/
sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
if (HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DACx_CHANNEL) != HAL_OK)
{
/* Channel configuration Error */
Error_Handler();
}
/*##-2- Enable DAC selected channel and associated DMA #############################*/
if (HAL_DAC_Start_DMA(&DacHandle, DACx_CHANNEL, (uint32_t *)aEscalator8bit, 6, DAC_ALIGN_8B_R) != HAL_OK)
{
/* Start DMA Error */
Error_Handler();
}
}
/**
* @brief DAC Channel1 Triangle Configuration
* @param None
* @retval None
*/
static void DAC_Ch1_TriangleConfig(void)
{
/*##-1- Initialize the DAC peripheral ######################################*/
if (HAL_DAC_Init(&DacHandle) != HAL_OK)
{
/* DAC initialization Error */
Error_Handler();
}
/*##-2- DAC channel2 Configuration #########################################*/
sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
if (HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DACx_CHANNEL) != HAL_OK)
{
/* Channel configuration Error */
Error_Handler();
}
/*##-3- DAC channel2 Triangle Wave generation configuration ################*/
if (HAL_DACEx_TriangleWaveGenerate(&DacHandle, DACx_CHANNEL, DAC_TRIANGLEAMPLITUDE_1023) != HAL_OK)
{
/* Triangle wave generation Error */
Error_Handler();
}
/*##-4- Enable DAC Channel1 ################################################*/
if (HAL_DAC_Start(&DacHandle, DACx_CHANNEL) != HAL_OK)
{
/* Start Error */
Error_Handler();
}
/*##-5- Set DAC channel1 DHR12RD register ################################################*/
if (HAL_DAC_SetValue(&DacHandle, DACx_CHANNEL, DAC_ALIGN_12B_R, 0x100) != HAL_OK)
{
/* Setting value Error */
Error_Handler();
}
}
/**
* @brief EXTI line detection callbacks
* @param GPIO_Pin: Specifies the pins connected EXTI line
* @retval None
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Change the wave */
ubKeyPressed = 1;
/* Change the selected waves forms */
ubSelectedWavesForm = !ubSelectedWavesForm;
}
/**
* @brief TIM6 Configuration
* @note TIM6 configuration is based on APB1 frequency
* @note TIM6 Update event occurs each TIM6CLK/256
* @param None
* @retval None
*/
void TIM6_Config(void)
{
static TIM_HandleTypeDef htim;
TIM_MasterConfigTypeDef sMasterConfig;
/*##-1- Configure the TIM peripheral #######################################*/
/* Time base configuration */
htim.Instance = TIM6;
htim.Init.Period = 0x7FF;
htim.Init.Prescaler = 0;
htim.Init.ClockDivision = 0;
htim.Init.CounterMode = TIM_COUNTERMODE_UP;
htim.Init.RepetitionCounter = 0;
htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_Base_Init(&htim);
/* TIM6 TRGO selection */
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig);
/*##-2- Enable TIM peripheral counter ######################################*/
HAL_TIM_Base_Start(&htim);
}
/**
* @brief CPU L1-Cache enable.
* @param None
* @retval None
*/
static void CPU_CACHE_Enable(void)
{
/* Enable I-Cache */
SCB_EnableICache();
/* Enable D-Cache */
SCB_EnableDCache();
}
Wednesday, April 8, 2020
$2- UART with DMA | STM32F7 Tutorial | Example code with HAL

@par Example Description
UART transmission (transmit/receive) in DMA mode between two boards.
Board: STM32F769I-DISCOVERY (embeds a STM32F769xx device)
Tx Pin: CN4.D1
Rx Pin: CN4.D0
_________________________ _________________________
| ______________| |______________ |
| |USART | | USART| |
| | | | | |
| | TX |_____________________| RX | |
| | | | | |
| | | | | |
| | | | | |
| | RX |_____________________| TX | |
| | | | | |
| |______________| |______________| |
| | | |
| GND|_____________________|GND |
|_STM32_Board 1___________| |_STM32_Board 2___________|
Two identical boards are connected as shown on the picture above.
Board 1: transmitting then receiving board
Board 2: receiving then transmitting board
The user presses the User push-button on board 1.
Then, board 1 sends in DMA mode a message to board 2 that sends it back to board 1 in DMA mode as well.
Finally, board 1 and 2 compare the received message to that sent.
If the messages are the same, the test passes.
WARNING: as both boards do not behave the same way, "TRANSMITTER_BOARD" compilation
switch is defined in /Src/main.c and must be enabled at compilation time before loading the executable in the board that first transmits then receives.
The receiving then transmitting board needs to be loaded with an executable software obtained with TRANSMITTER_BOARD disabled.
STM32F769I-DISCOVERY board LED is used to monitor the transfer status:
- While board 1 is waiting for the user to press the User push-button, its LED1 is blinking rapidly (100 ms period).
- While board 2 is waiting for the message from board 1, its LED1 is emitting
a couple of flashes every half-second.
- When the test passes, LED1 on both boards is turned on, otherwise the test has failed.
- If there is an initialization or transfer error, LED1 is slowly blinking (1 sec. period).
At the beginning of the main program the HAL_Init() function is called to reset
all the peripherals, initialize the Flash interface and the systick.
Then the SystemClock_Config() function is used to configure the system
clock (SYSCLK) to run at 216 MHz.
The UART is configured as follows:
- BaudRate = 9600 baud
- Word Length = 8 bits (8 data bits, no parity bit)
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Reception and transmission are enabled in the time
@note USARTx/UARTx instance used and associated resources can be updated in "main.h"
file depending hardware configuration used.
@note When the parity is enabled, the computed parity is inserted at the MSB
position of the transmitted data.
@note Care must be taken when using HAL_Delay(), this function provides accurate delay (in milliseconds)
based on variable incremented in SysTick ISR. This implies that if HAL_Delay() is called from
a peripheral ISR process, then the SysTick interrupt must have higher priority (numerically lower)
than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
To change the SysTick interrupt priority you have to use HAL_NVIC_SetPriority() function.
@note The application need to ensure that the SysTick time base is always set to 1 millisecond
to have correct HAL operation.
@par Keywords
Connectivity, UART, Baud rate, RS-232, Full-duplex, DMA, Parity, Stop bit, Transmission, Reception,
@Note If the user code size exceeds the DTCM-RAM size or starts from internal cacheable memories (SRAM1 and SRAM2),that is shared between several processors,
then it is highly recommended to enable the CPU cache and maintain its coherence at application level.
The address and the size of cacheable buffers (shared between CPU and other masters) must be properly updated to be aligned to cache line size (32 bytes).
@Note It is recommended to enable the cache and maintain its coherence, but depending on the use case
It is also possible to configure the MPU as "Write through", to guarantee the write access coherence.
In that case, the MPU must be configured as Cacheable/Bufferable/Not Shareable.
Even though the user must manage the cache coherence for read accesses.
Please refer to the AN4838 “Managing memory protection unit (MPU) in STM32 MCUs”
Please refer to the AN4839 “Level 1 cache on STM32F7 Series”
Code:
I compile both code of TX and RX boards in 1 main.c file.
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/** @addtogroup STM32F7xx_HAL_Examples
* @{
*/
/** @addtogroup UART_TwoBoards_ComDMA
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define TRANSMITTER_BOARD
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* UART handler declaration */
UART_HandleTypeDef UartHandle;
__IO ITStatus UartReady = RESET;
__IO uint32_t UserButtonStatus = 0; /* set to 1 after User Button interrupt */
/* Buffer used for transmission */
uint8_t aTxBuffer[] = " ****UART_TwoBoards communication based on DMA**** ****UART_TwoBoards communication based on DMA**** ****UART_TwoBoards communication based on DMA**** ";
/* Buffer used for reception */
uint8_t aRxBuffer[RXBUFFERSIZE];
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void Error_Handler(void);
static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);
static void CPU_CACHE_Enable(void);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
/* Enable the CPU Cache */
CPU_CACHE_Enable();
/* STM32F7xx HAL library initialization:
- Configure the Flash ART accelerator
- Systick timer is configured by default as source of time base, but user
can eventually implement his proper time base source (a general purpose
timer for example or other time source), keeping in mind that Time base
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis.
- Set NVIC Group Priority to 4
- Low Level Initialization
*/
HAL_Init();
/* Configure the system clock to 216 MHz */
SystemClock_Config();
/* Configure LED1 & LED2 */
BSP_LED_Init(LED1);
BSP_LED_Init(LED2);
/*##-1- Configure the UART peripheral ######################################*/
/* Put the USART peripheral in the Asynchronous mode (UART Mode) */
/* UART configured as follows:
- Word Length = 8 Bits
- Stop Bit = One Stop bit
- Parity = None
- BaudRate = 9600 baud
- Hardware flow control disabled (RTS and CTS signals) */
UartHandle.Instance = USARTx;
UartHandle.Init.BaudRate = 9600;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
if(HAL_UART_DeInit(&UartHandle) != HAL_OK)
{
Error_Handler();
}
if(HAL_UART_Init(&UartHandle) != HAL_OK)
{
Error_Handler();
}
#ifdef TRANSMITTER_BOARD
/* Configure User push-button in Interrupt mode */
BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);
/* Wait for User push-button press before starting the Communication.
In the meantime, LED1 is blinking */
while(UserButtonStatus == 0)
{
/* Toggle LED1*/
BSP_LED_Toggle(LED1);
HAL_Delay(100);
}
BSP_LED_Off(LED1);
/* The board sends the message and expects to receive it back */
/* DMA is programmed for reception before starting the transmission, in order to
be sure DMA Rx is ready when board 2 will start transmitting */
/*##-2- Program the Reception process #####################################*/
if(HAL_UART_Receive_DMA(&UartHandle, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)
{
Error_Handler();
}
/*##-3- Start the transmission process #####################################*/
/* While the UART in reception process, user can transmit data through
"aTxBuffer" buffer */
if(HAL_UART_Transmit_DMA(&UartHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
{
Error_Handler();
}
/*##-4- Wait for the end of the transfer ###################################*/
while (UartReady != SET)
{
}
/* Reset transmission flag */
UartReady = RESET;
#else
/* The board receives the message and sends it back */
/*##-2- Put UART peripheral in reception process ###########################*/
if(HAL_UART_Receive_DMA(&UartHandle, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)
{
Error_Handler();
}
/*##-3- Wait for the end of the transfer ###################################*/
/* While waiting for message to come from the other board, LED1 is
blinking according to the following pattern: a double flash every half-second */
while (UartReady != SET)
{
BSP_LED_On(LED1);
HAL_Delay(100);
BSP_LED_Off(LED1);
HAL_Delay(100);
BSP_LED_On(LED1);
HAL_Delay(100);
BSP_LED_Off(LED1);
HAL_Delay(500);
}
/* Reset transmission flag */
UartReady = RESET;
BSP_LED_Off(LED1);
/*##-4- Start the transmission process #####################################*/
/* While the UART in reception process, user can transmit data through
"aTxBuffer" buffer */
if(HAL_UART_Transmit_DMA(&UartHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
{
Error_Handler();
}
#endif /* TRANSMITTER_BOARD */
/*##-5- Wait for the end of the transfer ###################################*/
while (UartReady != SET)
{
}
/* Reset transmission flag */
UartReady = RESET;
/*##-6- Compare the sent and received buffers ##############################*/
if(Buffercmp((uint8_t*)aTxBuffer,(uint8_t*)aRxBuffer,RXBUFFERSIZE))
{
Error_Handler();
}
/* Turn on LED1 if test passes then enter infinite loop */
BSP_LED_On(LED2);
/* Infinite loop */
while (1)
{
}
}
/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 216000000
* HCLK(Hz) = 216000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSE Frequency(Hz) = 25000000
* PLL_M = 25
* PLL_N = 432
* PLL_P = 2
* PLL_Q = 9
* PLL_R = 7
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 7
* @param None
* @retval None
*/
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
HAL_StatusTypeDef ret = HAL_OK;
/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 432;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 9;
RCC_OscInitStruct.PLL.PLLR = 7;
ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Activate the OverDrive to reach the 216 MHz Frequency */
ret = HAL_PWREx_EnableOverDrive();
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);
if(ret != HAL_OK)
{
while(1) { ; }
}
}
/**
* @brief Tx Transfer completed callback
* @param UartHandle: UART handle.
* @note This example shows a simple way to report end of DMA Tx transfer, and
* you can add your own implementation.
* @retval None
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle)
{
/* Set transmission flag: trasfer complete*/
UartReady = SET;
}
/**
* @brief Rx Transfer completed callback
* @param UartHandle: UART handle
* @note This example shows a simple way to report end of DMA Rx transfer, and
* you can add your own implementation.
* @retval None
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
/* Set transmission flag: trasfer complete*/
UartReady = SET;
}
/**
* @brief UART error callbacks
* @param UartHandle: UART handle
* @note This example shows a simple way to report transfer error, and you can
* add your own implementation.
* @retval None
*/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle)
{
Error_Handler();
}
/**
* @brief EXTI line detection callbacks
* @param GPIO_Pin: Specifies the pins connected EXTI line
* @retval None
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == USER_BUTTON_PIN)
{
UserButtonStatus = 1;
}
}
/**
* @brief Compares two buffers.
* @param pBuffer1, pBuffer2: buffers to be compared.
* @param BufferLength: buffer's length
* @retval 0 : pBuffer1 identical to pBuffer2
* >0 : pBuffer1 differs from pBuffer2
*/
static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
while (BufferLength--)
{
if ((*pBuffer1) != *pBuffer2)
{
return BufferLength;
}
pBuffer1++;
pBuffer2++;
}
return 0;
}
/**
* @brief This function is executed in case of error occurrence.
* @param None
* @retval None
*/
static void Error_Handler(void)
{
/* Turn LED1 on */
BSP_LED_On(LED1);
while(1)
{
/* Error if LED1 is slowly blinking (1 sec. period) */
BSP_LED_Toggle(LED1);
HAL_Delay(1000);
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**
* @brief CPU L1-Cache enable.
* @param None
* @retval None
*/
static void CPU_CACHE_Enable(void)
{
/* Enable I-Cache */
SCB_EnableICache();
/* Enable D-Cache */
SCB_EnableDCache();
}
$1- GPIO and External Interrupt | STM32F7 Tutorial | Example code with HAL
@par Example Description
How to configure external interrupt lines.
In this example, one EXTI line (EXTI0) is configured to generate an interrupt on each rising edge.
In the interrupt routine a led connected to a specific GPIO pin is toggled.
In this example:
- EXTI0 is connected to PA.0 pin
- when rising edge is detected on EXTI0 by pressing User button, LED2 toggles once
On STM32F769I-DISCO:
- EXTI0 is connected to Use button
In this example, HCLK is configured at 216 MHz.
@note Care must be taken when using HAL_Delay(), this function provides accurate delay (in milliseconds)
based on variable incremented in SysTick ISR. This implies that if HAL_Delay() is called from
a peripheral ISR process, then the SysTick interrupt must have higher priority (numerically lower)
than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
To change the SysTick interrupt priority you have to use HAL_NVIC_SetPriority() function.
@note The application need to ensure that the SysTick time base is always set to 1 millisecond
to have correct HAL operation.
@Note If the user code size exceeds the DTCM-RAM size or starts from internal cacheable memories (SRAM1 and SRAM2),that is shared between several processors,then it is highly recommended to enable the CPU cache and maintain its coherence at application level.
The address and the size of cacheable buffers (shared between CPU and other masters) must be properly updated to be aligned to cache line size (32 bytes).
@Note It is recommended to enable the cache and maintain its coherence, but depending on the use case
It is also possible to configure the MPU as "Write through", to guarantee the write access coherence.
In that case, the MPU must be configured as Cacheable/Bufferable/Not Shareable.
Even though the user must manage the cache coherence for read accesses.
Please refer to the AN4838 “Managing memory protection unit (MPU) in STM32 MCUs”
Please refer to the AN4839 “Level 1 cache on STM32F7 Series”
main.c
/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void EXTI0_IRQHandler_Config(void);
static void CPU_CACHE_Enable(void);
/* Private functions ---------------------------------------------------------*/
int main(void)
{
/* Enable the CPU Cache */
CPU_CACHE_Enable();
/* STM32F7xx HAL library initialization:
- Configure the Flash prefetch
- Systick timer is configured by default as source of time base, but user
can eventually implement his proper time base source (a general purpose
timer for example or other time source), keeping in mind that Time base
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis.
- Set NVIC Group Priority to 4
- Low Level Initialization
*/
HAL_Init();
/* Configure the system clock to 216 MHz */
SystemClock_Config();
/* -1- Initialize LED2 */
BSP_LED_Init(LED2);
/* -2- Configure EXTI0 (connected to PA.00 pin) in interrupt mode */
EXTI0_IRQHandler_Config();
/* Infinite loop */
while (1)
{
}
}
/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 216000000
* HCLK(Hz) = 216000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSE Frequency(Hz) = 25000000
* PLL_M = 25
* PLL_N = 432
* PLL_P = 2
* PLL_Q = 9
* PLL_R = 7
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 7
* @param None
* @retval None
*/
static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
HAL_StatusTypeDef ret = HAL_OK;
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 432;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 9;
RCC_OscInitStruct.PLL.PLLR = 7;
ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Activate the OverDrive to reach the 216 MHz Frequency */
ret = HAL_PWREx_EnableOverDrive();
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);
if(ret != HAL_OK)
{
while(1) { ; }
}
}
/**
* @brief Configures EXTI line 0 (connected to PA.00 pin) in interrupt mode
* @param None
* @retval None
*/
static void EXTI0_IRQHandler_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOC clock */
__HAL_RCC_GPIOA_CLK_ENABLE();
/* Configure PC.13 pin as input floating */
GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = GPIO_PIN_0;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable and set EXTI line 0 Interrupt to the lowest priority */
HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
/**
* @brief EXTI line detection callbacks
* @param GPIO_Pin: Specifies the pins connected EXTI line
* @retval None
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_0)
{
/* Toggle LED2 */
BSP_LED_Toggle(LED2);
}
}
/**
* @brief CPU L1-Cache enable.
* @param None
* @retval None
*/
static void CPU_CACHE_Enable(void)
{
/* Enable I-Cache */
SCB_EnableICache();
/* Enable D-Cache */
SCB_EnableDCache();
}
How to configure external interrupt lines.
In this example, one EXTI line (EXTI0) is configured to generate an interrupt on each rising edge.
In the interrupt routine a led connected to a specific GPIO pin is toggled.
In this example:
- EXTI0 is connected to PA.0 pin
- when rising edge is detected on EXTI0 by pressing User button, LED2 toggles once
On STM32F769I-DISCO:
- EXTI0 is connected to Use button
In this example, HCLK is configured at 216 MHz.
@note Care must be taken when using HAL_Delay(), this function provides accurate delay (in milliseconds)
based on variable incremented in SysTick ISR. This implies that if HAL_Delay() is called from
a peripheral ISR process, then the SysTick interrupt must have higher priority (numerically lower)
than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
To change the SysTick interrupt priority you have to use HAL_NVIC_SetPriority() function.
@note The application need to ensure that the SysTick time base is always set to 1 millisecond
to have correct HAL operation.
@Note If the user code size exceeds the DTCM-RAM size or starts from internal cacheable memories (SRAM1 and SRAM2),that is shared between several processors,then it is highly recommended to enable the CPU cache and maintain its coherence at application level.
The address and the size of cacheable buffers (shared between CPU and other masters) must be properly updated to be aligned to cache line size (32 bytes).
@Note It is recommended to enable the cache and maintain its coherence, but depending on the use case
It is also possible to configure the MPU as "Write through", to guarantee the write access coherence.
In that case, the MPU must be configured as Cacheable/Bufferable/Not Shareable.
Even though the user must manage the cache coherence for read accesses.
Please refer to the AN4838 “Managing memory protection unit (MPU) in STM32 MCUs”
Please refer to the AN4839 “Level 1 cache on STM32F7 Series”
main.c
/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void EXTI0_IRQHandler_Config(void);
static void CPU_CACHE_Enable(void);
/* Private functions ---------------------------------------------------------*/
int main(void)
{
/* Enable the CPU Cache */
CPU_CACHE_Enable();
/* STM32F7xx HAL library initialization:
- Configure the Flash prefetch
- Systick timer is configured by default as source of time base, but user
can eventually implement his proper time base source (a general purpose
timer for example or other time source), keeping in mind that Time base
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis.
- Set NVIC Group Priority to 4
- Low Level Initialization
*/
HAL_Init();
/* Configure the system clock to 216 MHz */
SystemClock_Config();
/* -1- Initialize LED2 */
BSP_LED_Init(LED2);
/* -2- Configure EXTI0 (connected to PA.00 pin) in interrupt mode */
EXTI0_IRQHandler_Config();
/* Infinite loop */
while (1)
{
}
}
/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 216000000
* HCLK(Hz) = 216000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSE Frequency(Hz) = 25000000
* PLL_M = 25
* PLL_N = 432
* PLL_P = 2
* PLL_Q = 9
* PLL_R = 7
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 7
* @param None
* @retval None
*/
static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
HAL_StatusTypeDef ret = HAL_OK;
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 432;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 9;
RCC_OscInitStruct.PLL.PLLR = 7;
ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Activate the OverDrive to reach the 216 MHz Frequency */
ret = HAL_PWREx_EnableOverDrive();
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);
if(ret != HAL_OK)
{
while(1) { ; }
}
}
/**
* @brief Configures EXTI line 0 (connected to PA.00 pin) in interrupt mode
* @param None
* @retval None
*/
static void EXTI0_IRQHandler_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOC clock */
__HAL_RCC_GPIOA_CLK_ENABLE();
/* Configure PC.13 pin as input floating */
GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = GPIO_PIN_0;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable and set EXTI line 0 Interrupt to the lowest priority */
HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
/**
* @brief EXTI line detection callbacks
* @param GPIO_Pin: Specifies the pins connected EXTI line
* @retval None
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_0)
{
/* Toggle LED2 */
BSP_LED_Toggle(LED2);
}
}
/**
* @brief CPU L1-Cache enable.
* @param None
* @retval None
*/
static void CPU_CACHE_Enable(void)
{
/* Enable I-Cache */
SCB_EnableICache();
/* Enable D-Cache */
SCB_EnableDCache();
}
Saturday, April 4, 2020
Flash Program STM32 | Example code STM32 with Std Lib
@par Example Description
This example provides a description of how to program the FLASH memory integrated
within STM32F40xx/41xx and STM32F427x/437x Devices.
After Reset, the Flash memory Program/Erase Controller is locked. To unlock it,
the FLASH_Unlock function is used.
Before programming the desired addresses, an erase operation is performed using
the flash erase sector feature. The erase procedure starts with the calculation of
the number of sector to be used. Then all these sectors will be erased one by one.
Once this operation is finished, the programming operation will be performed using
the word programming function. The written data is then checked (read the
content of memory and compare it to the expected data).
If all the data are correct, the LED1 is on, otherwise the LED2 is on.
1. main,h
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
/* Includes ------------------------------------------------------------------*/
#if defined (USE_STM324xG_EVAL)
#include "stm324xg_eval.h"
#elif defined (USE_STM324x7I_EVAL)
#include "stm324x7i_eval.h"
#else
#error "Please select first the Evaluation board used in your application (in Project Options)"
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define FLASH_USER_START_ADDR ADDR_FLASH_SECTOR_4 /* Start @ of user Flash area */
#if defined (USE_STM324xG_EVAL)
#define FLASH_USER_END_ADDR ADDR_FLASH_SECTOR_11 /* End @ of user Flash area */
#else /* USE_STM324x7I_EVAL*/
#define FLASH_USER_END_ADDR ADDR_FLASH_SECTOR_23 /* End @ of user Flash area */
#endif
/* Base address of the Flash sectors */
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */
#if defined (USE_STM324x7I_EVAL)
#define ADDR_FLASH_SECTOR_12 ((uint32_t)0x08100000) /* Base @ of Sector 12, 16 Kbytes */
#define ADDR_FLASH_SECTOR_13 ((uint32_t)0x08104000) /* Base @ of Sector 13, 16 Kbytes */
#define ADDR_FLASH_SECTOR_14 ((uint32_t)0x08108000) /* Base @ of Sector 14, 16 Kbytes */
#define ADDR_FLASH_SECTOR_15 ((uint32_t)0x0810C000) /* Base @ of Sector 15, 16 Kbytes */
#define ADDR_FLASH_SECTOR_16 ((uint32_t)0x08110000) /* Base @ of Sector 16, 64 Kbytes */
#define ADDR_FLASH_SECTOR_17 ((uint32_t)0x08120000) /* Base @ of Sector 17, 128 Kbytes */
#define ADDR_FLASH_SECTOR_18 ((uint32_t)0x08140000) /* Base @ of Sector 18, 128 Kbytes */
#define ADDR_FLASH_SECTOR_19 ((uint32_t)0x08160000) /* Base @ of Sector 19, 128 Kbytes */
#define ADDR_FLASH_SECTOR_20 ((uint32_t)0x08180000) /* Base @ of Sector 20, 128 Kbytes */
#define ADDR_FLASH_SECTOR_21 ((uint32_t)0x081A0000) /* Base @ of Sector 21, 128 Kbytes */
#define ADDR_FLASH_SECTOR_22 ((uint32_t)0x081C0000) /* Base @ of Sector 22, 128 Kbytes */
#define ADDR_FLASH_SECTOR_23 ((uint32_t)0x081E0000) /* Base @ of Sector 23, 128 Kbytes */
#endif /* USE_STM324x7I_EVAL */
#define DATA_32 ((uint32_t)0x12345678)
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#endif /* __MAIN_H */
2 main.c
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint32_t uwStartSector = 0;
uint32_t uwEndSector = 0;
uint32_t uwAddress = 0;
uint32_t uwSectorCounter = 0;
__IO uint32_t uwData32 = 0;
__IO uint32_t uwMemoryProgramStatus = 0;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
static uint32_t GetSector(uint32_t Address);
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
files (startup_stm32f40xx.s/startup_stm32f427x.s) before to branch to
application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f4xx.c file
*/
/* Initialize LEDs on EVAL board ********************************************/
STM_EVAL_LEDInit(LED1);
STM_EVAL_LEDInit(LED2);
/* Unlock the Flash *********************************************************/
/* Enable the flash control register access */
FLASH_Unlock();
/* Erase the user Flash area ************************************************/
/* area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR */
/* Clear pending flags (if any) */
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
/* Get the number of the start and end sectors */
uwStartSector = GetSector(FLASH_USER_START_ADDR);
uwEndSector = GetSector(FLASH_USER_END_ADDR);
/* Strat the erase operation */
uwSectorCounter = uwStartSector;
while (uwSectorCounter <= uwEndSector)
{
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
be done by word */
if (FLASH_EraseSector(uwSectorCounter, VoltageRange_3) != FLASH_COMPLETE)
{
/* Error occurred while sector erase.
User can add here some code to deal with this error */
while (1)
{
}
}
/* jump to the next sector */
if (uwSectorCounter == FLASH_Sector_11)
{
uwSectorCounter += 40;
}
else
{
uwSectorCounter += 8;
}
}
/* Program the user Flash area word by word ********************************/
/* area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR */
uwAddress = FLASH_USER_START_ADDR;
while (uwAddress < FLASH_USER_END_ADDR)
{
if (FLASH_ProgramWord(uwAddress, DATA_32) == FLASH_COMPLETE)
{
uwAddress = uwAddress + 4;
}
else
{
/* Error occurred while writing data in Flash memory.
User can add here some code to deal with this error */
while (1)
{
}
}
}
/* Lock the Flash to disable the flash control register access (recommended
to protect the FLASH memory against possible unwanted operation) */
FLASH_Lock();
/* Check if the programmed data is OK ***************************************/
/* MemoryProgramStatus = 0: data programmed correctly
MemoryProgramStatus != 0: number of words not programmed correctly */
uwAddress = FLASH_USER_START_ADDR;
uwMemoryProgramStatus = 0;
while (uwAddress < FLASH_USER_END_ADDR)
{
uwData32 = *(__IO uint32_t*)uwAddress;
if (uwData32 != DATA_32)
{
uwMemoryProgramStatus++;
}
uwAddress = uwAddress + 4;
}
/* Check Data correctness */
if(uwMemoryProgramStatus)
{
/* KO */
/* Turn on LD2 */
STM_EVAL_LEDOn(LED2);
}
else
{
/* OK */
/* Turn on LD1 */
STM_EVAL_LEDOn(LED1);
}
while (1)
{
}
}
/**
* @brief Gets the sector of a given address
* @param None
* @retval The sector of a given address
*/
static uint32_t GetSector(uint32_t Address)
{
uint32_t sector = 0;
if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
{
sector = FLASH_Sector_0;
}
else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
{
sector = FLASH_Sector_1;
}
else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
{
sector = FLASH_Sector_2;
}
else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
{
sector = FLASH_Sector_3;
}
else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
{
sector = FLASH_Sector_4;
}
else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
{
sector = FLASH_Sector_5;
}
else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
{
sector = FLASH_Sector_6;
}
else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
{
sector = FLASH_Sector_7;
}
else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
{
sector = FLASH_Sector_8;
}
else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
{
sector = FLASH_Sector_9;
}
else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
{
sector = FLASH_Sector_10;
}
#if defined (USE_STM324xG_EVAL)
else/*(Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_11))*/
{
sector = FLASH_Sector_11;
}
#else /* USE_STM324x7I_EVAL */
else if((Address < ADDR_FLASH_SECTOR_12) && (Address >= ADDR_FLASH_SECTOR_11))
{
sector = FLASH_Sector_11;
}
else if((Address < ADDR_FLASH_SECTOR_13) && (Address >= ADDR_FLASH_SECTOR_12))
{
sector = FLASH_Sector_12;
}
else if((Address < ADDR_FLASH_SECTOR_14) && (Address >= ADDR_FLASH_SECTOR_13))
{
sector = FLASH_Sector_13;
}
else if((Address < ADDR_FLASH_SECTOR_15) && (Address >= ADDR_FLASH_SECTOR_14))
{
sector = FLASH_Sector_14;
}
else if((Address < ADDR_FLASH_SECTOR_16) && (Address >= ADDR_FLASH_SECTOR_15))
{
sector = FLASH_Sector_15;
}
else if((Address < ADDR_FLASH_SECTOR_17) && (Address >= ADDR_FLASH_SECTOR_16))
{
sector = FLASH_Sector_16;
}
else if((Address < ADDR_FLASH_SECTOR_18) && (Address >= ADDR_FLASH_SECTOR_17))
{
sector = FLASH_Sector_17;
}
else if((Address < ADDR_FLASH_SECTOR_19) && (Address >= ADDR_FLASH_SECTOR_18))
{
sector = FLASH_Sector_18;
}
else if((Address < ADDR_FLASH_SECTOR_20) && (Address >= ADDR_FLASH_SECTOR_19))
{
sector = FLASH_Sector_19;
}
else if((Address < ADDR_FLASH_SECTOR_21) && (Address >= ADDR_FLASH_SECTOR_20))
{
sector = FLASH_Sector_20;
}
else if((Address < ADDR_FLASH_SECTOR_22) && (Address >= ADDR_FLASH_SECTOR_21))
{
sector = FLASH_Sector_21;
}
else if((Address < ADDR_FLASH_SECTOR_23) && (Address >= ADDR_FLASH_SECTOR_22))
{
sector = FLASH_Sector_22;
}
else/*(Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_23))*/
{
sector = FLASH_Sector_23;
}
#endif /* USE_STM324x7I_EVAL */
return sector;
}
This example provides a description of how to program the FLASH memory integrated
within STM32F40xx/41xx and STM32F427x/437x Devices.
After Reset, the Flash memory Program/Erase Controller is locked. To unlock it,
the FLASH_Unlock function is used.
Before programming the desired addresses, an erase operation is performed using
the flash erase sector feature. The erase procedure starts with the calculation of
the number of sector to be used. Then all these sectors will be erased one by one.
Once this operation is finished, the programming operation will be performed using
the word programming function. The written data is then checked (read the
content of memory and compare it to the expected data).
If all the data are correct, the LED1 is on, otherwise the LED2 is on.
1. main,h
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
/* Includes ------------------------------------------------------------------*/
#if defined (USE_STM324xG_EVAL)
#include "stm324xg_eval.h"
#elif defined (USE_STM324x7I_EVAL)
#include "stm324x7i_eval.h"
#else
#error "Please select first the Evaluation board used in your application (in Project Options)"
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define FLASH_USER_START_ADDR ADDR_FLASH_SECTOR_4 /* Start @ of user Flash area */
#if defined (USE_STM324xG_EVAL)
#define FLASH_USER_END_ADDR ADDR_FLASH_SECTOR_11 /* End @ of user Flash area */
#else /* USE_STM324x7I_EVAL*/
#define FLASH_USER_END_ADDR ADDR_FLASH_SECTOR_23 /* End @ of user Flash area */
#endif
/* Base address of the Flash sectors */
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */
#if defined (USE_STM324x7I_EVAL)
#define ADDR_FLASH_SECTOR_12 ((uint32_t)0x08100000) /* Base @ of Sector 12, 16 Kbytes */
#define ADDR_FLASH_SECTOR_13 ((uint32_t)0x08104000) /* Base @ of Sector 13, 16 Kbytes */
#define ADDR_FLASH_SECTOR_14 ((uint32_t)0x08108000) /* Base @ of Sector 14, 16 Kbytes */
#define ADDR_FLASH_SECTOR_15 ((uint32_t)0x0810C000) /* Base @ of Sector 15, 16 Kbytes */
#define ADDR_FLASH_SECTOR_16 ((uint32_t)0x08110000) /* Base @ of Sector 16, 64 Kbytes */
#define ADDR_FLASH_SECTOR_17 ((uint32_t)0x08120000) /* Base @ of Sector 17, 128 Kbytes */
#define ADDR_FLASH_SECTOR_18 ((uint32_t)0x08140000) /* Base @ of Sector 18, 128 Kbytes */
#define ADDR_FLASH_SECTOR_19 ((uint32_t)0x08160000) /* Base @ of Sector 19, 128 Kbytes */
#define ADDR_FLASH_SECTOR_20 ((uint32_t)0x08180000) /* Base @ of Sector 20, 128 Kbytes */
#define ADDR_FLASH_SECTOR_21 ((uint32_t)0x081A0000) /* Base @ of Sector 21, 128 Kbytes */
#define ADDR_FLASH_SECTOR_22 ((uint32_t)0x081C0000) /* Base @ of Sector 22, 128 Kbytes */
#define ADDR_FLASH_SECTOR_23 ((uint32_t)0x081E0000) /* Base @ of Sector 23, 128 Kbytes */
#endif /* USE_STM324x7I_EVAL */
#define DATA_32 ((uint32_t)0x12345678)
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#endif /* __MAIN_H */
2 main.c
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint32_t uwStartSector = 0;
uint32_t uwEndSector = 0;
uint32_t uwAddress = 0;
uint32_t uwSectorCounter = 0;
__IO uint32_t uwData32 = 0;
__IO uint32_t uwMemoryProgramStatus = 0;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
static uint32_t GetSector(uint32_t Address);
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
files (startup_stm32f40xx.s/startup_stm32f427x.s) before to branch to
application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f4xx.c file
*/
/* Initialize LEDs on EVAL board ********************************************/
STM_EVAL_LEDInit(LED1);
STM_EVAL_LEDInit(LED2);
/* Unlock the Flash *********************************************************/
/* Enable the flash control register access */
FLASH_Unlock();
/* Erase the user Flash area ************************************************/
/* area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR */
/* Clear pending flags (if any) */
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
/* Get the number of the start and end sectors */
uwStartSector = GetSector(FLASH_USER_START_ADDR);
uwEndSector = GetSector(FLASH_USER_END_ADDR);
/* Strat the erase operation */
uwSectorCounter = uwStartSector;
while (uwSectorCounter <= uwEndSector)
{
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
be done by word */
if (FLASH_EraseSector(uwSectorCounter, VoltageRange_3) != FLASH_COMPLETE)
{
/* Error occurred while sector erase.
User can add here some code to deal with this error */
while (1)
{
}
}
/* jump to the next sector */
if (uwSectorCounter == FLASH_Sector_11)
{
uwSectorCounter += 40;
}
else
{
uwSectorCounter += 8;
}
}
/* Program the user Flash area word by word ********************************/
/* area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR */
uwAddress = FLASH_USER_START_ADDR;
while (uwAddress < FLASH_USER_END_ADDR)
{
if (FLASH_ProgramWord(uwAddress, DATA_32) == FLASH_COMPLETE)
{
uwAddress = uwAddress + 4;
}
else
{
/* Error occurred while writing data in Flash memory.
User can add here some code to deal with this error */
while (1)
{
}
}
}
/* Lock the Flash to disable the flash control register access (recommended
to protect the FLASH memory against possible unwanted operation) */
FLASH_Lock();
/* Check if the programmed data is OK ***************************************/
/* MemoryProgramStatus = 0: data programmed correctly
MemoryProgramStatus != 0: number of words not programmed correctly */
uwAddress = FLASH_USER_START_ADDR;
uwMemoryProgramStatus = 0;
while (uwAddress < FLASH_USER_END_ADDR)
{
uwData32 = *(__IO uint32_t*)uwAddress;
if (uwData32 != DATA_32)
{
uwMemoryProgramStatus++;
}
uwAddress = uwAddress + 4;
}
/* Check Data correctness */
if(uwMemoryProgramStatus)
{
/* KO */
/* Turn on LD2 */
STM_EVAL_LEDOn(LED2);
}
else
{
/* OK */
/* Turn on LD1 */
STM_EVAL_LEDOn(LED1);
}
while (1)
{
}
}
/**
* @brief Gets the sector of a given address
* @param None
* @retval The sector of a given address
*/
static uint32_t GetSector(uint32_t Address)
{
uint32_t sector = 0;
if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
{
sector = FLASH_Sector_0;
}
else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
{
sector = FLASH_Sector_1;
}
else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
{
sector = FLASH_Sector_2;
}
else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
{
sector = FLASH_Sector_3;
}
else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
{
sector = FLASH_Sector_4;
}
else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
{
sector = FLASH_Sector_5;
}
else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
{
sector = FLASH_Sector_6;
}
else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
{
sector = FLASH_Sector_7;
}
else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
{
sector = FLASH_Sector_8;
}
else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
{
sector = FLASH_Sector_9;
}
else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
{
sector = FLASH_Sector_10;
}
#if defined (USE_STM324xG_EVAL)
else/*(Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_11))*/
{
sector = FLASH_Sector_11;
}
#else /* USE_STM324x7I_EVAL */
else if((Address < ADDR_FLASH_SECTOR_12) && (Address >= ADDR_FLASH_SECTOR_11))
{
sector = FLASH_Sector_11;
}
else if((Address < ADDR_FLASH_SECTOR_13) && (Address >= ADDR_FLASH_SECTOR_12))
{
sector = FLASH_Sector_12;
}
else if((Address < ADDR_FLASH_SECTOR_14) && (Address >= ADDR_FLASH_SECTOR_13))
{
sector = FLASH_Sector_13;
}
else if((Address < ADDR_FLASH_SECTOR_15) && (Address >= ADDR_FLASH_SECTOR_14))
{
sector = FLASH_Sector_14;
}
else if((Address < ADDR_FLASH_SECTOR_16) && (Address >= ADDR_FLASH_SECTOR_15))
{
sector = FLASH_Sector_15;
}
else if((Address < ADDR_FLASH_SECTOR_17) && (Address >= ADDR_FLASH_SECTOR_16))
{
sector = FLASH_Sector_16;
}
else if((Address < ADDR_FLASH_SECTOR_18) && (Address >= ADDR_FLASH_SECTOR_17))
{
sector = FLASH_Sector_17;
}
else if((Address < ADDR_FLASH_SECTOR_19) && (Address >= ADDR_FLASH_SECTOR_18))
{
sector = FLASH_Sector_18;
}
else if((Address < ADDR_FLASH_SECTOR_20) && (Address >= ADDR_FLASH_SECTOR_19))
{
sector = FLASH_Sector_19;
}
else if((Address < ADDR_FLASH_SECTOR_21) && (Address >= ADDR_FLASH_SECTOR_20))
{
sector = FLASH_Sector_20;
}
else if((Address < ADDR_FLASH_SECTOR_22) && (Address >= ADDR_FLASH_SECTOR_21))
{
sector = FLASH_Sector_21;
}
else if((Address < ADDR_FLASH_SECTOR_23) && (Address >= ADDR_FLASH_SECTOR_22))
{
sector = FLASH_Sector_22;
}
else/*(Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_23))*/
{
sector = FLASH_Sector_23;
}
#endif /* USE_STM324x7I_EVAL */
return sector;
}
Flash Write Protection with STM32 | Example code STM32 with Std Lib
@par Example Description
This example provides a description of how to enable and disable the write protection
for FLASH integrated within STM32F40xx/41xx and STM32F427x/437x Devices.
By maintaining the Key push-button pressed at Reset, the program will check the
write protection status of FLASH_WRP_SECTORS (defined in main.c)
- If FLASH_WRP_SECTORS are write protected, the write protection will be disabled.
Then LED1 will turn ON, if the protection disable operation is done correctly,
otherwise LED3 turns ON.
- If FLASH_WRP_SECTORS are not write protected, the write protection will be enabled.
Then LED4 will turn ON, if the protection enable operation is done correctly,
otherwise LED3 turns ON.
If after reset the Key push-button is not pressed, the program will simply turn ON LED2.
2. main.c
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define FLASH_WRP_SECTORS (OB_WRP_Sector_2 | OB_WRP_Sector_3) /* sectors 2 and 3 */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
__IO uint32_t SectorsWRPStatus = 0xFFF;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f40xx.s/startup_stm32f427x.s) before to branch to
application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f4xx.c file
*/
/* Initialize LEDs mounted on EVAL board */
STM_EVAL_LEDInit(LED1);
STM_EVAL_LEDInit(LED2);
STM_EVAL_LEDInit(LED3);
STM_EVAL_LEDInit(LED4);
/* Initialize Key Button mounted on EVAL board */
STM_EVAL_PBInit(BUTTON_KEY, BUTTON_MODE_GPIO);
/* Test if Key push-button on EVAL board is pressed */
if (STM_EVAL_PBGetState(BUTTON_KEY) == 0x00)
{
/* Get FLASH_WRP_SECTORS write protection status */
SectorsWRPStatus = FLASH_OB_GetWRP() & FLASH_WRP_SECTORS;
if (SectorsWRPStatus == 0x00)
{
/* If FLASH_WRP_SECTORS are write protected, disable the write protection */
/* Enable the Flash option control register access */
FLASH_OB_Unlock();
/* Disable FLASH_WRP_SECTORS write protection */
FLASH_OB_WRPConfig(FLASH_WRP_SECTORS, DISABLE);
/* Start the Option Bytes programming process */
if (FLASH_OB_Launch() != FLASH_COMPLETE)
{
/* User can add here some code to deal with this error */
while (1)
{
}
}
/* Disable the Flash option control register access (recommended to protect
the option Bytes against possible unwanted operations) */
FLASH_OB_Lock();
/* Get FLASH_WRP_SECTORS write protection status */
SectorsWRPStatus = FLASH_OB_GetWRP() & FLASH_WRP_SECTORS;
/* Check if FLASH_WRP_SECTORS write protection is disabled */
if (SectorsWRPStatus == FLASH_WRP_SECTORS)
{
/* OK, turn ON LED1 */
STM_EVAL_LEDOn(LED1);
}
else
{
/* KO, turn ON LED3 */
STM_EVAL_LEDOn(LED3);
}
}
else
{ /* If FLASH_WRP_SECTORS are not write protected, enable the write protection */
/* Enable the Flash option control register access */
FLASH_OB_Unlock();
/* Enable FLASH_WRP_SECTORS write protection */
FLASH_OB_WRPConfig(FLASH_WRP_SECTORS, ENABLE);
/* Start the Option Bytes programming process */
if (FLASH_OB_Launch() != FLASH_COMPLETE)
{
/* User can add here some code to deal with this error */
while (1)
{
}
}
/* Disable the Flash option control register access (recommended to protect
the option Bytes against possible unwanted operations) */
FLASH_OB_Lock();
/* Get FLASH_WRP_SECTORS write protection status */
SectorsWRPStatus = FLASH_OB_GetWRP() & FLASH_WRP_SECTORS;
/* Check if FLASH_WRP_SECTORS are write protected */
if (SectorsWRPStatus == 0x00)
{
/* OK, turn ON LED4 */
STM_EVAL_LEDOn(LED4);
}
else
{
/* KO, turn ON LED3 */
STM_EVAL_LEDOn(LED3);
}
}
}
/* Turn ON LED2 */
STM_EVAL_LEDOn(LED2);
while (1)
{
}
}
3. Explain code
uint16_t FLASH_OB_GetWRP(void)
{
/* Return the FLASH write protection Register value */
return (*(__IO uint16_t *)(OPTCR_BYTE2_ADDRESS));
}
It will return Register value at address : OPTCR_BYTE2_ADDRESS.
(__IO uint16_t *)(OPTCR_BYTE2_ADDRESS) : Pointer point to address.
void FLASH_OB_Unlock(void)
{
if((FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) != RESET)
{
/* Authorizes the Option Byte register programming ,read datasheet to know these value*/
FLASH->OPTKEYR = FLASH_OPT_KEY1;
FLASH->OPTKEYR = FLASH_OPT_KEY2;
}
}
FLASH_OPTCR
0: Write protection active on sector i
1: Write protection not active on sector i
This example provides a description of how to enable and disable the write protection
for FLASH integrated within STM32F40xx/41xx and STM32F427x/437x Devices.
By maintaining the Key push-button pressed at Reset, the program will check the
write protection status of FLASH_WRP_SECTORS (defined in main.c)
- If FLASH_WRP_SECTORS are write protected, the write protection will be disabled.
Then LED1 will turn ON, if the protection disable operation is done correctly,
otherwise LED3 turns ON.
- If FLASH_WRP_SECTORS are not write protected, the write protection will be enabled.
Then LED4 will turn ON, if the protection enable operation is done correctly,
otherwise LED3 turns ON.
If after reset the Key push-button is not pressed, the program will simply turn ON LED2.
2. main.c
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define FLASH_WRP_SECTORS (OB_WRP_Sector_2 | OB_WRP_Sector_3) /* sectors 2 and 3 */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
__IO uint32_t SectorsWRPStatus = 0xFFF;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f40xx.s/startup_stm32f427x.s) before to branch to
application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f4xx.c file
*/
/* Initialize LEDs mounted on EVAL board */
STM_EVAL_LEDInit(LED1);
STM_EVAL_LEDInit(LED2);
STM_EVAL_LEDInit(LED3);
STM_EVAL_LEDInit(LED4);
/* Initialize Key Button mounted on EVAL board */
STM_EVAL_PBInit(BUTTON_KEY, BUTTON_MODE_GPIO);
/* Test if Key push-button on EVAL board is pressed */
if (STM_EVAL_PBGetState(BUTTON_KEY) == 0x00)
{
/* Get FLASH_WRP_SECTORS write protection status */
SectorsWRPStatus = FLASH_OB_GetWRP() & FLASH_WRP_SECTORS;
if (SectorsWRPStatus == 0x00)
{
/* If FLASH_WRP_SECTORS are write protected, disable the write protection */
/* Enable the Flash option control register access */
FLASH_OB_Unlock();
/* Disable FLASH_WRP_SECTORS write protection */
FLASH_OB_WRPConfig(FLASH_WRP_SECTORS, DISABLE);
/* Start the Option Bytes programming process */
if (FLASH_OB_Launch() != FLASH_COMPLETE)
{
/* User can add here some code to deal with this error */
while (1)
{
}
}
/* Disable the Flash option control register access (recommended to protect
the option Bytes against possible unwanted operations) */
FLASH_OB_Lock();
/* Get FLASH_WRP_SECTORS write protection status */
SectorsWRPStatus = FLASH_OB_GetWRP() & FLASH_WRP_SECTORS;
/* Check if FLASH_WRP_SECTORS write protection is disabled */
if (SectorsWRPStatus == FLASH_WRP_SECTORS)
{
/* OK, turn ON LED1 */
STM_EVAL_LEDOn(LED1);
}
else
{
/* KO, turn ON LED3 */
STM_EVAL_LEDOn(LED3);
}
}
else
{ /* If FLASH_WRP_SECTORS are not write protected, enable the write protection */
/* Enable the Flash option control register access */
FLASH_OB_Unlock();
/* Enable FLASH_WRP_SECTORS write protection */
FLASH_OB_WRPConfig(FLASH_WRP_SECTORS, ENABLE);
/* Start the Option Bytes programming process */
if (FLASH_OB_Launch() != FLASH_COMPLETE)
{
/* User can add here some code to deal with this error */
while (1)
{
}
}
/* Disable the Flash option control register access (recommended to protect
the option Bytes against possible unwanted operations) */
FLASH_OB_Lock();
/* Get FLASH_WRP_SECTORS write protection status */
SectorsWRPStatus = FLASH_OB_GetWRP() & FLASH_WRP_SECTORS;
/* Check if FLASH_WRP_SECTORS are write protected */
if (SectorsWRPStatus == 0x00)
{
/* OK, turn ON LED4 */
STM_EVAL_LEDOn(LED4);
}
else
{
/* KO, turn ON LED3 */
STM_EVAL_LEDOn(LED3);
}
}
}
/* Turn ON LED2 */
STM_EVAL_LEDOn(LED2);
while (1)
{
}
}
3. Explain code
uint16_t FLASH_OB_GetWRP(void)
{
/* Return the FLASH write protection Register value */
return (*(__IO uint16_t *)(OPTCR_BYTE2_ADDRESS));
}
It will return Register value at address : OPTCR_BYTE2_ADDRESS.
(__IO uint16_t *)(OPTCR_BYTE2_ADDRESS) : Pointer point to address.
void FLASH_OB_Unlock(void)
{
if((FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) != RESET)
{
/* Authorizes the Option Byte register programming ,read datasheet to know these value*/
FLASH->OPTKEYR = FLASH_OPT_KEY1;
FLASH->OPTKEYR = FLASH_OPT_KEY2;
}
}
FLASH_OPTCR
0: Write protection active on sector i
1: Write protection not active on sector i
Friday, April 3, 2020
ADC with DMA STM32 | Example code STM32 with Std Lib

This example describes how to use the ADC3 and DMA to transfer continuously
converted data from ADC3 to memory.
The ADC3 is configured to convert continuously channel7.
Each time an end of conversion occurs the DMA transfers, in circular mode, the
converted data from ADC3 DR register to the uhADCxConvertedValue variable.
In this example, the system clock is 168MHz, APB2 = 84MHz and ADC clock = APB2/2.
Since ADC3 clock is 42 MHz and sampling time is set to 3 cycles, the conversion
time to 12bit data is 12 cycles so the total conversion time is (12+3)/42= 0.36us(2.4Msps).
User can vary the ADC3 channel7 voltage using the Eval Board potentiometer
The converted voltage is displayed on the Eval Board LCD (when the define USE_LCD
is enabled in main.h)
@par Directory contents
- ADC/ADC_DMA/system_stm32f4xx.c STM32F4xx system clock configuration file
- ADC/ADC_DMA/stm32f4xx_conf.h Library Configuration file
- ADC/ADC_DMA/stm32f4xx_it.c Interrupt handlers
- ADC/ADC_DMA/stm32f4xx_it.h Interrupt handlers header file
- ADC/ADC_DMA/main.c Main program
- ADC/ADC_DMA/main.h Main program header file
1. main.h
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include <stdio.h>
#if defined (USE_STM324xG_EVAL)
#include "stm324xg_eval.h"
#include "stm324xg_eval_lcd.h"
#elif defined (USE_STM324x7I_EVAL)
#include "stm324x7i_eval.h"
#include "stm324x7i_eval_lcd.h"
#else
#error "Please select first the Evaluation board used in your application (in Project Options)"
#endif
/* Private define ------------------------------------------------------------*/
/* used to display the ADC converted value on LCD */
#define USE_LCD
/* if you are not using the LCD, you can monitor the converted value by adding
the variable "uhADCxConvertedValue" to the debugger watch window */
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
#if defined (USE_STM324xG_EVAL)
#define FOOTER_MESSAGE " ADC conversion w/DMA transfer example "
#define CONFIG1_MESSAGE "ADC Ch7 Conv @2.4Msps"
#define CONFIG2_MESSAGE " Turn RV1(PF.09) "
#define CONFIG3_MESSAGE " Potentiometer "
#define ADCx ADC3
#define ADC_CHANNEL ADC_Channel_7
#define ADCx_CLK RCC_APB2Periph_ADC3
#define ADCx_CHANNEL_GPIO_CLK RCC_AHB1Periph_GPIOF
#define GPIO_PIN GPIO_Pin_9
#define GPIO_PORT GPIOF
#define DMA_CHANNELx DMA_Channel_2
#define DMA_STREAMx DMA2_Stream0
#define ADCx_DR_ADDRESS ((uint32_t)0x4001224C)
#else /* defined (USE_STM324x7I_EVAL)*/
#define FOOTER_MESSAGE " ADC conversion w/DMA transfer example "
#define CONFIG1_MESSAGE "ADC Ch7 Conv @2.4Msps"
#define CONFIG2_MESSAGE " Turn RV1(PF.09) "
#define CONFIG3_MESSAGE " Potentiometer "
#define ADCx ADC3
#define ADC_CHANNEL ADC_Channel_7
#define ADCx_CLK RCC_APB2Periph_ADC3
#define ADCx_CHANNEL_GPIO_CLK RCC_AHB1Periph_GPIOF
#define GPIO_PIN GPIO_Pin_9
#define GPIO_PORT GPIOF
#define DMA_CHANNELx DMA_Channel_2
#define DMA_STREAMx DMA2_Stream0
#define ADCx_DR_ADDRESS ((uint32_t)0x4001224C)
#endif
/* Exported functions ------------------------------------------------------- */
#endif /* __MAIN_H */
2. main.c
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/** @addtogroup STM32F4xx_StdPeriph_Examples
* @{
*/
/** @addtogroup ADC_DMA
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
__IO uint16_t uhADCxConvertedValue = 0;
__IO uint32_t uwADCxConvertedVoltage = 0;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
static void ADC_Config(void);
#ifdef USE_LCD
static void Display_Init(void);
static void Display(void);
#endif /* USE_LCD */
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
files (startup_stm32f40xx.s/startup_stm32f427x.s) before to branch to
application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f4xx.c file
*/
#ifdef USE_LCD
/* LCD Display init */
Display_Init();
#endif
/* ADC configuration */
ADC_Config();
/* Start ADC Software Conversion */
ADC_SoftwareStartConv(ADCx);
while (1)
{
uwADCxConvertedVoltage = uhADCxConvertedValue *3300/0xFFF;
#ifdef USE_LCD
/* Display ADCx converted value on LCD */
Display();
#endif
}
}
/**
* @brief ADC3 channel07 with DMA configuration
* @note This function Configure the ADC peripheral
1) Enable peripheral clocks
2) DMA2_Stream0 channel2 configuration
3) Configure ADC Channel7 pin as analog input
4) Configure ADC3 Channel7
* @param None
* @retval None
*/
static void ADC_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable ADCx, DMA and GPIO clocks ****************************************/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
RCC_AHB1PeriphClockCmd(ADCx_CHANNEL_GPIO_CLK, ENABLE);
RCC_APB2PeriphClockCmd(ADCx_CLK, ENABLE);
/* DMA2 Stream0 channel2 configuration **************************************/
DMA_InitStructure.DMA_Channel = DMA_CHANNELx;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADCx_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&uhADCxConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA_STREAMx, &DMA_InitStructure);
DMA_Cmd(DMA_STREAMx, ENABLE);
/* Configure ADC3 Channel7 pin as analog input ******************************/
GPIO_InitStructure.GPIO_Pin = GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIO_PORT, &GPIO_InitStructure);
/* ADC Common Init **********************************************************/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC3 Init ****************************************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADCx, &ADC_InitStructure);
/* ADC3 regular channel7 configuration *************************************/
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, ADC_SampleTime_3Cycles);
/* Enable DMA request after last transfer (Single-ADC mode) */
ADC_DMARequestAfterLastTransferCmd(ADCx, ENABLE);
/* Enable ADC3 DMA */
ADC_DMACmd(ADCx, ENABLE);
/* Enable ADC3 */
ADC_Cmd(ADCx, ENABLE);
}
#ifdef USE_LCD
/**
* @brief Display ADC converted value on LCD
* @param None
* @retval None
*/
static void Display(void)
{
uint32_t uwVoltage = 0;
uint32_t uwMVoltage = 0;
uint8_t aTextBuffer[50];
uwVoltage = (uwADCxConvertedVoltage)/1000;
uwMVoltage = (uwADCxConvertedVoltage%1000)/100;
sprintf((char*)aTextBuffer," ADC = %d,%d V ", uwVoltage, uwMVoltage);
LCD_DisplayStringLine(LCD_LINE_6, aTextBuffer);
}
/**
* @brief Display Init (LCD)
* @param None
* @retval None
*/
static void Display_Init(void)
{
/* Initialize the LCD */
LCD_Init();
/* Clear the Background Layer */
LCD_Clear(LCD_COLOR_WHITE);
/* Set the LCD Back Color */
LCD_SetBackColor(LCD_COLOR_BLUE);
/* Set the LCD Text Color */
LCD_SetTextColor(LCD_COLOR_WHITE);
/* Set the LCD Text size */
LCD_SetFont(&Font8x12);
/* Display LCD Footer Message */
LCD_DisplayStringLine(LCD_LINE_19, (uint8_t*)FOOTER_MESSAGE);
/* Set the LCD Text size */
LCD_SetFont(&Font16x24);
/* Display Configuration Messages */
LCD_DisplayStringLine(LCD_LINE_0, (uint8_t*)CONFIG1_MESSAGE);
/* Set the LCD Back Color */
LCD_SetBackColor(LCD_COLOR_WHITE);
/* Set the LCD Text Color */
LCD_SetTextColor(LCD_COLOR_BLUE);
/* Display */
LCD_DisplayStringLine(LCD_LINE_2, (uint8_t*)CONFIG2_MESSAGE);
LCD_DisplayStringLine(LCD_LINE_4, (uint8_t*)CONFIG3_MESSAGE);
}
#endif /* USE_LCD */
Labels:
adc,
dma,
example stm32,
stm32,
stm32 tutorial,
study stm32
Subscribe to:
Posts (Atom)
