stm32平衡小车——CUBEMX初始化

前言

之前已经总结过正点原子风格的初始化,由于代码量的问题(可能),所以小车并不能完成动作,于是现在按照CUBEMX进行初始化剩下的一些逻辑代码再加在这个工程文件中就可以了
我这里贴一下上一篇文章:

https://blog.csdn.net/xhj12138/article/details/132739858

选择对应MCU

先安装好CUBEMX(默认已经装好了),我有5.6.0和6.4.0两个版本(一个可以用STM32-MAT,一个不能),任选一个打开就可以了,打开之后如下图所示,选择红框打开:

通过选择MCU新建工程

之后可能会下载资源什么的,大概10MB之类的,等一会就会出现如下界面,选择F1系列的f103的C8系列:

选择F103C8

出现如下界面,则选择完毕!

选择完成

配置System Core

SYS配置

首先在System Core里面,配置SYS的情况,因为板子上引脚资源有限,所以不支持JTAG模式(需要至少4个引脚,太浪费资源),所以可以配置为SW模式,如下图所示:

配置为SW

配置好之后,可以看到有两个引脚变绿了,说明被使用:

配置完成

配置RCC

需要选择时钟源,在高速时钟源中,选择晶振,相当于配置为HSE的8MHz主频:

配置HSE

配置Analog

这里就是配置ADC转换,在基础版本中,只需要配置PA6,读取电池电压就可以了。

选择ADC1(配置ADC2也可以),然后选择配置通道6(IN6):

选择ADC的通道6

之后,保持默认,也就是独立模式,右对齐,非扫描模式,不连续转换,不连续模式(开启了连续转换才需要)也不开启;开启规则通道,转换个数为1,排名为1,这些都保持默认只需要修改Rank中的采样时间选择最大239.5个周期,这样采样后更加准,默认是最短的1.5个周期,可能会导致读书不准—):

采样周期配置最大

配置Timers

这可以说是MCU的心脏,所有的运算都靠TIM来进行控制,这里完成平衡小车的4个定时器的初始化!

TIM1配置

先选中TIM1,配置时钟源为内部时钟,同时开启通道1和通道4的PWM输出

配置两路PWM输出

然后配置预分频系数为1,自动重装载值为7200(使得PWM的频率为10kHz,因为主频是72MHz,具体计算可以先学一下定时器),其余均保持默认,也就是不分频,RCR关闭,影子寄存器耶关闭;Trigger Output还有死区刹车控制均不开启;PWM选择模式1,Pulse就置0,之后通过操作CCRx来控制占空比,其余均默认。

配置psc和arr

为了方便,可以把对应的GPIO引脚改名,CH1对应为右电机,CH4为左电机。

TIM2和TIM4配置

这两个都用作直流有刷电机的编码器读取,所以放在一起讲。

在模式中拉到最下面,选择编码器模式

配置编码器模式

与TIM1类似,只要更改psc和arr即可,其余保持默认,预分频配置为0,而arr直接给最大值65535

配置psc和arr

编码器最灵魂的地方,就是这里的编码器模式的配置,配置为TI1 and TI2,这样的话相当于4倍频,精度更高;其余保持默认就可以了:

配置编码器的捕获方式

配置完,为了方便之后的读取,可以把GPIO的label进行修改,按照TIM2CH1,TIM2CH2,TIM4CH1,TIM4CH2的顺序命名为encoder的A,B,C,D。

TIM3配置

这个定时器用作超声波传感器的输入捕获,是用来记录超声波发射到接收信号的时差的,以此来计算距离。

选中CH3作为输入捕获通道

配置CH3为输入捕获

同样只需要配置psc和arr,配置预分频为71,arr直接给最大值65535,其余保持默认即可,也就是检测上升沿等;最后在NVIC中打开TIM3的中断即可:

配置psc和arr

打开TIM3中断

配置完,对应的GPIO可以改名,改为ultrasonic。

配置Connectivity

这里主要就是配置串口,usart1可以和PC进行串口通讯(轮趣小车是用这个和上位机通讯的,其实也可以不要,不配置都行),蓝牙的通讯走的是usart3,如果要手机调PID,这个就必须要!

USART1配置

直接打开异步通讯,其余保持默认,也就是波特率115200,8位长度,无校验位,1个停止位:

串口1配置

USART3配置

与USART1类似,打开异步通讯,这里由于通讯协议的问题,波特率需要设为9600,其余均默认:

配置波特率

然后在NVIC的选项中,打开串口的中断,之后的通讯函数需要在中断回调中实现

打开串口3中断

至此,所有的外设(除了GPIO口)配置已经完成!

配置时钟

在clock配置中,将HSE的PLL倍频配置为9(达到了F1系列允许的最高稳定频率72MHz),然后将系统时钟选择为PLL,同时APB1需要配置为2分频ADC需要配置为6分频(ADC稳定采集不能超过14MHZ):

时钟配置

配置GPIO

剩下的内容就是把对应的引脚和外设联系起来。

LED配置

LED接在了PA4上面,设置为IO输出,初始化为低电平,推挽输出,引脚电路为浮空,输出为高速,起名为LED,如图所示:

LED

KEY配置

按键接在PA5,因为是检测电平,所以要选择为IO输入,同时因为按键的电路,要选择为上拉电阻

KEY

超声波传感器引脚配置

除了TIM3的输入捕获,还有一个超声波的触发引脚,接在了PB1上,配置为IO输出,初始低电平,推挽输出模式,浮空电阻,输出的速度是高速:
超声波的trigger引脚

TB6612配置

直流有刷电机的驱动板,需要配置的PWM已经完成,但是为了驱动电机,还需要配置4个引脚,来完成对电机的启停以及转向的控制。

需要配置的引脚是PB12-PB15,对应为BIN2,BIN1,AIN1,和AIN2;全部配置为IO输出,初始低电平,推挽输出,浮空电阻,高速输出:

TB6612引脚

MPU6050中断配置

陀螺仪的配置,在GPIO中只需要配置INT引脚,用来通过下降沿触发外部中断,完成定时的控制计算;

需要打开配置IO为EXTI,触发为下降沿外部中断

MPU6050的int引脚

同时,还要进入NVIC的选项中,打开外部中断:

打开外部中断

OLED配置

现在来配置显示屏,也就是OLED;通过4个引脚的SPI来进行读写,需要配置的引脚是PA15,PB3,PB4,PB5分别对应RS,RST,SDIN以及SCLK。

配置方法是一样的,配置为IO输出,低电平,推挽输出,浮空电阻,中速的输出频率:

oled

MPU6050通讯配置

MPU6050是通过软件模拟IIC通讯协议来进行通讯的,需要配置PB8和PB9,对应SCL和SDA。

需要配置IO输出,低电平,推挽输出,浮空电阻,高速输出:

IIC

生成工程

经过以上,在CUBEMX中的配置就完成了,接下来根据你的编译器生成工程文件。

我的环境是Keil5,所以就选择对应的IDE,还需要对工程进行命名并选择保存位置,结构要选择高级,IDE也进行修改,如下图所示:

Project修改

在Code Generator中,建议在第一个大项中,选择仅拷贝所需lib来压缩空间;之后的选项都是我的个人习惯,生成.c和.h,所有空闲引脚都给模拟:

代码生成修改

最后保存ioc文件(也就是这个蓝色界面),再点击右上角的生成代码就大功告成了!

修改keil工程

修改usart

需要重定向printf,所以打开usart,然后在user code begin 0的地方加入以下代码:

/* USER CODE BEGIN 0 */
/******************************************************************************************/
/* 加入以下代码, 支持printf函数, 而不需要选择use MicroLIB */
#if 1
#pragma import(__use_no_semihosting)
struct __FILE
{
    int handle;
    /* Whatever you require here. If the only file you are using is */
    /* standard output using printf() for debugging, no file handling */
    /* is required. */
};


/* 定义_sys_exit()以避免使用半主机模式 */
void _sys_exit(int x)
{
    x = x;
}


/* FILE 在 stdio.h里面定义. */
FILE __stdout;

/* MDK下需要重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{
    while ((USART3->SR & 0X40) == 0);     /* 等待上一个字符发送完成 */

    USART3->DR = (uint8_t)ch;             /* 将要发送的字符 ch 写入到DR寄存器 */
    return ch;
}

#endif
/******************************************************************************************/
/* USER CODE END 0 */

修改gpio里的外部中断

这里因为外部中断需要最后开启,所以要在gpio.c中先关掉EXTI,如下代码:

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 1);
  //HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
  HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);

修改main.c

在main.c中进行外设的初始化,需要注意必须要先关闭JTAG才可以顺利初始化,不然之后的oled无法使用,同时对定时器的初始化也要完成:

  /* USER CODE BEGIN 2 */
  
  /* 自行添加PWM开启 */
  HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);      /* 开启定时器1通道1的PWM输出 */
  HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4);      /* 开启定时器1通道4的PWM输出 */
  /* 自行添加开启编码器模式 */
  HAL_TIM_Encoder_Start(&htim2,TIM_CHANNEL_ALL);        /* 开启定时器2的编码器模式 */
  /* 自行开启输入捕获中断和更新中断 */
  HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_3);        /* 打开定时器3通道3的输入捕获中断 */
  HAL_TIM_Base_Start_IT(&htim3);                    /* 打开定时器3通道3的更新中断 */
  /* 自行添加开启编码器模式 */
  HAL_TIM_Encoder_Start(&htim4,TIM_CHANNEL_ALL);        /* 开启定时器4的编码器模式 */
  
  __HAL_RCC_AFIO_CLK_ENABLE();
  __HAL_AFIO_REMAP_SWJ_NOJTAG();                 /* 禁用JTAG,使用SWD调试 */
    
  delay_init(72);                                /* 延时初始化 */
  oled_init();                                   /* oled初始化 */
  mpu6050_init();                                /* 初始化MPU6050 */
  mpu6050_dmp_init();                            /* 初始化MPU6050 DMP */
  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

  /* USER CODE END 2 */

总结

按照现在的初始化,加上我上一篇文章的代码,把他拷贝进去然后编译,已经可以发现小车的外设是全部能够动起来的!

下一次,我更新一下控制的PID算法以及滤波算法,可能由于时间问题,也不一定什么时候更新,也不一定会很具体,但是我会把工程直接发上来的!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值