• stm32通过电调带动电机(可按键调速)


    这几天在做32通过电调带动电机的实验,上网一查,发现这方面的资料很少,经过自己的亲自实践,总结出以下经验,供大家参考。

    论坛上也有很多人说自己在做,但是都遇到了同样的瓶颈。我想他们大多是pwm的频率和占空比没有调到合适的值吧。

    首先,我在网上只找到一片很好的文章,是瑞生大神写的:http://www.rationmcu.com/lpc1114/1126.html

    我的电机是银燕2212/1400kv经典电机 ,电调也是银燕40A无刷电调。

    通过它知道,当pwm设置为500hz的 时候电调才能正常的工作,刚开始时高电平时间要控制在0.7-1.9左右,让电机带电自检。

    通过按键控制占空比可以很好地 实现这一点。

    好了,下面上我的代码。

    先来头文件吧

    #ifndef _Motor_H_
    #define _Motor_H_
    #include "stm32f10x.h"
    
    /******************************************************************************
                                全局函数声明
    *******************************************************************************/ 
    void Motor_Init(void);
    //void Motor_Out(int16_t duty1,int16_t duty2,int16_t duty3,int16_t duty4);
    
    #endif

    主菜:

      1 /***************************************************************************************
      2   1/给单片机写程序:使得某引脚输出500Hz的PWM信号,初始化时高电平时间设置为1.9ms,
      3   然后在while循环里面加入检测按键的程序,当按键按下,把高电平设置为0.7ms。
      4     2/1.给单片机写程序,把刚才的PWM初始化的高电平设置为0.7ms,保证刚上电,电调不会让电机转动。
      5     然后给修改按键按下的程序,修改为,按一次按键,高电平时间增加一点点,最大增加到1.9ms。
      6     
      7     我的按键再c13(k2)和e0(k1)
      8     日期:2016.3.4
      9 ***************************************************************************************/
     10 
     11 #include "dianji.h"
     12 
     13   uint8_t indexWave[] = {5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};  //占空比表
     14     
     15 //声明函数
     16 void Tim2_init(void);
     17 void Motor_Init(void);
     18 void Init_NVIC(void);
     19 void Delay_Ms(uint16_t time);  
     20 void Delay_Us(uint16_t time); 
     21 void Init_TI_KEY(void);
     22 
     23         
     24 int main(void)
     25 {
     26  
     27     SystemInit();                //系统时钟配置
     28     Motor_Init();
     29     Tim2_init();
     30     Init_NVIC();                //中断向量表注册函数
     31     Init_TI_KEY();                //按键引脚中断初始化
     32     
     33     while(1);
     34     
     35 }
     36 
     37 
     38 void Tim2_init(void)
     39 {    
     40     
     41     TIM_TimeBaseInitTypeDef        TIM_TimeBaseStructure;
     42     TIM_OCInitTypeDef              TIM_OCInitStructure;
     43     
     44      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
     45     
     46     TIM_TimeBaseStructure.TIM_Period = 20-1;    //设置ARR的值为19,从0计数到19,刚好是2ms ,500hz
     47     TIM_TimeBaseStructure.TIM_Prescaler = 7200-1;//设置PSC的值为7199,这样的话每计数一次为0.1ms 
     48     
     49     
     50     TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
     51     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIMx向上计数模式
     52     TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseStructure中指定的参数初始化外设TIM2
     53     
     54     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式
     55     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
     56     
     57     TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值,刚开始可以设置为0.
     58     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
     59     
     60     TIM_OC1Init(TIM2, &TIM_OCInitStructure); 
     61     TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR1上的预装载寄存器
     62 
     63     TIM_ARRPreloadConfig(TIM2, ENABLE); //使能TIM2在ARR上的预装载寄存器
     64     TIM_Cmd(TIM2, ENABLE);  //使能TIM2外设
     65 }
     66 
     67 /******************************************************************************
     68 函数原型:    void Motor_Init(void)
     69 功    能:    PWM初始化
     70 *******************************************************************************/ 
     71 void Motor_Init(void)
     72 {
     73     
     74     GPIO_InitTypeDef GPIO_InitStructure;
     75     
     76     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);   //使能电机用的时钟
     77     
     78     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;     //设置电机使用到得管脚
     79     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
     80     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
     81     GPIO_Init(GPIOA, &GPIO_InitStructure);
     82 
     83 }
     84 
     85 /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
     86 ** 函数名称: KEY_TI_Init
     87 ** 功能描述: 按键 中断配置 
     88 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
     89 void Init_TI_KEY(void)
     90 {
     91     EXTI_InitTypeDef  EXTI_InitStructure;                    //定义一个EXTI结构体变量
     92 
     93     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);        //使能IO复用功能,使用中断功能重要!!!
     94 
     95     GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);//配置端口C的13引脚为中断源      重要!! 板上标号INT2
     96     GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource0); //配置端口E的0引脚为中断源      重要!! 板上标号INT1
     97     EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line13;//
     98     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;        //中断模式为中断模式
     99     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;    //下降沿出发
    100     EXTI_InitStructure.EXTI_LineCmd = ENABLE;                //使能中断线
    101     EXTI_Init(&EXTI_InitStructure);                            //根据参数初始化中断寄存器
    102 }
    103 
    104 /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    105 ** 函数名称: Init_NVIC
    106 ** 功能描述: 系统中断配置
    107 
    108 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    109 void Init_NVIC(void)
    110 { 
    111     NVIC_InitTypeDef  NVIC_InitStructure;
    112          
    113     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                  //设置中断优先级分组2
    114 
    115     NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;        //设定中断源为PC13
    116     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    //中断占优先级为2
    117     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            //副优先级为0
    118     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                //使能中断
    119     NVIC_Init(&NVIC_InitStructure);                                   //根据参数初始化中断寄存器
    120 
    121     NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;            //设定中断源为PE0
    122     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;    //中断占优先级为1
    123     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            //副优先级为0
    124     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                //使能中断
    125     NVIC_Init(&NVIC_InitStructure);                                   //根据参数初始化中断寄存器
    126 }
    127 
    128 
    129 /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    130 ** 函数名称: EXTI15_10_IRQHandler
    131 ** 功能描述: 中断15_10入口函数            
    132 
    133 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    134 void EXTI15_10_IRQHandler(void)   //占空比减小
    135 {
    136     static uint8_t pwm_index = 0;            //用于PWM查表
    137     static uint8_t period_cnt = 0;        //用于计算周期数
    138     //就是上面两个静态变量没有设置 ,导致一开始按键只能按一次,在往下按他的pwm表就不往下查表了,我想了一晚上啊。
    139     //今天早晨我突然发现可能是这两个静态变量没有设置,一试,果然。开心至极。2016.3.5
    140     
    141     if(EXTI_GetITStatus(EXTI_Line13)!= RESET)      //判断是否发生中断,发生则中断标志置1
    142     {
    143            Delay_Ms(5);  //消抖
    144 
    145              period_cnt++;            
    146                 
    147                 TIM2->CCR1 = indexWave[pwm_index];    //根据PWM表修改定时器的比较寄存器值
    148                 pwm_index++;                                                //标志PWM表的下一个元素
    149             
    150                 if( pwm_index >=  15)                                //若PWM脉冲表已经输出完成一遍,重置PWM查表标志
    151                 {
    152                     pwm_index=0;                                
    153                 }
    154                 
    155                     
    156     //TIM_ClearITPendingBit (TIM2, TIM_IT_Update);    //必须要清除中断标志位
    157         
    158     EXTI_ClearITPendingBit(EXTI_Line13);        //清楚中断挂起位,重要!!            
    159 }
    160     
    161 }
    162 
    163 
    164 /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    165 ** 函数名称: EXTI0_IRQHandler
    166 ** 功能描述: 中断0入口函数            
    167 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    168 void EXTI0_IRQHandler(void)    //占空比增大
    169 {
    170     if(EXTI_GetITStatus(EXTI_Line0)!= RESET)     //判断是否发生中断,发生则中断标志置1
    171     {
    172       Delay_Ms(5);
    173         
    174         //暂时不用
    175     }
    176     EXTI_ClearITPendingBit(EXTI_Line0);             //清楚中断挂起位,重要!!            
    177 }
    178 
    179 /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    180 ** 函数名称: Delay_Ms_Ms
    181 ** 功能描述: 延时1MS (可通过仿真来判断他的准确度)            
    182 ** 参数描述:time (ms) 注意time<65535
    183 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    184 void Delay_Ms(uint16_t time)  //延时函数
    185 { 
    186     uint16_t i,j;
    187     for(i=0;i<time;i++)
    188           for(j=0;j<10260;j++);
    189 }
    190 /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    191 ** 函数名称: Delay_Ms_Us
    192 ** 功能描述: 延时1us (可通过仿真来判断他的准确度)
    193 ** 参数描述:time (us) 注意time<65535                 
    194 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    195 void Delay_Us(uint16_t time)  //延时函数
    196 { 
    197     uint16_t i,j;
    198     for(i=0;i<time;i++)
    199           for(j=0;j<9;j++);
    200 }
    201 /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    202 End:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D:-D
    203 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

    本人也是新手,最近在做四旋翼,有什么问题欢迎交流。

  • 相关阅读:
    SQL Server创建复合索引时,复合索引列顺序对查询的性能影响
    SQL 查询性能优化----解决书签查找
    从源码分析 Spring 基于注解的事务
    jQuery最佳实践(不断更新中...)
    Java 8 LongAdders:管理并发计数器的正确方式
    Java中的显示锁 ReentrantLock 和 ReentrantReadWriteLock
    在IE8等不支持placeholder属性的浏览器中模拟placeholder效果
    颠覆式前端UI开发框架:React
    Whitecoin区块链钱包高级功能使用命令
    消息队列使用的四种场景介绍
  • 原文地址:https://www.cnblogs.com/qsyll0916/p/6504303.html
Copyright © 2020-2023  润新知