代码主要在这个文件里:C:\Users\DQ_SZU\Desktop\RoboFlyDEMO\Drive\src\motor.c
我们要利用mos管的特性,定义4个引脚复用推挽输出,同时要注意每一个引脚对应的时钟,接下来就是定义TIM3作为PWM波输出的计数器,通过其4个通道进行输出:
TIM_OC1Init(TIM3,&TIM_OCInitStruct); TIM_OC2Init(TIM3,&TIM_OCInitStruct); TIM_OC3Init(TIM3,&TIM_OCInitStruct); TIM_OC4Init(TIM3,&TIM_OCInitStruct);
输出极性低即一开始是从0开始的然后转速慢慢增大,大概可以如下理解(可能不准确)当你输入1000时,占空比为1,也就是主控接到电机的引脚一直是高电平(占空比=高电平时间/总的时间,简单的理解就是占空比越大能量输出持续时间越长,一个周期内转速越快)





每个定时器有4个输出通道,所以只需要1个定时器即可控制4个电机

#define Moto_PwmMax 1000  输出最大
int16_t MOTO1_PWM = 0;
int16_t MOTO2_PWM = 0;
int16_t MOTO3_PWM = 0;
int16_t MOTO4_PWM = 0;/************************************************************
* 函  数:void MOTOR_Init(void)
* 功  能:电机引脚初始化 以及TIM3 配置输出PWM
* 参  数:无
* 返回值:无
* 备  注:TIM3 CH1(PWM1) -> PA6
*         TIM3 CH2(PWM2) -> PA7
*         TIM3 CH3(PWM3) -> PB0
*         TIM3 CH4(PWM4) -> PB1
*******************************/
void MOTOR_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct;   //定义GPIO结构体变量TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;   //定义定时器结构体变量TIM_OCInitTypeDef TIM_OCInitStruct;   //定义输出比较结构体变量RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);   //GPIOA、B、复用时钟使能RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);   //使能TIM3的时钟GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;   //配置GPIO第6、7引脚GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;      //配置GPIO为复用推挽输出GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;        //配置GPIO速率GPIO_Init(GPIOA,&GPIO_InitStruct);   //GPIO初始化函数GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;   //配置GPIO第0、1引脚GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;      //配置GPIO为复用推挽输出GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;        //配置GPIO速率GPIO_Init(GPIOB,&GPIO_InitStruct);   //GPIO初始化函数TIM_TimeBaseInitStruct.TIM_Period=1000-1;        //设置自动重装载的周期值TIM_TimeBaseInitStruct.TIM_Prescaler=100;         //设置预分频值TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;     //设置时钟分割TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);              //定时器初始化函数TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;   //PWM模式1TIM_OCInitStruct.TIM_Pulse=0;                            //初始化占空比为0TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;         //输出比较极性低TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;   //比较输出使能TIM_OC1Init(TIM3,&TIM_OCInitStruct);                       //比较输出初始化函数TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);   //输出比较1预装载寄存器使能TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;   //PWM模式1TIM_OCInitStruct.TIM_Pulse=0;                              //初始化占空比为0TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;         //输出比较极性低TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;      //比较输出使能TIM_OC2Init(TIM3,&TIM_OCInitStruct);                        //比较输出初始化函数TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);   //输出比较2预装载寄存器使能TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;   //PWM模式1TIM_OCInitStruct.TIM_Pulse=0;                             //初始化占空比为0TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;         //输出比较极性低TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;      //比较输出使能TIM_OC3Init(TIM3,&TIM_OCInitStruct);                        //比较输出初始化函数TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);   //输出比较3预装载寄存器使能TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;   //PWM模式1TIM_OCInitStruct.TIM_Pulse=0;                             //初始化占空比为0TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;         //输出比较极性低TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;      //比较输出使能TIM_OC4Init(TIM3,&TIM_OCInitStruct);                        //比较输出初始化函数TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);   //输出比较4预装载寄存器使能TIM_Cmd(TIM3,ENABLE);   //TIM3使能
}

下面函数是将遥控器传输来的ADC值转化为输入比较的值,并对它进行限幅处理,因为电机不可能无限输出

/************************************************************************************************
* 函  数:void Moto_Pwm(int16_t MOTO1_PWM,int16_t MOTO2_PWM,int16_t MOTO3_PWM,int16_t MOTO4_PWM)
* 功  能:电机要输出数值转换成PWM波形输出
* 参  数:MOTO1_PWM 电机1
*         MOTO2_PWM 电机2
*         MOTO3_PWM 电机3
*         MOTO3_PWM 电机4
* 返回值:无
* 备  注:无
************************************************************************************************/
void Moto_Pwm(int16_t MOTO1_PWM,int16_t MOTO2_PWM,int16_t MOTO3_PWM,int16_t MOTO4_PWM)
{       if(MOTO1_PWM>Moto_PwmMax)    MOTO1_PWM = Moto_PwmMax;if(MOTO2_PWM>Moto_PwmMax)   MOTO2_PWM = Moto_PwmMax;if(MOTO3_PWM>Moto_PwmMax)   MOTO3_PWM = Moto_PwmMax;if(MOTO4_PWM>Moto_PwmMax)   MOTO4_PWM = Moto_PwmMax;if(MOTO1_PWM<0) MOTO1_PWM = 0;if(MOTO2_PWM<0)   MOTO2_PWM = 0;if(MOTO3_PWM<0)   MOTO3_PWM = 0;if(MOTO4_PWM<0)   MOTO4_PWM = 0;TIM3->CCR1 = MOTO1_PWM;TIM3->CCR2 = MOTO2_PWM;TIM3->CCR3 = MOTO3_PWM;TIM3->CCR4 = MOTO4_PWM;
}

整理一下思路:确定哪个TIM作为PWM输出,确定电机输出的最大转速,初始化时钟(自动转载值、预分频值、计数模式,设置TIM_OCInitStruct.TIM_OCMode模式为PWM1、设置初始占空比、设置输出比较极性,使能预转载寄存器,4个通道重复同样的操作,最后使能时钟),最后直接用寄存器赋值TIM3->CCRx = MOTOx_PWM;

typedef struct
{__IO uint16_t CR1;uint16_t  RESERVED0;__IO uint16_t CR2;uint16_t  RESERVED1;__IO uint16_t SMCR;uint16_t  RESERVED2;__IO uint16_t DIER;uint16_t  RESERVED3;__IO uint16_t SR;uint16_t  RESERVED4;__IO uint16_t EGR;uint16_t  RESERVED5;__IO uint16_t CCMR1;uint16_t  RESERVED6;__IO uint16_t CCMR2;uint16_t  RESERVED7;__IO uint16_t CCER;uint16_t  RESERVED8;__IO uint16_t CNT;uint16_t  RESERVED9;__IO uint16_t PSC;uint16_t  RESERVED10;__IO uint16_t ARR;uint16_t  RESERVED11;__IO uint16_t RCR;uint16_t  RESERVED12;__IO uint16_t CCR1;//注意这里uint16_t  RESERVED13;__IO uint16_t CCR2;uint16_t  RESERVED14;__IO uint16_t CCR3;uint16_t  RESERVED15;__IO uint16_t CCR4;uint16_t  RESERVED16;__IO uint16_t BDTR;uint16_t  RESERVED17;__IO uint16_t DCR;uint16_t  RESERVED18;__IO uint16_t DMAR;uint16_t  RESERVED19;
} TIM_TypeDef;

定时器补充资料:
stm32的定时器分为高级定时器(TIM1 TIM8)、通用定时器(TIM2-5)、基本定时器(TIM6-7),
高级定时器


通用定时器



基本定时器


小马哥robofly四轴代码解读:PWM电机输出相关推荐

  1. 小马哥四轴代码解读-SPI-flash篇

    小马哥四轴代码解读-SPI-flash篇 SPI通信 SPI是一种高速的.全双工.同步的通信总线,主要应用于EEPROM.FLASH.实时时钟.AD转换器和etc SPI内部结构图: SPI接口总共有 ...

  2. 小马哥robofly四轴气压计定高的不完全解读

    我看过正点原子的定高算法,好像是直接用气压计测量得到的高度作为反馈进行,而小马哥的robofly是结合气压计获得的高度和运动情况下获得Z轴的位移2者结合来获取高度,但是2者结合的过程看得一知半解,下面 ...

  3. 小马哥RoboFly开源STM32F103四轴简介

    RoboFly是小马哥团队在2018年8月推出的一款完全开源的小四轴. 这款四轴面向的人群是电子相关专业(包括自动化.电气自动化.电子信息工程.计算机.测控等专业)的大学生,通过一个完整的四轴项目来学 ...

  4. Jsoup代码解读之三-Document的输出

    转载自   Jsoup代码解读之三-Document的输出 Jsoup官方说明里,一个重要的功能就是***output tidy HTML***.这里我们看看Jsoup是如何输出HTML的. HTML ...

  5. pwm波如何控制电机代码_电动车电机如何选择功率匹配的电机控制器?

    一般和整车厂进行技术沟通时他们会给控制器的线束图纸及功能要求图纸.功能要求中罗列了控制器的相关功能及线束总成,技术要求一般如低电平/高电平防盗.巡航.过欠压.平均电流等. 电机控制器客户输入技术要求图 ...

  6. STM32学习心得十八:通用定时器基本原理及相关实验代码解读

    记录一下,方便以后翻阅~ 主要内容: 1) 三种定时器分类及区别: 2) 通用定时器特点: 3) 通用定时器工作过程: 4) 实验一:定时器中断实验补充知识及部代码解读: 6) 实验二:定时器PWM输 ...

  7. H桥驱动电机,STM32 PWM互补输出功能误用分析

    如果排查的思路对你有帮助,请记住 消雨匆匆 or  大吊工. 码字和排查很累,仅此而已 硬件不是抄电路,拿烙铁,懂点软件,细致分析,找问题和破案搜集线索是一样的. 导航车设计项目中,一个新人设计了如下 ...

  8. STM32小车——PWM电机调速

    PWM电机调速(寄存器版) 我的上一篇博客已经写了如何用定时器产生PWM来实现LED灯的呼吸灯效果,当我想实现PWM来控制电机调速时,网上翻阅了很多的资料但是大多数是在呼吸灯的基础上改一下代码实现的, ...

  9. 关于iic协议和对AT24C02进行读写数据的理解和代码解读

    关于iic协议和对AT24C02进行读写数据的理解和代码解读 认识IIC协议 IIC协议软件模拟方法 管脚初始化 时序 AT24C02 简介 存储大小计算 工作方式 流程(代码) 认识IIC协议 本文 ...

  10. STM32: 利用高级定时器产生6路互补PWM波形输出在BLDC中H-PWM-L-ON驱动方式下驱动无刷电机

    原文网址:http://jingyan.eeboard.com/article/73847#/prettyPhoto%5Bpp_gal%5D/6/ http://jingyan.eeboard.com ...

最新文章

  1. HTML中checked1001无标题,是否可以一键切换两个CSS`:checked`伪类?
  2. 后宫佳丽三千,皇后只有一个
  3. python代码命令行tab补齐_Python在命令行下Tab键自动补全脚本
  4. win32 api 消息解释
  5. MySQL的优化与执行
  6. 利用ASP.NET2.0向导控件一步步建立与用户的交互--------提高和自定义用户体验
  7. 688:画圈游戏(思维)
  8. opencv2.2.0源代码(include文件)分析
  9. python list remove 删除引用_Python——list列表操作一坑(remove)
  10. python计算期望值_机器学习:计算方差时为何除以n-1
  11. 指定Pycharm在py3.6环境下启动
  12. 【组合数学】递推方程 ( 特特解示例 1 汉诺塔 完整求解过程 | 特解示例 2 特征根为 1 的情况下的特解处理 )
  13. Java八大基础数据类型转换
  14. 棋牌搭建,APP新手教程
  15. 试用了40+款日记APP,才知道好软件有多难求...
  16. tensorflow2没有slim模块
  17. 计算机基础2,计算机基础总结2
  18. 下载 线代 薛威_考研线代李永乐真的首选吗?
  19. DDR3 HYPERLYNX SI仿真
  20. 虚拟主机、VPS、云服务器三者的区别

热门文章

  1. LED显示屏安装方法
  2. php调用会员头像,DEDECMS会员头像调用方法
  3. 西北工业大学计算机转专业,2021年西北工业大学大一新生转专业及入学考试相关规定...
  4. 上海公积金网上提取全流程(图文版)在职公积金,离职公积金都可以提取
  5. 雪花飘落代码java_JavaScript实现雪花飘落效果
  6. 【c++】《搜索习题集》题解,更新至DFS之搜索顺序
  7. 多传感器融合的四种经典结构
  8. 高效领导者提升思考力的5个底层法则
  9. Torus:为Kubernetes量身打造的分布式存储方案
  10. 在Windows平台上使用Git和pathogen管理gVim插件