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

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

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

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

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

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

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

好了,下面上我的代码。

先来头文件吧

[html]  view plain  copy
  1. #ifndef _Motor_H_  
  2. #define _Motor_H_  
  3. #include "stm32f10x.h"  
  4.   
  5. /******************************************************************************  
  6.                             全局函数声明  
  7. *******************************************************************************/   
  8. void Motor_Init(void);  
  9. //void Motor_Out(int16_t duty1,int16_t duty2,int16_t duty3,int16_t duty4);  
  10.   
  11. #endif  


主菜:

[html]  view plain  copy
  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. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/  

你可能感兴趣的:(单片机)