2016-09-23 13:09:09 qq_33869658 阅读数 56205
  • 51单片机综合项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3419 人正在学习 去看看 朱有鹏

        这是我大二做某实验室管理员,为了方便自己管理整理,都是一些51单片机的小作品,适合给刚学完51单片机的新手练手!

一目录

1基于51单片机的火灾温度烟雾报警器

2基于51单片机的声光电子琴

3基于51单片机的音乐喷泉

4基于51单片机的智能温控风扇

5基于51单片机的超声波测距

6基于51单片机的无线温湿度控制系统设计

7基于51单片机脉搏心率计

8.基于51单片机led音乐频谱

9.基于51单片机的智能充电器

10.基于51单片机的贪吃蛇游戏

11.基于51单片机的电子秤

12.基于51单片机的视力保护器

13.基于51单片机防人水位检测报警系统

14.基于51单片机的声光控制器设计

15.基于51单片机的红外计数器

16.基于51单片机的自行车码表设计

17.基于51单片机的计算器的设计

18.基于51单片机的酒精浓度测试仪设计

19.基于51单片机的智能台灯设计

20.基于51单片机的卫星定位

21.基于51单片机防尘PM2.5灰尘设计

22.基于51单片机的无线音乐门铃

23基于51单片机的短信收发控制器

24.基于51单片机的智能插座定时开关设计

25.基于51单片机的4*4*4单片机的光立方设计


二.作品参考图

1基于51单片机的火灾温度烟雾报警器



2基于51单片机的声光电子琴



3基于51单片机的音乐喷泉



4基于51单片机的智能温控风扇



5基于51单片机的超声波测距



6基于51单片机的无线温湿度控制系统设计


7基于51单片机脉搏心率计


8.基于51单片机led音乐频谱


9.基于51单片机的智能充电器


10.基于51单片机的贪吃蛇游戏


11.基于51单片机的电子秤


12.基于51单片机的视力保护器


13.基于51单片机防人水位检测报警系统


14.基于51单片机的声光控制器设计


15.基于51单片机的红外计数器


16.基于51单片机的自行车码表设计


17.基于51单片机的计算器的设计


18.基于51单片机的酒精浓度测试仪设计


19.基于51单片机的智能台灯设计


20.基于51单片机的卫星定位


21.基于51单片机防尘PM2.5灰尘设计


22.基于51单片机的无线音乐门铃


23基于51单片机的短信收发控制器



24.基于51单片机的智能插座定时开关设计



25.基于51单片机的4*4*4单片机的光立方设计












2018-08-23 13:41:08 monkey2018 阅读数 14229
  • 51单片机综合项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3419 人正在学习 去看看 朱有鹏

51单片机作为基础入门的单片机应用十分广泛,一直以来基于51单片机的作品就层出不穷,推陈出新,有一段时间没有给大家整理关于51单片机的作品了,今天给大家分享电路城上最新的基于51单片机的作品,尤其是智能家居方面。

1、智能手机蓝牙控制家电开关设计方案

本文利用所学51 单片机基础知识结合自动控制技术和蓝牙2.0 通信技术设计完成一套无线遥控家电开关系统。整个系统以STC89C52 单片机为核心,单片机实现HC-05 蓝牙指令的解析与继电器开关控制指令的发出。 为了使系统设计简便,操作演示方便,家用电器部分采用4 种LED 灯来模拟替代,通过继电器开关上接的LED灯的亮灭来模拟所控制的电器的开启和关闭,系统LCD12864 液晶实时显示4 种家电开关的开启与关闭状态。

http://www.cirmall.com/circuit/4062/details?1

 

2、2013年全国大学生电子设计竞赛G手写绘图板(一等奖作品)

本设计是使用51单片机实现的,目的得到一个较为精确的手写绘图板,我们通过一个恒流源接入覆铜板并将八个精密电阻引入,当触摸笔接触到覆铜板任意一个位置时便会检测到一个小电压信号,通过这一原理我们在覆铜板上通过表笔的移动采集差分信号,差分信号有助于信号传输,我们将采集到的信号进行电压跟随以提高电路带负载的能力从而得到较为稳定的小电压信号,再进行前置高精度较高增益放大并通过低通滤波然电路后进入电压跟随电路从而得到更稳定的信号并提高信号准确度及性价比。被放大的电压信号被高精度的AD采集,经过51单片机的处理得到信号数据并将处理的信号显示到液晶上,从而实现实时显示表笔的位置坐标的要求及其他的显示要求。

http://www.cirmall.com/circuit/1727/details?1

 

3、基于51单片机智能家居设计

该智能家居基于51单片机控制, 同时外接DS1302和DS18B20以及LCD液晶屏等,对智能家居智进行简易的控制。

该设计运用到的芯片:STC89C58+DS18B20+DHT11+DS1302+LCD12864+红外人体感应器+无线遥控。

http://www.cirmall.com/circuit/609/details?1

 

4、多功能自动调光器 智能节能LED灯台灯设计(毕业设计)

智能节能LED灯台灯可以根据环境光强自动调节发光强度,调节过程为渐亮或渐暗;调光器具有人体感应功能,当感知空间内无人时自动熄灭,空间内有人时自动开灯;电路采用51单片机作为主控制芯片,有16LED。整个系统通过USB接口供电,通过1602显示节能LED的具体亮度,红外人体感应器是外界模块,附件里有介绍。

http://www.cirmall.com/circuit/918/details?1

 

5、基于51单片机的智能窗帘

采用51单片机+LCD1602液晶+步进电机+光敏传感器+蜂鸣器+红外遥控+键盘设计而成。

通过将光敏电阻与比较器的配合连接识别白天和黑夜,窗帘的控制电机为步进电机,可通过键盘设置为三种模式。并且液晶实时显示目前窗帘状态。

实现功能:

1. 窗帘控制有三种模式:智能模式,手动模式,遥控模式;

2. 智能模式下,由光敏信号感应光线强度,电机会相应的白天上拉或夜晚下降。此过程碰触相应的限位行程开关,停止转动。

3. 手动模式下,由相应按键控制窗帘的上拉和下降;

4. 遥控模式下,可以遥控上拉、下降窗帘。

http://www.cirmall.com/circuit/3465/details?1

 

6、基于51单片机的电子密码锁系统设计制作,电路图+源程序

这款基于51单片机的电子密码锁系统,单片机用STC89C52RC单片机,电路简单,制作过程中不需要进行调试,支持密码掉电保存功能!密码储存于单片机内部自带的的EEPROM中,不需要外置AT24C01保存密码,是学习电子密码锁比较好的教学试验系统。

http://www.cirmall.com/circuit/3449/details?1

 

7、LED音乐频谱制作教程、原理图、参考源代码

利用 51 单片机制作 LED 音乐频谱显示的原理:

1、 选择一款具有高速 ADC 采样的单片机,采集音频信号的电压幅度,比如 WQX 推荐是STC12C5A60S。该单片机具有 8 通道 10 位 ADC 采样封装模块。 每秒钟可以采样 25 万次。 满足我们的设计需要。传统的单片机开发板自带的 ADC0804 采样速度不能满足。不推荐。

2、 采样结果,通过 FFT 运算,得出各种频段的幅度值。分别保存在 15 个字节的数组变量中。我们人耳能够听到的极限频率是 20Hz--20KHz 。但是 我们平时的音乐歌曲的频段大概是100Hz---4KHz(极少部分乐器的频率能达到 6K 以上)。所以,我们的显示频率范围定为100Hz---4KHz 。

3、 利用 IO 口驱动 8*15=120 颗 LED 组成的矩阵灯点。显示 15 个频段的幅度值。并且多添加一行作为平面,让效果更美观。

http://www.cirmall.com/circuit/3162/details?1

 

8、51开发板原理图+PCB+BOM清单+程序共享下载

51开发板也称51单片机实验板、51单片机学习板。是用于学习51型号的单片机的实验及学习器件,他是将51单片机常用的外围。比如流水灯,数码管,矩阵键盘,EEPROM,时钟,蜂鸣器,继电器及集成在一小块电路板上。便于携带及学习,直接插在PC机上面。

http://www.cirmall.com/circuit/3203/details?1

 

9、双人对战五子棋电路+源代码等

该设计为基于51单片机+TFT320240+按键的双人对战五子棋

实现功能:

1)白棋,黑棋轮流下子

2)判断是否五子相连

3)判断是否和局

4)悔棋

5)重新开始游戏

http://www.cirmall.com/circuit/2866/details?1

 

10、基于51单片机的实时时钟系统(MF界面编程完成PC界面)

本系统通过上位机与下位机之间的通行协议,实现在三个更新周期内,上位机时间与下位机时间完全同步,适用于时间要求严格的系统。系统运行后,每过3秒钟,会有一个更新信号,防止上位机与下位机时间发生不同步现象。而且该更新周期可根据对时间精度的要求进行更改。通过软件上的复杂度换取时间上的精确度。

http://www.cirmall.com/circuit/2863/details?1

 

11、(电子大赛)自动售水机源码分享

该自动售水机采用51单片机作为主控制芯片,pcf8591用于AD转换,并将结果显示在数码管上。整个设计基于专用版CT107D设计。

http://www.cirmall.com/circuit/2940/details?1

 

12、基于51的简单智能家居控制系统

  1. 分享自己做的毕业设计--基于51单片机的智能家居控制系统
  2. 本系统主要使用了两块51单片机作为控制mcu,
  3. 步进电机模拟窗帘,三个LED灯模拟灯光,
  4. 使用了四个传感器:温度传感器(DS18B20)、烟雾传感器、光敏传感器、红外传感器
  5. 远程通信:使用SIM900A模块作为短信报警,
  6. 近距通信:使用HC06主从一体蓝牙模块
  7. APP为安卓版本,借助MIT APP inventor 2 开发。

http://www.cirmall.com/circuit/2417/details?1

2020-01-20 22:23:28 weixin_42585316 阅读数 9
  • 51单片机综合项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3419 人正在学习 去看看 朱有鹏

门锁介绍

这个门锁是我2018年暑假做的一个小作品,是我入门单片机后的第二个作品,第一个是一个船,使用串口通讯,完成了对船的遥控,而在假期,利用放假时间做了这个门锁,做出来已经好长时间了,就做个简单的展示,为刚学51单片机、而且想做一个自己作品的同学提供一个参考。门锁整体由外部(安装后的室外)矩阵键盘和1602显示器,一个电源开关、内部(室内)主控芯片,两个开关门状态控制开关,一个电源开关,一个蜂鸣器,一个L298N电机驱动及一个电动推杆组成。在外部通过4*4矩阵键盘输入密码和操作控制,LCD1602显示器显示状态提示或已输入密码位数;内部由两个按键分别控制开关门。开门或关门后有灯光和蜂鸣器提示状态。

门锁软硬件介绍

STC8989C52单片机

STC89C52RC是STC公司生产的一种低功耗、高性能CMOS8位微控制器,具有8K字节系统可编程Flash存储器。STC89C52使用经典的MCS-51内核,但是做了很多的改进使得芯片具有传统51单片机不具备的功能。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
8k字节Flash,512字节RAM, 32 位I/O 口线,看门狗定时器,内置4KB EEPROM,MAX810复位电路,3个16 位定时器/计数器,4个外部中断,一个7向量4级中断结构(兼容传统51的5向量2级中断结构),全双工串行口。另外 STC89C52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU 停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。最高运作频率35MHz,6T/12T可选。
居中的图片: 在这里插入图片描述

LCD1602显示屏

工业字符型液晶,能够同时显示16x02即32个字符,16列2行)。1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形(用自定义CGRAM,显示效果也不好)。1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。市面上字符液晶大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。
居中的图片:
lcd1602
LCD1602操作参考:
链接:https://blog.csdn.net/weixin_42133183/article/details/80911996
链接:https://blog.csdn.net/qq_34706280/article/details/53165561
链接 :https://blog.csdn.net/weixin_42625444/article/details/84331059
上面两个大佬的介绍很详尽了,而我也基本参考各种例程,将其简单驱动起来,显示我想要的字符。
故,我用P2 ^3作为LCD寄存器选择引脚,P2 ^4作为读写选择引脚,P2 ^5作为读写使能引脚,P0作为数据引脚。根据时序写出写数据和写命令函数。

/*********************液晶写数据函数******************/
void writedate(uchar date) //写命令
{
	P0=date;			//写入命令
	rs=1;				//选择数据寄存器
	lcden=0;			//写入数据
	delay_xs(10);		//稍作延时保证数据写入
	lcden=1;			//停止写入
	delay_xs(10);
	lcden=0;
}
/*********************液晶写命令函数******************/
void writecom(uchar com) //写命令
{
	P0=com;				//写入命令
	rs=0;               //选择指令寄存器
	lcden=0;            //写入数据
	delay_xs(10);       //稍作延时保证数据写入
	lcden=1;            //停止写入
	delay_xs(10);
	lcden=0;
}

矩阵键盘

为了减少I/O口的占用,将按键排列成矩阵形式。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如P3口)就可以构成4*4=16个按键。当按键没有按下时,所有的输入端都是高电平,代表无键按下。行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。确定矩阵式键盘上何键被按下介绍一种“行扫描法”。行扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键识别方法。
1、判断键盘中有无键按下 将全部行线置低电平,然后检测列线的状态。只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。若所有列线均为高电平,则键盘中无键按下。
2、判断闭合键所在的位置 在确认有键按下后,即可进入确定具体闭合键的过程。其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。
门锁为了实现部分功能,有些按键没有使用,有些按键在室内,通过并联按键实现同样功能,具体实现如下代码:

/******************键盘扫描函数**************************/
void keyscan()
{
	uchar temp;
	/**************第一行扫描********************/
	P3=0xfe;
	temp=P3&0xf0;
	if(temp!=0xf0)
	{
		delay_xs(10);
		if(temp!=0xf0) 
			temp=P3;
		switch(temp)
		{
			case 0xee: keydeal1(); break;
			case 0xde: keydeal2(); break;
			case 0xbe: keydeal3(); break;
			case 0x7e: keydeal4(); break;
		}
		while((P3&0xf0)!=0xf0); //松手检测
	}
/******************第二行扫描**********************/
	P3=0xfd;
	temp=P3&0xf0;
	if(temp!=0xf0)
	{
		delay_xs(10);
		if(temp!=0xf0) temp=P3;
		switch(temp)
		{
			case 0xed: keydeal5(); break;
			case 0xdd: keydeal6(); break;
			case 0xbd: keydeal7(); break;
			case 0x7d: keydeal8(); break;		
		}
		while((P3&0xf0)!=0xf0);   //松手检测
	}
/*****************第三行扫描*********************/
	P3=0xfb; 
	temp=P3&0xf0;
	if(temp!=0xf0)
	{
	delay_xs(10);
	if(temp!=0xf0) 
	temp=P3;
	switch(temp)
	{
		case 0xeb: keydeal9(); break;
		case 0xdb: keydeal10(); break;
		case 0xbb: keydeal11(); break;
		case 0x7b: keydeal12(); break;	
	}
		while((P3&0xf0)!=0xf0);	
	}
/********************第四行扫描********************/
	P3=0xf7;
	temp=P3&0xf0;
	if(temp!=0xf0)
		{
		delay_xs(10);
		if(temp!=0xf0) 
		temp=P3;
		switch(temp)
		{
			case 0xe7: keydeal13();	break;
			case 0xd7: keydeal14();	break;
			case 0xb7: /*keydeal15();*/ break;
			case 0x77: /*keydeal16();*/ break;
		}
		while((P3&0xf0)!=0xf0);	
	}
}
/*

链接:https://blog.csdn.net/dlf1769/article/details/90599686

L298N电机驱动和电动推杆

逻辑部分实现后为实现门锁的功能,我采用了电动推杆作为门销,对门进行简单改造,利用电动推杆伸出来的杆体将门销住。电动推杆里面是一个电机,所以我采用了一个L298N来驱动电机。当密码正确或者有人在内部开门,就让电机开始正转就行,关门时相反。代码简单,也没写单独的函数,在这就不展示了。

门锁实物展示

居中的图片:在这里插入图片描述
居中的图片:在这里插入图片描述
居中的图片:在这里插入图片描述

门锁代码展示

/*——————密码门锁————————*/
/*——————密码86445131——————*/

#include<reg52.h>

#define uchar unsigned char
#define uint unsigned int

sbit l1=P2^0;
sbit bump=P1^3; //蜂鸣器控制
sbit IN1=P1^0;//驱动引脚
sbit IN2=P1^1;
sbit rs=P2^3;	  //液晶屏控制位
sbit rw=P2^4;	  //读写选择端
sbit lcden=P2^5;  //使能控制端

/**********显示内容**************************/
uchar code xianshi0[]="input  password:";
uchar code xianshi1[]="please come in!";
uchar code xianshi2[]="close the door!";
uchar code xianshi3[]="*";
uchar code xianshi4[]=" you are thief!";
uchar code xianshi5[]="  first error!";
uchar code xianshi6[]="  second error!";
uchar code xianshi7[]="  third error!!";
uchar code xianshi8[]="  Good Bye!!";
uchar code xianshi9[]=" Wait a moment! ";
static uchar table[8]; //给按键输入留取存储空间
static uchar mima[8]={8,6,4,4,5,1,3,1};
uchar num=0,etimes=0,s=0;
bit cpflog=0,mimaqueren=0;

void compare();	//密码比较函数
void keydeal13();	//关门
void keydeal14();	//开门
void keyscan();		//键盘扫描函数
void init();	//初始化函数

/********************延时一毫秒函数**************/ 
void delay_xs(uint x)
{   
	uint i,j;
	for(i=x;i>0;i--)
	for(j=110;j>0;j--)
	;
}
/*********************液晶写数据函数******************/
void writedate(uchar date) //写命令
{
	P0=date;			//写入命令
	rs=1;				//选择数据寄存器
	lcden=0;			//写入数据
	delay_xs(10);		//稍作延时保证数据写入
	lcden=1;			//停止写入
	delay_xs(10);
	lcden=0;
}
/*********************液晶写命令函数******************/
void writecom(uchar com) //写命令
{
	P0=com;				//写入命令
	rs=0;               //选择指令寄存器
	lcden=0;            //写入数据
	delay_xs(10);       //稍作延时保证数据写入
	lcden=1;            //停止写入
	delay_xs(10);
	lcden=0;
}

/************各按键对应处理函数***************/
/*************各按键功能*********************/
/************1-2-3-4-5-6-7-8-9-0************/
/**************数字按键*******************/
void keydeal1()                 //按键1
{
	table[num]=1;
	num++;
}
void keydeal2()                //按键2
{
	table[num]=2;
	num++;
}
void keydeal3()               //按键3
{
	table[num]=3;
	num++;
}
void keydeal4()               //按键4
{
	table[num]=4;
	num++;
}
void keydeal5()               //按键5
{
	table[num]=5;
	num++;
}
void keydeal6() //按键6
{
	table[num]=6;
	num++;
}
void keydeal7() //按键7
{
	table[num]=7;
	num++;
}
void keydeal8()  //按键8
{
	table[num]=8;
	num++;
}
void keydeal9()   //按键9
{
	table[num]=9;
	num++;
}
void keydeal10()   //按键10
{
	table[num]=0;   
	num++;
}

/******************功能键*****************/
/***********确定,取消,开门,关门*******/
//确认键
void keydeal11()  //确认键
{
	uchar j,i;
	if(num==8)         //判断是否输入八个数字
	{
		num=0;         //将输入数字个数清零
		compare();         //进行密码比较
		for(j=0;j<8;j++) //用FFFFFFFF将输入的数据清空
		{
			table[j]=0;
		}
	}
	if(cpflog==1) //如果密码正确,标志位为1
	{
		l1=0; //点亮开锁灯
		cpflog=0; //使比较密码标志位归零
		etimes=0; //使记错次数归零
		IN1=1;
		IN2=0;		 //开始开门
		delay_xs(1000);
		delay_xs(1000);
		delay_xs(1000);
		delay_xs(1000);
		IN1=0;
		IN2=0;	    //完成开门		  
		writecom(0x01); //液晶屏清空显示
		writecom(0x80); //让液晶显示“please come in!”
		for(j=0;j<15;j++)
		{
			writedate(xianshi1[j]);
			delay_xs(3);
		}
		for(j=0;j<2;j++)  //蜂鸣器响两声提示开锁成功
		{
			bump=0; 
			delay_xs(200);
			bump=1; 
			delay_xs(200);
			bump=0; 
			delay_xs(200);
			bump=1; 
			delay_xs(200);
			bump=0;
		}
		writecom(0x01); 
		writecom(0x80);//清屏
		for(i=0;i<15;i++)				  //显示“close the door”
		{	
			writedate(xianshi2[i]); 
		} 
		mimaqueren=1;			  //关门标志置一,等待关门
		while(s==0)				 //等待关门
		{
			keyscan();			//键盘扫描,等待按下关门键
			l1=~l1;
			delay_xs(100);	
		}
		s=0;
		mimaqueren=0;	//关门标志置零,开始关门
		keydeal13();	//关门
	}
	else //否则密码错误,执行密码错误指令
	{
		num=0; //将输入数据个数清零
		etimes++; //记录错误次数加1 
		for(j=0;j<8;j++)  //清空修改密码输入数据
		{ 
			table[j]=0x0f; 
		}
		if(etimes==1)  //如果输错一次
		{
			writecom(0x01);   //清屏
			writecom(0x80);
			for(j=0;j<14;j++)   //显示first error
			{ 
				writedate(xianshi5[j]); 
			}
			delay_xs(2000);   //延时两秒
			writecom(0xc);
			writecom(0x80);
			for(j=0;j<16;j++)   //第一行显示input passsword
			{
				writedate(xianshi0[j]); 
				delay_xs(5);
			}   
			writecom(0x80+0x40+4); //第二行显示--------
			for(j=0;j<8;j++) 
			{
				writedate('-'); 
			}
		}
		if(etimes==2)   //如果输错两次
		{
			writecom(0x01); 
			writecom(0x80);
			for(j=0;j<15;j++)   //显示second error
			{
				writedate(xianshi6[j]);
			}
			delay_xs(2000);   //延时两秒
			writecom(0xc);
			writecom(0x80);
			for(j=0;j<16;j++) //第一行显示input passsword
			{
				writedate(xianshi0[j]); 
				delay_xs(5);
			}
			writecom(0x80+0x40+4);
			for(j=0;j<8;j++) //第二行显示--------
			{
				writedate('-');
			}
		}
		if(etimes==3) //如果输错三次
		{
			writecom(0x01);
			writecom(0x80);
			for(j=0;j<15;j++) //显示  third error!!
			{
				writedate(xianshi7[j]);
			}
			writecom(0x01);
			writecom(0x80);
			for(j=0;j<15;j++) //显示you are thief!
			{
				writedate(xianshi4[j]);
			}			
			for(j=0;j<10;j++) //报警十秒钟
			{
				bump=0; 
				delay_xs(500);
				bump=1; 
				delay_xs(500);
			}
			writecom(0x01);
			writecom(0x80);
			for(j=0;j<16;j++) //显示Wait a moment
			{
				writedate(xianshi9[j]);
			}
			delay_xs(10000);													   
			init(); //初始化
		}
	}
}
void keydeal12()	   //重新输入
{
	init();
}
void keydeal13()	   //关门
{
	uchar i;
	if(mimaqueren==1)
	{
		s=1;
	}
	if(mimaqueren==0)
	{
		IN1=0;
		IN2=1;		   //通电,开始关门
		delay_xs(1000);
		delay_xs(1000);
		delay_xs(1000);
		delay_xs(1000);
		IN1=0;
		IN2=0;				
		writecom(0x01); 
		writecom(0x80);//清屏
		for(i=0;i<12;i++)				  //显示“Good bye”
		{	
			writedate(xianshi8[i]); 
		}
		for(i=0;i<4;i++)  //蜂鸣器响两声提示开锁成功
		{
			bump=0; 
			delay_xs(200);
			bump=1; 
			delay_xs(200);
			bump=0; 
			delay_xs(200);
			bump=1; 
			delay_xs(200);
			bump=0;
		}
		l1=0;		   //ledl亮,显示可以下次正常输入
		init();		   //初始化,为下次开门做准备
	}
}
void keydeal14()		   //开门
{
	uchar i,j;
	IN1=1;
	IN2=0;		
	delay_xs(1000);
	delay_xs(1000);
	delay_xs(1000);
	delay_xs(1000);
	IN1=0;
	IN2=0;
	delay_xs(100);
	IN1=0;
	IN2=0;		   
	writecom(0x01); 
	writecom(0x80);//清屏
	for(i=0;i<15;i++)				  //显示“please come in”
	{	
		writedate(xianshi1[i]); 
	}
	delay_xs(1000);		  //延时,保证门确实开开
	for(j=0;j<4;j++)  //蜂鸣器响两声提示开锁成功
	{
		bump=0; 
		delay_xs(200);
		bump=1; 
		delay_xs(200);
		bump=0; 
		delay_xs(200);
		bump=1; 
		delay_xs(200);
		bump=0;
	}	
	l1=1;
	writecom(0x01); 
	writecom(0x80);//清屏
	for(i=0;i<15;i++)				  //显示“close the door”
	{	
		writedate(xianshi2[i]); 
	}
	while(P3!=0xe7);	//等待关门
	init();		  //关门后初始化,为下次输入做准备
}
void compare() //比较密码正确与否函数
{
	uchar j,i=0;
	for(j=0;j<8;j++)
	{
		if(table[j]==mima[j])
		{			
			i=i+1 ;
		}
	}
	if(i==8)
	{
		cpflog=1;	 //密码正确标志置1
	}	 
}
/******************键盘扫描函数**************************/
void keyscan()
{
	uchar temp;
	/**************第一行扫描********************/
	P3=0xfe;
	temp=P3&0xf0;
	if(temp!=0xf0)
	{
		delay_xs(10);
		if(temp!=0xf0) 
			temp=P3;
		switch(temp)
		{
			case 0xee: keydeal1(); break;
			case 0xde: keydeal2(); break;
			case 0xbe: keydeal3(); break;
			case 0x7e: keydeal4(); break;
		}
		while((P3&0xf0)!=0xf0); //松手检测
	}
/******************第二行扫描**********************/
	P3=0xfd;
	temp=P3&0xf0;
	if(temp!=0xf0)
	{
		delay_xs(10);
		if(temp!=0xf0) temp=P3;
		switch(temp)
		{
			case 0xed: keydeal5(); break;
			case 0xdd: keydeal6(); break;
			case 0xbd: keydeal7(); break;
			case 0x7d: keydeal8(); break;		
		}
		while((P3&0xf0)!=0xf0);   //松手检测
	}
/*****************第三行扫描*********************/
	P3=0xfb; 
	temp=P3&0xf0;
	if(temp!=0xf0)
	{
	delay_xs(10);
	if(temp!=0xf0) 
	temp=P3;
	switch(temp)
	{
		case 0xeb: keydeal9(); break;
		case 0xdb: keydeal10(); break;
		case 0xbb: keydeal11(); break;
		case 0x7b: keydeal12(); break;	
	}
		while((P3&0xf0)!=0xf0);	
	}
/********************第四行扫描********************/
	P3=0xf7;
	temp=P3&0xf0;
	if(temp!=0xf0)
		{
		delay_xs(10);
		if(temp!=0xf0) 
		temp=P3;
		switch(temp)
		{
			case 0xe7: keydeal13();	break;
			case 0xd7: keydeal14();	break;
			case 0xb7: /*keydeal15();*/ break;
			case 0x77: /*keydeal16();*/ break;
		}
		while((P3&0xf0)!=0xf0);	
	}
}
/****************显示函数*************/
void display()
{
	uint c;
	writecom(0x80+0x40+4);
	for(c=0;c<num;c++)
	{ 
		writedate('*'); 
		delay_xs(5); 
	}
}
/*******************初始化函数***********/
void init()
{
	uint a,b;
	bump=0;
	num=0;  //输入数据个数清零
	etimes=0;
	IN1=0;	//关门
	IN2=0;
	l1=0;   //关闭开锁灯
	delay_xs(5); 
	rw=0;
	writecom(0x38);   //显示模式设置:16×2显示,5×7点阵,8位数据接口
	delay_xs(20);
	writecom(0x0f);   //显示模式设置
	delay_xs(20);
	writecom(0x06);   //显示模式设置:光标右移,字符不移
	delay_xs(20);
	writecom(0x01);   //清屏幕指令,将以前的显示内容清除
	delay_xs(20);
	for(a=0;a<16;a++) //显示input password:
	{
		writedate(xianshi0[a]); 
		delay_xs(5);
	}
	writecom(0x80+0x40+4); //第二行显示--------
	for(b=0;b<8;b++)
	{ 
		writedate('-'); 
	} 
}
/*****************主函数******************/
void main()
{
	init();   //初始化
	while(1) //不停地对键盘和显示进行扫描
	{
		keyscan(); //键盘扫描和密码输入处理
		display(); //LCD显示
	}
}

附上整个工程代码,上面代码无法复现可试试工程。
链接:https://download.csdn.net/download/weixin_42585316/12110359

参考文档

参考文档https://blog.csdn.net/matsukawahikari/article/details/83756903
参考文档https://blog.csdn.net/dlf1769/article/details/90599686
参考文档 https://blog.csdn.net/weixin_42133183/article/details/80911996
参考文档https://blog.csdn.net/qq_34706280/article/details/53165561
参考文档https://blog.csdn.net/weixin_42625444/article/details/84331059

总结

制作成中各种困难,从中发现了好多学习过程中没注意到的地方,比如说在学习过程中没太注意矩阵按键行扫描时的数据应该怎么去算,在做的过程中再去回顾,算了好几次,中间多次出错,多次检查更正,总算合适,完成了简单地密码输入及各种逻辑。再用LCD1602时因为之前没怎么用过,花了好长时间,做的过程中慢慢摸索,有点门道后参考例程,完成我想要的结果,之后再做其他小作品的时候慢慢深化。
密码门锁的功能是完成了,但相对简单,功能单一,没有新奇之处,但通过这次制作我对所学到的STC89C52单片机的知识有了很好的深化,之后还会对其完善,加上其他各种功能,比如射频卡、指纹等。

2013-08-04 17:32:52 czjsky818 阅读数 11880
  • 51单片机综合项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3419 人正在学习 去看看 朱有鹏

STC51单片机一般是通过串口线下载程序到MCU。但是,有时候单片机放在作品上,串口线不够长,不方便下载,或者频繁拔插单片机,也不方便。

本方法,通过笔记本蓝牙,蓝牙串口模块HC-05,即可实现STC51单片机无线下载程序到MCU。


需要以下准备:

  1. 有蓝牙模块的笔记本。

  2. 蓝牙串口模块HC-05

  3. STC51单片机

  4. STC-ISP V6.53(只要能任意选择COM口的都行。)

  5. USB转串口模块


第一步:

 打开笔记本蓝牙模块。首先你要确定你有蓝牙模块和装好相应的驱动,这里我就不详细展开了。不同笔记本打开方式不同。我的联想Y笔记本如图1:


第二步:

将USB转串口和HC-05的VCC,GND,相连,TXD接RXD,RXD接TXD。将USB转串口模块插入笔记本。此时HC-05指示灯应该是快速闪烁。

如上图,点击添加设备,搜索到HC-05后连接,输入设备的配对码 1234 ,如图2,


然后就连接成功,在 控制面板\硬件和声音\设备和打印机 里便可以看到HC-05了。在HC-05上右键,属性,硬件,便可以看到COM口号,COM28,如图3。



第三步:

将HC-05模块的PIO11置高(我买的模块有个按键),上电,模块便进入AT命令响应模式。此时HC-05指示灯应该是慢速地闪烁。

此时可以打开任意串口助手软件,如STC-ISP的串口助手,设置波特率38400,数据位8位,停止位1位,无校验位,无流控制。

串口发送字符: AT(后面要加个回车键,我之前不知道,以为没进入AT模式),成功则返回OK。

接下来设置HC-05工作模式:波特率9600,数据位8位,停止位1位,偶校验,无流控制。串口发送字符:AT+UART=9600,0,2

然后就可以关闭串口了。



第四步:

将HC-05插到单片机上,还是一样,VCC,GND,相连,TXD接RXD,RXD接TXD。

硬件部分就完成了。


第五步:

在单片机程序中加入ISP.c,ISP.h,在程序开关调用函数 UARTInit(); 实现STC51单片机的ISP。

/******************************************************************************
* 文    件: ISP.c
* 原作者: 李锋源
* 修  改: ZhnJa 
* 创建日期: 2011-7-15
* 修改日期: 2013-8-01
* 说 明: 原文件为阿土开发板的Driver.c,提取出来的ISP下载程序。
******************************************************************************/

#include "ISP.h"
#include "STC12C5A60S2.h"
#include <intrins.h> 

#ifdef	Self_Define_ISP_Download			//如果有自定义ISP下载功能
unsigned char bufptr;
code unsigned char passward[]={ICPCODE};
unsigned char buf[sizeof(passward)*2];		//静态串口缓冲区
#endif
 
/******************************************************************************
*                               UART初始化            
*描    述:串口初始化函数, 通常是在使用串口前调用本函数来进行初始化, 通常是在
*          main函数中调用。
*入口参数:无
*返    回:无
*注    意:串口使用的是中断模式
******************************************************************************/
void UARTInit(void)
{
	#define Fclk 11059200UL	//晶振 11.059M 不可以写成11059200
	#define BitRate 9600UL	//9600b/s
	unsigned char i;
	unsigned int j;
#ifdef	Self_Define_ISP_Download   //自定义下载使用到
	bufptr = 0;
	for( i=0; i<sizeof(buf); i++)
	{
		buf[i] = 0;
	}
#endif
	EA=0; 							//暂时关闭中断
	TMOD &= 0x0F;
	TMOD |=0x20;    				//定时器1工作在模式2,自动重装模式
	SCON=0x50;     					//串口工作在模式1
	TH1=256-(Fclk/(BitRate*12*16)); //计算定时器重装值
	TL1=256-(Fclk/(BitRate*12*16));
	PCON|=0x80;    					//串口波特率加倍
   // ES=1;         				//串行中断允许
	TR1=1;        					//启动定时器1
	REN=1;        					//允许接收 
	EA=1;         					//允许中断 

  	for(i=0;i<8;i++)			 	//短暂延时判断有无ISP下载命令
	{	
	 	for(j=0;j<40000;j++)
		{
		 	if(RI)
			{
				RI = 0;
				IAP_CONTR = 0x60;	 //复位到IAP
			}
		}
	}
	ES=1;         					//串行中断允许
}


/******************************************************************************
*                               延时1s函数            
*描    述:延时1s函数,在UartInit()调用供ISP延时。
*入口参数:无
*返    回:无
*注    意:
******************************************************************************/
void delay1s(void)
{
 	unsigned char i,j,k;
	for(i=0;i<200;i++)
	{
	 	for(j=0;j<200;j++)
		{
			k = 10;
			while(k--);
		}
	}
}
/******************************************************************************
*                           发送一个字符            
*描    述:向串口发送一个字符。
*入口参数:要发送的字符
*返    回:无
*注    意:
******************************************************************************/
void SendByte(unsigned char c)	 
{
    SBUF = c;
    while(!TI);
    TI = 0;
}
/******************************************************************************
*                          发送一个字符串            
*描    述:向串口发送一个字符串
*入口参数:*s要发送的字符串
*返    回:无
*注    意:
******************************************************************************/
void SendStr(char *s)			
{
	while(*s)
	{
		SendByte(*s++);
	}
}

/******************************************************************************
*                               串口0中断            
*描    述:串口0(UART0)中断。
*入口参数:无
*返    回:无
*注    意:
******************************************************************************/
void UartISR(void) interrupt 4
{
#ifdef Self_Define_ISP_Download
	
	unsigned char ptScr,ptDst;
	if(RI)
	{
		RI = 0;				//清标志位
		buf[bufptr] = SBUF;
		ptScr = bufptr;	
		if(bufptr==sizeof(buf))
		{
			bufptr = 0;
		}
		else
		{
			bufptr++;
		}
		while(buf[ptScr] == passward[ptDst])
		{
			if(ptScr == 0)
			{
				ptScr = sizeof(buf)-1;
			}
			else
			{
				ptScr--;
			}
			if(ptDst == 0)
			{
			//	reset();
			delay1s();            
			//复位前提示程序
			IAP_CONTR = 0x60;	 	//复位到IAP
			}
			else
			{
				ptDst--;
			}	
		}
		//用户程序开始
		
		
		//用户程序结束
	}//End if(RI) 
	if(TI)							//发送完成
	{		   	
	 	TI = 0;						//清标志位
	}
#else		   						//如果不使用自定义ISP下载程序
	if(RI)
	{
		RI = 0;
	}
	else
	{
	 	TI = 0;
	}
#endif
}

/*======================End Of File====================*/

/******************************************************************************
* 文    件: ISP.h
* 原作者: 李锋源
* 修  改: ZhnJa 
* 创建日期: 2011-7-15
* 修改日期: 2013-8-01
******************************************************************************/
#ifndef	__ISP_H__
#define __ISP_H__

#include "STC12C5A60S2.h"
//系统配置
#define Self_Define_ISP_Download			//ISP下载
#define ICPCODE		0x12,0x34,0x56,0x78,0x90,0xAB,0xCD,0xEF
#define FOSC	11059000UL
#define T100HZ  (FOSC/12/100)


//函数声明

//串口
void UARTInit(void);
void UARTInit(void);

void SendByte(unsigned char c);
void SendStr(char *s);

void delay1s(void);


#endif

第六步:

先用普通的正常下载方式将包含有ISP功能的程序下载到STC51单片机上。

打开STC-ISP(V6.53),设置如图,点击发送自定义下载命令即可实现远程下载。

补充:最高,最低波特率要设置为9600



说明1:
ISP,即In-System Programming,在线编程。
具有ISP功能的单片机芯片,可以通过简单的下载线直接在电路板上给芯片写入或者擦除程序,并且支持在线调试。
说明2:
须先下载一次有ISP功能的程序到单片机,之后才能实现冷启动下载程序,即ISP功能。

2018-11-12 10:40:42 qq_19760839 阅读数 508
  • 51单片机综合项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3419 人正在学习 去看看 朱有鹏

       13年开始接触51单片机,从最开始觉得新奇好玩,到现在觉得值得仔细研究,其中对51单片机态度发生了转变。这些年自己做了不少51单片机的小项目,在实践中总结自己对51单片机的认识。这样也算是有了基础。

       因为自己平时经常接一些本科毕设的项目,有那么一段时间觉得,单片机就和工匠手中的锤子、扳手差不多,就是一个工具,用的得当了,你也可以做出满意的作品。然而事实并不是这样,从最开始自己敲写代码,到现在将自己写好的整块直接拿来使用,工作量变小了,效率更高了,但是对于单片机的了解也变得不那么深入了。最近两年做了些许cortexM3架构单片机相关的项目,发现51单片机是基础,需要更深入的学习。这也就是我想写这个系列文章的原因,重新再复习一下51单片机的基础知识,用自己的语音总结,归到自己的认知体系当中,让基础知识做一次升华。

       51单片机相关的书籍有很多,我的指导老师也写过一本。我自然不会让这系列文章像书籍一样,我也达不到那样的水平。我会结合自己做小项目的经验,从自身的实践当中总结,从自己做过的实践当中来重新归整这些知识点。不一样的角度也许有不一样的风味。

这系列文章需要你有简单C语言基础,不少相关书籍都介绍汇编语言,因为这样能更好的理解单片机的工作原理,但是汇编更难读懂,这个系列的文章都是依托C语言编辑的。文章中大概会涉及一下几个方面(不做特殊说明的话“单片机”指的是AT89C52单片机):

  1. 单片机特点和应用;
  2. AT89C52结构和工作原理;
  3. 引脚的输入输出;
  4. 中断;
  5. 单片机的定时器,计数器;
  6. 串行接口;
  7. 并行扩展技术;
  8. 串行扩展技术;
  9. 部分小项目介绍;

大致内容如以上9点所述,后期会有些许变化,以上仅供参考。本人能力不高,水平有限,系列文章中肯定会出现不少纰漏,如有发现,还大神请指明,谢谢!

 

没有更多推荐了,返回首页