使用单片机驱动步进电机及PWM输出并行

  学习51单片机是一个复杂的过程,但是如果能有些示例借鉴示范通常会好很多。在本科期间,笔者曾经做过一个步进电机的MCS-51系列MCU程序控制,步进电机的正反转很容易实现,而对于电机速度控制,最初的思想是利用PWM方波来调控,然而在查阅资料后,发现步进电机速度控制需要使用脉冲频率或者相序转换周期来实现,因此程序尚待完善,在此挂出,如果大家有什么宝贵意见欢迎在评论区提出!

下面首先介绍keil的基础操作

(1)建立文件夹,命名随你喜好而定

(2)运行Keil C51μVision

(3)建立工程(Project)文件:ALT+P→NewμVision Project→创建路径指向MCUEX1_1文件夹(工程文件建议与文件夹同名,或者在菜单栏上也可以选择新建工程。)

(4)选择单片机类型:按照适应你项目版本的芯片来选择

(5)建立C源文件:ALT+F→New→保存至MCUEX1_1文件夹,后缀必须为“.c”(或者右键选择add files to group)

(6)将C源文件添加到源组:右键选择Source Group 1 →Add Files to Group’Source Group 1’

(7)编写C程序并编译,在树状图头文件右击在“options”中选择output点击生成“.hex”文件。只有hex文件才能允许在Proteus中被执行。

说明:由于笔者使用keil5版本,可能会有同学存在版本不兼容的状况,遇到问题,请善用搜索引擎,而且温馨提醒,keil编译器支持中文,但是汉化可能会让软件丢失一部分功能!

Proteus的软件操作颇为简单,在此不过多赘述。

#include <reg51.h>//主函数
#include "key.h"//调用定义的按键函数
    
#define pole_AB1 {AA=1;BB=1;CC=0;DD=0;}	//AB相通电,其他相断电
#define pole_BC1 {AA=0;BB=1;CC=1;DD=0;}	//BC相通电,其他相断电
#define pole_CD1 {AA=0;BB=0;CC=1;DD=1;}	//CD相通电,其他相断电
#define pole_DA1 {AA=1;BB=0;CC=0;DD=1;}	//D相通电,其他相断电
#define pole_A1 {AA=1;BB=0;CC=0;DD=0;}	//A相通电,其他相断电
#define pole_B1 {AA=0;BB=1;CC=0;DD=0;}	//B相通电,其他相断电
#define pole_C1 {AA=0;BB=0;CC=1;DD=0;}	//C相通电,其他相断电
#define pole_D1 {AA=0;BB=0;CC=0;DD=1;}	//D相通电,其他相断电
#define pole_OFF {AA=0;BB=0;CC=0;DD=0;}//全部断电


unsigned char Rev_Sign=0;//电机正反转标志 0-正转 1-反转
unsigned char KeyNumber;//键值存储变量
unsigned char Start_Stop = 0;//电机启动标志
unsigned char Val;//pwm函数变量


unsigned char Key_set();//按键函数
void run_stp_m();//电机转动函数
void delay1();//pwm函数延时
void delay();//电机拖动延时

/*步进电机连接端口*/
sbit AA=P0^0;//步进电机A相接p0.0口
sbit BB=P0^1;//以下递推。。
sbit CC=P0^2;//
sbit DD=P0^3;//
/*AD转换接口*/
sbit CLK=P3^0;//A|D模数转换定义端口
sbit ST=P3^1;//启动信号
sbit EOC=P3^2;//转换结束信号
sbit OE=P3^3;//输出使能
sbit PWM=P3^4;
/*led连接端口*/
sbit LED1=P0^4;
sbit LED2=P0^5;

void delay(){
    unsigned int i=8912;
    while (i--);
}

void delay1(unsigned int ms)
{
    unsigned char i;
    while(ms--)for(i=0;i<120;i++);
}

void main()//主函数
{
    delay1(1000);//上电延时
    TMOD &= 0x0F;
	TMOD |= 0x01;					//定时器0工作于模式1,16位定时器
	TL0 = 0x18;//注入初值
	TH0 = 0xFC;						//定时器0,定时用于步进电机转速控制  1ms
	ET0 = 1;						//允许T0中断
	TR0 = 1;						//打开定时器0
	EA = 1;//打开总中断
    while(1){
     KeyNumber=key();//赋值语句
     Key_set();//寻态函数
       if(Start_Stop == 1){        //判断是否启动
		    run_stp_m();
               ST=0;ST=1;ST=0;//启动A|D转换
               while(!EOC);//等待转换完成
               OE=1;
               Val=P1;//读转换值
               OE=0;
              if(Val==0)//pwm占空比为0%输出
              {
                PWM=0;
               delay1(0xff);
               continue;
              }
             if(Val==0xff)//PWM占空比100%输出
             {
               PWM=1;
              delay1(0xff);
              continue;
             }   
              PWM=1;//PWM输出,占空比0%~100%
              delay1(Val);
              PWM=0;
             delay1(0xff-Val);
       }
    }
}

void timer0() interrupt 1//中断函数(产生pwm波形)
{
        CLK=~CLK;
}

unsigned char Key_set()//寻态函数
{
	switch (KeyNumber)
	{
		case 1:  
              Start_Stop = 1;
               Rev_Sign=0;	//启动!正转!
               KeyNumber = 0;
						break;							
		case 2:					
			  Start_Stop = 1;//启动反转
               Rev_Sign=1;	
			   KeyNumber = 0;
						break;
        case 3:                 
              Start_Stop = 0;	
               KeyNumber = 0;
						break;		
        default:;
    }
    return Rev_Sign;
}

//-----------电机转序----------!//
void run_stp_m()
{
		static unsigned char const_tmp = 0;			//循环变量
	if(Rev_Sign == 0)//rev_sign为正反转标志
	{LED1=~LED1;
		switch(const_tmp)			//正转  A-AB-B-BC-C-CD-D-DA
		{
			case 0:pole_A1;		const_tmp++;delay();break;
			case 1:pole_AB1;	const_tmp++;delay();break;
			case 2:pole_B1;		const_tmp++;delay();break;
			case 3:pole_BC1;	const_tmp++;delay();break;
			case 4:pole_C1;		const_tmp++;delay();break;
			case 5:pole_CD1;	const_tmp++;delay();break;
			case 6:pole_D1;		const_tmp++;delay();break;
			case 7:pole_DA1;	const_tmp=0;delay();break;
			default:break;
		}		
	}else 
	{LED2=~LED2;
		switch(const_tmp)			//反转 DA-D-CD-C-BC-B-AB-A 
		{
			case 7:pole_A1;		const_tmp=0;delay();break;
			case 6:pole_AB1;	const_tmp++;delay();break;
			case 5:pole_B1;		const_tmp++;delay();break;
			case 4:pole_BC1;	const_tmp++;delay();break;
			case 3:pole_C1;		const_tmp++;delay();break;
			case 2:pole_CD1;	const_tmp++;delay();break;
			case 1:pole_D1;		const_tmp++;delay();break;
			case 0:pole_DA1;	const_tmp++;delay();break;
			default:break;
		}	           
	}
	
}
//-----------电机转序----------i//

按键函数

#include <reg51.h>//按键函数
#include "Delay.h"

sbit KEY_1 = P2^0;//按键1端口
sbit KEY_2 = P2^1;按键2端口
sbit KEY_3 = P2^2;按键3端口

unsigned char key() {
    unsigned char KeyNumber = 0;  // 定义变量KeyNumber并初始化为0
    if(KEY_1==0){Delay(20);while(KEY_1==0);Delay(20);KeyNumber = 1;}
	if(KEY_2==0){Delay(20);while(KEY_2==0);Delay(20);KeyNumber = 2;}
	if(KEY_3==0){Delay(20);while(KEY_3==0);Delay(20);KeyNumber = 3;}
    return  KeyNumber;
    }      

延时函数

 #include <Delay.h> 
void Delay(unsigned int t)		//延时函数
{
	
	unsigned char i, j;
	while(t){
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		t--;
	}
 
	
}

代码也是笔者研究转化而来,大佬如能有优化,深感钦佩,再次说明由于我的key函数与我的delay函数并不在一个C文件内,因此在其他C文件里编译和调用时就需要自己创建与调用一个.h文件

所有文件已经打包好在此给出,欢迎参考。

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值