《嵌入式-STM32开发指南》第二部分 基础篇 - 第5章 PWM(HAL库)

发布者:幸福旅程最新更新时间:2025-01-06 来源: jianshu关键字:STM32  PWM  HAL库 手机看文章 扫描二维码
随时随地手机看文章

5.1 PWM_输出

5.1.1 PWM输出的工作原理

脉冲宽度调制(PWM),是英文“ Pulse Width Modulation” 的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。 简单一点,就是对脉冲宽度的控制。

STM32 的定时器除了 TIM6 和 7(基本定时器)。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样, STM32 最多可以同时产生 30 路 PWM 输出。

每个定时器有四个通道,每一个通道都有一个捕获比较寄存器,,将寄存器值和计数器值比较,通过比较结果输出高低电平,便可以实现脉冲宽度调制模式(PWM信号)。

在上一节,讲解了定时器的相关寄存器即基本原理,本节将不再赘述。下面谈谈如何使用定时器的寄存器进行PWM输出的。若配置脉冲计数器TIMx_CNT为向上计数,而重载寄存器TIMx_ARR配置为N,即TIMx_CNT的当前计数值数值X在TIMxCLK时钟源的驱动下不断累加,当TIMx_CNT的数值X大于N时,会重置TIMx_CNT数值为0重新计数。而在TIMxCNT计数的同时,TIMxCNT的计数值X会与比较寄存器TIMx_CCR预先存储了的数值A进行比较,当脉冲计数器TIMx_CNT的数值X小于比较寄存器TIMx_CCR的值A时,输出高电平(或低电平),相反地,当脉冲计数器的数值X大于或等于比较寄存器的值A时,输出低电平(或高电平)。如此循环,得到的输出脉冲周期就为重载寄存器TIMx_ARR存储的数值(N+1)乘以触发脉冲的时钟周期,其脉冲宽度则为比较寄存器TIMx_CCR的值A乘以触发脉冲的时钟周期,即输出PWM的占空比为A/(N+1)。

估计很多初学者看了上面的一段话都很蒙圈,没关系,下面以向上计数模式为例进行讲解。

图1向上计数模式

在PWM输出模式下,除了CNT(计数器当前值)、ARR(自动重装载值)之外,还多了一个值CCRx(捕获/比较寄存器值)。当CNT小于CCRx时,TIMx_CHx通道输出低电平;当CNT等于或大于CCRx时,TIMx_CHx通道输出高电平。因此得到PWM的一个周期如下:

1.定时器从0开始向上计数;
2.当0-t1段,定时器计数器TIMx_CNT值小于CCRx值,输出低电平;
3.t1-t2段,定时器计数器TIMx_CNT值大于CCRx值,输出高电平;
4.当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数...循环此过程。

至此一个PWM周期完成。针对PWM重点关注两个寄存器,TIMx_ARR寄存器确定PWM频率,TIMx_CCRx寄存器确定占空比。

上文提到了PWM的输出模式,下面讲解PWM的工作模式:

  • PWM模式1(向上计数)  :计数器从0计数加到自动重装载值(TIMx_ARR),然后重新从0开始计数,并且产生一个计数器溢出事。

  • PWM模式2(向下计数)  :计数器从自动重装载值(TIMx_ARR)减到0,然后重新从重装载值(TIMx_ARR)开始递减,并且产生一个计数器溢出事件。

[ps] 本文以F1系列为例进行讲解,ST不同系列其定时器个数不同

STM32F1系列共有8个定时器:

高级定时器(TIM1、TIM8);通用定时器(TIM2、TIM3、TIM4、TIM5);基本定时器(TIM6、TIM7)。

5.1.2 STM32Cube生成工程

本文介绍在STM32CubeMX进行定时器的配置,这里我们仅利用 TIM3的 4路通道输出,方便我们比较波形。具体不同定时器对应引脚在对应芯片数据手册的引脚说明(pin description) 中查看。

表1 STM32F1定时器输出通道引脚

1.设置RCC

设置高速外部时钟HSE,选择外部时钟源。

图2 RCC配置

2.时钟配置

笔者的板子使用的外部晶振为8MHz,选择外部时钟HSE 8MHz ,PLL锁相环9倍频后为72MHz,系统时钟来源选择为PLL,设置APB1分频器为 /2,这时候定时器的时钟频率为72Mhz。本文笔者使用的定时器是TIM3,TIM3挂在APB1上,不同的定时器挂在不同总线上的。

图 3时钟配置

3.Times配置

选择TIM,使能TIM3,指定时钟源。

图4使能TIM3时钟源

【注】TIM2的时钟源有两个选项

选项1 :Internal Clock 内部时钟
选项2 : ETR2 外部触发输入(ETR)(仅适用TIM2,3,4)

本文要使用TIM3的四个通道,因此需要将其使能。每个通道有很多模式,这里选择PWM输出。当对应的通道打开后,对应的GPIO也会被使能。

图5使能TIM3的通道

【注】如果使能通道前通道中GPIO使用过,STM32CubeMX会自动将GPIO配置为重映射的GPIO。举个例子,当PB0被占用了,那么四个GPIO会重映射到PC6-PC9。

PWM参数配置如下:

  • Counter setting

Prtscaler (定时器分频系数) : 0
Counter Mode(计数模式) :Up(向上计数模式)
Counter Period(自动重装载值) : 999
CKD(时钟分频因子) : No Division 不分频
选项: 可以选择二分频和四分频
auto-reload-preload(自动重装载) : Enable 使能

  • TRGO Output (TRGO) Parameters

Master/Slave Mode(MSM bit):Disable
TRGO:定时器的触发信号输出 在定时器的定时时间到达的时候输出一个信号(如:定时器更新产生TRGO信号来触发ADC的同步转换,)

  • PWM Generation Channel (四个CH)

Mode(定时模式):PWM mode 1
Pulse(计数比较值):四个通道分别为500,375,250,125
CH Polarity(输出极性):High

图6 PWM输出参数配置

根据前面的参数配置,我们可以算出PWM的输出周期:

PWM=1/(Tclk/(psc+1))*(arr+1)

这里我们arr=999, psc=0, Tclk=72Mhz

PWM=1/(72Mhz/(1))*(999+1)=72ms

本文选择的是PWM模式1,在向上计数时,一旦TIMx_CNT < TIMx_CCR1(计数比较值)。时通道1为有效电平,否则为无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。输出比较极性的指的是你在比较匹配之后输出口输出的极性,也就是设置比较输出的有效电平。你可以设置为高电平有效或者低电平有效。如果设置为高电平有效,那么当定时器比较匹配之后,输出口输出高电平,否则就反一下。

如果是PWM模式1,且向上计数,如果极性设置为低,那么 TIMx_CNT < TIMx_CCR1 时,输出低电平,更简单就是占空比为1 -TIMx_CCR1/(ARR+1). 如果极性为高,占空比就是TIMx_CCR1/(ARR+1)。

好了,到这里,配置就完成了,生成工程就行了。

5.1.3 PWM输出的具体代码分析

我们先看看主函数,其代码如下:

int main(void)


{


  /* USER CODE BEGIN 1 */


  /* USER CODE END 1 */


  /* MCU Configuration--------------------------------------------------------*/


  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */


  HAL_Init();


  /* USER CODE BEGIN Init */


  /* USER CODE END Init */


  /* Configure the system clock */


  SystemClock_Config();


  /* USER CODE BEGIN SysInit */


  /* USER CODE END SysInit */


  /* Initialize all configured peripherals */


  MX_GPIO_Init();


  MX_TIM3_Init();


  /* USER CODE BEGIN 2 */


/*使能定时3*/


  HAL_TIM_Base_Start_IT(&htim3);


HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);


HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);


HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);


HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);


//HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_ALL);


  /* USER CODE END 2 */


  /* Infinite loop */


  /* USER CODE BEGIN WHILE */


  while (1)


  {


    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */


  }


  /* USER CODE END 3 */


}


在主循环前面,需要对TIM3进行初始化配置:

HAL_TIM_Base_Start_IT(&htim3);

然后再开启四路通道的PWM:

HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);


HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);


HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);


HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);


如果全部开启,可使用以下代码:

HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_ALL);

PWM输出最重要就是MX_TIM3_Init()函数,这个函数包含了TIM3的PWM配置,具体再讲。

5.1.4 PWM输出的实验现象

现在,TIM3 的通道 1(PA.06)、2(PA.07)、3(PB.00)、4(PB.01)就会输出不同占空比的 PWM 信号了。PWM 信号可以通过示波器看到。考虑到并不是每个用户手头上都有示波器,我们在这里采用软件仿真的方式来验证我们的程序。

以前我们都是通过 J_LINK 直接将我们的代码烧到开发板的 Flash 中去调试,现在要换成软件仿真,得首先设置一下我们的开发环境,按照如下步骤所示。

1)点击 Target Options 选项图标,选中 Debug 选项卡,选中 Use Simulator 选项,按图中所示进行设置,然后点击“OK”按钮,见图7所示。

图7模拟调试设置

2)点击 Start/Stop Debug Session 选项图标,点击System Analysis Windows的下拉选项的 Logic Analysis,弹出窗口后点击Setup…选项卡,在弹出的 Setup Logic Analysis 串口中点击 New(Insert)按钮,然后在文本栏里面分别输入:PORTA.6 、PORTA.7、PORTB.0、PORTB.1,记住,是 New 一个就输入一个信号的 IO,输完之后需要再 New。对应的相关设置见图8。

图8 端口输出配置

需要注意的是Display Range的设置,默认的设置是看不到波形的。

3)设置完信号源之后,点击 RUN 按钮,仿真信号即出来了,当信号出来之后,可点击STOP 按钮,让信号不再变化,方便观察。其中 In、Out、All 这三个按钮可以调节显示信号的疏密程度,见图9。

图9波形输出

其中 Cursor 选项可以帮助我们测量信号的时间差,Amplitute 则可以帮助我们测量信号的幅值。

【注】有的STM32cudeMX生成的工程不一定能 ,如果实在没法看结果,直接看呼吸灯实验吧。

5.2呼吸灯

5.2.1呼吸灯的工作原理

呼吸灯,就是指灯光设备的亮度随着时间由暗到亮逐渐增强,再由亮到暗逐渐衰减,很有节奏感地一起一伏,就像是在呼吸一样,因而被广泛应用于手机、电脑等电子设备的指示灯中。冰冷的电子设备应用呼吸灯后,顿时增添了几分温暖。

要使用数字器件控制灯光的强弱,我们很自然就想到 PWM(脉冲宽度调制)技术。假如以LED 作为灯光设备,且由控制器输出的 PWM 信号可以直接驱动 LED,PWM 信号中的低电平可点亮 LED 灯。当 LED 以较高的频率进行开关(亮灭)切换时,由于视觉暂留效应,人眼是看不到 LED 灯的闪烁现象的,反映到人眼中能感觉到的是亮度的差别。即以一定的时间长度为周期,LED 灯亮的平均时间越长,亮度就越高,反之越暗。因此,我们可以使用高频率的 PWM 信号,通过调制信号的占空比,控制 LED 灯的亮度。

那么具体我们应该控制 LED 灯以怎样的亮度曲线变化能够达到最好的效果呢?亮度随着时间逐渐变强再衰减,可以用两种常见的数学函数表示,分别是半个周期的正弦函数与指数上升曲线及其对称得到的下降曲线。

图10正弦曲线与指数曲线

相对来说,使用下凹函数曲线灯光处于暗的状态更长,所以指数函数的曲线更符合我们呼吸灯的亮度变化要求。

接下来就要确定呼吸灯的呼吸频率(即一个亮度起伏过程)。据统计,成人的一个呼吸周期为 3 秒钟,即吸气时间(亮度上升时间) 1.5 秒,呼气时间(亮度衰减时间)1.5 秒。我们使用定时器即可精确控制它的呼吸频率,当然,读者想把呼吸灯的频率调快或慢一点都是可以的,呼吸周期为 3 秒钟只是一个参考值。

5.2.2 STM32Cube生成工程

和上一节内容差不多,稍微有些不同罢了。

1.设置RCC

设置高速外部时钟HSE,选择外部时钟源。

图11 RCC配置

2.时钟配置

笔者的板子使用的外部晶振为8MHz,选择外部时钟HSE 8MHz ,PLL锁相环9倍频后为72MHz,系统时钟来源选择为PLL,设置APB1分频器为 /2,这时候定时器的时钟频率为72Mhz。本文笔者使用的定时器是TIM3,TIM3挂在APB1上,不同的定时器挂在不同总线上的。

图12时钟配置

3.Times配置

选择TIM,使能TIM3,指定时钟源。

图13使能TIM3时钟源

本节要使用TIM3的CH3通道,因此需要将其使能。这里选择PWM输出。当对应的通道打开后,对应的GPIO也会被使能。笔者的板子的LED接到了PB0上,这里要根据自己的板子来配置TIM和CH。

图14使能TIM3的CH3通道

PWM参数配置如下:

  • Counter setting

Prtscaler (定时器分频系数) : 1999
Counter Mode(计数模式) :Up(向上计数模式)
Counter Period(自动重装载值) : 255
CKD(时钟分频因子) : No Division 不分频
选项: 可以选择二分频和四分频
auto-reload-preload(自动重装载) : Enable 使能

  • TRGO Output (TRGO) Parameters

Master/Slave Mode(MSM bit):Disable
TRGO:定时器的触发信号输出 在定时器的定时时间到达的时候输出一个信号(如:定时器更新产生TRGO信号来触发ADC的同步转换,)

  • PWM Generation Channel (四个CH)

Mode(定时模式):PWM mode 1
Pulse(计数比较值):0
CH Polarity(输出极性):High

图15 PWM输出参数配置

根据前面的参数配置,我们可以算出PWM的输出周期:

PWM=1/(Tclk/(psc+1))*(arr+1)

这里我们 arr=255 , psc=1999, Tclk=72Mhz

PWM=1/(72Mhz/(1+1999))*(255+1)

这个要开启中断。

图16 开启TIM3 的中断

另外将设置GPIO的速度为高速。

图17设置GPIO速度

好了,到这里,就配置完成了。

5.2.3呼吸灯的具体代码分析

我们还是先看看主函数。

int main(void)


{


  /* USER CODE BEGIN 1 */


  /* USER CODE END 1 */


  /* MCU Configuration--------------------------------------------------------*/


  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */


  HAL_Init();


  /* USER CODE BEGIN Init */


  /* USER CODE END Init */


  /* Configure the system clock */


  SystemClock_Config();


  /* USER CODE BEGIN SysInit */


  /* USER CODE END SysInit */


  /* Initialize all configured peripherals */


  MX_GPIO_Init();


  MX_TIM3_Init();


  /* USER CODE BEGIN 2 */


HAL_TIM_Base_Start_IT(&htim3);


HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);


  /* USER CODE END 2 */


  /* Infinite loop */


  /* USER CODE BEGIN WHILE */


  while (1)


  {


    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */


  }


  /* USER CODE END 3 */


}


主函数和上一节的差不多,还好了几句,这个只需初始化TIM3的CH3。那么是哪里不同呢,在回答这个问题之前,先看看呼吸灯的编程流程。

1)硬件初始化,系统时钟初始化;

2)GPIO初始化,TIM3以及PWM初始化;

3)启动定时器和PWM相应通道。

4)调用中断回调函数,不断改变TIMx_CCR寄存器的值。

我们就根据这个思路来看看呼吸灯的具体代码。

1.生成指数曲线 PWM 数据

要实现 LED 亮度随着指数曲线变化,我们需要使用占空比呈指数曲线变化的 PWM 信号,而这样的信号由定时器经过查表产生。这个表的数据存储在程序中的数组 indexWave中。

image.png?imageView2/2/w/1000

图18 LED 变化曲线

uint8_t indexWave[] = {1,1,2,2,3,4,6,8,10,14,19,25,33,44,59,80,


107,143,191,255,255,191,143,107,80,59,44,33,25,19,14,10,8,6,4,3,2,2,1,1};


这个表有 40 个数字,从图中可以看到这些数字呈指数上升再衰减,正好是呼吸灯的一个控制周期。数字的大小范围是 0~ 255,即把 LED 的亮度分为了 0 ~ 255 个等级。

假如我们把定时器的脉冲计数器 TIMx_CNT 上限设置为 255,把这个表的数据一个一个地赋值到定时器的比较寄存器 TIMx_CCR 中,那么在每个 PWM 周期中,当 TIMx_CNT的计数值小于比较寄存器 TIMx_CCR 的值时, 就会在通道中输出低电平,点亮 LED,而随着 TIMx_CCR 的值由 LED 亮度表得来,所以 LED 点亮的时间就会呈图中的曲线变化,实现呼吸灯的功能。

这个表的数据是使用 matlab 软件生成的。该代码运行后会生成一个“index_wave.c”的文件,用户把该文件中的数据复制到工程中的数组中即可。

%本代码用于产生呼吸灯使用的指数函数数据


clear;


x = [0 : 8/19 : 8];      %设置序列 ,指数上升


up = 2.^x ;              %求上升指数序列 


up = uint8(up);          %化为8位数据


y = [8: -8/19 :0];      %设置序列 ,指数下降


down = 2.^y ;            %求下降指数序列


down = uint8(down);      %化为8位数据


line = [[0:8/19:8],[8:8/19:16]]        %拼接序列


val = [up , down]                      %拼接输出序列


dlmwrite('index_wave.c',val);      %输出到文件index_wave.c


plot(line,val,'.');                %显示波形图


2.初始化GPIO和定时器

硬件初始化,系统时钟初始化就不说了,我们看看GPIO和定时器初始化。

/**


  * @brief TIM3 Initialization Function


  * @param None


  * @retval None


  */


static void MX_TIM3_Init(void)


{


  /* USER CODE BEGIN TIM3_Init 0 */


  /* USER CODE END TIM3_Init 0 */


  TIM_ClockConfigTypeDef sClockSourceConfig = {0};


  TIM_MasterConfigTypeDef sMasterConfig = {0};


  TIM_OC_InitTypeDef sConfigOC = {0};


  /* USER CODE BEGIN TIM3_Init 1 */


  /* USER CODE END TIM3_Init 1 */


  htim3.Instance = TIM3;


  htim3.Init.Prescaler = 1999;


  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;


  htim3.Init.Period = 255;


  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;


  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;


  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)


  {

[1] [2]
关键字:STM32  PWM  HAL库 引用地址:《嵌入式-STM32开发指南》第二部分 基础篇 - 第5章 PWM(HAL库)

上一篇:用STM32实现MPU6050原始数据的读取
下一篇:【STM32学习笔记6.2】USART实践

推荐阅读最新更新时间:2026-03-24 13:48

STM32 HAL库 模拟I²C
在使用单片机的过程中,I²C总线是常用的一种通信方式,然而由于某些原因,STM32CubeMx直接初始化I²C会出现接收不到信息和各种问题,为此我们需要使用IO口来模拟I²C。 I²C的简介: https://www.bilibili.com/opus/591043733946717098 用STM32CubeMx初始化模拟I²C的引脚: STM32CubeMx的GPIO的配置可以参考: https://www.bilibili.com/opus/484177792198506654 所用到的两个IO口分别对应I²C总线的串行数据线和串行时钟线。 SDA:PB7 SCL:PB6 头文件和源文件皆是依据
[单片机]
STM32 HAL库 模拟SPI驱动 ADS1118
首先是SPI相关的简介: https://www.bilibili.com/opus/515342298243272188 然后是用STM32CubeMx初始化模拟SPI的引脚: STM32CubeMx的GPIO输入输出的配置可以参考: https://www.bilibili.com/opus/484177792198506654 我所用到的四个输出口分别对应ADS1118上的三个SPI通信口。 SYNC:PA4 SCLK:PA5 DOUT:PA6 DIN:PA7 在具体的应用中可以自行修改头文件中的GPIO口以配合硬件完成工程。 ADS1
[单片机]
STM32 HAL库 模拟SPI驱动 DAC8564
之前写过DAC8560的模拟SPI驱动,相比较而言DAC8564能够在网上找到的内容更加的丰富,本文主要是介绍讲解STM32 HAL库使用模拟SPI驱动DAC8564。 DAC8560 https://www.bilibili.com/opus/519334650730238240 SPI相关的简介: https://www.bilibili.com/opus/515342298243272188 然后是用STM32CubeMx初始化模拟SPI的引脚: STM32CubeMx的GPIO输出的配置可以参考: https://www.bilibili.com/opus/484177792198506654 这里
[单片机]
STM32 HAL库】 STM32H743的电源配置和时钟配置
文章内容偏向HAL库的移植和使用,以个人观点及了解为主,若与事实不符,则以www.st.com、www.stmcu.org.cn等平台为准。 使用的软件: VSCode(1.36版,带C/C++ IntelliSense插件) Keil MDK(5.26版) 芯片:STM32H743ZIT6(Nucleo-H743平台) 所使用的库:STM32Cube_FW_H7_V1.3.0,下载地址:https://www.st.com/content/st_com/en/products/embedded-software/mcu-mpu-embedded-software/stm32-emb
[单片机]
【<font color='red'>STM32</font> <font color='red'>HAL库</font>】 STM32H743的电源配置和时钟配置
STM32定时器中断详解(HAL库实战讲解)
1、定时器简单介绍 以STM32F103C8T6中几个定时器为例: TIM1:这是一个高级定时器,不仅具备基本的定时中断功能,还拥有内外时钟源选择、输入捕获、输出比较、编码器接口以及主从触发模式等多种功能。这使得TIM1能够适用于各种复杂的应用场景,为开发者提供强大的时间控制和信号处理能力。 TIM2、TIM3和TIM4:这些是通用定时器,同样具有定时功能,但在功能上与高级定时器有所区别。通用定时器通常用于实现一些基本的定时任务,如LED闪烁、脉冲宽度测量等。 每个定时器都由一个**16位计数器、预分频器和自动重装寄存器的时基单元组成。**预分频器可以对时钟进行分频,计数器则对预分频后的时钟进行计数。当计数器的值达到设定值时,
[单片机]
<font color='red'>STM32</font>定时器中断详解(<font color='red'>HAL库</font>实战讲解)
基于STM32 HAL库的平衡循迹小车技术详解:串级PID控制、MPU移植及电赛应用
1.硬件设计(仅限参考) 先是原理图如下 主要模块:灰度,电源,mpu(陀螺仪),oled,tb6612,含有编码器的电机 2.mpu模块的使用和移植 想要使平衡车保持平衡,mpu是最重要的模块,大家可以参考这个博主写的 http://t.csdnimg.cn/ITLI3 如果大家没有时间或者移植失败,也可以直接移植我代码之中的mpu模块: 链接: https://pan.baidu.com/s/1-9Vstj5v0Wgqkm1AFrCt_w?pwd=k8g8 提取码: k8g8 3.代码的主要逻辑 1.通过mpu获得pitch,roll,yaw的值来进行处理 2.获得编码器的数值3.通过处理之后的数据
[单片机]
基于<font color='red'>STM32</font> <font color='red'>HAL库</font>的平衡循迹小车技术详解:串级PID控制、MPU移植及电赛应用
STM32 HAL库、标准外设库、LL库(STM32 Embedded Software)
STM32 Embedded Software   工作以来一直使用ST的STM32系列芯片,ST为开发者提供了非常方便的开发库。到目前为止,有标准外设库(STD库)、HAL库、LL库 三种。前两者都是常用的库,后面的LL库是ST最近才添加,目前支持的芯片也偏少。各库如下所示: 其中,STD库和HAL库两者相互独立,互不兼容。几种库的比较如下: 目前几种库对不同芯片的支持情况如下: 上图中,LL库目前有部分芯片不支持,官方计划2017年逐步完善。 STM32Snippets   它是代码示例的集合,直接基于STM32外设寄存器,可在文档和软件包中使用。由于处在最底层,因此需要开发者直接操作外设寄存器,对开发者要求
[单片机]
<font color='red'>STM32</font> <font color='red'>HAL库</font>、标准外设库、LL库(<font color='red'>STM32</font> Embedded Software)
STM32 HAL库利用DMA实现串口不定长度接收方法
我这里使用的芯片是 F1 系列的,主要是利用 DMA 数据传输方式实现的,在配置工程的时候要注意配置好 DMA,并开启中断。 如果出现数据长度对,可是数据接收不完整,把Memory勾选即可: 1、利用STM32 cubemx 建立一个工程,工程建立请参考我以前的文章:https://www.cnblogs.com/xingboy/p/9597464.html 2、利用STM32 cubemx 生成代码后,我们先定义一些变量来使用 /* 自己添加代码部分 */ volatile uint8_t rx_len=0; //接收数据长度 volatile uint8_t recv_end_fl
[单片机]
<font color='red'>STM32</font> <font color='red'>HAL库</font>利用DMA实现串口不定长度接收方法
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved