Nucleo-F411RE (STM32F411)LL库体验 8 - PWM的使用

news/2025/1/31 6:43:45/

Nucleo-F411RE (STM32F411)LL库体验 8 - PWM的使用

1、简述

LD2连接PA5,而PA5可以映射TIM2_CH1,配合TIM2,可以输出PWM。
本片文章大量工作是添加了shell命令,可以通过pwm命令开关pwm以及设置pwm的频率,占空比等。
在这里插入图片描述
在这里插入图片描述

2、TIM2的初始化

prescaler以及period的计算,之前的文章里已经讲了很多了,不管gd32、mm32 ,stm32都是类似了。

__STATIC_INLINE void  BOARD_ConfigureTim2PwmOutput(void)
{/*************************//* GPIO AF configuration *//*************************//* Enable the peripheral clock of GPIOs */LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);/* GPIO TIM2_CH1 configuration */LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_5, LL_GPIO_MODE_ALTERNATE);LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_5, LL_GPIO_PULL_DOWN);LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_5, LL_GPIO_SPEED_FREQ_HIGH);LL_GPIO_SetAFPin_0_7(GPIOA, LL_GPIO_PIN_5, LL_GPIO_AF_1);/***********************************************//* Configure the NVIC to handle TIM2 interrupt *//***********************************************/NVIC_SetPriority(TIM2_IRQn, 0);NVIC_EnableIRQ(TIM2_IRQn);/******************************//* Peripheral clocks enabling *//******************************//* Enable the timer peripheral clock */LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); /***************************//* Time base configuration *//***************************//* Set counter mode *//* Reset value is LL_TIM_COUNTERMODE_UP *///LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);/* Set the pre-scaler value to have TIM2 counter clock equal to 10 kHz */LL_TIM_SetPrescaler(TIM2, __LL_TIM_CALC_PSC(SystemCoreClock, 1000000));/* Enable TIM2_ARR register preload. Writing to or reading from the         *//* auto-reload register accesses the preload register. The content of the   *//* preload register are transferred into the shadow register at each update *//* event (UEV).                                                             */  LL_TIM_EnableARRPreload(TIM2);/* Set the auto-reload value to have a counter frequency of 1000 Hz *//* TIM2CLK = SystemCoreClock / (APB prescaler & multiplier)               */LL_TIM_SetAutoReload(TIM2, __LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(TIM2), 1000));/*********************************//* Output waveform configuration *//*********************************//* Set output mode *//* Reset value is LL_TIM_OCMODE_FROZEN */LL_TIM_OC_SetMode(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_PWM1);/* Set output channel polarity *//* Reset value is LL_TIM_OCPOLARITY_HIGH */LL_TIM_OC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_OCPOLARITY_HIGH);/* Set compare value to half of the counter period (50% duty cycle ) */LL_TIM_OC_SetCompareCH1(TIM2, ( (LL_TIM_GetAutoReload(TIM2) + 1 ) / 2));/* Enable TIM2_CCR1 register preload. Read/Write operations access the      *//* preload register. TIM2_CCR1 preload value is loaded in the active        *//* at each update event.                                                    */LL_TIM_OC_EnablePreload(TIM2, LL_TIM_CHANNEL_CH1);/**************************//* TIM2 interrupts set-up *//**************************//* Enable the capture/compare interrupt for channel 1*/LL_TIM_EnableIT_CC1(TIM2);/**********************************//* Start output signal generation *//**********************************//* Enable output channel 1 */LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1);/* Enable counter */LL_TIM_EnableCounter(TIM2);/* Force update generation */LL_TIM_GenerateEvent_UPDATE(TIM2);
}

这边开了一个捕获中断,这里只是在捕获到高电平时,获取了一下当前的计数值,用来计算占空比。

void TIM2_IRQHandler(void)
{/* Check whether CC1 interrupt is pending */if(LL_TIM_IsActiveFlag_CC1(TIM2) == 1){/* Clear the update interrupt flag*/LL_TIM_ClearFlag_CC1(TIM2);/* TIM2 capture/compare interrupt processing(function defined in main.c) */TimerCaptureCompare_Callback();}
}
uint16_t uwMeasuredDutyCycle;void TimerCaptureCompare_Callback(void)
{uwMeasuredDutyCycle = (LL_TIM_GetCounter(TIM2) * 100) / ( LL_TIM_GetAutoReload(TIM2) + 1 );
}

3、shell 命令添加。

pwm -i 获取系统信息
在这里插入图片描述

pwm -h 命令帮助
在这里插入图片描述

pwm -d xx 设置占空比
在这里插入图片描述

pwm -f xx 设置pwm的频率
在这里插入图片描述
pwm -p xx 设置tim的presclaer,设置后频率设置为1000HZ

在这里插入图片描述
pwm -b 1开启呼吸灯,pwm -b 0关闭呼吸灯

命令代码:

#include "extend_shell.h"
#include "shell_port.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "getopt.h"
#include "main.h"volatile bool isRunBreath = false;const char *ocMode[] = {"LL_TIM_OCMODE_FROZEN","LL_TIM_OCMODE_ACTIVE","LL_TIM_OCMODE_INACTIVE","LL_TIM_OCMODE_TOGGLE","LL_TIM_OCMODE_FORCED_INACTIVE","LL_TIM_OCMODE_FORCED_ACTIVE","LL_TIM_OCMODE_PWM1","LL_TIM_OCMODE_PWM2"
};uint32_t TypeOcMode[8] = {LL_TIM_OCMODE_FROZEN,LL_TIM_OCMODE_ACTIVE,LL_TIM_OCMODE_INACTIVE,LL_TIM_OCMODE_TOGGLE,LL_TIM_OCMODE_FORCED_INACTIVE,LL_TIM_OCMODE_FORCED_ACTIVE,LL_TIM_OCMODE_PWM1,LL_TIM_OCMODE_PWM2};static const char * Find_OCModeName(uint32_t ocModeType)
{uint32_t i=0;for (i=0; i< 8;i++){if (ocModeType == TypeOcMode[i])break;}return ocMode[i];
}                        void PWM_ShowUsage(void)
{printf("Usage:\r\n");printf("  pwm (-h | --help)\r\n");printf("  pwm (-i | --info)\r\n");printf("  pwm (-r | --reload)       set pwm reload (0-65535)\r\n");printf("  pwm (-p | --prescaler)    set pwm prescaler (0-65535)\r\n");printf("  pwm (-d | --duty)         set pwm duty (1-100)\r\n");printf("  pwm (-e | --enable)       enable/disable pwm mode (0/1) \r\n");printf("  pwm (-b | --breath)       enable/disable led breath mode (0/1)\r\n");}void PWM_ShowInfomation(void)
{LL_RCC_ClocksTypeDef rccClock;LL_RCC_GetSystemClocksFreq(&rccClock);printf("Nucleo-F411RE Info:\r\n");printf(" Version                : %s %s\r\n",__DATE__,__TIME__);printf(" System Clock           : %ld\r\n",rccClock.SYSCLK_Frequency);printf(" AHB Clock              : %ld\r\n",rccClock.HCLK_Frequency);printf(" APB1 Clock             : %ld\r\n",rccClock.PCLK1_Frequency);printf(" APB2 Clock             : %ld\r\n",rccClock.PCLK2_Frequency);printf(" TIM2 Status            : %s\r\n",LL_TIM_IsEnabledCounter(TIM2)==1?"enable" : "disable");printf(" TIM2 OC Mode           : %s\r\n",Find_OCModeName(LL_TIM_OC_GetMode(TIM2,LL_TIM_CHANNEL_CH1)));printf(" TIM2 CHannel Status    : %s\r\n",LL_TIM_CC_IsEnabledChannel(TIM2,LL_TIM_CHANNEL_CH1) ==1 ?"enable": "disable");printf(" TIM2 PWM Prescaler     : %ld\r\n",LL_TIM_GetPrescaler(TIM2) + 1);printf(" TIM2 PWM AutoReload    : %ld\r\n",LL_TIM_GetAutoReload(TIM2) + 1);printf(" TIM2 PWM Duty          : %.1f%%\r\n",(float)(LL_TIM_OC_GetCompareCH1(TIM2)* 100)/(LL_TIM_GetAutoReload(TIM2) + 1));printf(" TIM2 PWM Freq          : %ldHZ\r\n",(rccClock.SYSCLK_Frequency)/((LL_TIM_GetPrescaler(TIM2) + 1)*(LL_TIM_GetAutoReload(TIM2) + 1)));
}int PWM_Control(int argc,char *argv[])
{       int c;int longindex = 0;int duty = 0;int breath = 0;const char short_options[] = "hid:e:b:p:f:";const struct option long_options[] ={{"help",            0,  NULL,     'h'},{"info",            0,  NULL,     'i'},{"duty",            1,  NULL,     'd'},{"enable",          1,  NULL,     'e'},{"breath",          1,  NULL,     'b'},{"freq",            1,  NULL,     'f'},{"prescaler",       1,  NULL,     'p'},{NULL,              0,  NULL,     0},};if (argc == 1){/* goto the help */PWM_ShowUsage();return 0;}/* init 0 */optind = 0;opterr = 0;/* parse */do{/* parse the args */c = getopt_long(argc, argv, short_options, long_options, &longindex);switch (c){case 'f':printf("Now set pwm freq %s\r\n",optarg);int freq = strtol(optarg,NULL,10);if (freq > 0){int reload = __LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(TIM2), freq);if (reload + 1 > 65535){printf("auto reload value must 0-65535,please set prscaler first\r\n");return 0;}else{LL_TIM_DisableCounter(TIM2);LL_TIM_SetAutoReload(TIM2, __LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(TIM2), freq));LL_TIM_OC_SetCompareCH1(TIM2, ( (LL_TIM_GetAutoReload(TIM2) + 1 ) / 2));LL_TIM_EnableCounter(TIM2);}}else{printf(" set freq error ,must pwm -f xx\r\n");return 0;}break;    case 'p':printf("Now set pwm prescaler %s\r\n",optarg);int prescaler = strtol(optarg,NULL,10);if (prescaler > 0 && (prescaler) < 65535){LL_TIM_DisableCounter(TIM2);LL_TIM_SetPrescaler(TIM2,prescaler-1);int reload = __LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(TIM2), 1000); //修改perscaler 默认1000HZif (reload + 1 > 65535){printf("reload value must 0-65525\r\n");return 0;}else{LL_TIM_SetAutoReload(TIM2,reload);LL_TIM_OC_SetCompareCH1(TIM2, ( (LL_TIM_GetAutoReload(TIM2) + 1 ) / 2));LL_TIM_EnableCounter(TIM2);}}else{printf(" set prescaler error ,must pwm -f xx\r\n");return 0;}break;case 'h'/* constant-expression */:/* code */PWM_ShowUsage();return 0;case 'i':PWM_ShowInfomation();break;case 'd': duty = strtol(optarg,NULL,10);printf("Now set pwm duty %s\r\n",optarg);if (duty >= 0 && duty <=100){duty = (duty  * (LL_TIM_GetAutoReload(TIM2) + 1)) / 100;LL_TIM_OC_SetCompareCH1(TIM2, duty);}else{printf(" set duty error,must between 0 and 100\r\n");return 0;}break;case 'e': printf("Now set pwm state\r\n");break;case 'b': breath = strtol(optarg,NULL,10);if (breath == 1){isRunBreath = true;}else if (breath == 0){isRunBreath = false;}else{printf(" error ,must be 0/1\r\n");}printf("Now set pwm breath\r\n");break;default:break;}}while (c != -1);return 0;
}SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), pwm, PWM_Control, PWM_Control);

代码

代码下载


http://www.ppmy.cn/news/440280.html

相关文章

004依赖

传递 一个坐标引入多个jar 传递 子工程 引入了父pom 也是一种传递 继承 继承是为了消除重复&#xff0c;如果将 dao、service、web 分开创建独立的工程则每个工程的 pom.xml 文件中的内容存在重复&#xff0c;比如&#xff1a;设置编译版本、锁定 spring 的版本的等&#xff…

红米note4x开启root权限

红米Note 4X有啥好方法获取了ROOT超级权限&#xff1f; 百度搜索红米note4x线刷包&#xff0c;下载稳定版、开发版的版本&#xff08;刷机成功之后&#xff0c;可以直接在<设置——应用管理——权限——root权限管理>里面开启手机的root权限&#xff09;&#xff0c;可以…

红米手机5 Plus启用root超级权限的步骤

红米手机5 Plus怎么开启root超级权限&#xff1f;做开发的人清楚&#xff0c;Android机器有root超级权限&#xff0c;一旦手机开启root相关权限&#xff0c;就可以实现更强的功能&#xff0c;举个栗子做开发的人企业的营销部门的妹子&#xff0c;使用大多数营销软件都需要在roo…

怎么开启小米Note 3的root超级权限

小米Note 3有没有办法获得Root权限&#xff1f;我们都知道&#xff0c;android设备有Root权限&#xff0c;一旦手机获得root相关权限&#xff0c;就能够实现更好的功能&#xff0c;举个栗子我们单位的营销部门的妹纸&#xff0c;使用一些营销工具都需要在Root权限下工作&#x…

三星s4 android 5.0 root权限,三星S4(i9500)一键ROOT权限获取+USB驱动

三星S4手机上月15号就上市了,中国版本暂时还没有真机,但是本月就可以买到了,本手机有暂时有2个版本(I9505和I9500) I9505是移动3G版本,I9500为标准版,支移动和联通,电信版本还暂时没有出来,电信版本为I959,联通3G版本为I9502. 手机配置为4核CPU处理器三星Exynos 5410 1.8GHz,5.…

Android 如何永久性开启adb 的root权限 M

分类&#xff1a; Android MTK 2013-12-11 18:00 427人阅读 评论(0) 收藏 举报 csdn Android google apk frameworks 前言 欢迎大家我分享和推荐好用的代码段~~ 声明 欢迎转载&#xff0c;但请保留文章原始出处&#xff1a; CSDN&#xff1a;ht…

【Android系统源码修改】默认开启root权限

1.找到&#xff1a;system\core\adb\adb.c中的static int should_drop_privileges() 方法&#xff0c;直接返回0&#xff1b; 2.找到external\sepolicy\Android.mk中的 sepolicy_policy_recovery.conf : $(intermediates)/policy_recovery.conf $(sepolicy_policy_recovery.co…

root开启后怎么关闭,手机root开启后怎么关闭

如何关闭root权限&#xff1f; 取消root权限的方法其实是比较简单的&#xff0c;一般通常是需要重新刷机或固件升级都是可以取消root权限&#xff0c;也可以去体验店或售后进行固件升级都是可以的。取消root权限的具体方法&#xff1a; 1、下载手机刷机软件&#xff0c;并打开软…