cubeMX入门使用教程

本文以STM32F429IGT6为例讲解如何使用cubeMX配置STM32, 基于HAL库进行编程。

[TOC]

初始化工程

建立工程

ACCESS TO MCU

image-20210814165034535

输入型号,选择对应MCU

image-20210814165132318

配置时钟树

在RCC选项中激活外部时钟,HSE选择外部晶振作为时钟源

image-20210814165414554

配置时钟树,将HCLK频率设置为最高(看使用需求)

image-20210814165620210

在sys选项中激活DEBUG,选择serial wire。

image-20210814165714498

配置工程

在Project Manager中配置工程的名字,选择IDE为MDK-ARM

image-20210814165909024

在Code Generator中勾选选项

image-20210814170028428

点击GENERATE CODE即可生成工程文件

image-20210814170121101

如何编写代码

注释规范

如你所见,官网生成的工程文件中注释全部使用/**/进行注释,全篇没有出现一处//注释。所以为了一致性,尽量不要使用//注释(强迫症)。

用户代码

用户编写的代码都要放入 USER CODE BEGIN 和 USER CODE END 之间,否则下一侧生成代码后用户代码就会被覆盖。

配置USART

箭头位置配置为Asynchronous即可

image-20210814170217959

使用:

包含头文件: #include <stdio.h>

printf重定向: 在main.c的user code 0中加入代码:

1
2
3
4
5
6
7
/* printf重定向 */
int fputc(int ch, FILE *f)
{
uint8_t temp[1] = {ch};
HAL_UART_Transmit(&huart1, temp, 1, 2); /* huart1需要根据你的配置修改 */
return ch;
}

即可在程序中使用printf

配置GPIO

输入

点击引脚,在选择GPIO_INPUT即可

image-20210814172012257

输出

点击引脚,在选择GPIO_OUTPUT即可

image-20210814171320220

其他的模式选项怎么用会在后面介绍

详细配置

侧栏中选择GPIO点击想要配置的引脚

image-20210814172139106

Configuration中,从上到下依次是:

GPIO初始化电平

GPIO输入(输出)模式

GPIO上下拉

GPIO速率

GPIO标签 (很重要)给GPIO设置标签以后(就和之前编程给引脚设置宏定义一个道理),移植程序就会方便很多,兼容性大大提高

使用HAL_GPIO_WritePin(); 控制IO电平

使用HAL_GPIO_ReadPin(); 读取IO状态

配置PWM输出

选择TIM,然后选择通道。选择PWM Generator 即可

选项解释:

PWM Generation CHx 正向PWM

PWM Generation CHxN 反向PWM

PWM Generation CHx 和 CHxN 组成一对互补PWM输出

image-20210815095241640

设置PSC和Period来设置PWM的频率。

频率 = 定时器时钟(TIM挂载在的总线上的时钟) / (Prescaler 预分频 + 1)/ (Counter Period 计数值 + 1) Hz

image-20210815095345037

占空比 = Pulse ( 对比值) / (C ounter Period 计数值)%

image-20210815095748381

1
2
3
4
/* 使能timx的通道y */
HAL_TIM_PWM_Start(&htimx,TIM_CHANNEL_y);
/* 修改timx的通道y的pwm比较值为z,即修改占空比 */
__HAL_TIM_SET_COMPARE(&htimx, TIM_CHANNEL_y, z);

编码器模式

适用于ABZ相的正交编码器

在Combined Channels中选择Encoder Mode。

image-20210815100153999

Encoder Mode选择Encoder Mode TL1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* @brief 读取对应编码器的值
* @param uint8_t TIMx 编码器的所用的TIM
* @return Encoder_TIM 编码器的值
*/
int Read_Encoder(uint8_t TIMx)
{
int Encoder_TIM;
switch(TIMx) {
case 1: Encoder_TIM= (short)TIM1 -> CNT; TIM1 -> CNT=0;break;
case 2: Encoder_TIM= (short)TIM2 -> CNT; TIM2 -> CNT=0;break;
case 3: Encoder_TIM= (short)TIM3 -> CNT; TIM3 -> CNT=0;break;
case 4: Encoder_TIM= (short)TIM4 -> CNT; TIM4 -> CNT=0;break;
case 5: Encoder_TIM= (short)TIM5 -> CNT; TIM5 -> CNT=0;break;
case 6: Encoder_TIM= (short)TIM6 -> CNT; TIM6-> CNT=0;break;
case 7: Encoder_TIM= (short)TIM7 -> CNT; TIM7 -> CNT=0;break;
case 8: Encoder_TIM= (short)TIM8 -> CNT; TIM8 -> CNT=0;break;
#if 1 /* 如果没有更多的TIM就改为 #if 0 */
case 9: Encoder_TIM= (short)TIM9 -> CNT; TIM9 -> CNT=0;break;
case 10: Encoder_TIM= (short)TIM10 -> CNT; TIM10 -> CNT=0;break;
case 11: Encoder_TIM= (short)TIM11 -> CNT; TIM11 -> CNT=0;break;
case 12: Encoder_TIM= (short)TIM12 -> CNT; TIM12 -> CNT=0;break;
case 13: Encoder_TIM= (short)TIM13 -> CNT; TIM13 -> CNT=0;break;
case 14: Encoder_TIM= (short)TIM14 -> CNT; TIM14 -> CNT=0;break;
#endif
}
return Encoder_TIM;
}

通过设置Input Filter来设置编码器的软件滤波。

image-20210815212108817

(和其他模式的比较 待补充)

定时器中断

如图,将TIM的internal Clock打上勾,然后设置psc和period。

定时频率 = 定时器时钟 / (预分频 +1)/(计数值 + 1 )Hz。

定时时间 = 1 / 定时频率。

image-20210815212215907

再将Global interrupt打上勾,就可以使用定时器中断了。

image-20210815212323488

如果是高级定时器,勾选 TIM X update interrupt 后的 Enabled 框即可。

1
2
3
4
5
6
7
8
9
10
11
12
HAL_TIM_Base_Start_IT(&htim1);  /* 使能定时器 */

/* 定时器中断回调函数 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == htim1.Instance) {

}
else if(htim-> Instance == htim2.Instance) {

}
}

中断回调函数机制

在HAL库中,中断服务函数不再像标准库那样编写。

在cubeMX自动生成的代码中,每个使能的中断的回调函数都有一个__weak

修饰,代表着若函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak声明的函数,并且编译器不会报错。

用户将中断服务函数写在回调函数中即可。

外部中断

点击引脚,选择GPIO_EXTI

image-20210815213517511

GPIO mode 设置边沿触发模式

GPIO Pull-up/Pull-down 设置上下拉

image-20210815213558683

最后使能中断

image-20210815213718000

1
2
3
4
5
6
7
/* 外部触发回调函数 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == PWM_Pin) {

}
}

配置GPIO(附加说明)

根据数据手册可知,有些功能并不是只有一个引脚,比如说TIM8的CH1就有PC6和PI5可以用。

在Pinout View中设置了GPIO的mode后,在设置对应的外设,外设的引脚就会被映射到你所选择的引脚。

比如点击PI5选择TIM8_CH1,然后在在TIM8中设置CH1为PWM输出,那么PI5就会作为PWM输出脚。

PC6同理。

image-20210815214556670

以上是我个人使用cubeMX的一些经验,我会不断的补充。