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



















