8位機最常見的應用單片機驅動馬達IC工作,馬達可支持無級調速(PWM),正轉,反轉,剎車。該應用簡單高效適應於各種應用,節約成本的不二選擇。
今天就跟大家分享曾經做過的馬達驅動IC的應用。
主電路由8位單片機提供控制信號,正轉,反轉,PWM調速,以及一個峰值電流400ma的馬達驅動IC構成。見電路圖。
S1按一下正轉,按一下停機
S2按一下反轉,按一下停機
S3按一下加一級速度
S4按一下減一級速度
由於硬件不支持PWM,PWM使用IO模擬的方式產生。
/* ========================================================================= * Project: GPIO_Setting * File: main.c * Description: Set GPIO of PORTB * 1. PORTB I/O state * - PB4 set input mode and enable pull-high resistor * - PB2 set output mode * - PB1 set input mode and enable pull-low resistor * - PB0 set open-drain output mode * * Author: JasonLee * Version: V1.1 * Date: 2018/09/07 =========================================================================*/ #include <ny8.h> #include "ny8_constant.h" #include <stdint.h> #define UPDATE_REG(x) __asm__("MOVR _" #x ",F") uint8_t pwmdcycle = 0; //計數1000為一個周期 uint8_t pwmduty1 = 0; uint8_t pwmduty2 = 0; uint8_t pwmduty1s = 0; uint8_t pwmduty2s = 0; uint8_t spstate = 1; uint8_t direction = 0; //stop 0 fw 1 bk 2 //uint8_t spdstate = 1; //10檔 int16_t seccount = 0; int16_t tim1count = 0; int16_t tim1scount = 0; uint8_t sw1flg = 0; int16_t tim2count = 0; int16_t tim2scount = 0; uint8_t sw2flg = 0; uint16_t tim3count = 0; uint8_t sw3flg = 0; uint8_t tim4count = 0; uint8_t sw4flg = 0; void peripinit(void) { //;Initial GPIO // ; PORTB I/O state // ; PB0、PB1、PB2 set output mode and enable pull-high resister BPHCON = (uint8_t) ~( C_PB5_PHB | C_PB4_PHB | C_PB2_PHB) ; // Enable PB5、PB4、PB2 Pull-High Resistor,others disable IOSTB = (uint8_t) (C_PB5_Input | C_PB4_Input | C_PB3_Input | C_PB2_Input) ; // Set PB5、PB3、PB3 PB2 to output mode,others set to input mode PORTB = 0x00; //;Initial time1 // ;instrclk i_hrc 4/4M div = 1 計數8次溢出即可 // ; TMR1 = 0xC8; //到0下溢出中斷,計數 //4M/200 = 20K/20 = 1K T1CR1 = C_TMR1_Reload | C_TMR1_En; //自動重載 T1CR2 = C_TMR1_ClkSrc_Inst | C_PS1_Dis ; //指令時鍾 //T1CR1 =( T1CR1 | C_TMR1_En ); //使能定時器 INTE = INTE | C_INT_TMR1; } //盡量減小中斷代碼時長 void isr_hw(void) __interrupt(0) { if(INTFbits.T1IF) //占空比為 cycle-duty { pwmdcycle++; if( pwmdcycle == pwmduty1s ) { if(direction == 1) //FW { PORTBbits.PB0 = 1; PORTBbits.PB1 = 0; } else if(direction == 2) //BK { PORTBbits.PB0 = 0; PORTBbits.PB1 = 1; } else if(direction == 0) //停機 { PORTBbits.PB0 = 0; PORTBbits.PB1 = 0; } } if(pwmdcycle == 20) { pwmduty1s = pwmduty1; //必須保證周期結束才能更改此值 pwmduty2s = pwmduty2; //必須保證周期結束才能更改此值 PORTBbits.PB1 = 0; PORTBbits.PB0 = 0; pwmdcycle = 0; seccount ++; } INTFbits.T1IF = 0; } } void main(void) { DISI(); peripinit(); ENI(); while(1) { //PB2 正轉 if(PORTBbits.PB4 == 0) { if(sw1flg == 0) { tim1count = seccount + 3000; tim1scount = seccount + 40; sw1flg = 1; } if((tim1count == seccount)&&(sw1flg == 2)) { if(direction != 0) //關機 { direction = 0; } else { direction = 1; spstate = 1; } sw1flg = 3; } if((seccount == tim1scount)&&(sw1flg == 1)) { sw1flg = 2; } } else { if(sw1flg == 2 ) //短按有效 { if(direction == 1) { direction = 2; } else if(direction == 2) { direction = 1; } } tim1count = 0; tim1scount = 0; sw1flg = 0; } //PB3 if(PORTBbits.PB3 == 0) { if(sw2flg == 0) { tim2count = seccount + 3000; //延時3s tim2scount = seccount + 40 ; sw2flg = 1; } if((tim2count == seccount)&&(sw2flg == 2)) { if(direction != 0) //開機 { direction = 0; } else { direction = 1; spstate = 1; } sw2flg = 3; } if((seccount == tim2scount)&&(sw2flg == 1)) { sw2flg = 2; } } else { if(sw2flg == 2 ) { if(direction == 1) { direction = 2; } else if(direction == 2) { direction = 1; } } tim2count = 0; tim2scount = 0; sw2flg = 0; } //PB5 加速換擋 if(PORTBbits.PB5 == 0) { if(sw3flg == 0) { tim3count = seccount + 30; sw3flg = 1; } if((tim3count == seccount)&&(sw3flg == 1)) { spstate ++; if(spstate == 11) { spstate = 1; } sw3flg = 2; } } else { tim3count = 0; sw3flg = 0; } //CLRWDT(); //pb4/pb5_加減速 if(spstate == 1) { pwmduty1 = 10; } else if(spstate == 2) { pwmduty1 = 9; } else if(spstate == 3) { pwmduty1 = 8; } else if(spstate == 4) { pwmduty1 = 7; } else if(spstate == 5) { pwmduty1 = 6; } else if(spstate == 6) { pwmduty1 = 5; } else if(spstate == 7) { pwmduty1 = 4; } else if(spstate == 8) { pwmduty1 = 3; } else if(spstate == 9) { pwmduty1 = 2; } else if(spstate == 10) { pwmduty1 = 1; } } }


