- This repository was created because the course
is so interestingsucks.
- STM32-Embedded-System-Lab
- Example of some labs
You have to download STM32CubeIDE First. Then, select board STM32F4DISCOVERY and select debugger as J-LINK (OR ST-Link).
Each TIM uses different clock source frequency according to the table provided below.
| APB1 Domain | APB2 domain |
|---|---|
| TIM2 | TIM1 |
| TIM3 | TIM8 |
| TIM4 | TIM9 |
| TIM5 | TIM10 |
| TIM6 | TIM11 |
| TIM7 | |
| TIM12 | |
| TIM13 | |
| TIM14 |
| LED | GPIOD_PD |
|---|---|
| Green (LD4) | PD12 |
| Orange (LD3) | PD13 |
| Red (LD5) | PD14 |
| Blue (LD6) | PD15 |
| Button | GPIOA_PA |
|---|---|
| User button (blue button) | PA0 |
x in GPIOx for A, B, C, D eg. "GPIOA", "GPIOD"
// Read pin // HAL_GPIO_ReadPin(GPIOx, GPIO_PIN_xx); HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_12); // read from PD12 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0); // read from user button // Write pin // HAL_GPIO_WritePin(GPIOx, GPIO_PIN_xx, GPIO_PIN_SET/GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); //turn on light // Toggle on/off pin // HAL_GPIO_TogglePin(GPIOx, GPIO_PIN_xx); HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);// toggle pin 12 // Delay // HAL_Delay(uint32_t Delay); HAL_Delay(1000); // delay for 1000 millisecond or 1 second| Register | Responsibility |
|---|---|
| Port Mode Register (MODER) | configure the I/O direction mode (input/output/alternate/analog) |
| Port Mode Register (MODER) | configure the I/O direction mode (input/output/alternate/analog) |
| Output Type Register (TYPER) | configure the output type of the I/O port (push-pull/open-drain) |
| Output Speed Register (OSPEEDR) | configure the I/O output speed (2/25/50/100 MHz) |
| Pull-Up/Pull-Down Register (PUPDR) | configure the I/O pull-up or pull-down (no pull-up, pull-down/pull-up/pull-down) |
| Input Data Register (IDR) | contain the input value of the corresponding I/O port |
| Output Data Register (ODR) | can be read and written by software (ODR bits can be individually set and reset by writing to the BSRR) |
| Bit Set/Reset Register (BSRR) | can be used for atomic bit set/reset |
| Configuration Lock Register (LCKR) | used to lock the configuration of the port bits when a correct write sequence is applied to bit 16 |
| Alternate Function Low Register (AFRL) | configure alternate function I/Os |
| Alternate Function High Register (AFRH) | configure alternate function I/Os |
int state = 0; int push = 0; if (state == 0) { ... if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == HAL_OK && !push) { push = 1; } if (!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == HAL_OK && push) { push = 0; state = 1; } } else if (state == 1) { ... if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == HAL_OK && !push) { push = 1; } if (!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == HAL_OK && push) { push = 0; state = 0; } }- Another way
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)){ while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)) { } }Universal Asynchronous Receiver and Transmitter
- Connectivity >> USART2 >> Mode (Asynchronous)
- Connect the wire from RX (UART) to TX (Board) and from TX (UART) to RX (Board)
- Connect the ET-MINI USE-TTL Board to Computer
- Open terminal (e.g. Tera Term)
- Download Tera Term
- Very fricking important: set serial port to 115200 in Tera Term
Receive and print char one by one to terminal:
// Private variable UART_HandleTypeDef huart2;// program generated // User code while(1){ // User variable char buffer[1]; if (HAL_UART_Receive(&huart2, buffer, sizeof(buffer), HAL_MAX_DELAY) == HAL_OK){ HAL_UART_Transmit(&huart2, buffer, sizeof(buffer), HAL_MAX_DELAY); } }Print whole string at terminal:
// Private variable UART_HandleTypeDef huart2;// program generated // User variable int myValue; char buffer[20]; while(1){ // sprintf(char *, char format, arguments...) sprintf(buffer, "%d \r\n", myValue); HAL_UART_Transmit(&huart2, &buffer, strlen(buffer), HAL_MAX_DELAY); // Transmit }**for mac user
-
Connect UART
-
Type in terminal : ls /dev/tty.*
-
Look for /dev/tty.usbserialXXXXXX and copy
-
Type in terminal : screen /dev/tty.usbserialXXXXXX 115200
*115200 is baud rate of STM32F4
If terminal return busy
- type : screen -ls
- kill everything by type : screen -X -S "session" kill
- System Core >> GPIO >> GPIO tab >> PA0 >> External Interrupt Mode with your prefered edge trigger detection
- System Core >> GPIO >> NVIC tab >> Enable EXTI line0 interrupt
- System Core >> NVIC >> NVIC tab >> set EXTI line0 interrupt preemptive priority to higher value (Higher number means lower priotity)
- Note : if you can't change the priority value, change priority group to higher bits
// Write this function in your main.c // External interrupt/event controller (EXTI) void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ ... // do something HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15); while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)); // Debounce HAL_Delay(100); __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); }- TIMx >> Set up PWM >> (see PWM)
- TIMx >> Parameter Setting >> Set up parameter(see Timer)
- TIMx >> auto-reload preload >> Enable
- TIMx >> NVIC Settings >> Enable TIM3 Global Interrupt or System Core >> NVIC >> Enable TIMx Global Interrupt
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_14); if (htim->Instance == TIM3) HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12); } int main(void) { // Init() HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); HAL_TIM_Base_Start_IT(&htim2); HAL_TIM_Base_Start_IT(&htim3); while (1) { ... } }- Pinout View >> Choose LED channel (PD12 to PD14) >> Change it to TIM4_CHx
- TIM4 >> Set up PWM >> (see PWM)
- TIM4 >> Parameter Setting >> Set up parameter(see Timer)
- LED will blink in the frequency that you have set.
- TIMx->CNT - Clock Counter (For ioc: Clock Configuration >> APB1 Timer clocks)
- TIMx->PSC - Prescaler Value (For ioc: TIMx >> Parameter Setting >> Prescaler)
- TIMx->ARR - Period Value (For ioc: TIMx >> Parameter Setting >> Counter Period)
- TIMx->CCRx - PWM for Channel x (For ioc: TIMx >> Parameter Setting >> PWM Generation Channel x >> Pulse)
- Tips : If you set APB1 Timer clocks = 16 MHz, Prescaler = 15999, you will be able to set Counter Period and Pulse in millisec.
Pulse Width Modulation
- TIMx >> Clock Source >> Internal Clock
- TIMx >> Channelx >> PWM Generation CHx
// Private variable TIM_HandleTypeDef htim4; // program generated // Don't forget to write this start method HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3); while (1) { TIM4->CCR3 = myPulse; // If you want to change PWM }Analog to Digital Converter
- Select your prefered Pin (e.g. PC3, PC2) and set mode to ADCxIN_x (e.g. ADC1_IN13)
- Go to Analog >> ADCx >> check INx
// Private variable ADC_HandleTypeDef hadc1; // program generated int adcValue; while (1) { HAL_ADC_Start(&hadc1); if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK) { adcValue = HAL_ADC_GetValue(&hadc1); } }Serial Peripheral Interface Bus
- Connectivity >> SPI2
- For transmitter select
Transmit Only Master - For receiver select
Receive Only Slave
- For transmitter select
- Connect
SCKandMOSI
// Transmitter HAL_SPI_Transmit(&hspi1, "a", 1, HAL_MAX_DELAY); // Receiver HAL_SPI_Receive(&hspi1, "a", 1, HAL_MAX_DELAY);Inter-Integrated Circuit Bus
- Connectivity >> I2C1
- Select
I2C
- Select
- Connect
SLCandSDA - Set some
{address}
// Transmitter HAL_I2C_Master_Transmit(&hi2c1, {address}, "a", 1, HAL_MAX_DELAY); // Receiver HAL_I2C_Slave_Receive(&hi2c1, {address}, "a", 1, HAL_MAX_DELAY);Real Time Operating System
- Read through this link for additional infomation!
- Middleware >> FREERTOS >> Interface (CMSIS_1)
- Task and Queue >> Task >> Add
... void StartDefaultTask(void const * argument); ... int main(void) { ... osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128); defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL); osKernelStart(); ... while (1) { ... } } void StartDefaultTask(void const * argument) { /* USER CODE BEGIN */ /* USER CODE END */ }- Config parameters >> software timer definitions >> USE_TIMERS (Enabled)
- Timers and Semaphores >> Timers >> Add
... osTimerId myTimer01Handle; void Callback01(void const * argument); ... int main(void) { ... osTimerDef(myTimer01, Callback01); myTimer01Handle = osTimerCreate(osTimer(myTimer01), osTimerPeriodic, NULL); osTimerStart(myTimer01Handle, 25); ... while (1) { ... } } void Callback01(void const * argument) { /* USER CODE BEGIN Callback01 */ /* USER CODE END Callback01 */ }osSemaphoreWait(myBinarySem01Handle, 10000); osSemaphoreRelease(myBinarySem01Handle);