精华内容
下载资源
问答
  • 基于51单片机的交通灯控制系统设计

    万次阅读 多人点赞 2018-11-24 13:38:11
    本设计为基于51单片机交通灯系统的设计,采用模块化、层次化设计。运用单片机AT89C51进行数据的分析和处理,为显示提供信号,显示部分采用8位数码管显示倒计时值。系统电路简单、集成度高、工作稳定、调试方便、检测...

    第一章 硬件设计与原理
    以AT89C51单片机为核心,起着控制作用。系统包括数码管显示电路、复位电路、时钟电路、发光二级管电路和按键电路。设计思路分为六个模块:复位电路、晶振电路模块、AT89C51、数码管显示电路、发光二级管电路和按键电路这六个模块。

    在这里插入图片描述

    1.2 硬件设计分析
    1.2.1 电源的设计
    系统电源使用直流5伏。
    由电脑USB接口提供电源。
    USB是通用串行总线(Universal Serial Bus)接口的简称。它是目前使用比较广泛的电脑接口之一,主要版本有1.0、1.1和最新的2.0三种版本。根据USB总线的工业标准,它可以提供额定功率为5V/500mA的电源供USB设备使用。
    1.2.2 单片机最小系统
    51单片机是对目前所有兼容intel 8031指令系统的单片机的统称。该系列单片机的始祖是intel的8031单片机,后来随着技术的发展,成为目前广泛应用的8为单片机之一。单片机是在一块芯片内集成了CPU、RAM、ROM、定时器/计数器和多功能I/O口等计算机所需要的基本功能部件的大规模集成电路,又称为MCU。51系列单片机内包含以下几个部件:
    一个8位CPU;一个片内振荡器及时钟电路;
    4KB的ROM程序存储器;
    一个128B的RAM数据存储器;
    寻址64KB外部数据存储器和64KB外部程序存储空间的控制电路;
    32条可编程的I/O口线;
    两个16位定时/计数器;
    一个可编程全双工串行口;
    5个中断源、两个优先级嵌套中断结构。
    如图1-2-1所示为AT89C51单片机基本构造,其基本性能介绍如下:
    图1-2-1 AT89C51单片机

    AT89C51本身内含40个引脚,32个外部双向输入/输出(I/O)端口,同时内含2个外中端口,3个16位可编程定时计数器,2个全双工串行通信口,STC89C51RC可以按照常规方法进行编程,但不可以在线编程。其将通用的微处理器和Flash存储器结合在一起,特别是可反复擦写的Flash存储器可有效地降低开发成本。
    AT89C51的主要特性如下表所示:

    在这里插入图片描述

    AT89C51为40脚双列直插封装的8位通用微处理器,采用工业标准的C51内核,在内部功能及管脚排布上与通用的8xc52相同,其主要用于会聚调整时的功能控制。功能包括对会聚主IC内部寄存器、数据RAM及外部接口等功能部件的初始化,会聚调整控制,会聚测试图控制,红外遥控信号IR的接收解码及与主板CPU通信等。主要管脚有:XTAL1(19脚)和XTAL2(18脚)为振荡器输入输出端口,外接12MHz 晶振。RST/Vpd(9脚)为复位输入端口,外接电阻电容组成的复位电路。VCC(40脚)和VSS(20脚)为供电端口,分别接+5V电源的正负端。P0~P3 为可编程通用I/O脚,其功能用途由软件定义,在本设计中,P0端口(32~39脚)被定义为N1功能控制端口,分别与N1的相应功能管脚相连接,13脚定义为IR输入端,10脚和11脚定义为I2C总线控制端口,分别连接N1的SDAS(18脚)和SCLS(19脚)端口,12脚、27脚及28脚定义为握手信号功能端口,连接主板CPU的相应功能端,用于当前制式的检测及会聚调整状态进入的控制功能。
    P0口:P0口是一组8位漏极开路型双向I/O 口,也即地址/数据总线复用口。作为输出口用时,每位能吸收电流的方式驱动8个TTL逻辑门电路,对端口P0写“1”时,可作为高阻抗输入端用。在访问外部数据存储器或程序存储器时,这组口线分时转换地址(低8位)和数据总线复用,在访问期间激活内部上拉电阻。在Flash 编程时,P0口接收指令字节,而在程序校验时,输出指令字节,校验时,要求外接上拉电阻。
    P1口:P1是一个带内部上拉电阻的8位双向I/O口,P1的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口。作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。与AT89C51不同之处是,P1.0和P1.1还可分别作为定时/计数器2 的外部计数输入(P1.0/T2)和输入(P1.1/T2EX)。Flash编程和程序校验期间,P1接收低8位地址。
    P2口:P2是一个带有内部上拉电阻的8 位双向I/O口,P2的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口P2写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口,作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。在访问外部程序存储器或16位地址的外部数据存储器(例如执行MOVX @DPTR指令)时,P2口送出高8位地址数据。在访问8位地址的外部数据存储器(如执行MOVX @RI指令)时,P2口输出P2锁存器的内容。Flash编程或校验时,P2亦接收高位地址和一些控制信号。
    P3口:P3口是一组带有内部上拉电阻的8位双向I/O口。P3口输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对P3口写入“1”时,它们被内部上拉电阻拉高并可作为输入端口。此时,被外部拉低的P3口将用上拉电阻输出电流(IIL)。P3口除了作为一般的I/O口线外,更重要的用途是它的第二功能P3口还接收一些用于Flash 闪速存储器编程和程序校验的控制信号。
    RST:复位输入。当振荡器工作时,RST引脚出现两个机器周期以上高电平将使单片机复位。
    ALE/PROG:当访问外部程序存储器或数据存储器时,ALE(地址锁存允许)输出脉冲用于锁存地址的低8位字节。一般情况下,ALE仍以时钟振荡频率的1/6输出固定的脉冲信号,因此它可对外输出时钟或用于定时目的。要注意的是:每当访问外部数据存储器时将跳过一个AL脉冲。对Flash存储器编程期间,该引脚还用于输入编程脉冲(PROG)。如有必要,可通过对特殊功能寄存器(SFR)区中的8EH单元的D0位置位,可禁止ALE操作。该位置位后,只有一条 MOVX 和MOVC指令才能将ALE激活。此外,该引脚会被微弱拉高,单片机执行外部程序时,应设置ALE禁止位无效。
    PSEN:程序储存允许(PSEN)输出是外部程序存储器的读选通信号,当AT89C51由外部程序存储器取指令(或数据)时,每个机器周期两次PSEN有效,即输出两个脉冲。在此期间,当访问外部数据存储器,将跳过两次PSEN信号。
    EA/VPP:外部访问允许。欲使CPU仅访问外部程序存储器(地址为0000H—FFFFH),EA端必须保持低电平(接地)。需注意的是:如果加密位LB1被编程,复位时内部会锁存EA端状态。如EA端为高电平(接Vcc端),CPU则执行内部程序存储器中的指令。Flash存储器编程时,该引脚加上+12V的编程允许电源Vpp,当然这必须是该器件是使用12V编程电压Vpp。
    XTAL1:振荡器反相放大器的及内部时钟发生器的输入端。
    XTAL2:振荡器反相放大器的输出端。
    单片机最小原理图如图1-2-2所示。
    图1-2-2 单片机最小系统

    单片机最小系统说明:
    时钟信号的产生:在MCS-51芯片内部有一个高增益反相放大器,其输入端为芯片引脚XTAL1,其输出端为引脚XTAL2。而在芯片的外部,XTAL1和XTAL2之间跨接晶体振荡器和微调电容,从而构成一个稳定的自激振荡器,这就是单片机的时钟振荡电路。
    时钟电路产生的振荡脉冲经过触发器进行二分频之后,才成为单片机的时钟脉冲信号。
    一般地,电容C2和C3取30pF左右,晶体的振荡频率范围是1.2-12MHz。如果晶体振荡频率高,则系统的时钟频率也高,单片机的运行速度也就快。
    单片机复位使CPU和系统中的其他功能部件都处在一个确定的初始状态下,并从这个状态开始工作。单片机复位条件:必须使9脚加上持续两个机器周期(即24个振荡周期)的高电平。
    1.2.3 显示系统
    数码管是一种半导体发光器件,其基本单元是发光二极管。
    数码管按段数分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元(多一个小数点显示);按能显示多少个“8”可分为1位、2位、4位等等数码管;按发光二极管单元连接方式分为共阳极数码管和共阴极数码管。共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管。共阳数码管在应用时应将公共极COM接到+5V,当某一字段发光二极管的阴极为低电平时,相应字段就点亮。当某一字段的阴极为高电平时,相应字段就不亮。。共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管。共阴数码管在应用时应将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮。当某一字段的阳极为低电平时,相应字段就不亮。
    数码管要正常显示,就要用驱动电路来驱动数码管的各个段码,从而显示出我们要的数字,因此根据数码管的驱动方式的不同,可以分为静态式和动态式两类。
    1) 静态显示驱动:静态驱动也称直流驱动。静态驱动是指每个数码管的每一个段码都由一个单片机的I/O端口进行驱动,或者使用如BCD码二-十进制译码器译码进行驱动。静态驱动的优点是编程简单,显示亮度高,缺点是占用I/O端口多,如驱动5个数码管静态显示则需要5×8=40根I/O端口来驱动(要知道一个89C51单片机可用的I/O端口才32个呢),实际应用时必须增加译码驱动器进行驱动,增加了硬件电路的复杂性。
    2) 动态显示驱动:数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是那个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态驱动。
    本设计中数码管采用的是动态驱动方式。
    数码管外形如图1-2-3,数码管电路结构如图1-2-4。

    图1-2-3 数码管外形图
    图1-2-4 数码管电路结构示意图

    在这里插入图片描述
    图1-2-5 数码管显示电路
    1.2.4 发光二级管电路

    图1-2-6 发光二级管电路
    1.2.5 按键电路
    图1-2-7 按键电路

    第二章 软件设计与分析
    2.1 软件设计的组成
    该系统由延时子函数、数码管显示子函数、定时器0中断子函数、主函数和数据定义这几部分组成。
    在这里插入图片描述

    在这里插入图片描述

    //----------------------------------------------------------------------//
    上传过程感觉繁琐,里面可能有不全面的地方,请见谅。下面的是实现的目的。以及电路原理图

    **本次设计的主要目的是设计一个城市十字路口的交通灯控制系统,设计中将交通灯控制系统分为东西方向(主干道)和南北方向(次干道)两个方向,且在东西南北四个路口的每个路口设置红、绿、黄三个交通信号灯(用发光二极管模拟)和一个二位的LED数码显示管。设计的要求是规定在每一段时间内东西和南北两个方向中只有一个方向能够通行,另一个方向处于禁行状态,然后在经过一段时间后,禁行的方向和通行的方向互相转换状态,原来通行的状态变禁行状态,原来禁行的状态变为通行状态,如此循环下去。详细过程如下图2-1:
    状态① 状态②
    图 1图2-1 交通灯状态图
    状态①:东西方向的交通灯黄灯闪烁3秒后,红灯熄灭,绿灯点亮(东西方向允许车辆和行人通行),同时南北方向绿灯熄灭,红灯点亮(南北方向禁止车辆和行人通行),LED数码管倒计时显示40秒,在倒计时3秒时进入状态②。
    状态②:南北方向黄灯闪烁3秒后,红灯熄灭绿灯点亮(南北允许车辆和行人通行);同时东西方向绿灯熄灭,红灯点亮
    (东西方向禁止车辆和行人通行),LED数码管倒计时显示40秒,在倒计时3秒时进入状态①。
    接下来在没有人为干涉下将会一直按照上述进行循环。设计中还外设6个按键实现对交通灯控制系统的调控作用。

    电路原理图

    在这里插入图片描述

    在这里插入图片描述

    //——————————————————————————-——————————//
    相应的代码已经上传

    下载地址
    https://download.csdn.net/download/weixin_43442020/12231456

    下载链接里可以下载,解压后里面有压缩文件,压缩文件里面的资料更详细

    展开全文
  • 基于51单片机电子时钟

    万次阅读 多人点赞 2019-01-05 21:39:20
    1 基于51单片机用LCD1602实现时-分的显示 2. 按键控制时-分的调整 3. 能实现整时报时的功能(蜂鸣器响) 4. 闹钟模式 5.按键切换模式(模式一:时-分显示,模式二:60秒倒计时) 一、设计思路: 主体: 通过外部中断...

    keil工程与protues仿真电路

    1 基于51单片机用LCD1602实现时-分的显示
    2. 按键控制时-分的调整
    3. 能实现整时报时的功能(蜂鸣器响)
    4. 闹钟模式
    5.按键切换模式(模式一:时-分显示,模式二:60秒倒计时)

    一、设计思路:
    主体:
    通过外部中断0来控制mod值;mod=0,1.2,3分别对应时钟模式,调整模式,闹钟设置模式,一分钟倒计时模式。
    细节:
    mod0
    通过定时计数器,每一秒增加变量秒(s),每60秒,增加1分(min)并且s置0,每60min,增加1小时h,当h>23,h=0;进行一天循环
    mod1
    按键控制增加min,h和s制0
    mod2
    另外设置变量min1,h1,当min=min1,h=h1时蜂鸣器响
    mod3
    设置变量daojishi=60, 通过定时计数器,每一秒daojishi减1,当daojishi<0时,蜂鸣器响
    另外:
    1.设置外部中断2,关闭蜂鸣器
    2.时间发送一次只能发送一个位

    程序:

    #include<reg52.h>
    //K1后K3加分钟,K4加时间,K2加秒,K1进入闹钟设置,K2退出
    //K2关闭闹钟
    
    typedef unsigned int u16;	  //对数据类型进行声明定义
    typedef unsigned char u8;
    
    #define data8b P1
    
    sbit K1=P3^2;               //外部中断0
    sbit K2=P3^3;               //外部中断1
    sbit K3=P3^0;
    sbit K4=P3^1;
    
    sbit BUZ=P2^4;       //蜂鸣器,0响
    sbit RW=P2^5;        //4脚,数据(1)or命令(0)
    sbit RS=P2^6;        //5脚,读(1)写(0)
    sbit E=P2^7;         //6脚,使能信号
    
    u8 code dat1[]={0X30,0X31,0X32,0X33,
    	                               0X34,0X35,0X36,0X37,
    	                               0X38,0X39};
    
    void delay(u16 i)      //延时函数
    {
    	while(i--);
    }
    
    void open012()   //打开中断0,1,定时器中断0
    {
    	TMOD|=0X01;   //选择为定时器0模式,工作方式1
      
    	
    	ET0=1;        //打开定时器0中断允许
    	
    	EA=1;        //打开总中断
    	
    	TR0=1;       //打开定时器			
    	
    	EX0=1;              //打开外部中断0
    	IT0=1;             //边沿触发方式
    	EX1=1;              //打开外部中断1
    	IT1=1;             //边沿触发
      
    }
    
    
    void wrm(u8 dat)              //写入命令
    {
    	delay(1000);
    	RS=0;
    	RW=0;
    	E=0;
    	data8b=dat;
    	E=1;
    	delay(1000);
    	E=0;
    }
    
    
    void wrd(u8 dat)             //写入数据
    {
    	delay(1000);
    	RS=1;
    	RW=0;
    	E=0;
    	data8b=dat;
    	E=1;
    	delay(1000);
    	E=0;
    }
    
    void zero()
    {
    	wrm(0X38);                 //八位数据,两行显示,5*7
    	wrm(0X0c);                  //无光标,打开显示
    	wrm(0X06);                  //光标右移,屏幕不移动
    	wrm(0X01);                  //清屏
    	wrm(0X80);                  //设置数据指针起点
    }
    
    u8 fg=0,sg=0,bfg=0,bsg=0;
    u16 i=0;
    u8 s=0;
    u8 mod=0;
    char dingshi;
    bit bell=0;
    bit zanting=1;
    
    void fangsong()
    {
      wrd(dat1[sg/10]);                 //时十位
    	wrd(dat1[sg%10]);                 //时个位
    	wrd(0x3A);                     //:
    	wrd(dat1[fg/10]);                 //分十位
    	wrd(dat1[fg%10]);                 //分个位
    	wrd(0x3A);                     //:
    	wrd(dat1[(s/10)]);                 //秒十
    	wrd(dat1[(s%10)]);                 //秒个
    }
    
    
    void fangsong1()
    {
    	wrm(0X80);   
      wrd(dat1[sg/10]);                 //时十位
    	wrd(dat1[sg%10]);                 //时个位
    	wrd(0x3A);                     //:
    	wrd(dat1[fg/10]);                 //分十位
    	wrd(dat1[fg%10]);                 //分个位
    	wrd(0x3A);                     //:
    	wrd(dat1[(s/10)]);                 //秒十
    	wrd(dat1[(s%10)]);                 //秒个
    }
    void chuli()
    {
    	if(fg==60)
    	{
    		sg++;
    		fg=0;
    	}
    
    	if(sg==24)
    	{
    	
    		sg=0;
    	}
    	
    }
    
    
    
    void main()
    {
    	u8 shijian;
    	open012();
    	zero();
    	chuli();
    	fangsong();
    	shijian=100;
    	
    	
    	while(1)
    	{
    		while(mod==0)
    	{
    		EX1=1;              //打开外部中断1
    		if(s==60)
    		 {
    			 fg++;       //60秒转化为1分钟
    			 s=0;
    		 }
    				chuli();
    				if((fg==0)&&(shijian!=sg))
    				 {
    				  BUZ=0;
    					shijian=sg;
    				 }
    				fangsong1();
    				if((BUZ==0)&&(bell==0))
    			  {
    				delay(1000);
    				BUZ=1;
    			  }
    			if((fg==bfg)&&(sg==bsg)&&(bell==1))
    				BUZ=0;
    			else BUZ=1;
    			}
    	
    	
    			
    			while(mod==1)
    		{
    			EX1=0;              //关闭外部中断1
    			zero();
    	    fangsong();
    			if(K3==0)
    			  {
    				  delay(1000);
    				  if(K3==0)
    					  fg++;
    			   }
    			if(K4==0)
    			   {
    				  delay(1000);
    				  if(K4==0)
    					 sg++;
    			   }
    				 if(K2==0)
    			   {
    				  delay(1000);
    				  if(K2==0)
    					 s=0;
    			   }
    				 if(fg>59)
    				 {
    					 fg=0;
    				 }
    				  if(sg>23)
    				 {
    					 sg=0;
    				 }
    				 if(s>=59)
    				 {
    					 s=0;
    				 }
    	     }
    		
    			 
    			 
    			 while(mod==2)   //设置闹钟
    		{
    	    if(bfg==60)
    	    {
    		    bsg++;
    		    bsg=0;
    	    }
    	
    	    if(bsg==24)
    	    {
    		     bsg=0;
    	     }
    	    zero();
    			wrd(0x20);
    			wrd(0x20);
    			wrd(0x20);
    		  wrd(dat1[(bsg/10)]);                 //时十位
    	    wrd(dat1[(bsg%10)]);                 //时个位
    	    wrd(0x3A);                     //:
    	    wrd(dat1[(bfg/10)]);                 //分十位
    	    wrd(dat1[(bfg%10)]);                 //分个位
    			 if(K3==0)
    			{
    				delay(1000);
    				if(K3==0)
    					bfg++;
    			}
    			if(K4==0)
    			{
    				delay(1000);
    				if(K4==0)
    					bsg++;
    			}
    			bell=1;
    			zero();
    }
    		
    while(mod==3)
    {
    	while(zanting)
    	{
    	dingshi=60;
    	EX1=1;              //打开外部中断1
    	wrm(0X80);   
    	 wrd(dat1[(dingshi/10)]);                 //时十位
    	 wrd(dat1[(dingshi%10)]);            	//时个位
       }
       wrm(0X80);   
    	 wrd(dat1[(dingshi/10)]);                 //时十位
    	 wrd(dat1[(dingshi%10)]);            	//时个位	
    	while(dingshi<0)
    	{
    		wrm(0X80);   
    		 wrd(dat1[0]);                 //时十位
    	   wrd(dat1[0]);            	//时个位
    		BUZ=0;
    	}
    }
    }
    }
    
    void time0() interrupt 1
    {
       TH0=0XFC;	     //给定时器赋初值,定时1ms
    	 TL0=0X18;
    	 i++;
    	 if(i==1000)     //ms转化为s
    	 {
    		i=0;
    		 s++;
    		 dingshi--;
    	 }	
    }
    
    void key1() interrupt 0     //外部中断0,调整时间
    {
    	delay(1000);
    	if(K1==0)
    	  { 
    		  mod++;
    			while(!K1);
    	  }
    
    if(mod>3)
    {
    	mod=0;
    }
    	 zero();
    }
    
    void naozhong()  interrupt 2                     //开关闹钟
    {
    	if(K2==0)
    		{
    			delay(1000);           //消抖
    				if(K2==0)
    					{
    						bell=0;
    						BUZ=1;
    						zanting=~zanting;
    					}                       //关闭蜂鸣器
    						while(!K2);          //确认按键松开
         }
    }
    
    
    
    

    在这里插入图片描述

    二、收获
    1.更熟练掌握了定时器中断和外部中断的使用
    在这里插入图片描述

    在这里插入图片描述

    可以通过打开和关闭外部中断使同一个按键实现不同的功能

    2.了解到了一点寄存器操作

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    3.中断配置小结
    外部中断
    在这里插入图片描述
    定时器中断
    在这里插入图片描述

    串口通信
    在这里插入图片描述
    4.更熟练使用proteus
    制作了一个小型软件开发版
    在这里插入图片描述

    5.学会了如何学习一个新元器件(LCD1602)
    1.看说明书,重点是看时序图,真值表等
    2.按照时序图写程序
    3.一二都不成立时,查找相关资料
    6.下载原理
    单片机的烧写原理:
    单片机烧写,又称为单片机程序下载、烧录等,本质上是单片机和PC机按照芯片厂家规定的编程协议,通过芯片厂家规定的接口,把已编译好的程序传输到单片机,单片机把数据存储到自身存储器中。
    理解这个原理需要知道几个知识点:
    单片机内部是有程序的,是出厂时固化在硬件中,用户无法修改的(这也会被认为它内部没有程序),这些程序可以调用各种通信接口、内部存储器等;
    可以下载的通信接口:JTAG,SPI,UART,usb等;(还有很多可以扩展485、以太网等)
    编程协议:一般大厂都会公开的,在芯片的专用技术手册中会有;
    存储器:有很多种,掩膜,EPROM,EEROM,flash等寿命不一样,掩膜只能一次,而且要工厂做,flash擦写次数10000+;
    可以这样比喻性的理解:单片机就是电脑的主板,我们写的程序就是操作系统,主板里面装入引导操作系统的基本程序,下载程序就是给电脑装系统!

    7.其他
    1.理解了现在电子表的操作原理
    2.学会了借助现成品(电子表)作参考,写程序
    3.懂得了与人交流的重要性(受王同学的启发,完善了原有程序)

    三.后期计划
    1、继续32的学习
    2、练习焊功
    3、继续51其他外设的学习
    4、按兴趣学习电路、模电、数电、DXP等相关知识

    展开全文
  • 基于51单片机警灯

    2019-03-24 01:17:59
    基于51单片机警灯,附加详细代码注释讲解,给大家带来方便
  • 基于51单片机W5500

    2016-07-22 16:49:59
    基于51单片机W5500
  • 基于51单片机的智能窗户设计-基于五一单片机的只能窗户.rar
  • 基于51单片机的数字时钟
  • 基于51单片机呼吸灯

    2019-03-24 01:30:46
    基于51单片机的开发详细讲解,为大家更好的学习51单片机,方便交流
  • 基于51单片机的开发详细讲解,为大家更好的学习51单片机,方便交流
  • 基于51单片机的对讲机 原理图 原代码
  • 基于51单片机的电子琴,文件内有程序的项目文件以及仿真文件,适合入门学习51单片机的爱好者。
  • 基于51单片机电子音乐门铃设计,采用89c51单片机基于51单片机电子音乐门铃设计,采用89c51单片机
  • 基于51单片机电压表

    2019-03-24 01:27:37
    基于51单片机的开发,附加详细代码讲解,为大家更好的理解
  • 基于51单片机设计的简易电子琴

    万次阅读 多人点赞 2018-06-10 16:55:42
    基于51单片机设计的简易电子琴
    基于51单片机设计的简易电子琴

    下面直接给出proteus仿真电路。仿真和代码下载点击这里

    代码如下:

    #include <reg51.h> 
    #define uint unsigned int 
    #define uchar unsigned char
    #define output P1
    #define input P1
    //方便移植在其他电路板上,我的电路使用P1口做键盘输入接口
    //定义16个按键
    enum KEY{key0,key1,key2,key3,key4,key5,key6,key7,key8,key9,key10,key11,key12,key13,key14,key15};
    uchar code table[]={				  //数组定义,显示数码管
    	    0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
    	    0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    unsigned int code Freqtab[] = { 	//定时半周期的初始值
         64021,64103,64260,64400,      //低音3 4 5 6
         64524,64580,64684,64777,      //低音7,中音1 2 3
         64820,64898,64968,65030,      //中音4 5 6 7
         65058,65110,65157,65178};     //高音1 2 3 4
    uint FreqTemp;
    //蜂鸣器声音不怎么样,我们使用扬声器,接P3.7口
    sbit SPEAK = P3^7;
    void delay1ms(uint n)   //误差 0us ,延时n毫秒
    {
        uint a,b,c;
    	for(c=n;c>0;c--)
        	for(b=199;b>0;b--)
            	for(a=1;a>0;a--);
    }
    
    uint key_input(void)
    {
    	uchar temp1,temp2;			//临时保存读取的行或者列
    	uchar num = 16;			   	//返回按键的值
    	output = 0x0f;		
       	temp1 = input;				//先读取行
    	if(0x0f != temp1)   		//按键按下
    	{				   	
    		delay1ms(5);			//延时,消除抖动
    		temp1 = input;			//再次读取行
    		if(0x0f != temp1)		//说明按键确实按下	
    		{
    			temp1 = temp1 & 0x0f;	//保留低4位
    			output = 0xf0;			//准备读取列
    			delay1ms(1);			//延时一下,防止下一句读不到
    			temp2 = input;			//直接读取列
    			temp2 = temp2 & 0xf0;	//保留高4位
    			temp1 = temp1 | temp2;	//将temp1和temp2的值合并
    		}
    	}
    	switch(temp1)
    	{
    		case 0xee:num=0;break;  
            case 0xde:num=1;break;  
            case 0xbe:num=2;break;   
            case 0x7e:num=3;break; 
    		case 0xed:num=4;break;               
            case 0xdd:num=5;break;           
            case 0xbd:num=6;break;             
            case 0x7d:num=7;break;   
    		case 0xeb:num=8;break;    
            case 0xdb:num=9;break;    
            case 0xbb:num=10;break;   
            case 0x7b:num=11;break;    
    		case 0xe7:num=12;break;   
            case 0xd7:num=13;break;   
            case 0xb7:num=14;break;    
            case 0x77:num=15;break;      
    		default:break;
    	}
    	return num;
    }
    void T0_INT(void) interrupt 1
    {
         TL0 = FreqTemp;                //载入定时半周期的初始值
         TH0 = FreqTemp >> 8;
         SPEAK = ~SPEAK;                    //发音
    } 
    int main()
    {
    	TMOD = 0X01;		//定时器T0设置为方式1
    	EA = 1;
    	ET0 = 1;
    	TR0 = 0;
    	while(1)
    	{
    		uint num,temp;
    		num = key_input();
    		temp = num;
    		P0 = table[num];
    		if(16 != num)
    		{
    			FreqTemp = Freqtab[num];
    			TR0 = 1;
    			while(0xf0 != output);		//检测按键松开
    			TR0 = 0;
    			SPEAK = 1;	
    		}		
    	}
    	return 0;
    }
    展开全文
  • 基于51单片机的温控系统,可控制温度,并实时显示在lcd上。
  • 基于51单片机四路循迹小车

    万次阅读 多人点赞 2018-11-14 13:54:59
    这学期开设的51单片机课程的课程设计即将验收,今天开始正式着手做循迹小车~

    这学期开设的51单片机课程的课程设计即将验收,今天开始正式着手做循迹小车~

    一. 任务要求

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

    二. 系统原理

    本系统以设计题目的要求为目的,采用STC89C52单片机为控制核心,利用红外传感器检测轨道,控制电动小汽车的自动循迹,快慢速行驶。

    这里的轨道是指汽车沿着白色地板上的黑线行驶。由于黑线与白地板的反射系数不同,可以根据接收到的反射光的强度来判断“道路”。常用的方法是红外检测。

    红外检测方法,即在汽车行驶过程中,利用红外光在具有不同颜色的物体表面的不同反射特性,不断向地面发射红外光。当红外光与白纸地板相遇时,会发生漫反射,反射光被安装在车内的接收器接收,如果遇到黑线,就会变成红色。外部光被吸收,车内的接收器不能接收红外线。单片机根据是否接收到反射的红外光来确定黑线的位置和汽车的行驶路线。

    三. 整体方案

    1. 控制模块

    小车的核心控制部件采用STC公司生产的8位单片机STC89C52。它是一种低功耗、高性能CMOS8位微控制器,具有8K字节系统可编程Flash存储器。STC89C52使用经典的MCS-51内核,但是做了很多的改进使得芯片具有传统51单片机不具备的功能。STC89C52有3个16 位定时器/计数器,2个外部中断,1个串口中断。

    最小系统

    51单片机的具体引脚功能不细说,不了解的可自行百度。直接上最小系统电路图(自己画的,凑合着看)。顺便说一句,在我看来一个没有指示灯的电路是最烦的电路<(`^´)> 我的复位一定要有灯才行!

    在这里插入图片描述
    三部分:
    ①电源电路:给单片机提供5V的电源
    ②时钟电路:外接11.0592M石英晶振。
    ③复位电路:确保单片机是从一个确定的初始状态开始。

    焊接时注意P0口要接上拉电阻,否则不能用,一般都用排阻做上拉电阻(当然如果能自己画板子就更好了)。

    去除AD网格线

    记一下怎么去除AD网格线,如图步骤,最后去掉Visible前面的对勾即可,别忘记最后点OK:
    在这里插入图片描述

    2. 电机驱动模块

    我使用的是最经典的LM298N电机驱动:

    我太喜欢用298了。不仅可以接至12v(即拥有更强的驱动能力),而且有过电流保护功能,当出现电机卡死时,可以保护电路和电机等。且自带7805降压模块可直接给单片机供电~~
    实物图:
    在这里插入图片描述
    驱动与各部分的连接简介:
    输出A、B:分别接到左右马达上,通过使能A、使能B来控制电机正常工作(接高电平为正常工作);
    单片机IO控制输入(即IN1-IN4):用来控制马达正反转。接单片机引脚,通过在程序中给引脚高低电平实现正转或反转(详见下边输入输出关系表);
    12V输入:接电池盒正极;
    5V输入:接单片机VCC,给单片机供电;
    电源地(即GND):把电池盒负极和单片机的GND一起接入。
    在这里插入图片描述
    电路图:
    在这里插入图片描述
    输入输出关系(使能ENA、ENB均为1的状态下):

    In1 In2 运转状态
    1 0 正转
    0 1 反转
    1 1 刹停
    0 0 停止

    3. 电源模块

    我自己使用的是两节18500锂电池供电。如果觉得两节电池不够,三节12V又太大,也可以在中间加一个7809稳压管把电压降到9V再接入驱动:
    在这里插入图片描述

    4. 循迹模块

    光电循迹是由四对红外收发管组成,通过检测接收到的反射光强,判断黑白线。

    当模块探测灯检测到黑线时指示灯熄灭,同时 OUT端口持续输出高电平信号,反之未检测到黑线的探测灯应常亮,OUT端口输出低电平。该模块检测距离 2~60cm,检测角度 35 ° ,检测距离可以通过电位器进行调节,顺时针调电位器,灵敏度增加;逆时针调电位器,灵敏度减少。
    在这里插入图片描述
    原理图由红外对管和电压比较器两部分组成,红外对管输出的模拟电压通过电压比较器转换成数字电平输出到单片机。

    主控板的电路图:
    在这里插入图片描述
    小板电路图:
    在这里插入图片描述
    注意连接的时候:VCC-VCC、GND-GND、IN-OUT。

    比较器LM339
    在这里插入图片描述

    5. 超声波测距模块

    实物图:
    在这里插入图片描述
    电路图:
    在这里插入图片描述
    工作原理
      (1)采用IO口TRIG触发测距,给至少10us的高电平信号;
      (2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
      (3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
      测试距离=(高电平时间*声速(340M/S))/2;

    四. 车体实物图

    在这里插入图片描述

    五. 软件实现

    #include<reg52.h>
    typedef unsigned int u16;
    typedef unsigned char u8;
    
    sbit ENA = P2^0;   //右点机使能
    sbit IN1 = P2^1;   //为0右轮反转
    sbit IN2 = P2^2;   //为0右轮正转
    sbit IN3 = P2^3;   //为0左轮正转
    sbit IN4 = P2^4;   //为0左轮反转
    sbit ENB = P2^5;   //左电机使能
    
    sbit left1 = P1^3;
    sbit left2 = P1^2;
    sbit right1 = P1^1;
    sbit right2 = P1^0;
    
    u8 PWMCnt1 = 0;
    u8 PWMCnt2 = 0;
    u8 cntPWM1 = 0;
    u8 cntPWM2 = 0;
    
    void Timer0Init();
    void XunJi();
    
    void main()
    {
    	Timer0Init();
    	while(1)
    	{
    		XunJi();
    
    	}	
    }
    // i = 1时, 大概延时10us
    //void delay(u16 i)
    //{
    //    while (i--);
    //}
    
    void Timer0Init()
    {
    	TH0 = 0xFF;
    	TL0 = 0xA3;
    	TMOD &= 0xF0;
    	TMOD |= 0x01;
    	EA = 1;
    	ET0 = 1;
    	TR0 = 1;
    }
    
    void TurnRight1()		   //右转
    {
    	IN1 = 0;	//右轮反转
    	IN2 = 1;
    
    	IN3 = 0;	//左轮正转
    	IN4 = 1;
    	cntPWM1 = 70;
    	cntPWM2	= 55;
    }
    
    void TurnRight2()		   //右转
    {
    	IN1 = 0;	//右轮反转
    	IN2 = 1;
    
    	IN3 = 0;	//左轮正转
    	IN4 = 1;
    	cntPWM1 = 50;
    	cntPWM2	= 40;
    }
    
    void TurnLeft1()				//左转
    {
    	IN1 = 1;
    	IN2 = 0;   	//右轮正转
    
    	IN3 = 1;
    	IN4 = 0;   	//左轮反转
    	cntPWM1 = 55;
    	cntPWM2	= 70;
    }			  	
    
    void TurnLeft2()				//左转
    {
    	IN1 = 1;
    	IN2 = 0;   	//右轮正转
    
    	IN3 = 1;
    	IN4 = 0;   	//左轮反转
    	cntPWM1 = 40;
    	cntPWM2	= 50;
    }	
    	
    void Forward()				 //前进
    {
    	IN1 = 1;
    	IN2 = 0;   	//右轮正转
    
    	IN3 = 0;   	//左轮正转
    	IN4 = 1;
    
    	cntPWM1 = 40;
    	cntPWM2	= 40;
    }
    
    //void Backward()					 //后退
    //{
    //	IN1 = 0;	//右轮反转
    //	IN2 = 1;
    //
    //	IN3 = 1;
    //	IN4 = 0;	//左轮反转
    //	cntPWM1 = 30;
    //	cntPWM2	= 30;
    //}
    
    void Stop()					  //停止
    {
    	IN1 = 0;
    	IN2 = 0;
    
    	IN3 = 0;
    	IN4 = 0;
    }
    void XunJi()
    
    {
    	unsigned char flag = 0;
    
    	if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0))   //0 0 0 0
    		flag = 0;
    
    	if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1))   //0 0 0 1
    		flag = 1;
    
    	if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0))   //0 0 1 0
    		flag = 0;
    
    	if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1))   //0 0 1 1
    		flag = 1;
    
    	if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0))   //0 1 0 0
    		flag = 0;
    
    	if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1))   //0 1 0 1
    		flag = 4;
    
    	if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0))   //0 1 1 0
    		flag = 0;
    	
    	if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1))    //0 1 1 1
    		flag = 1;
    	
    	if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0))   //1 0 0 0
    		flag = 3;
    	
    	if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1))   //1 0 0 1
    		flag = 0;
    	
    	if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0))   //1 0 1 0
    		flag = 2;
    	// ?
    	if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1))   //1 0 1 1
    		flag = 0;
    	
    	if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0))   //1 1 0 0
    		flag = 3;
    	 //?
    	if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1))   //1 1 0 1
    		flag = 0;
    
    	if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0))   //1 1 1 0
    		flag = 3;
    	
    	if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1))   //1 1 1 1
    		flag = 5;
    	
    	switch(flag)
    	
    {
    		case 0:Forward();break;
    		
    		
    		case 1:TurnRight1();break;
    		
    		
    		case 2:TurnRight2();break;
    		
    		
    		case 3:TurnLeft1();break;
    		
    		
    		case 4:TurnLeft2();break;
    
    
    		default:Stop();break;
    	}
    }
    
    void InterruptTime0() interrupt 1
    {
    	PWMCnt1++;
    	PWMCnt2++;
    	
    	if(PWMCnt1  >= 200)
    	{
    		PWMCnt1 = 0;
    	}
    	if(PWMCnt1 <= cntPWM1)
    	{
    		ENA = 1;
    	}
    	else
    	{
    		ENA = 0;
    	}
    
    	if(PWMCnt2 >= 200)
    	{
    		PWMCnt2 = 0;
    	}
    	if(PWMCnt2 <= cntPWM2)
    	{
    		ENB = 1;
    	}
    	else
    	{
    		ENB = 0;
    	}
    
    	TH0 = (65536 - 50)/256;
    	TL0 = (65536 - 50)%256;
    }
    
    展开全文
  • 基于51单片机的广州塔,含原理图,程序,焊接步骤等等,
  • 基于51单片机的贪吃蛇
  • 基于51单片机智能热水器程序 基于51单片机智能热水器程序.rar
  • 基于51单片机的温控风扇,里面含有源程序,原理图,仿真以及PCB图
  • rc522基于51单片机资料

    2019-04-21 22:00:24
    rc522基于51单片机的相关读写程序和资料
  • 基于51单片机的智能计算器
  • 基于51单片机的电子秤程序,是学校校赛比赛做的,可以实现1g精度,代码用keil打开即可运行,简单易懂
  • 基于51单片机的温室测试系统、电子技术,开发板制作交流
  • 基于C51单片机实现简单点阵五子棋Keil程序与protues电路仿真图
  • 基于51单片机打铃系统.rar
  • 基于51 单片机自制触摸屏,一个基于51单片机的简单触摸例子
  • 本文给大家分享了基于51单片机can总线头文件定义。
  • 基于51单片机160种例程,欢迎大家下载参考,谢谢!
  • 基于51单片机的开发详细讲解,为大家更好的学习51单片机,方便交流
  • 基于51单片机八路抢答器,欢迎大家下载,本人亲测!

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,388
精华内容 2,555
关键字:

基于51单片机