基于51单片机的知识总结,使用protues和keil共同学习。
我使用的是protues7.8 和 keil4,需要软件的联系我。
源码及protues仿真:https://download.youkuaiyun.com/download/sinat_33734313/11839391
LCD1602+步进电机
protues电路仿真
仿真元器件
LCD:LM016L
ULN2003A
步进电机:MOTOR-STEPPER
仿真电路截图
硬件说明
1.LCD
1.1 引脚定义
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 地址和屏幕对应关系
2.步进电机
程序
/*-------------------------------------------
FileName:main.c
Function: MCU控制步进电机
Description:控制步进电机的正转、反转、加速、减速;
LCD1602实时显示步进电机状态;
---------------------------------------------
Author: Ethan Chen
Date: 2019-10-9
-------------------------------------------*/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
#include "lcd.h"
#include<intrins.h> //因为要用到左右移函数,所以加入这个头文件
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]);
}
}