目 录
1 引言 1
2 总体设计方案 2
2.1 系统设计原理 2
2.2 总体设计框图 2
3系统硬件模块的组成 3
3.1单片机控制模块 3
3.1.1 STC89C52主要结构 3
3.1.2 STC89C52功能特性描述 3
3.1.3 时钟电路 6
3.1.4复位电路 6
3.2 步进电机模块 7
3.2.1 步进电机简介 7
3.2.2步进电机的结构 8
3.2.3 28BYJ-48步进电机工作原理 8
3.3 ULN2003芯片概述与特点 9
3.4 红外线发射接收模块 10
3.4.1 红外线遥控的介绍 10
3.4.2红外通信基本原理 10
3.4.3 红外遥控发射系统 12
3.4.4 红外遥控接收系统 12
3.4.5 TL1838与单片机的接口 14
3.5 12864显示模块 14
3.5.1 12864液晶的特点 14
3.5.2 12864液晶的引脚说明 15
3.5.3 12864液晶的读写操作 17
3.5.4 12864液晶的控制指令 17
3.5.5 12864液晶接口电路 20
3.6 蜂鸣器模块 20
3.6.1 蜂鸣器介绍 20
3.6.2 蜂鸣器的接口电路 21
4 软件设计与调试 22
4.1 主程序流程图 22
4.2程序设计思路 23
4.2.1 遥控器的解码 23
4.2.2 步进电机的控制 23
4.2.3 显示屏的控制 24
4.2.4 蜂鸣器的控制 24
4.2.5 模块中的通信 24
5 编程与下载软件 25
5.1 Keil软件 25
5.2 STC-ISP下载软件 26
6 硬件电路制作 27
6.1 原理图的绘制 27
6.2 电路实现的基本步骤 27
7 结 论 30
谢 辞 31
参考文献 32
附 录 33
2 总体设计方案
2.1 系统设计原理
单片机STC89C52是整个系统关键部分,通过对遥控器上键盘的命令输入,经遥控器编码后发出红外信号,TL1838接收到信号并在单片机中解码。本文提出的采用38KHZ的遥控器为核心控制器件的步进电机控制系统, 根据输出信号的不同可以控制步进电机的转动状态,其中采用了28BYJ-48的步进电机,以ULN2003为驱动芯片,并通过单片机程序控制和处理, 从而实现了步进电机的状态控制及相应状态显示。
本系统采用STC89C52单片机为核心处理器,遥控器为命令输入模块,由ULN2003及28BYJ-48步进电机组成的转动模块、12864液晶的输出模块共同组成的基于单片机的步进电机控制系统。
2.2 总体设计框图
本设计采用STC89C52单片机为核心处理器,利用载波为38KHZ的遥控器为输入模块键盘输入模块,控制步进电机的正转和反转,并以三种不同的速度进行转动,并且转动状态在12864液晶上显示。系统构成如图2-1所示。
图2-1 系统框图
由系统框图可知,遥控器和TL1838为输入装置,步进电机、12864液晶、蜂鸣器为输出装置,单片机为中心处理装置,ULN2003为驱动器。
3系统硬件模块的组成
3.1单片机控制模块
主控电路中,以单片机为主体,通过分析遥控输入的指令,改变步进电机的运行参数和显示参数。它是系统的大脑。
单片机(Micro Controller,又称微控制器)是在一块硅片上集成了各种部件的微型机算计,这些部件包括中央处理器CPU、数据存贮器RAM、程序存贮器ROM、定时器/计数器和多种I/O接口电路[3]。
3.1.1 STC89C52主要结构
STC89C52是一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash 存储器。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。 具有以下标准功能: 8k字节Flash,512字节RAM, 32 位I/O 口线,内置4KB EEPROM,MAX810复位电路,三个16 位定时器/计数器,一个6向量2级中断结构,全双工串行口[4]。
3.1.2 STC89C52功能特性描述
STC89C52是一种低功耗、高性能CMOS8位微控制器,具有8K 在系统可编程Flash 存储器。使用宏晶公司高密度非易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、有效的解决方案。STC89C52具有以下标准功能:8k字节Flash、256字节RAM、32 位I/O 口线、看门狗定时器、2个数据指针、三个16 位定时器/计数器、一个6向量2级中断结构、全双工串行口、片内晶振及时钟电路。另外,STC89C52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下个中断或硬件复位为止[5]。STC89C52的引脚结构如图3-1所示。文章来源:https://www.toymoban.com/news/detail-440533.html
#include<reg51.h>
#include<stdlib.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define DataPort P1
sbit RS = P3^0; //寄存器选择输入
sbit RW = P3^1; //液晶读/写控制
sbit E = P3^3; //液晶使能控制
sbit PSB = P3^4;
sbit IR=P3^2;
sbit BEEP=P0^0;
uchar code mottor1[8]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};
uchar code mottor2[8]={0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01};
unsigned char a[4];
unsigned char b=0xF8;
unsigned char c=0xF4;
unsigned char d=0xF0;
unsigned char f=0xEC;
unsigned char g=0xE8;
unsigned char ga=0x1c;
unsigned char gb=0x17; //储存用户码、用户反码与键数据码、键数据反码
unsigned int LowTime,HighTime; //储存高、低电平的宽度
uint num;
uint num1=0;
uint num2=1;
uchar num3=0;
uchar num4=0;
uint i;
void DelayUs2x(unsigned char t)
{
while(--t);
}
void delay_1ms(uint x)
{
uint i,j;
for(j=0;j<x;j++)
for(i=0;i<110;i++);
}
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
void Delay(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
delay1ms();
}
void beep() //蜂鸣器响一声函数
{
unsigned char i;
for (i=0;i<100;i++)
{
delay1ms();
BEEP=!BEEP; //BEEP取反
}
BEEP=1; //关闭蜂鸣器
Delay(250); //延时
}
void Check_Busy()
{
RS=0;
RW=1;
E=1;
DataPort=0xff;
while((DataPort&0x80)==0x80);//忙则等待
E=0;
}
void Write_Cmd(unsigned char Cmd)
{
Check_Busy();
RS=0;
RW=0;
E=1;
DataPort=Cmd;
DelayUs2x(5);
E=0;
DelayUs2x(5);
}
void Write_Data(unsigned char Data)
{
Check_Busy();
RS=1;
RW=0;
E=1;
DataPort=Data;
DelayUs2x(5);
E=0;
DelayUs2x(5);
}
void LCD_init()
{
Delay(40); //大于40MS的延时程序
PSB=1; //设置为8BIT并口工作模式
Delay(1); //延时
//RES=0; //复位
Delay(1); //延时
//RES=1; //复位置高
Delay(10);
Write_Cmd(0x30); //选择基本指令集
DelayUs2x(50); //延时大于100us
Write_Cmd(0x30); //选择8bit数据流
DelayUs2x(20); //延时大于37us
Write_Cmd(0x0c); //开显示(无游标、不反白)
DelayUs2x(50); //延时大于100us
Write_Cmd(0x01); //清除显示,并且设定地址指针为00H
Delay(15); //延时大于10ms
Write_Cmd(0x06); //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位,光标从右向左加1位移动
DelayUs2x(50); //延时大于100us
}
void LCD_PutString(unsigned char x,unsigned char y,unsigned char code *s)
{
switch(y)
{
case 1: Write_Cmd(0x80+x);break;
case 2: Write_Cmd(0x90+x);break;
case 3: Write_Cmd(0x88+x);break;
case 4: Write_Cmd(0x98+x);break;
default:break;
}
while(*s>0)
{
Write_Data(*s);
s++;
DelayUs2x(50);
}
}
/*------------------------------------------------
清屏
------------------------------------------------*/
void LCD_clear()
{
Write_Cmd(0x01);
Delay(15);
}
bit DeCode(void)
{
unsigned char i,j;
unsigned char temp; //储存解码出的数据
for(i=0;i<4;i++) //连续读取4个用户码和键数据码
{
for(j=0;j<8;j++) //每个码有8位数字
{
temp=temp>>1; //temp中的各数据位右移一位,因为先读出的是高位数据
TH0=0; //定时器清0
TL0=0; //定时器清0
TR0=1; //开启定时器T0
while(IR==0) //如果是低电平就等待
; //低电平计时
TR0=0; //关闭定时器T0
LowTime=TH0*256+TL0; //保存低电平宽度
TH0=0; //定时器清0
TL0=0; //定时器清0
TR0=1; //开启定时器T0
while(IR==1) //如果是高电平就等待
;
TR0=0; //关闭定时器T0
HighTime=TH0*256+TL0; //保存高电平宽度
if((LowTime<370)||(LowTime>640))
return 0; //如果低电平长度不在合理范围,则认为出错,停止解码
if((HighTime>420)&&(HighTime<620)) //如果高电平时间在560微秒左右,即计数560/1.085=516次
temp=temp&0x7f; //(520-100=420, 520+100=620),则该位是0
if((HighTime>1300)&&(HighTime<1800)) //如果高电平时间在1680微秒左右,即计数1680/1.085=1548次
temp=temp|0x80; //(1550-250=1300,1550+250=1800),则该位是1
}
a[i]=temp; //将解码出的字节值储存在a[i]
}
if(a[2]=~a[3]) //验证键数据码和其反码是否相等,一般情况下不必验证用户码
return 1; //解码正确,返回1
}
void init()
{
EX0=1; //开外中断0
ET0=1; //定时器T0中断允许
IT0=1; //外中断的下降沿触发
TR0=0; //定时器T0关闭
TMOD=0x11;
TH1=(65536-2500)/256;
TL1=(65536-2500)%256;
EA=1;ET1=0; TR1=1;
}
void xianshi()
{
LCD_PutString(0,1,"步进电机控制系统");
LCD_PutString(0,4," 方向:");
if(num3==1) LCD_PutString(4,4,"RIGHT");
else LCD_PutString(4,4,"LEFT ");
if(num2==0)
{LCD_PutString(0,2," 速度:15 t/m");
LCD_PutString(0,3," 速度ONE ");
}
else if(num2==2)
{
LCD_PutString(0,2," 速度: 4t/m ");
LCD_PutString(0,3," 速度TWO ");
}
else
{
LCD_PutString(0,2," 速度: 2t/m");
LCD_PutString(0,3," 速度THREE ");
}
}
void main()
{
init();
LCD_init();
PT1=1;
ET1=1;
xianshi();
TR1=1;
while(1);
}
void Int0(void) interrupt 0
{ ET0=0;
EX0=0; //关闭外中断0,不再接收二次红外信号的中断,只解码当前红外信号
TH0=0; //定时器T0的高8位清0
TL0=0; //定时器T0的低8位清0
TR0=1; //开启定时器T0
while(IR==0); //如果是低电平就等待,给引导码低电平计时
TR0=0; //关闭定时器T0
LowTime=TH0*256+TL0; //保存低电平时间
TH0=0; //定时器T0的高8位清0
TL0=0; //定时器T0的低8位清0
TR0=1; //开启定时器T0
while(IR==1); //如果是高电平就等待,给引导码高电平计时
TR0=0; //关闭定时器T0
HighTime=TH0*256+TL0; //保存引导码的高电平长度
if((LowTime>7800)&&(LowTime<8800)&&(HighTime>3600)&&(HighTime<4700))
{
//如果是引导码,就开始解码,否则放弃,引导码的低电平计时
//次数=9000us/1.085=8294, 判断区间:8300-500=7800,8300+500=8800.
if(DeCode()==1) // 执行遥控解码功能
{ ET1=1;
PX1=1;
if(!(a[0]^ga))
LCD_PutString(7,3,"A ");
else if(!(a[0]^gb))
LCD_PutString(7,3,"B ");
else LCD_PutString(7,3,"NO");
if(!(a[2]^b))
{
num2=0;
beep();
}
else if(!(a[2]^c))
{
num2=2;
beep();
}
else if(!(a[2]^d))
{
num2=6;
beep();
}
else if(!(a[2]^f))
{ if(num3==0)num3=1;
else num3=0;
beep();
}
else if(!(a[2]^g))
{
TR1=~TR1;
beep();
}
xianshi();
}
}
EX0=1; //开启外中断EX0
}
void T1_tim() interrupt 3
{
TH1=(65536-1000)/256;
TL1=(65536-1000)%256;
// keysc();
if(i>7)i=0;
if(num1>num2)
{ num1=0;
if(num3==0)
P2=mottor1[i++];
else P2=mottor2[i++];
}
num1++;
}
文章来源地址https://www.toymoban.com/news/detail-440533.html
到了这里,关于基于单片机的步进电机控制系统设计与实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!