×
单片机 > 单片机程序设计 > 详情

stm32通过电调带动电机

发布时间:2020-09-02 发布时间:
|

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

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

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

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

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

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

好了,下面上我的代码。

先来头文件吧


  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  



主菜:


  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

  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

  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. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/  


就是以上这些,有问题欢迎讨论。


关键字:stm32  电调  电机 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
单片机制作超级流水灯