目录

  • 1 项目1  电子琴设计
    • 1.1 课程概述
    • 1.2 蜂鸣器发声
    • 1.3 不同音阶发声和控制
    • 1.4 多功能电子琴
      • 1.4.1 播放一首乐曲的程序编写与仿真
      • 1.4.2 具有多功能电子琴设计与实施
      • 1.4.3 具有多功能电子琴程序编写和仿真
      • 1.4.4 具有多功能电子琴设计--直播程序讲解
  • 2 项目2  LED流水灯设计
    • 2.1 左右依次循环点亮的流水灯设计
    • 2.2 多种花样点亮的流水灯设计
    • 2.3 可调节型多功能亮灯的流水灯设计
  • 3 项目3 直流电机控制
    • 3.1 直流电机的双向转动设计
    • 3.2 转速可调的直流电机转动设计
    • 3.3 多功能直流电机双向转动设计
  • 4 项目4  步进电机控制
    • 4.1 步进电机的双向转动设计
    • 4.2 转速可调的步进电机转动设计
    • 4.3 多功能步进电机双向转动设计
  • 5 项目5 直流电机、步进电机、舵机综合设计
    • 5.1 综合设计
  • 6 项目6 广告灯设计
    • 6.1 在8*8点阵上显示一个字符
    • 6.2 在16*16点阵上显示一个汉字
    • 6.3 在16*16点阵上显示滚动汉字
  • 7 项目7 液晶显示设计
    • 7.1 在1602液晶屏上显示字符
    • 7.2 在1602液晶屏上显示自定义符号和图形
  • 8 电子万年历的制作
    • 8.1 简单万年历的制作
    • 8.2 复杂万年历的制作
    • 8.3 创新万年历的制作
  • 9 作品考核--制作18B20温控风扇
    • 9.1 任务书(拟实现的主要功能)
      • 9.1.1 单片机相关资料
      • 9.1.2 18B20相关资料
      • 9.1.3 PWM脉宽调制资料
      • 9.1.4 74H573介绍
      • 9.1.5 数码管介绍
    • 9.2 原理图、PCB图、焊接图、仿真图
    • 9.3 程序
综合设计

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;

}

}

/********** 完毕 **********/