stm32控制电机
一、總體思路
使用端口GPIOA來(lái)連接電機(jī),所以給GPIOA編程就可以控制電機(jī)。使用系統(tǒng)時(shí)鐘SysTick來(lái)周期性的給電機(jī)發(fā)送脈沖。用四個(gè)按鈕來(lái)控制需要發(fā)送脈沖的個(gè)數(shù),每個(gè)按鈕被按下就設(shè)置給電機(jī)發(fā)送脈沖的個(gè)數(shù),如果上一次給電機(jī)發(fā)送的脈沖沒有發(fā)送完成,這次按鈕發(fā)送的脈沖將不被響應(yīng)。二、GPIOA端口的設(shè)置
由于需要控制兩個(gè)電機(jī),所以將GPIOA端口的1,2,3號(hào)引腳與電機(jī)0相連(分別控制電機(jī)的使能,旋轉(zhuǎn)方向和脈沖),GPIOA的4,5,6號(hào)引腳與電機(jī)1相連。具體對(duì)端口的初始化代碼為: GPIO_InitTypeDef GPIO_InitStruct; //開啟電機(jī)0外設(shè)時(shí)鐘 DJ_EnablePeriphClock_0(); //初始化電機(jī)0 GPIO_InitStruct.GPIO_Pin = DJ_EN_0 | DJ_DR_0 | DJ_MC_0; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(DJ_GPIO_0, &GPIO_InitStruct); //設(shè)置電機(jī)0的初始化狀態(tài) DJ_DisEnable(DJ_GPIO_0, DJ_EN_0); //關(guān)閉電機(jī)0 上面的代碼是對(duì)與電機(jī)0連接的引腳的初始化,電機(jī)1的初始化是一樣的,只是引腳不同了。從上面的代碼可以看到引腳的輸出模式是推挽的(為了做Debug),實(shí)際應(yīng)該使用開漏的,由于我們要給電機(jī)輸入5V的高電平,所以我們應(yīng)該在外部接一個(gè)上拉電阻,電源為5V。三、SysTick設(shè)置
SysTick是一個(gè)系統(tǒng)定時(shí)器,系統(tǒng)的滴答是可以配置的,在控制電機(jī)的程序中我們將系統(tǒng)滴答設(shè)置為100us,理論上可以將系統(tǒng)滴答設(shè)置為1/72000000s,由于系統(tǒng)的時(shí)鐘為72MHz。每個(gè)脈沖間隔為5個(gè)滴答。也就是說(shuō)每隔500us發(fā)送一個(gè)脈沖,脈沖周期為1ms。 設(shè)置系統(tǒng)滴答通過宏: #define TICK 10000 ?//100us一個(gè)滴答 實(shí)際的配置是通過下面代碼: SysTick_Config(SystemCoreClock / TICK); 為了實(shí)現(xiàn)每隔5個(gè)系統(tǒng)滴答發(fā)送一個(gè)脈沖,定義了兩個(gè)全局變量TimingDelay和TimingLoad?,可以通過函數(shù)Timer來(lái)設(shè)置這個(gè)變量的值: void Timer(__IO uint32_t nTime){TimingDelay = nTime;TimingLoad = nTime;} TimingDelay表示當(dāng)前距離發(fā)送下一個(gè)脈沖還需要等待的滴答數(shù),TimingLoad 表示發(fā)送脈沖的間隔,如果每個(gè)脈沖間隔為5個(gè)滴答,則TimingLoad =5。這樣在系統(tǒng)時(shí)鐘的每次中斷代碼中將TimingDelay減1,當(dāng)TimingDelay為0時(shí)就向電機(jī)發(fā)送脈沖(將對(duì)應(yīng)電機(jī)脈沖的引腳的值變反就可以了),然后重新將TimingLoad賦值給TimingDelay來(lái)準(zhǔn)備下一個(gè)脈沖的發(fā)送。具體代碼如下: if (TimingDelay)TimingDelay--;else{TimingDelay = TimingLoad; if (dj_GetMc()) //判斷是否還需要發(fā)送脈沖 {printfd("\r\nsend %dth pulse, %d", dj_GetMc(), 1 - GPIO_ReadOutputDataBit (DJ_GPIO_0, DJ_MC_0)); //用于調(diào)試DJ_IO(1 - GPIO_ReadOutputDataBit (DJ_GPIO_0, DJ_MC_0), DJ_GPIO_0, DJ_MC_0); //用于發(fā)送脈沖 dj_DesMc(); }elseSysTick_Shutdown(); //關(guān)閉系統(tǒng)時(shí)鐘} dj_GetMc函數(shù)和dj_DesMc函數(shù)分別獲得全局變量dj_McCount的值和對(duì)該全局變量減1,這個(gè)全局變量代表總共需要發(fā)送幾個(gè)脈沖。正如開頭說(shuō)的,按下一個(gè)鍵就設(shè)置需要發(fā)送的脈沖數(shù),當(dāng)脈沖發(fā)完了,就關(guān)閉系統(tǒng)定時(shí)器。四、按鍵設(shè)置
使用ARM板自帶的WAKEUP,TAMPER,USER1,USER2四個(gè)鍵來(lái)配置需要發(fā)送脈沖的個(gè)數(shù),它們分別配置為需要發(fā)送2,20,200,2000個(gè)脈沖。我們通過中斷的方式來(lái)檢查哪個(gè)鍵被按下了。配置將四個(gè)按鍵與EXTI相連,讓EXTI產(chǎn)生中斷到中斷控制器NVIC。首先需要配置NVIC的搶占優(yōu)先級(jí)和響應(yīng)優(yōu)先級(jí),直接調(diào)用庫(kù)函數(shù)就可以了:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
然后是配置按鍵與EXTI相連,具體配置代碼如下: static void NVIC_SetVector( IRQn_Type IRQn, uint8_t PreemptionPriority, uint8_t SubPriority) {NVIC_InitTypeDef NVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel = IRQn;//EXTI0_IRQn | EXTI9_5_IRQn | EXTI3_IRQn | EXTI15_10_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = PreemptionPriority;NVIC_InitStruct.NVIC_IRQChannelSubPriority = SubPriority;NVIC_Init(&NVIC_InitStruct); } //WAKEUP鍵 static void EXTI_PA0_Config(void) {GPIO_InitTypeDef GPIO_InitStruct;EXTI_InitTypeDef EXTI_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);NVIC_SetVector(EXTI0_IRQn, 0, 0); //配置NVICGPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //配置GPIOA_Pin0為EXTI0線EXTI_InitStruct.EXTI_Line = EXTI_Line0;EXTI_InitStruct.EXTI_LineCmd = ENABLE;EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //中斷模式EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising ; //上升沿觸發(fā)EXTI_Init(&EXTI_InitStruct); }? ? ?上面的代碼顯示了配置WAKEUP鍵,其它鍵也是同樣的配置。當(dāng)按下一個(gè)鍵時(shí),對(duì)應(yīng)的中斷響應(yīng)函數(shù)就會(huì)執(zhí)行,我們?cè)陧憫?yīng)函數(shù)中判斷全局變量dj_McCount是否為0,如果不為0,說(shuō)明上一次按鍵的脈沖還沒有發(fā)生完成,則直接退出中斷響應(yīng)函數(shù);如果為0,說(shuō)明當(dāng)前沒有在發(fā)生脈沖,則設(shè)置dj_McCount為2,開啟系統(tǒng)定時(shí)器來(lái)發(fā)送脈沖。代碼如下: //WAKEUP void EXTI0_IRQHandler(void) { if (EXTI_GetFlagStatus(EXTI_Line0) != RESET) //看是否產(chǎn)生了EXTI_Line0中斷 {printfd("\r\nexti0");if (dj_GetMc() == 0){dj_SetMc(1);SysTick_Startup();}EXTI_ClearFlag(EXTI_Line0); //清除中斷標(biāo)志位 } }
?
源代碼:http://pan.baidu.com/s/1uy6PK
總結(jié)
- 上一篇: Forefront_TMG_2010-T
- 下一篇: Oracle与MySQL性能比较