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; } } }