這幾天在做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 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
本人也是新手,最近在做四旋翼,有什么問題歡迎交流。