学习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文件
所有文件已经打包好在此给出,欢迎参考。