51_LCD1602+步进电机

基于51单片机的知识总结,使用protues和keil共同学习。
我使用的是protues7.8 和 keil4,需要软件的联系我。
源码及protues仿真:https://download.csdn.net/download/sinat_33734313/11839391

LCD1602+步进电机

protues电路仿真

仿真元器件

LCD:LM016L
ULN2003A
步进电机:MOTOR-STEPPER

仿真电路截图

51_LCD1602+步进电机_第1张图片
51_LCD1602+步进电机_第2张图片

硬件说明

1.LCD
1.1 引脚定义
51_LCD1602+步进电机_第3张图片
1.2 基本操作时序:
读状态 输入:RS=L,RW=H,E=H 输出:DB0~DB7=状态字
写指令 输入:RS=L,RW=L,E=下降沿脉冲,DB0~DB7=指令码 输出:无
读数据 输入:RS=H,RW=H,E=H 输出:DB0~DB7=数据
写数据 输入:RS=H,RW=L,E=下降沿脉冲,DB0~DB7=数据 输出:无

1.3 关键指令:
清屏指令
在这里插入图片描述
功能:<1> 清除液晶显示器,即将 DDRAM 的内容全部填入"空白"的 ASCII
码 20H;
<2> 光标归位,即将光标撤回液晶显示屏的左上方;
<3> 将地址计数器(AC)的值设为 0。

进入模式设置指令
在这里插入图片描述
功能 : 设定每次定入 1 位数据后光标的移位方向 , 并且设定每次写入的一个字符是否移动。参数设定的情况如下所示:

位名 设置
I/D 0=写入新数据后光标左移,1=写入新数据后光标右移
S 0=写入新数据后显示屏不移动,1=写入新数据后显示屏整体右移 1 个字符

显示开关控制指令
在这里插入图片描述
功能:控制显示器开/关、光标显示/关闭以及光标是否闪烁。参数设定的情
况如下:

位名 设置
D 0=显示功能关,1=显示功能开
C 0=无光标,1=有光标
B 0=光标闪烁,1=光标不闪烁

功能设定指令
在这里插入图片描述
功能:设定数据总线位数、显示的行数及字型。参数设定的情况如下:

位名 设置
DL 0=数据总线为 4 位 ,1=数据总线为 8 位
N 0=显示 1 行,1=显示 2 行
F 0=5×7 点阵/每字符,1=5×10 点阵/每字符

1.4 地址和屏幕对应关系
51_LCD1602+步进电机_第4张图片
2.步进电机

程序

/*-------------------------------------------
FileName:main.c
Function: MCU控制步进电机
Description:控制步进电机的正转、反转、加速、减速;
LCD1602实时显示步进电机状态;
---------------------------------------------
Author: Ethan Chen
Date: 2019-10-9
-------------------------------------------*/

#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include "lcd.h"
#include		//因为要用到左右移函数,所以加入这个头文件

typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;

/*******************************************************************************
* 函 数 名         : delay
* 函数功能		   : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(unsigned short i)
{
	while(i--);	
}

void KeyScan(void)
{
	if(!SpeedUp)
	{
		delay(1000);
		if(!SpeedUp)
		{
			if(speed < 3)
			{
				speed++;
			}
			else
			{
				speed = 3;
			}
			while(!SpeedUp);
		}
	}
	if(!SlowDown)
	{
		delay(1000);
		if(!SlowDown)
		{
			if(speed != 0)
			{
				speed--;
			}
			else
			{
				speed = 0;
			}
			while(!SlowDown);
		}
	}
	if(!ChangeDirection)
	{
		delay(1000);
		if(!ChangeDirection)
		{
			while(!ChangeDirection);
			direcFlag = ~direcFlag;
		}
	}
}

void execute(void)
{
	uchar i, j;
	startPos = (direcFlag == 0) ? 4 : 0; 
	for(i = startPos; i < (startPos + 4); i++)
	{
		P1 = pulseTable0[i];
		for(j = 0; j < (speed + 1) * Factor; j++)
		{
			delay(10);
		} 
	}
}
/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{
	LcdInit();
	displayInit();
	while(1)
	{
		KeyScan();
		display(0, direcFlag);
		display(1, speed);
		P1 = 0x00;
		execute();
		P1 = 0x00;
	}
}

/*-----------------------------
FileName:lcd.c
Function: LCD1602控制
Author: Ethan Chen
Date: 2019-10-9
------------------------------*/
#include "lcd.h"
#include "string.h"
/*******************************************************************************
* 函 数 名         : Lcd1602_Delay1ms
* 函数功能		   : 延时函数,延时1ms
* 输    入         : c
* 输    出         : 无
* 说    名         : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/

void Lcd1602_Delay1ms(uint c)   //误差 0us
{
    uchar a,b;
	for (; c>0; c--)
	{
		 for (b=199;b>0;b--)
		 {
		  	for(a=1;a>0;a--);
		 }      
	}
    	
}

/*******************************************************************************
* 函 数 名         : LcdWriteCom
* 函数功能		   : 向LCD写入一个字节的命令
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
void LcdWriteCom(uchar com)	  //写入命令
{
	LCD1602_E = 0;     //使能
	LCD1602_RS = 0;	   //选择发送命令
	LCD1602_RW = 0;	   //选择写入
	
	LCD1602_DATAPINS = com;     //放入命令
	Lcd1602_Delay1ms(1);		//等待数据稳定

	LCD1602_E = 1;	          //写入时序
	Lcd1602_Delay1ms(5);	  //保持时间
	LCD1602_E = 0;
}
/*******************************************************************************
* 函 数 名         : LcdWriteData
* 函数功能		   : 向LCD写入一个字节的数据
* 输    入         : dat
* 输    出         : 无
*******************************************************************************/		   
void LcdWriteData(uchar dat)			//写入数据
{
	LCD1602_E = 0;	//使能清零
	LCD1602_RS = 1;	//选择输入数据
	LCD1602_RW = 0;	//选择写入

	LCD1602_DATAPINS = dat; //写入数据
	Lcd1602_Delay1ms(1);

	LCD1602_E = 1;   //写入时序
	Lcd1602_Delay1ms(5);   //保持时间
	LCD1602_E = 0;
}
/*******************************************************************************
* 函 数 名       : LcdInit()
* 函数功能		 : 初始化LCD屏
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/		   
void LcdInit()						  //LCD初始化子程序
{
	LCD1602_E = 0;
 	LcdWriteCom(0x38);  //开显示
	LcdWriteCom(0x0c);  //开显示不显示光标
	LcdWriteCom(0x06);  //写一个指针加1
	LcdWriteCom(0x01);  //清屏
	LcdWriteCom(0x80);  //设置数据指针起点
}

void displayInit(void)
{
	uchar i;
	LcdWriteCom(0x80);
	for(i = 0; i < strlen(table0); i++)
	{
		LcdWriteData(table0[i]);
		delay(5);
	}
	
	LcdWriteCom(0x80 + 0x40);
	for(i = 0; i < strlen(table1); i++){
		LcdWriteData(table1[i]);
		delay(5);
	}
}
void display(uchar oper, uchar dat)
{
	if(oper == 0)
	{
		if(dat == 0)
		{
			LcdWriteCom(0x80 + strlen(table0));
			LcdWriteData(table3[0]);
		}
		else if(dat == 1)
		{
			LcdWriteCom(0x80 + strlen(table0));
			LcdWriteData(table3[1]);
		}
	}
	if(oper == 1)
	{
		LcdWriteCom(0x80 + 0x40 + strlen(table1));
		LcdWriteData(table2[dat]);
	}
}

你可能感兴趣的:(#,51仿真+实验源码)