实验8 基于51单片机的直流电动机转速控制系统设计

一、实验项目:

  基于51单片机的直流电动机转速控制系统设计

二、实验目的:

本系统设计的目的是通过实践操作掌握Proteus硬件仿真软件的使用技巧和Keil uvision程序开发的使用技巧,理解单片机应用系统软硬件开发的过程,掌握基本的I/0控制方法。
基本要求: 选择一款直流电动机,利用51单片机控制该直流电动机的转速,设置五个按键,分别能够实现对直流电动机的加速、减速、正转、反转、停止的操作,给出上述功能系统的硬件设计电路和软件设计程序。

三、实验原理:

在本实验中,我们使用AT89C51单片机来搭载电机驱动模块,按键BUTTON来进行控制的操作。其中,通过L298电机驱动模块来实现对直流电机MOTOR-DC的加速、减速、正转、反转、停止的操作。
1、直流电机:输出或输入为直流电能得旋转电机,能实现直流电能和机械能互相转换的电机。当它作电动机运行时是直流电动机,将电能转换为机械能;作发电机运行时是直流发电机,将机械能转换为电能。
2、直流电动机的方向控制:直流电机只有正负极,只需交换正负极就可以调节正反转。
直流电动机的转速控制:在负载变化不大的时候,加在直流电动机两端的电压大小与其速度近似成正比。
3、对于直流电动机的具体的转速的控制,在这里利用PWM技术,通过调节高电平在信号传输的占空比的大小来实现电压大小的控制,并通过对电压的大小的调控,转化为直流电动机的转速控制。
占空比:D为PWM信号的占空比:D=t1/T(即高电平持续时间比整个周期的值),则电动机的电枢组两端电压平均值U为:U = (t1/T)Us=DUs。

四、硬件电路图:

在这里插入图片描述

在实验结果中,利用Proteus软件在进行仿真时,由于只能显示静态的变化,因此给出具体的现象显示。
1.在实现正转的情况下,可以通过调节加速和减速按键来实现直流电机的速度的变化,并且可以看到直流电机的电压的占空比的值为负值,实现正转。在实现正转的时候,先按下停止的按键,可以发现直流电机的转速明显下降,实现了转速的调控。
2.在实现反转的情况下,可以通过调节加速和减速按键来实现直流电机的速度的变化,并且可以看到直流电机的电压的占空比的值为正值,实现反转。在实现反转的时候,先按下停止的按键,可以发现直流电机的转速明显下降,实现了转速的调控。
3.基于上面的电动机的正转、反转,通过停止按键,可以实现电动机的停止。

五、C语言代码:

#include <reg51.h> // 包含 8051 系列单片机头文件
#define uint  unsigned int  // 定义 uint 为无符号整数类型 unsigned int
#define uchar unsigned char // 定义 uchar 为无符号字符类型 unsigned char
sbit IN1=P1^0;  // 定义 P1.0 管脚为 IN1
sbit IN2=P1^1;	// 定义 P1.1 管脚为 IN2
sbit ENA=P1^2; 	// 定义 P1.2 管脚为 ENA 
sbit k0=P2^0; //正转,并对每一个管脚进行命名
sbit k1=P2^1; //反转
sbit k2=P2^2; //加速
sbit k3=P2^3; //减速
sbit k4=P2^4; //停止
// Counter 用于计数器计数,Compare 用于控制电机的占空比
uchar Counter=0,Compare=0;
//延时函数,传入参数 n 表示延时的时间,使用 for 循环进行延时。
void delay(uint n)
{
	uint i=0,j=0;
	for(i=0;i<n;i++)
	{
		for(j=0;j<120;j++);
	}
}
//定时器初始化函数,设置定时器模式为模式1,计时初值为 0x9CFF,开启定时器中断,开启总中断,启动定时器0 
void Timer0_init()   //100us
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x9C;		    //设置定时初值
	TH0 = 0xFF;		    //设置定时初值
	ET0=1;	   //使能定时器0中断
	EA=1;	//开启总中断
	TR0=1;	   //启动定时器0
}
void main()
{ ENA=0;
	IN1=0;
	IN2=0;    //一开始让电机停止
	Timer0_init();	 //初始化定时器
	Compare=50;	  //初始占空比为 50%
	while(1)
	{		if(k0==0)//正转
		{
			delay(100);	 //延时 100 毫秒
			while(!k0);	 //等待按键释放
              ENA=1;		//使能电机
			IN1=1;	    //IN1 管脚为高电平
			IN2=0;		 //IN2 管脚为低电平
		}
	  else if(k1==0)//反转
		{
			delay(100);
			while(!k1);
              ENA=1;
			IN1=0;	 //IN1 管脚为低电平
			IN2=1;	  //IN2 管脚为高电平
		}
		else if(k2==0)//加速
		{
			delay(100);
			while(!k2);
			Compare=Compare+20;	 //占空比加 20%
		}
		else if(k3==0)//减速
		{
			delay(100);
			while(!k3);
			Compare=Compare-20;	 //占空比减 20%
		}
		if(k4==0)//停止
		{
			delay(100);
			while(!k4);
			ENA=0;	 //关闭电机使能
			TR0=0;	 //关闭定时器
			IN1=0;	 //IN1管脚为低电平
			IN2=0;	 //IN2管脚为低电平							
		}			 
	}
} 
//定时器中断函数,每 100 微秒触发一次中断,更新计数器的值,根据计数器和占空比的大小关系控制 IN1 管脚的电平状态。当计数器小于占空比时,IN1 管脚为高电平,反之为低电平
void Timer0() interrupt 1
{
	TL0 = 0x9C;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	Counter++;	   //计数器自增
	Counter%=100;  //计数器取模,最大值为 99
	if(Counter<Compare)  //如果小于占空比,IN1 管脚为高电平
	{
		IN1=1;
	}
	else
	{
		IN1=0;
	}
}

六、汇编语言代码:

PWMH DATA 30H    ; 声明变量 PWMH,高电平脉冲的个数 ,存储在地址 30H
PWM DATA 31H     ; 声明变量 PWM周期,存储在地址 31H
COUNTER DATA 32H ; 声明变量 COUNTER
TEMP DATA 33H    ; 声明变量 TEMP
ORG 0000H        
AJMP MAIN        ; 跳转到 MAIN 标签
ORG 000BH        
AJMP INTT0       ; 跳转到 INTT0 标签
ORG 0100H        ; 设置程序代码的起始地址为 0100H
MAIN:            
  MOV SP,#60H    ; 设置堆栈指针 SP 的初始值为 60H
  MOV PWMH,#02H  ; 将变量 PWMH 的值设置为 02H
  MOV COUNTER,#01H ; 将变量 COUNTER 的值设置为 01H
  MOV PWM,#15H   ; 将变量 PWM 的值设置为 15H
  MOV TMOD,#02H  ; 将计时器模式寄存器 TMOD 的值设置为 02H,表示定时器 0 工作在方式 28 位自动重载)下
  MOV TL0,#38H   ; 将计时器 0 的低 8 位初值设置为 38H,表示计时器 0 的周期为 1ms
  MOV TH0,#38H   ; 将计时器 0 的高 8 位初值设置为 38H
  SETB ET0       ; 使能定时器 0 中断
  SETB EA        ; 全局使能中断
  SETB TR0       ; 启动定时器 0
KSCAN:             ; 标签 KSCAN,用于轮询按键状态
  JNB P2.2,K1CHECK ; 如果按键 K1 没有按下,则跳转到 K1CHECK 
  JNB P2.3,K2CHECK ; 如果按键 K2 没有按下,则跳转到 K2CHECK 
  JNB P2.1,K3CHECK ; 如果按键 K3 没有按下,则跳转到 K3CHECK 
  JNB P2.0,K4CHECK ; 如果按键 K4 没有按下,则跳转到 K4CHECK 
  JNB P2.4,K0CHECK ; 如果按键 K0 没有按下,则跳转到 K0CHECK 
  SJMP KSCAN      ; 如果所有按键都没有按下,则继续轮询
K3CHECK:         ; 标签 K3CHECK,用于检测按键 K3 是否按下
  JB P2.1,K3HANDLE ; 如果按键 K3 没有按下,则跳转到 K3HANDLE 
  SJMP K3CHECK    ; 如果按键 K3 没有按下,则继续检测
K3HANDLE:        ; 标签 K3HANDLE,用于处理按键 K3 的按下
  MOV P1, #01H    ; 将 P1 端口的值设置为 01H,点亮 LED1
  SJMP KSCAN      ; 处理完成后,继续轮询
K4CHECK:         ; 标签 K4CHECK,用于检测按键 K4 是否按下
  JB P2.0,K4HANDLE ; 如果按键 K4 没有按下,则跳转到 K4HANDLE 
  SJMP K4CHECK    ; 如果按键 K4 没有按下,则继续检测
K4HANDLE:        ; 标签 K4HANDLE,用于处理按键 K4 的按下
  MOV P1, #02H    ; 将 P1 端口的值设置为 02H,点亮 LED2
  SJMP KSCAN      ; 处理完成后,继续轮询
K0CHECK:         ; 标签 K0CHECK,用于检测按键 K0 是否按下
  JB P2.4,K0HANDLE ; 如果按键 K0 没有按下,则跳转到 K0HANDLE
  SJMP K0CHECK    ; 如果按键 K0 没有按下,则继续检测
K0HANDLE:        ; 标签 K0HANDLE,用于处理按键 K0 的按下
  MOV P1, #03H    ; 将 P1 端口的值设置为 03H,点亮 LED1 和 LED2
  SJMP KSCAN      ; 处理完成后,继续轮询
K1CHECK:         ; 标签 K1CHECK,用于检测按键 K1 是否按下
  JB P2.2,K1HANDLE ; 如果按键 K1 没有按下,则跳转到 K1HANDLE 
  SJMP K1CHECK    ; 如果按键 K1 没有按下,则继续检测
K1HANDLE:        ; 标签 K1HANDLE,用于处理按键 K1 的按下
  MOV A,PWMH      ; 将变量 PWMH 的值加载到累加器 A 中
  CJNE A,PWM,K1H0 ; 如果累加器 A 的值等于变量 PWM 的值,则跳转到 K1H0 
  SJMP KSCAN      ; 如果累加器 A 的值不等于变量 PWM 的值,则继续检测
K1H0:           ; 标签 K1H0,用于处理按键 K1 
  MOV A,PWMH      ; 将变量 PWMH 的值加载到累加器 A 中
  INC A           ; 将累加器 A 的值加 1
  CJNE A,PWM,K1H1 ; 如果累加器 A 的值等于变量 PWM 的值,则跳转到 K1H1 
  CLR TR0         ; 停止定时器 0
  SETB P2.7       ; 设置 P2.7 为高电平,关闭 PWM 输出
  SJMP K1H2       ; 跳转到 K1H2 标签
K1H1:           ; 标签 K1H1,用于处理按键 K1 
  CJNE A,#02H,K1H2 ; 如果累加器 A 的值不等于 02H,则跳转到 K1H2 
  SETB TR0         ; 启动定时器 0
K1H2:           ; 标签 K1H2,用于更新 PWM 输出的占空比
  INC PWMH         ; 将变量 PWMH 的值加 1
  SJMP KSCAN      ; 处理完成后,继续轮询
K2CHECK:         ; 标签 K2CHECK,用于检测按键 K2 是否按下
  JB P2.3,K2HANDLE ; 如果按键 K2 没有按下,则跳转到 K2HANDLE 
  SJMP K2CHECK    ; 如果按键 K2 没有按下,则继续检测
K2HANDLE:        ; 标签 K2HANDLE,用于处理按键 K2 的按下
  MOV A,PWMH      ; 将变量 PWMH 的值加载到累加器 A 中
  CJNE A,#01H,K2H0 ; 如果累加器 A 的值不等于 01H,则跳转到 K2H0 
  SJMP KSCAN      ; 如果累加器 A 的值等于 01H,则继续检测
K2H0:           ; 标签 K2H0,用于处理按键 K2 
  MOV A,PWMH      ; 将变量 PWMH 的值加载到累加器 A 中
  MOV TEMP,PWM    ; 将变量 PWM 的值加载到变量 TEMP 中
  DEC A           ; 将累加器 A 的值减 1
  CJNE A,#00H,K2H1 ; 如果累加器 A 的值不等于 00H,则跳转到 K2H1 
  MOV PWM,A ; 将累加器 A 的值存储到变量 PWM 中
  MOV PWMH,#01H ; 将变量 PWMH 的值设置为 01H
  CLR TR0 ; 停止定时器 0
  SETB P2.7 ; 设置 P2.7 为高电平,关闭 PWM 输出
  MOV TL0,#38H ; 将计时器 0 的低 8 位初值设置为 38H,表示计时器 0 的周期为 1ms
  MOV TH0,#38H ; 将计时器 0 的高 8 位初值设置为 38H
  SJMP K2H2 ; 跳转到 K2H2 标签
K2H1: ; 标签 K2H1,用于处理按键 K2 
  MOV PWM,TEMP ; 将变量 TEMP 的值存储到变量 PWM 中
  MOV PWMH,#00H ; 将变量 PWMH 的值设置为 00H
  K2H2: ; 标签 K2H2,用于更新 PWM 输出的占空比
  SJMP KSCAN ; 处理完成后,继续轮询
INTT0: ; 标签 INTT0,用于处理定时器 0 中断
  CPL P2.7 ; 反转 P2.7 的值,实现 PWM 输出的占空比控制
  MOV TH0,#38H ; 重新加载计时器 0 的初值,以实现定时 1ms 的周期
  INC COUNTER ; 将变量 COUNTER 的值加 1
  CJNE COUNTER,#100,KSCAN ; 如果变量 COUNTER 的值不等于 100,则跳转到 KSCAN ,继续轮询按键状态
  MOV COUNTER,#01H ; 如果变量 COUNTER 的值等于 100,则将其重置为 01H,并继续查询按键状态
  RETI ; 返回中断结束
  END ; 程序结束

评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jerry独爱电子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值