51_交通灯

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

LCD1602+交通灯

protues电路仿真

仿真元器件

LCD:LM016L
LED

仿真电路截图

在这里插入图片描述
在这里插入图片描述

硬件说明

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/D0=写入新数据后光标左移,1=写入新数据后光标右移
S0=写入新数据后显示屏不移动,1=写入新数据后显示屏整体右移 1 个字符

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

位名设置
D0=显示功能关,1=显示功能开
C0=无光标,1=有光标
B0=光标闪烁,1=光标不闪烁

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

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

1.4 地址和屏幕对应关系
在这里插入图片描述

程序

/*-------------------------------------------
FileName:main.c
Function: MCU控制红绿灯
Description:模拟路口
LCD1602实时显示步进电机状态;
---------------------------------------------
Author: Ethan Chen
Date: 2019-10-10
-------------------------------------------*/

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

#define FOSC	12000000L

#define T1MS	(65535-FOSC/12/1000)

sbit X_Green=P1^0;
sbit X_Yellow=P1^1;
sbit X_Red=P1^2;
sbit Y_Green=P1^3;
sbit Y_Yellow=P1^4;
sbit Y_Red=P1^5;

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

u8 Second;

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

void Timer0Init(void)
{
	TMOD|=0x01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

	TH0=T1MS>>8;	//给定时器赋初值,定时1ms
	TL0=T1MS;
	ET0=1;//打开定时器0中断允许
	EA=1;//打开总中断
	TR0=1;//打开定时器
}
/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{
	u8 PrintFlag = 0;
	Second = 1;
	Timer0Init();
	LcdInit();
	displayInit();
	while(1)
	{
		if( Second >= 90 )
			Second = 1;
		
		if( Second <= 40 )
		{
			if( PrintFlag == 0 )
			{
				PrintFlag = 1;
				X_Green = 0;
				X_Yellow = 1;
				X_Red = 1;
				Y_Green = 1;
				Y_Yellow = 1;
				Y_Red = 0;
				display(0, 2);
			}
		}
		else if( Second <= 45 )
		{
			if( PrintFlag == 1 )
			{
				PrintFlag = 0;
				X_Green = 1;
				X_Yellow = 0;
				X_Red = 1;
				Y_Green = 1;
				Y_Yellow = 1;
				Y_Red = 0;
				display(1, 2);
			}
		}
		else if( Second <= 85 )
		{
			if( PrintFlag == 0 )
			{
				PrintFlag = 1;
				X_Green = 1;
				X_Yellow = 1;
				X_Red = 0;
				Y_Green = 0;
				Y_Yellow = 1;
				Y_Red = 1;
				display(2, 0);
			}
		}
		else
		{			
			if( PrintFlag == 1 )
			{
				PrintFlag = 0;
				X_Green = 1;
				X_Yellow = 1;
				X_Red = 0;
				Y_Green = 1;
				Y_Yellow = 0;
				Y_Red = 1;
				display(2, 1);
			}
		}
	}
}

void Timer0() interrupt 1
{
	static u16 i;
	TH0=T1MS>>8;	//给定时器赋初值,定时1ms
	TL0=T1MS;
	i++;
	if(i==1000)
	{
		i=0;
		Second ++;	
	}	
}
/*-----------------------------
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]);
	}
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值