STM32学习笔记:PWM互补输出(无刷直流电机驱动控制)

2023-05-16

需要达成的目的为CH1通道输出PWM波,CH1N通道输出高电平等。

最新方法已在新博客贴出,更为简便。

==========================以下为较为复杂的初始方法===========================

最近科研训练在做无刷电机的控制。

需要达成的目的为CH1通道输出PWM波,CH1N通道输出高电平等。

算法采用六步换向算法,开环系统。

主控芯片选用STM32F103VCT6。

PWM输出引脚如下:

采用了高级定时器TIM1的完全重映射引脚。

PE9->UH   1        

PE10->UL  2N

PE11->VH  2

PE12->VL   3N

PE13->WH 3

PE14->WL  4

通道设置的有点问题,正确的较为方便的应该是UH1接CH1,UL1接CH1N(1通道的互补通道),后续利用飞线解决问题。(这里不处理也可以)

利用光耦将功率电与控制部分隔离开。光耦芯片使用6N137,注意:6N137是反逻辑的。即输入高电平经光耦后输出低电平。  

6N137的真值表:

隔离电路设计:

 

 驱动芯片选用IR2136,由于尚未实测IR2136是否能成功驱动MOSFET,暂不贴电路设计了。

无刷电机旋转时,需要导通一个上桥臂和一个下桥臂,如UH、WL导通,其他桥臂关断(UH指U相上桥臂,WL为W相下桥臂),此时需要PWM_UH与PWM_WL引脚输出PWM波,其他引脚为高电平输出(经光耦后反相为低电平)。

在这里贴出一个比较容易理解的方法:

需要说明的是:

需要达成的目的为CH1通道输出PWM波,CH1N通道输出高电平。(并不一定是这样的输出,只是通过修改CCR寄存器的值与比较值时,CH1与CH1N无法达到这样的目的,只能同时输出相同或互补的PWM波)。

这里达成目的的简单粗暴的方法为:首先所有通道正常输出PWM波,然后失能所有不需要输出PWM的引脚,通过配置GPIO,使这些不需要输出PWM的引脚输出高电平。

PWM输出相关配置:

PWM的占空比在主函数中配置。

//PE9(UH)、PE11(VH)、PE13(WH)、PE14(WL)、PE10(UL)、PE12(VL) PWM 输出
void TIM1_PWM_Init(u16 arr,u16 psc)
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;	
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);  //使能GPIOE时钟时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //时钟使能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  //使能AFIO时钟
	GPIO_PinRemapConfig(GPIO_FullRemap_TIM1,ENABLE);//映射为TIMx
	
	//设置该引脚为复用输出功能,输出TIMx_CHx的PWM脉冲波形
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_10|GPIO_Pin_12; //TIMx_CHx
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOE, &GPIO_InitStructure);
 
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  不分频
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;//互补通道输出比较极性为低
	
	//根据TIM_OCInitStruct中指定的参数初始化外设TIMx
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //PE9
	TIM_OC2Init(TIM1, &TIM_OCInitStructure);	//PE11
	TIM_OC3Init(TIM1, &TIM_OCInitStructure);  //PE13
	TIM_OC4Init(TIM1, &TIM_OCInitStructure);	//PE14
		
	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能或者失能 TIMx 在 CCR1 上的预装载寄存器
	TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
	TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
	TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
	
	TIM_CtrlPWMOutputs(TIM1,ENABLE);	//MOE 主输出使能	
	TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
	TIM_Cmd(TIM1, ENABLE);  //使能TIMx
}

GPIO配置:

void GPIOx_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); 	// 使能PE端口时钟
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_10|GPIO_Pin_12;					
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;			// 推挽输出
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;			// IO口速度为50MHz
	GPIO_Init(GPIOE, &GPIO_InitStructure); 	   				// 根据设定参数初始化GPIOB.5
	//GPIO_SetBits(GPIOE, GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_10|GPIO_Pin_12);	
}

以UH、WL输出PWM,其他引脚输出高电平为例:

void GPIOE_High(void)
{
	 GPIOx_Init();
 	 GPIO_SetBits(GPIOE,GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_12|GPIO_Pin_10);//引脚输出高电平	
}

利用宏定义:

#define     PWMUVW_Dis        TIM1->CCER &= ~(TIM_CCER_CC1E|TIM_CCER_CC2NE|TIM_CCER_CC2E|TIM_CCER_CC3NE|TIM_CCER_CC3E|TIM_CCER_CC4E);//取消使能UVW所有的输出,所有管子均关闭
#define     UH_ON             TIM1->CCER |= TIM_CCER_CC1E;
#define     UL_ON             TIM1->CCER |= TIM_CCER_CC2NE;
#define     VH_ON             TIM1->CCER |= TIM_CCER_CC2E;
#define     VL_ON             TIM1->CCER |= TIM_CCER_CC3NE;
#define     WH_ON             TIM1->CCER |= TIM_CCER_CC3E;
#define     WL_ON             TIM1->CCER |= TIM_CCER_CC4E;
                                
#define     PWMUH_ON_WL_ON	  PWMUVW_Dis; UH_ON; WL_ON;  GPIOx_Init(); GPIO_SetBits(GPIOE,GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_12|GPIO_Pin_10);

最后进行主函数的编写:

int main(void)
 {    
	 //delay_init();	  
	 //PWM输出测试
  
	 TIM1_PWM_Init(1799,1);//不分频。PWM频率=72000/(1799+1)=40 KH
	 TIM_SetCompare1(TIM1,300);	//PE9,通过修改300这个数字来修改占空比
	 TIM_SetCompare2(TIM1,300);	//PE11、PE10
	 TIM_SetCompare3(TIM1,300);  //PE13
	 TIM_SetCompare4(TIM1,300); //PE14	
   	 PWMUH_ON_WL_ON;
}

利用KEIL自带的虚拟示波器验证结果:

发现,只有PE9与PE14输出PWM, 其他引脚输出高电平,达成目的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32学习笔记:PWM互补输出(无刷直流电机驱动控制) 的相关文章

  • 2021-02-11

    多旋翼飞行器学习笔记 一 多旋翼基本组成 1 1机架 xff08 机身 起落架 涵道 xff09 1 机身 机身要考虑的有 xff1a 尺寸 布局 材料 强度 重量 指标参数包括 xff1a 重量 轴距 xff08 外圈电机围城圆的直径 x
  • JAVA学习51-线程礼让

    线程礼让 礼让线程 xff0c 让当前正在执行的线程暂停 xff0c 但不阻塞 将线程从运行状态转换为就绪状态 让CPU重新调度 xff0c 礼让不一定成功 xff0c 看CPU心情 span class token keyword pub
  • Jetson nano安装librealsense和realsense ROS wrapper

    1 安装librealsense librealsense可以使用外国dalao的安装脚本一键安装 git clone https github com JetsonHacksNano installLibrealsense git 这里选
  • ACFly A9飞控使用T265作为位置传感器

    使用一块Jetson nano读取T265数据发送给飞控代替光流实现室内定点飞行 1 Jetson nano数据发送 sudo apt get install ros melodic serial cd ros ws src catkin
  • In grDevices::dev.off() : agg could not write to the given file

    R语言画图保存是报的错误 stackoverflow和github上都没有相关问题 原因是 xff0c 保存的名字字符或标点不对 名字中的标点符号之类的不符合命名原则
  • C++ 创建txt文件,并实现读写txt文件

    最近在逐渐接触C 43 43 xff0c 看了网上很多回答 xff0c 做个汇总的记录 xff0c 方便以后查看 include lt fstream gt include lt iostream gt include lt string
  • eslint:vue报错 error Component name ““ should always be multi-word

    在使用vue cli创建项目 xff0c 命名好组件的时候 xff0c 报错 xff1a error Component name xxx should always be multi word xff0c 解决办法看最后 原因是官方的建议
  • PX4仿真

    XTDrone仿真 运行PX4仿真 span class token builtin class name cd span PX4 Firmware roslaunch px4 mavros posix sitl launch 通过下条命令
  • 安卓期末考试复习题

    安卓试题题型 1 选择题 xff08 10x1 39 xff09 2 填空题 xff08 5x2 39 xff09 3 简答题 xff08 4x5 39 xff09 4 程序分析题 xff08 10 39 xff09 5 编程题 xff08
  • GNURadio 运行报错:ERROR thread[thread-per-block[12]: <block ofdm_cyclic_prefixer(8)>]: Buffer too small

    在修改 GR 的 OFDM 例程时 xff0c 将 OFDM 子载波数从原来的 64 调整为 128 后运行出现了这个问题 xff0c 更全的错误提示如下 xff1a gr log ERROR thread body wrapper ERR
  • kalibr标定realsenseD435i(三)--imu+双目标定

    步骤一 xff1a 编写camchain yaml 具体的参数参考上面得到的yaml文件 xff0c 没有的参数可以删除 cam0 camera model pinhole distortion coeffs 0 3741003900681
  • VINS定位和即时八叉树建图步骤

    在工作空间catkin ws终端运行 1 先source一下 xff0c 以免报错 xff08 注 xff1a 后面每一步都可以source一下 xff09 source catkin ws devel setup bash 2 打开D43
  • ros中的launch文件

    对照运行的mav path plan launch文件进行一个学习 xff08 一 xff09 什么是roslaunch roslaunch是ROS提供的一个启动工具 xff0c 它能够使得启动多个ROS节点的过程变得简单 xff0c 同时
  • EGO Planner代码解析----CMakeLists.txt和package.xml

    ROS本质上就是由一个又一个的package组成的 xff0c package可以说是ROS的细胞 在catkin make的时候它会一个一个的去找package然后生成目标文件 一个package可以有多个节点 判断是否为Package
  • EGO Planner代码解析bspline_optimizer部分(3)

    1 int BsplineOptimizer earlyExit void func data const double x const double g const double fx const double xnorm const d
  • EGO Swarm翻译

    目录 摘要 介绍 相关工作 A 单四旋翼局部规划 B 拓扑规划 C 分布式无人机集群 基于梯度的局部规划隐式拓扑轨迹生成 A 无需ESDF梯度的局部路径规划 B 隐式拓扑轨迹生成 无人机集群导航 A 机间避碰 B 定位漂移补偿 C 从深度图
  • 嵌入式刷题训练1——牛客网

    嵌入式软件工程师面试常考题 文章目录 Q1 xff1a extern关键字的作用是什么 xff1f Q2 xff1a 关于virtual void Draw 61 0 xff0c 下面说法正确的有几个 xff1f Q3 xff1a 对于类的
  • Ubuntu桌面卡死解决办法

    Ubuntu桌面卡死解决办法 我采用这种方式圆满解决 同时按住 Ctrl 和 Alt 键 xff0c 按住不要放
  • sonic 编译

    本文是转载 xff0c sonic 编译 sonic编译过程讲解 xff0c 点击这里
  • arduino总线舵机+实时串口通信控制

    arduino语法 digitalWrite 函数 digitalWrite pin value 定义引脚的电平 pin xff1a 你希望设置模式的引脚的编号 0 xff5e 13 value xff1a 表示为HIGH 高电平 或LOW

随机推荐