完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1、系列目录
基本计时实验 输入捕获实验(实验3的基础) 电容按键检测实验 输出PWM实验 PWM驱动无刷电机实验 2、程序设计分析 本次我们采用按键控制无刷电机的转速,实验本质是通过按键中断改变CCR的值,从而使PWM的占空比跟随按键改变,将PWM信号输入电调,最终实现对无刷电机的控制。 3、实验用具 正点原子STM32F1精英板 新西达30A无刷电调 A2212 1000KV无刷电机 4、程序设计分析 程序设计可以分为三大块: 定时器、按键配置 电机控制程序 按键中断服务函数 1、定时器、按键的配置: 定时器选择TIM4,因为TIM4的四个通道引脚刚好都在板子上,并且不需要重定义端口,比较方便,四个通道分别为PB6、7、8、9。 原子的板子上总共有KEY0(PE4),KEY1(PE3),KEY_UP(PA0)三个按键。刚好可以配置为加速键(KEY1)、减速键(KEY0)、刹车键(PA0)。 2、电机控制程序: 根据按键,改变写入CCR寄存器的值,CCR/ARR的比值及为输出PWM的占空比。直接通过TIMx-》CCR1 = x;写入CCR的值。这是寄存器变成的一种方法,可以直接给CCR寄存器赋值,很好用。 3、按键中断函数,这里可以设置两个变量ccr_val和add_val。ccr_val代表输出占空比5%的PWM的CCR的值。电调通过5%-10%的PWM信号控制电机0-100%的转速。所以占空比最高为10%的PWM。add_val是每次按键增加或者减少的CCR。最后写入寄存器的CCR=ccr_val+add_val。 电机控制流程 电路连接——开发板上电,电机上电——电调校对油门——按键——电机启动 如果不理解电调校对油门以及相关操作,点击这里 5、代码示例,很多思想一看程序就明白 1、TIM初始化 //MOT_GPIO PB6,7,8,9#define MOT_GPIO GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9#define MOT_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd#define MOT_GPIO_CLK RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO#define MOT_TIM TIM4#define MOT_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd#define MOT_TIM_CLK RCC_APB1Periph_TIM4/** TIM4定时器基础配置 * 功能: * 入口参数:arr;psc * 返回值:无 */void PWM_TIM_GPIO_Config(u16 arr,u16 psc){ GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; MOT_GPIO_APBxClock_FUN(MOT_GPIO_CLK,ENABLE); MOT_TIM_APBxClock_FUN(MOT_TIM_CLK,ENABLE); //PB6,7,8,9 配置 GPIO_InitStructure.GPIO_Pin = MOT_GPIO; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure); //TIM5基础配置 //计时器时钟 = APB总线时钟/分频因子 // psc TIM_TimeBaseStructure.TIM_Period = arr;//重装载值/最大计数值 TIM_TimeBaseStructure.TIM_Prescaler = psc;//预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(MOT_TIM,&TIM_TimeBaseStructure); }/** PWM 配置 * 功能:配置四路PWM控制电机,后期可扩展为电机解锁程序 * 入口参数:无 * 返回值:无 */void PWM_OC_Config(u16 ccr){ TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_Pulse = ccr; //前左电机 CCR1 PB6 TIM_OC1Init(MOT_TIM, &TIM_OCInitStructure); TIM_OC1PreloadConfig(MOT_TIM, TIM_OCPreload_Enable); //使能MOT_TIM在CCR1上的预装载寄存器 //前右电机 CCR2 PB7 TIM_OC2Init(MOT_TIM, &TIM_OCInitStructure); TIM_OC2PreloadConfig(MOT_TIM, TIM_OCPreload_Enable); //使能MOT_TIM在CCR2上的预装载寄存器 //后左电机 CCR3 PB8// TIM_OC3Init(MOT_TIM, &TIM_OCInitStructure); // TIM_OC3PreloadConfig(MOT_TIM, TIM_OCPreload_Enable); //使能MOT_TIM在CCR3上的预装载寄存器 //后右电机 CCR4 PB9 TIM_OC4Init(MOT_TIM, &TIM_OCInitStructure); TIM_OC4PreloadConfig(MOT_TIM, TIM_OCPreload_Enable); //使能MOT_TIM在CCR4上的预装载寄存器 TIM_ARRPreloadConfig(MOT_TIM, ENABLE); //使能MOT_TIM在ARR上的预装载寄存器 TIM_Cmd(MOT_TIM, ENABLE); //使能MOT_TIM外设 }void PWM_Config(void){ PWM_TIM_GPIO_Config(2000,720-1); PWM_OC_Config(200); } 2、电机驱动,实验初期先不需要考虑各个CCR的准确值,后期加入PID之后可以通过PID精确控制每个电机 /****************************************************** 通过按键中断方式控制电机转速(优先级 KEY0和KEY1属于不同操作,优先级KEY0》KEY1(减速》加速))*满油门 CCR 200 10%*零油门 CCR 100 5% * KEY0 (PE4) 减速 [0,20]次* KEY1 (PE3) 加速 [0,20]次* KEY_UP (PA0) 刹车 CCR=5%*现阶段控油门转速仅有五个等级,后期按比例增加,按等比例分配为 100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180*其中KEY_UP仅用作电调初始化,初始CCR=200(10%),KEY_UP为CCR=100(5%),可以做紧急刹车使用**2021年1月31日10:13:03***************************************************************/#include “bsp_motor.h”#include “delay.h”#include “usart.h”#include “key.h”#include “led.h”#include “beep.h”/** 电机控制程序 * 功能:控制四个通道的CCR * 入口参数:ccr1,ccr2,ccr3,ccr4 * 返回值:无 * 注:取值[0,0xFFFF] */void MOT_Control(u16 ccr1,u16 ccr2,u16 ccr3,u16 ccr4){ TIM4-》CCR1 = ccr1; TIM4-》CCR2 = ccr2; TIM4-》CCR3 = ccr3; TIM4-》CCR4 = ccr4;} 3、按键中断服务函数,通过这个函数控制CCR的改变 (1)中断配置 /** 按键中断配置 * 功能:配置三个按键的中断设置 * 入口参数:无 * 返回值:无 */static void EXTI_Config(void){ EXTI_InitTypeDef EXTI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);//加速键PE3 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);//减速键PE4 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//停止键PA0 EXTI_InitStructure.EXTI_Line = EXTI_Line3 | EXTI_Line4 | EXTI_Line0; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); }static void NVIC_Config(void){ NVIC_InitTypeDef NVIC_InitStructure; //加速键PE3 NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //减速键PE4 NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //停止键PA0 NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }void KEY_EXTI_Config(void){ EXTI_Config(); NVIC_Config(); EXTI_ClearFlag(EXTI_Line0); EXTI_ClearFlag(EXTI_Line3); EXTI_ClearFlag(EXTI_Line4);} (2)中断服务函数 u16 ccr_val = 100;//5%的CCR,起始状态int add_val = 0;//每次按键CCR增加的值int a =0;//实际设置写入的CCR=ccr_val+add_val/** 按键中断服务函数 * 功能:根据不同的按键设置不同的CCR的值 * 入口参数:无 * 返回值:无 *///加速void EXTI3_IRQHandler(void){ delay_ms(10); if(EXTI_GetITStatus(EXTI_Line3) != RESET) { if(KEY1 == 1) { add_val += 5; LED1 = !LED1; if(add_val《81)//最高允许加速到80% { MOT_Control(ccr_val+add_val,ccr_val+add_val,ccr_val+add_val,ccr_val+add_val); printf(“3CCR = %drn”,TIM_GetCapture1(TIM4)); } else { BEEP; add_val = 80; } } EXTI_ClearITPendingBit(EXTI_Line3); }}//减速void EXTI4_IRQHandler(void){ delay_ms(10); if(EXTI_GetITStatus(EXTI_Line4) != RESET) if(KEY0 == 1) { add_val -=5; printf(“%drn”,add_val); LED0 = !LED0; if(add_val 》 -1) { MOT_Control(ccr_val+add_val,ccr_val+add_val,ccr_val+add_val,ccr_val+add_val); printf(“4CCR = %drn”,TIM_GetCapture1(TIM4)); } else { BEEP; add_val = 0; printf(“add_val已归零,add_val = %drn”,add_val); } } EXTI_ClearITPendingBit(EXTI_Line4);}//停止void EXTI0_IRQHandler(void){ delay_ms(10); if(EXTI_GetITStatus(EXTI_Line0) != RESET) { if(KEY1 == 1) { BEEP = !BEEP; MOT_Control(ccr_val,ccr_val,ccr_val,ccr_val); printf(“0CCR = %drn”,TIM_GetCapture1(TIM4)); } printf(“刹车成功rn”); EXTI_ClearITPendingBit(EXTI_Line0); }} 6、实验现象 可以看到加速成功,绿色LED灯闪烁,电机速度加快。 串口输出CCR,ccr_val和add_val正常。 7、总结 PWM控制无刷电机的使用在显示中非常广泛,还可以控制步进电机、伺服电机。现在的高精度加工制造产业都脱离不了伺服电机,所以先学习好PWM控制无刷电机这种简单的控制,才能为以后打好基础。后期我将会把四旋翼无人机的设计上传,本节课的控制电机实验就是无人机所需要使用的电机控制程序。 |
|
|
|
只有小组成员才能发言,加入小组>>
567浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-5 10:22 , Processed in 0.745633 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号