iTOP-STM32MP157开发板采用ST推出的双核cortex-A7+单核cortex-M4异构处理器,既可用Linux、又可以用于STM32单片机开发。开发板采用核心板+底板结构,主频650M、1G内存、8G存储,核心板采用工业级板对板连接器,高可靠,牢固耐用,可满足高速信号环境下使用。共240PIN,CPU功能全部引出:底板扩展接口丰富底板板载4G接口(选配)、千兆以太网、WIFI蓝牙模块HDMI、CAN、RS485、LVDS接口、温湿度传感器(选配)光环境传感器、六轴传感器、2路USB OTG、3路串口,CAMERA接口、ADC电位器、SPDIF、SDIO接口等
第三十二章Cortex-M4 PWM呼吸灯实验
本章节最终所完成的实验例程存放路径为“iTOP-STM32MP157开发板网盘资料汇总\06_Cortex-M4实验例程\08_PWM.zip”。
32.1 PWM简介
32.1.1什么是PWM
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
以单片机为例,我们知道,单片机的IO口输出的是数字信号,IO口只能输出高电平和低电平。
假设高电平为5V 低电平则为0V 那么我们要输出不同的模拟电压,就要用到PWM,通过改变IO口输出的方波的占空比从而获得使用数字信号模拟成的模拟电压信号。
我们知道,电压是以一种连接1或断开0的重复脉冲序列被夹到模拟负载上去的(例如LED灯,直流电机等),连接即是直流供电输出,断开即是直流供电断开。通过对连接和断开时间的控制,理论上来讲,可以输出任意不大于最大电压值(即0~5V之间任意大小)的模拟电压。
比方说 占空比为50% 那就是高电平时间一半,低电平时间一半,在一定的频率下,就可以得到模拟的2.5V输出电压 那么75%的占空比得到的电压就是3.75V。
pwm的调节作用来源于对“占周期”的宽度控制,“占周期”变宽,输出的能量就会提高,通过阻容变换电路所得到的平均电压值也会上升,“占周期”变窄,输出的电压信号的电压平均值就会降低,通过阻容变换电路所得到的平均电压值也会下降。
也就是,在一定的频率下,通过不同的占空比即可得到不同的输出模拟电压。
32.1.2 PWM 输出模式
PWM 有两种输出模式,分别为 PWM 模式 1 和 PWM 模式 2。可以理解 PWM 模式1是与PWM 模式 2 互补的波,PWM 模式 1 为高电平时,PWM 模式 2 为低电平,反之亦然。PWM模式和计数器计数模式对通道输出的 PWM 波电平有影响:在 PWM 模式 1 下,当计数器向上计数时,如果 CNT< CCRx 时,通道为有效电平,否则为无效电平;当计数器向下计数时,如果CNT>CCRx 时,通道为无效电平,否则为有效电平。示意框图如下图所示:
PWM 模式 | 计数器计数方向 | 电平情况 |
PWM 模式 1 | 向上计数 | 如果 CNT< CCRx 时,通道为有效电平;否则为无效电平 |
向下计数 | 如果 CNT>CCRx 时,通道为无效电平;否则为有效电平 | |
PWM 模式 2 | 向上计数 | 如果 CNT< CCRx 时,通道为无效电平;否则为有效电平 |
向下计数 | 如果 CNT>CCRx 时,通道为有效电平;否则为无效电平 |
STM32MP157 的定时器除了基本定时器 TIM6 和 TIM7,其他的定时器都可以用来产生PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4 路的 PWM 输出。
32.1.3 PWM生成
PWM 波频率由自动重装载寄存器(TIMx_ARR)的值决定,其占空比则由捕获/比较寄存器(TIMx_CCRx)的值决定。它们生成 PWM 的原理如图下图所示:
上图就是一个简单的 PWM 原理示意图。图中,我们假定定时器工作在边沿对齐,向上计数 PWM 模式,且当 CNT<CCRx 时,输出 0,当 CNT>=CCRx 时输出 1。那么就可以得到如上的 PWM 示意图:当 CNT 值小于 CCRx 的时候,IO 输出低电平(0),当 CNT 值大于等于 CCRx的时候,IO 输出高电平(1),当 CNT 达到 ARR 值的时候,重新归零,然后重新向上计数,依次循环。改变 CCRx 的值,就可以改变 PWM 输出的占空比,改变 ARR 的值,就可以改变 PWM输出的频率,这就是 PWM 输出的原理。
定时器除了支持单向的向上或向下计数模式外,还支持中心对齐计数模式,以后我们会对此进行讲解。
32.2实验目的
1)学习使用STM32CubeIED配置基本定时器
2)学习基本定时器的使用
3)STM32CubeIED的熟练
本实验我们使用 TIM1 的 CH4 通道产生一路 PWM输出来控制 LED2(PE14) 为例进行学习,如下图STM32MP157 数据手册关于PE14的部分功能截图:
PE14 可以复用为 TIM1_CH4,通过配置 TIM1_CH4 产生 PWM 波形可以控制LED2工作。
32.3实验步骤
32.3.1建立PWM工程
首先我们打开STM32CubeIDE软件,进入软件界面之后,我们点击File属性,选择NEW下的STM32 Project的选项,如下图所示:
然后我们会进入下图所示界面:在Part Number选择框输入STM32MP157A,然后在右边的选择界面选择STM32MP157AAA,然后点击Next选项
在Project Name框中输入工程名字PWM,然后点击Finish选项即可,如下图所示:
等待工程创建完毕,会询问我们是否要安装OpenSTLinux ,由于我们是在windows环境下,所以我们不需要安装,点击NO即可
至此我们的工程创建完毕,进入工程界面如下图所示界面:
32.3.2 GPIO功能引脚配置
首先我们在下面的搜索框之中输入我们要配置的引脚,我们在这里搜索PE14,输入名称之后,对应的引脚在工程中会闪烁,如下图所示:
然后我们使用鼠标左键点击对应的引脚会弹出PE14的复用功能选择,我们在这里选择复用为TIM1_CH4功能,如下图所示:
32.3.3 时钟与定时器的配置
首先我们本次实验所采用的时钟为外部时钟HSE,所以我们要在左侧属性栏中的System Core 属性下找到RCC将High Speed Clock选择为Crystal/Ceramic Resonator(晶体/陶瓷晶振)。如下图所示:
然后在Clock Configuration里我们选择 HSE,作为锁相环 PLL3P 的时钟源,在 MCU 子系统时钟里输入 209 并回车,软件会自动设置相应的倍频和分频,如下图所示:
设置完成之后,如下图所示,然后再手动配置 APB1DIV、APB2DIV 和 APB3DIV的分频值为 2。当 APB1DIV 的分频数大于 1 的时候,基本定时器的倍频器倍频值始终为 2,所以基本定时器的时钟频率为 209MHz。
配置完时钟之后,下面我们将要对TIM1进行配置按照步骤配置 :
在TimersàTIM1中配置如下,Clock Source选择Internal Clock,表示选择内部时钟,Channel4 选择PWM Generation CH4,表示使用TIM1的通道4产生PWM波形,其它选项保持默认配置。
接下来我们进入同一界面下方的configuration配置界面,来设置TIM1的Counter Settings ,Counter Settings 用于配置计数器的参数:
l Prescaler:配置定时器的分频系数,这里配置 209-1;
l Counter Mode:定时器的计数模式,我们选择 UP,即向上计数模式;
l Counter Period:计数周期,即自动重装载值,也就是装在 TIM1_ARR 的值,这里配置为500-1;
l auto-reload preload:这里设置为 Enable,定时器自动重装载使能,即使能 TIMx_ARR寄存器进行缓冲;
上述参数可以计算定时器的时钟频率为:
PWM Generation Channel4 用于配置通道 4 的参数,其中:
l Mode:用于配置 PWM 的模式,这里选择 PWM mode 1,即 PWM 模式 1。另外还有 PWM 模式 2,可以理解 PWM mode l 是与 PWM mode 2 模式互补的波,PWM 模式 1 为高电平,PWM 模式 2 为低电平,反之亦然。
l Pulse (16 bits value):是占空比值,即 TIM1_CCR4 的值,也就是有效电平的值,可以配置在 0-500 之间,例如配置 0。这里配置 250,即占空比为 50%。在后面的实验中,我们会对TIMx_CCR4 寄存器写入新的值来改变占空比,从而控制 LED 逐渐点亮和熄灭。定时器要每秒溢出产生中断,所以我们要使能定时器全局中断,并配置中断优先级。如下图,勾选 TIM6 定时器全局中断:
l Output compare preload:输出比较预加载项选择Enable,即在定时器工作时是否能修改Pulse的值,如果禁用此项,表示定时器工作时不能进行修改,只能等到更新事件到来的时候才能进行修改,所以这里选择使能。
l CH Polarity:输出极性,这里我们选择 High(LED3 是低电平有效),配置完成如下图所示:
配置完成之后我们需要在Project Manage下的Code Generator选项下勾选 Generate peripheral initialization as a pair of ".c/.h' files per peripheral 选项,这样可以独立生成对应外设的初始化.h 和.c 文件(方便配置的查看),如下图所示:
32.3.4工程的生成与完善
在上述的步骤完成之后,按下键盘的“Ctrl+S”组合键保存保存 PWM.ioc 文件,系统开始生成初始化代码,工程生成之后如下图所示:
然后我们进行工程的完善,以及添加对应的逻辑代码。
我们要修改的main.c文件路径如下图所示:
然后在 /* USER CODE BEGIN 0 */和/* USER CODE END 0 */之间添加以下内容:
uint16_t ledrpwmval[11] = {0,30,60,90,120,150,180,210,240,270,300};
uint8_t cnt = 0;
定义了一个数组和一个变量,数组中存放的为占空比的变化值,而cnt用来表示循环计数的变量。 添加完成如下图所示:
然后在 /* USER CODE BEGIN 2 */和/* USER CODE END 2 */之间添加以下内容:
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
打开定时器1的PWM输出通道4,添加完成如下图所示:
最后在while循环中添加以下内容:
(TIM1->CCR4)=ledrpwmval[cnt];
HAL_Delay(500);
cnt++;
if (cnt == 11)cnt = 1;
每500ms改变一次占空比,不断循环,添加完成,如下图所示
32.3.5工程的编译
在完成以上步骤之后我们点击工具栏的小锤子进行编译,编译图标如下图所示:
编译完成会在下方的终端中显示打印信息,如下图所示:
如果报错,需要自己根据错误的提示信息来进行问题的寻找和改正。
32.3.6工程的调试
由于STM32MP157的裸机部分和一般的单片机有些区别,他没有内部的存储,所以只能在程序编译成功之后,通过debug的方式来进行调试(将程序放在内存之中),调试过程如下:
首先,点击菜单栏中的小甲虫Debug调试按钮,弹出以下界面,
在弹出来的界面,按步骤,选择响应的属性(该步骤为Jlink的步骤,如果是STLink,调试探头选择对应的即可)。如下图所示:
选择完成之后,点击右下角的Debug按钮,点击之后,会进行再一次的编译,编译完成之后会弹出如下内容(作者用的是J-LinK),这里弹出的是J-link关于设备的选择,不同调试器的弹窗可能会不同
在弹出来的界面中,选择Accept接受,会弹出以下内容,继续点击下方的OK。
之后会来到设备选择界面,我们选择Cortex-M4,如下图所示:
选择Cortex-M4之后,点击右下角的OK,会弹出以下界面,选择右下角Switch.
然后会弹出一个新的页面,选择菜单栏的 resume按钮开始调试。
此时,LED2会逐渐变亮,最亮之后熄灭,然后再逐渐变亮,循环往复。
如果想关闭调试,则点击菜单栏的终止按钮即可。