1、直流电机、步进电机、舵机综合应用设计
2、直流电机、步进电机、舵机综合应用设计--程序编写
3、直流电机、步进电机、舵机综合应用设计--仿真测试
程序如下:
#include"at89x52.h"
#define uchar unsigned char
#define uint unsigned int
#define KEY P1 //按键控制
#define T1_COUNT 100 //定时器0的计数值
//直流电机(DC_motor)
#define PWM 100 //PWM计数值的上限值
#define INIT_VAL_PWM 20 //PWM占空比初始值
#define INCREMENT_PWM 10 //PWM控制时的增量大小
//步进电机(stepping motor)
#define SM P0 //步进电机输出
#define BEAT_MAX_SM 8 //步进电机转一圈的节拍数
#define ADJUST_MAX_SM 150 //步进电机节拍间隔时间的最大值(单位时间:T1定时时间)
#define ADJUST_MIN_SM 30 //步进电机节拍间隔时间的最小值(单位时间:T1定时时间)
#define INCREMENT_SM 10 //步进电机节拍之间的时间调整增量
#define INIT_VAL_SM 100 //步进电机节拍之间的时间初始值
//舵机(steering engine)
#define POLUS_SE 20000 //产生20ms的计数值
#define ERROR_SE 28 //占空比输出误差平衡值
#define INCREMENT_SE 100 //舵机角度变化增量 大概10度
#define INIT_VAL_SE 1400 //舵机初始值,指向0度
#define ADJUST_MAX_SE 2300 //占空比上限值
#define ADJUST_MIN_SE 500 //占空比下限值
sbit DC_Moto_A = P2^0; //脉冲输入引脚
sbit DC_Moto_B = P2^1;
sbit SE_Polus = P2^2; //SE(steering engine)舵机控制脉冲输出引脚
sbit LED_DC = P2^3; //直流电机LED指示灯,0:点亮LED,直流电机处于被控制状态
sbit LED_SM = P2^4; //步进电机LED指示灯,0:点亮LED,步进电机处于被控制状态
sbit LED_SE = P2^5; //舵机LED指示灯,0:点亮LED,舵机处于控制状态
uchar sel_motor; //选择控制电机
//直流电机控制变量定义
uchar count_PWM; //PWM计数值
uchar val_PWM; //PWM占空比的值
bit forward_flag_DC; //直流电机正反转标志, 1:电机正转 0:电机反转
bit stop_flag_DC; //直流电机停止/运行标志 1:停止 0;运行
bit suspend_flag_DC; //直流电机暂停/继续标志 1:暂停 0:继续
//步进电机控制变量定义
/*A AB B BC C CD D DA*/
uchar forward_SM[8]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09}; //四相八拍 正转
/* A AD D DC C CB B BA*/
uchar reversal_SM[8]={0x01,0x09,0x08,0x0c,0x04,0x06,0x02,0x03}; //四相八拍 反转
uint count_SM; //节拍之间的延时计时
uint beat_time_SM; //一个节拍的时间
uchar beat_count_SM; //节拍计数
bit forward_flag_SM; //(stepping moto)步进电机正反转标志, 1:电机正转 0:电机反转
bit stop_flag_SM; //(stepping moto)步进电机停止/运行标志 1:停止 0;运行
bit suspend_flag_SM; //(stepping moto)步进电机暂停/继续标志 1:暂停 0:继续
//舵机控制变量定义
uint up_val_SE; //高电平时间,单位时间为T0定时时间
uint temp_SE; //暂存高电平或低电平的时间值
uchar th0;
uchar tl0;
/*-------------------------
函数名称:delay_ms
形 参:uint n:延时时间的长度
功 能:软件延时,延时的单位时间在1ms左右
返 回 值:无
-------------------------*/
void delay_ms(uint n)
{
uint i;
uchar j;
for(i=0;i<n;i++)
for(j=0;j<120;j++);
}
/*-------------------------
函数名称:key_scan
形 参:无
功 能:按键扫描
返 回 值:扫描的结果,"0"为无按键按下、非"0"为按键值
-------------------------*/
uchar key_scan()
{
uchar temp = 0;
KEY = 0xff;
if(KEY!=0xff)
{
delay_ms(10); //按键消抖
KEY = 0xff;
if(KEY!=0xff)
{
temp = KEY;
while(KEY!=0xff) //等待按键释放
KEY = 0xff;
}
}
return temp;
}
/*-------------------------
函数名称:key_contorl_DC
形 参:uchar key_val:按键值
功 能:控制直流电机的按键功能
返 回 值:无
-------------------------*/
void key_contorl_DC(uchar key_val) //直流电机按键控制
{
switch(key_val)
{
case 0xfe: //直流电机加速
if((0==stop_flag_DC)&&(0==suspend_flag_DC))
{
val_PWM += INCREMENT_PWM; //增加占空比
if(val_PWM>PWM)
val_PWM = PWM;
}
break;
case 0xfd: //直流电机减速
if((0==stop_flag_DC)&&(0==suspend_flag_DC))
{
if(val_PWM>=INCREMENT_PWM)
val_PWM -= INCREMENT_PWM; //减少占空比
}
break;
case 0xfb: //直流电机正或反转选择
if((0==stop_flag_DC)&&(0==suspend_flag_DC))
forward_flag_DC = ~forward_flag_DC; //切换电机旋转模式
break;
case 0xf7: //直流电机暂停/继续
if(stop_flag_DC==0)
{
suspend_flag_DC = ~suspend_flag_DC;
DC_Moto_A = 0;
DC_Moto_B = 0;
}
break;
case 0xef: //直流电机停止/运行
stop_flag_DC =~ stop_flag_DC;
if(stop_flag_DC)
{ //停止
val_PWM = INIT_VAL_PWM; //初始化变量和标志
forward_flag_DC = 1;
suspend_flag_DC = 0;
DC_Moto_A = 0;
DC_Moto_B = 0;
}
break;
default:break;
}
}
/*-------------------------
函数名称:key_contorl_SM
形 参:uchar key_val:按键值
功 能:控制步进电机的按键功能
返 回 值:无
-------------------------*/
void key_contorl_SM(uchar key_val) //步进电机按键控制
{
switch(key_val)
{
case 0xfe: //步进电机加速
if((0==stop_flag_SM)&&(0==suspend_flag_SM))
{
beat_time_SM -= INCREMENT_SM;
if(beat_time_SM<ADJUST_MIN_SM)
beat_time_SM = ADJUST_MIN_SM;
}
break;
case 0xfd: //步进电机减速
if((0==stop_flag_SM)&&(0==suspend_flag_SM))
{
if(beat_time_SM<ADJUST_MAX_SM)
beat_time_SM += INCREMENT_SM;
}
break;
case 0xfb: //步进电机正或反转选择
if((0==stop_flag_SM)&&(0==suspend_flag_SM))
{
forward_flag_SM = ~forward_flag_SM; //切换电机旋转模式
beat_count_SM = 0; //换转向后将节拍指向数组的第一个
}
break;
case 0xf7: //步进电机暂停/继续
if(stop_flag_SM==0)
suspend_flag_SM = ~suspend_flag_SM;
break;
case 0xef: //步进电机停止/运行
stop_flag_SM =~ stop_flag_SM;
if(stop_flag_DC)
{ //停止
forward_flag_SM = 1; //变量、标志初始化
suspend_flag_SM = 0;
count_SM = 0;
beat_time_SM = INIT_VAL_SM;
beat_count_SM = 0;
}
break;
default:break;
}
}
/*-------------------------
函数名称:key_contorl_SE
形 参:uchar key_val:按键值
功 能:控制舵机的按键功能
返 回 值:无
-------------------------*/
void key_contorl_SE(uchar key_val) //舵机按键控制
{
switch(key_val)
{
case 0xfe: //舵机向左增大角度
if(up_val_SE<ADJUST_MAX_SE) //上限2300
up_val_SE += INCREMENT_SE; //100一个增量为10度
break;
case 0xfd: //舵机向右增大角度
up_val_SE -= INCREMENT_SE;
if(up_val_SE<ADJUST_MIN_SE) //下限500
up_val_SE = ADJUST_MIN_SE;
break;
default:break;
}
}
/*-------------------------
函数名称:key_behav
形 参:uchar key_val:按键值
uchar mod:控制的对象,0:直流电机;1:步进电机;2:舵机
功 能:实现按键功能
返 回 值:无
-------------------------*/
void key_behav(uchar key_val) //switch选择语句 (选择不同的电机)
{
switch(key_val)
{
case 0xdf:
sel_motor = 0;
LED_DC = 0; //点亮直流电机指示灯
LED_SM = 1; //熄灭步进电机指示灯
LED_SE = 1; //熄灭舵机指示灯
break;
case 0xbf:
sel_motor = 1;
LED_DC = 1; //熄灭直流电机指示灯
LED_SM = 0; //点亮步进电机指示灯
LED_SE = 1; //熄灭舵机指示灯
break;
case 0x7f:
sel_motor = 2;
LED_DC = 1; //熄灭直流电机指示灯
LED_SM = 1; //熄灭步进电机指示灯
LED_SE = 0; //点亮舵机指示灯
break;
default:
switch(sel_motor)
{
case 0: key_contorl_DC(key_val);break; //控制直流电机
case 1: key_contorl_SM(key_val);break; //控制步进电机
case 2: key_contorl_SE(key_val);break; //控制舵机
default:break;
}
break;
}
}
/*-------------------------
函数名称:interrupt_init
形 参:无
功 能:中断寄存器初始化
返 回 值:无
-------------------------*/
void interrupt_init()
{
TMOD = 0x11;
TH1 = (65536-T1_COUNT)/256; //定时器/计数器1计数
TL1 = (65536-T1_COUNT)%256;
TH0 = (65536-up_val_SE)/256; //定时器/计数器0计数 舵机控制的定时器
TL0 = (65536-up_val_SE)%256;
ET1 = 1;
TR1 = 1;
PT0 = 1; //定时器/计数器0,1中断优先级控制位PT0=1为高优先级,否则为低优先级
ET0 = 1;
TR0 = 1;
EA = 1;
}
/*-------------------------
函数名称:variable_init
形 参:无
功 能:变量、标志初始化
返 回 值:无
-------------------------*/
void variable_init()
{
sel_motor = 0; //选择哪种电机
//直流电机初始化
val_PWM = INIT_VAL_PWM;
forward_flag_DC = 1;
suspend_flag_DC = 0;
stop_flag_DC = 1;
DC_Moto_A = 0;
DC_Moto_B = 0;
//步进电机初始化
forward_flag_SM = 1;
stop_flag_SM = 1;
suspend_flag_SM = 0;
count_SM = 0;
beat_time_SM = INIT_VAL_SM;
beat_count_SM = 0;
//舵机控制变量初始化
up_val_SE = INIT_VAL_SE; //高电平时间 1400
temp_SE = POLUS_SE-up_val_SE; //低电平的时间 20000-1400
th0 = (65536-temp_SE+ERROR_SE)>>8; //65536-temp_SE+28
tl0 = (65536-temp_SE+ERROR_SE)&0x00ff;
LED_DC = 0; //点亮直流电机指示灯,程序启动时默认控制直流电机
LED_SM = 1; //熄灭步进电机指示灯
LED_SE = 1; //熄灭舵机指示灯
}
/*-------------主函数----------*/
void main()
{
uchar key_val = 0;
variable_init();
interrupt_init();
while(1)
{
while(!key_val)
key_val = key_scan();
key_behav(key_val);
key_val = 0;
}
}
/*-------------------------
疲篋C_SM_moto_run
形 参:无
功 能:T0中断函数;舵机驱动
返 回 值:无
--------------------------*/
void SE_moto_run() interrupt 1 //定时器/计数器0中断
{
TH0 = th0;
TL0 = tl0;
if(temp_SE<2400)
{
temp_SE = POLUS_SE-up_val_SE; //定时器下次的计数值&&(temp_SE>400)
SE_Polus = 1;
}
else
{
temp_SE = up_val_SE; //定时器下次的计数值
SE_Polus = 0;
}
th0 = (65536-temp_SE+ERROR_SE)>>8; //下次定时器的初值
tl0 = (65536-temp_SE+ERROR_SE)&0x00ff;
}
/*-------------------------
函数名称:DC_SM_mo to_run
形 参:无
功 能:T1中断函数;步进电机和直流电机驱动
返 回 值:无
--------------------------*/
void DC_SM_moto_run() interrupt 3 //定时器/计数器3中断
{
TH1 = (65536-T1_COUNT)/256;
TL1 = (65536-T1_COUNT)%256;
// 直流电机部分
count_PWM++;
if((0==stop_flag_DC)&&(0==suspend_flag_DC))
{
if(forward_flag_DC)
{ //电机正转
DC_Moto_B = 0;
if(count_PWM<val_PWM) //产生PWM
DC_Moto_A = 1;
else
DC_Moto_A = 0;
}
else
{ //电机反转
DC_Moto_A = 0;
if(count_PWM<val_PWM) //产生PWM
DC_Moto_B = 1;
else
DC_Moto_B = 0;
}
if(count_PWM>=PWM)
count_PWM = 0;
}
//步进电机部分
count_SM++; //节拍时间计时
if((count_SM>=beat_time_SM)&&(0==stop_flag_SM)&&(0==suspend_flag_SM))
{
count_SM = 0;
if(forward_flag_SM)
SM = forward_SM[beat_count_SM]; //输出正转节拍
else
SM = reversal_SM[beat_count_SM]; //输出反转节拍
beat_count_SM++;
if(beat_count_SM>=BEAT_MAX_SM) //节拍循环,从最后一个节拍转到第一个节拍
beat_count_SM = 0;
}
}
/********** 完毕 **********/

