当前位置:网站首页>Pandora IOT development board learning (HAL Library) - Experiment 9 PWM output experiment (learning notes)
Pandora IOT development board learning (HAL Library) - Experiment 9 PWM output experiment (learning notes)
2022-07-06 03:46:00 【Xiaohui_ Super】
This code refers to the punctual atomic routine
List of articles
Experimental function
Routine source code :(main.c)
The functions realized in this experiment : use PWM Wave control motor rotation , By controlling PWM Duty cycle of , So as to control the speed of the motor .
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "pwm.h"
/********************************************************************************* ___ _ _____ _____ _ _ _____ _____ _ __ / _ \ | | |_ _|| ___|| \ | ||_ _|| ___|| | / / / /_\ \| | | | | |__ | \| | | | | |__ | |/ / | _ || | | | | __| | . ` | | | | __| | \ | | | || |_____| |_ | |___ | |\ | | | | |___ | |\ \ \_| |_/\_____/\___/ \____/ \_| \_/ \_/ \____/ \_| \_/ * ****************************************************************************** * The punctual atoms Pandora STM32L475 IoT Development board experiment 9 * PWM Output experiment HAL Library version * Technical support :www.openedv.com * Taobao shop :http://openedv.taobao.com * Focus on wechat public platform wechat :" The punctual atoms ", Free access STM32 Information . * Guangzhou Xingyi Electronic Technology Co., Ltd * author : The punctual atoms @ALIENTEK * ******************************************************************************/
int main(void)
{
u8 time = 0;
u8 speed = 1; // speed control 0: Speed up 1: Slow down
u8 dir = 1; // Forward and reverse signs 0: The motor is turning forward 1: The motor reverses
u16 pwmval = 500; // The default value is
HAL_Init();
SystemClock_Config(); // Initialize the system clock to 80M
delay_init(80); // Initialization delay function 80M The system clock
uart_init(115200); // Initialize serial port , The baud rate is 115200
LED_Init(); // initialization LED
PWM_Init(1000 - 1, 80 - 1); //TIM2 clock frequency 80M/80=1M Counting frequency 1M/1000=1KHZ The default duty cycle is 50%
while(1)
{
if(speed) pwmval += 5;
else pwmval -= 5;
if(pwmval >= 1000) speed = 0;
if(pwmval <= 500)
{
speed = 1;
dir = dir ^ 0x01; // Change the motor direction when the speed becomes the minimum
}
if(dir)
{
TIM_SetTIM2Compare1(pwmval);
TIM_SetTIM2Compare2(0);
}
else
{
TIM_SetTIM2Compare1(0);
TIM_SetTIM2Compare2(pwmval);
}
time++;
if( time%20 == 0 )
LED_B_TogglePin;
delay_ms(15);
}
}
Code analysis
HAL_Init()
HAL_Init()
The definition is as follows :( See notes for specific functions )
HAL_StatusTypeDef HAL_Init(void)
{
HAL_StatusTypeDef status = HAL_OK;
/* To configure Flash Prefetch , Instruction cache , Data caching */
/* Default configuration is : Pre access is closed Instruction cache and data cache are enabled */
#if (INSTRUCTION_CACHE_ENABLE == 0) // Flash Enable pre access configuration , Can accelerate CPU Execution of code
__HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
#endif /* INSTRUCTION_CACHE_ENABLE */
#if (DATA_CACHE_ENABLE == 0)
__HAL_FLASH_DATA_CACHE_DISABLE();
#endif /* DATA_CACHE_ENABLE */
#if (PREFETCH_ENABLE != 0)
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2); // To configure NVIC Priority groups
/* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */
if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) // Initialize tick timer , The clock beat is set to 1ms
{
status = HAL_ERROR;
}
else
{
/* Init the low level hardware */
HAL_MspInit(); // Low speed peripheral initialization , such as GPIO、 Interrupt, etc ( Use STM32CubeMx Low speed peripherals are initialized when generating code
// The code is in this kind of function , In other cases, this function can be ignored
}
/* Return function status */
return status;
}
HAL_InitTick()
Tick timer clock beat initialization function
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
HAL_StatusTypeDef status = HAL_OK;
/*Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock/1000UL) != 0U) // The system clock /1000, The interruption period is 1ms
{
status = HAL_ERROR;
}
else
{
/*Configure the SysTick IRQ priority */
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0); // Set the interrupt priority of the tick timer to the highest
}
/* Return function status */
return status;
}
SystemClock_Config()
SystemClock_Config()
The function is defined as follows :( See notes for specific functions , For reference only )
void SystemClock_Config(void)
{
HAL_StatusTypeDef ret = HAL_OK;
RCC_OscInitTypeDef RCC_OscInitStruct; // Define oscillator initialization structure variables
RCC_ClkInitTypeDef RCC_ClkInitStruct; // Define clock initialization structure variables
__HAL_RCC_PWR_CLK_ENABLE(); // Enable power control clock
/*Initializes the CPU, AHB and APB busses clocks*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // take HSE( External high-speed clock ) As a clock source
RCC_OscInitStruct.HSEState = RCC_HSE_ON; // Turn on HSE
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // Turn on PLL( PLL )
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // take HSE As PLL The clock source of
RCC_OscInitStruct.PLL.PLLM = 1; // PLL-VCO Input clock frequency division coefficient ,1 Express 2 frequency division (8 / 2 = 4M, The external crystal oscillator frequency of the development board is 8MHz)
RCC_OscInitStruct.PLL.PLLN = 20; // PLL-VCO Output clock frequency multiplication coefficient ,4 * 20 = 80M, That is, the output clock frequency is 80MHz
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7; // SAI Frequency division coefficient of clock
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; // SDMMC1, RNG and USB Clock frequency division coefficient
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; // Frequency division coefficient of the main system clock
ret = HAL_RCC_OscConfig(&RCC_OscInitStruct); // Initialize clock configuration
if(ret != HAL_OK) while(1);
/*Initializes the CPU, AHB and APB busses clocks*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; // Configure all clocks at the same time
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // take PLL As the clock source of the system
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB Regardless of the frequency
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // APB1 Regardless of the frequency
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2 Regardless of the frequency
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4); // Configure the initial structure variable of the clock ,
// Use Flash Delay 4, Wait state ( Delay ) The quantity of should be according to CPU The clock (HCLK) Frequency and internal voltage range , How to
// Please refer to the chip manual
if(ret != HAL_OK) while(1);
/*Configure the main internal regulator output voltage*/
ret = HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // Internal register output voltage configuration
// Here is HAL_PWREx_ControlVoltageScaling() Part of the function description :
//PWR_REGULATOR_VOLTAGE_SCALE1 Regulator voltage output range 1 mode, typical output voltage
// at 1.2 V, system frequency up to 80 MHz.
if(ret != HAL_OK) while(1);
}
delay_init()
The tick timer is already HAL_Init()
Initialization in , The following function is actually for fac_us
Given a value ( At present, the operating system is not involved , Other code will not be studied for the time being ).
static u32 fac_us = 0; //us Delay multiplier
/** * @brief Initialization delay function ,SYSTICK The clock is fixed to AHB The clock * * @param SYSCLK System clock frequency * * @return void */
void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS // If support is needed OS.
u32 reload;
#endif
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick The frequency is HCLK
fac_us = SYSCLK; // Whether used or not OS,fac_us You need to use
#if SYSTEM_SUPPORT_OS // If support is needed OS.
reload = SYSCLK; // The number of counts per second Unit is K
reload *= 1000000 / delay_ostickspersec; // according to delay_ostickspersec Set the overflow time
//reload by 24 Bit register , Maximum :16777216, stay 80M Next , about 209.7ms about
fac_ms = 1000 / delay_ostickspersec; // representative OS The minimum unit that can delay
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // Turn on SYSTICK interrupt
SysTick->LOAD = reload; // Every time 1/OS_TICKS_PER_SEC Second break once
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // Turn on SYSTICK
#else
#endif
}
LED_Init()
/** * @brief LED IO Initialization function * * @param void * * @return void */
void LED_Init(void)
{
/* LED-B PE9 LED-G PE8 LED-R PE7 */
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOE_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9, GPIO_PIN_SET);
}
PWM_Init()
This experiment uses TIM2 To output PWM, Here is TIM2 Initialization function for .TIM2 The clock frequency of is 80MHz,main() The frequency division coefficient in the function is 80 - 1,80M / 80 = 1MHz, The corresponding timing period is 1us; The overload value is 1000 - 1, that PWM The cycle is 1ms.
/** * @brief TIM2 PWM Output initialization function * * @param arr Auto reload value * @param psc Clock presplitting frequency * * @return void */
void PWM_Init(u16 arr, u16 psc)
{
TIM2_Handler.Instance = TIM2; // Timer 2
TIM2_Handler.Init.Prescaler = psc; // Timer frequency division
TIM2_Handler.Init.CounterMode = TIM_COUNTERMODE_UP; // Upcount mode
TIM2_Handler.Init.Period = arr; // Automatic reload load value
TIM2_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_PWM_Init(&TIM2_Handler); // initialization PWM
TIM2_CHnHandler.OCMode = TIM_OCMODE_PWM1; // Mode selection PWM1
TIM2_CHnHandler.Pulse = arr / 2; // Set the comparison value , This value is used to determine the duty cycle , The default comparison value is half of the automatic reload value , That is, the duty cycle is 50%
TIM2_CHnHandler.OCPolarity = TIM_OCPOLARITY_HIGH; // The output comparison polarity is low
HAL_TIM_PWM_ConfigChannel(&TIM2_Handler, &TIM2_CHnHandler, TIM_CHANNEL_1); // To configure TIM2 passageway 1
HAL_TIM_PWM_Start(&TIM2_Handler, TIM_CHANNEL_1); // Turn on PWM passageway 1
HAL_TIM_PWM_ConfigChannel(&TIM2_Handler, &TIM2_CHnHandler, TIM_CHANNEL_2); // To configure TIM2 passageway 2
HAL_TIM_PWM_Start(&TIM2_Handler, TIM_CHANNEL_2); // Turn on PWM passageway 2
}
HAL_TIM_Base_MspInit()
above HAL_TIM_PWM_Init()
Function will call timer (PWM) The underlying driver initialization function , This function is configured with PWM Corresponding to the channel GPIO.
/** * @brief Timer bottom drive , Clock enable , Pin configuration , This function will be HAL_TIM_PWM_Init() call * * @param htim Timer handle * * @return void */
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_TIM2_CLK_ENABLE(); // Enable timer 2
__HAL_RCC_GPIOA_CLK_ENABLE(); // Turn on GPIOA The clock
GPIO_Initure.Pin = GPIO_PIN_0 | GPIO_PIN_1; //PA0.1
GPIO_Initure.Mode = GPIO_MODE_AF_PP; // Multiplexing push pull output
GPIO_Initure.Pull = GPIO_PULLUP; // Pull up
GPIO_Initure.Speed = GPIO_SPEED_HIGH; // High speed
GPIO_Initure.Alternate = GPIO_AF1_TIM2; //PA1 Reuse as TIM2_CH1.CH2
HAL_GPIO_Init(GPIOA, &GPIO_Initure);
}
TIM_SetTIM2Compare1()
TIM2 passageway 1 Duty cycle setting function , Direct to CCR1 Register filling value .
/** * @brief Set up TIM2 passageway 1 Duty cycle of * * @param compare It's worth * * @return void */
void TIM_SetTIM2Compare1(u32 compare)
{
TIM2->CCR1 = compare;
}
passageway 2 Duty cycle setting principle and channel 1 identical .
/** * @brief Set up TIM2 passageway 2 Duty cycle of * * @param compare It's worth * * @return void */
void TIM_SetTIM2Compare2(u32 compare)
{
TIM2->CCR2 = compare;
}
HAL The library also comes with a duty cycle configuration function , It's also about writing CCR register .
/** * @brief Set the TIM Capture Compare Register value on runtime without calling another time ConfigChannel function. * @param __HANDLE__ TIM handle. * @param __CHANNEL__ TIM Channels to be configured. * This parameter can be one of the following values: * @arg TIM_CHANNEL_1: TIM Channel 1 selected * @arg TIM_CHANNEL_2: TIM Channel 2 selected * @arg TIM_CHANNEL_3: TIM Channel 3 selected * @arg TIM_CHANNEL_4: TIM Channel 4 selected * @arg TIM_CHANNEL_5: TIM Channel 5 selected * @arg TIM_CHANNEL_6: TIM Channel 6 selected * @param __COMPARE__ specifies the Capture Compare register new value. * @retval None */
#define __HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__) \ (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1 = (__COMPARE__)) :\ ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2 = (__COMPARE__)) :\ ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3 = (__COMPARE__)) :\ ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCR4 = (__COMPARE__)) :\ ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCR5 = (__COMPARE__)) :\ ((__HANDLE__)->Instance->CCR6 = (__COMPARE__)))
LED Operation function
LED The control function of is a macro function , We used HAL_GPIO_WritePin()
and HAL_GPIO_TogglePin()
Two library functions .
//RGB Interface definition
#define LED_R(n) (n?HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,GPIO_PIN_RESET))
#define LED_R_TogglePin HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_7) //LED_R Level flip
#define LED_G(n) (n?HAL_GPIO_WritePin(GPIOE,GPIO_PIN_8,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOE,GPIO_PIN_8,GPIO_PIN_RESET))
#define LED_G_TogglePin HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_8) //LED_G Level flip
#define LED_B(n) (n?HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,GPIO_PIN_RESET))
#define LED_B_TogglePin HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_9) //LED_B Level flip
delay_ms()
delay_ms()
What runs in the is delay_us()
, delay_us()
Delay by ticking timer . above delay_init()
Have already put fac_us Set up in order to 80, Tick timer counts 80 Time required 10-6 second ( The system clock is 80MHz), namely 1us.
/** * @brief Delay milliseconds (ms) function * * @param nms How many milliseconds does it take * * @return void */
void delay_ms(u16 nms)
{
u32 i;
for(i = 0; i < nms; i++) delay_us(1000);
}
/** * @brief Delay microseconds (us) function * * @remark nus:0~190887435( The maximum value is 2^32/[email protected]_us=22.5) * * @param nus How many microseconds do you need to delay * * @return void */
void delay_us(u32 nus)
{
u32 ticks;
u32 told, tnow, tcnt = 0;
u32 reload = SysTick->LOAD; //LOAD Value
ticks = nus * fac_us; // The number of beats needed
told = SysTick->VAL; // Counter value at the time of first entry
while(1)
{
tnow = SysTick->VAL;
if(tnow != told)
{
if(tnow < told)tcnt += told - tnow; // Notice here SYSTICK It's a decreasing counter .
else tcnt += reload - tnow + told;
told = tnow;
if(tcnt >= ticks)break; // For more than / Equal to the time to delay , The exit .
}
}
}
边栏推荐
- How do we make money in agriculture, rural areas and farmers? 100% for reference
- Image super resolution using deep revolutionary networks (srcnn) interpretation and Implementation
- mysql关于自增长增长问题
- 2.2 fonctionnement stm32 GPIO
- Microkernel structure understanding
- Containerization Foundation
- Alibaba testers use UI automated testing to achieve element positioning
- Shell pass parameters
- 登录mysql输入密码时报错,ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: NO/YES
- The solution of permission denied (750 permissions should be used with caution)
猜你喜欢
ESBuild & SWC浅谈: 新一代构建工具
SAP ALV颜色代码对应颜色(整理)
BUAA计算器(表达式计算-表达式树实现)
EDCircles: A real-time circle detector with a false detection control 翻译
2.1 rtthread pin device details
C#(二十七)之C#窗体应用
如何修改表中的字段约束条件(类型,default, null等)
[slam] orb-slam3 parsing - track () (3)
Remote Sensing Image Super-resolution and Object Detection: Benchmark and State of the Art
Flask learning and project practice 8: introduction and use of cookies and sessions
随机推荐
Flask learning and project practice 9: WTF form verification
[practice] mathematics in lottery
Indicator system of KQI and KPI
Pytorch基础——(2)张量(tensor)的数学运算
出现Permission denied的解决办法(750权限谨慎使用)
1. New project
Deno介绍
SWC introduction
three. JS page background animation liquid JS special effect
pytorch加载数据
How do we make money in agriculture, rural areas and farmers? 100% for reference
C#(三十一)之自定义事件
JS Vanke banner rotation chart JS special effect
C#(二十八)之C#鼠标事件、键盘事件
Multi project programming minimalist use case
2. GPIO related operations
Remote Sensing Image Super-resolution and Object Detection: Benchmark and State of the Art
KS003基于JSP和Servlet实现的商城系统
3.2 detailed explanation of rtthread serial port device (V2)
2.2 STM32 GPIO operation