一 、单片机IO实验

本文介绍了通过AT89C51单片机进行IO口控制的三个实验:LED流水灯、交替移动及闪烁、蜂鸣器发声。实验详细阐述了电路设计、程序编写及Proteus仿真过程,展示了如何实现单片机对IO口的输入输出控制以及延时子程序的编写。同时,作者分享了自我设定的交通灯控制系统设计,包括倒计时和暂停功能,以及绿灯时长的串口通信控制。
摘要由CSDN通过智能技术生成

一、 单片机IO实验

​ 自律 学习 坚强 ,拒绝迷茫。

作者:行走的皮卡丘

时间:2021/03/23

喜欢就去追,这个红灯等不到,说不定下一个红灯等到了,嘻嘻!!!!!!!

一、实验目的

  • 1、掌握AT89C51 单片机IO 口的输入输出。

  • 2、掌握用查表方式实现AT89C51 单片机IO 口的控制。

  • 3、练习单片机简单延时子程序的编写。

  • 4、熟练运用Proteus 设计、仿真AT89C51 系统。

  • 5、使用单片机开发试验仪来验证实验结果。

二、实验原理

1、 单片机最小系统由单片机芯片、时钟电路以及复位电路构成。

img

2、I/O 口

P0 口:8 位双向I/O 口。在访问外部存储器时,P0 口可用于分时传送低8 位地址总线和8 位数据总线。能驱动8 个LSTTL 门。

P1 口:8 位准双向I/O 口(“准双向”是指该口内部有固定的上拉电阻)。能驱动4 个LSTTL门。

P2 口:8 位准双向I/O 口。在访问外部存储器时,P2 口可用于高8 位地址总线。能驱动4 个LSTTL 门。

P3 口:8 位准双向I/O 口。能驱动4 个LSTTL 门。P3 口还有第二功能。

P1 口作为输出口时与一般的双向口使用方法相同。当P1口用为输入口时,必须先对它置1。若不先对它置1,读入的数据可能是不正确的。

三、设计步骤:

【PROTEUS电路设计】

在ISIS 中进行电路图设计,发光二极管流水灯实验装置电路原理图如下图所示。

在这里插入图片描述

图一

  • 1、按照元件清单从PROTEUS 库中选取元器件,进行第2、3、4、5、6 步,完成原理图。
元件名称所属类所属子类
AT89C51(单片机)Microprocessor ICs8051 Family
RES(电阻)ResistorsGeneric
LED-YELLOW(黄色发光二极管)OptoelectronicsLEDs
CAP(电容)CapacitorsGeneric
CAP-ELEC(电解电容)CapacitorsGeneric
CRYSTAL(晶振)Miscellaneous
SWITCH(按键)Switich&relaysSwitchs
  • 2、放置元器件;

  • 3、放置电源和地;

  • 4、连线;

  • 5、参照原理图进行元件属性设置;

  • 6、电气检查。

【实验程序设计】

  • 1、流程图:

  • 2、在KeilC 中进行源程序设计:

  • 3、编译、生成目标代码

【PROTUES 仿真】

  • 1、在AT89C51 属性页中加载KeilC 中生成的目标代码;

  • 2、仿真、调试代码

  • 3、注意使用观察窗口

四、实验内容

1、见图一。通过AT89C51 单片机控制8 个发光二极管发光,实现亮点以由上到下循环移动,间隔时间为0.1S。

img

电路连接图:

img

代码

#include "reg52.h"
#include "intrins.h"
#define uint unsigned int  //无符号整型
#define uchar unsigned char //无符号字符型
#define led P1	//对整个P2端口进行操作

uchar temp;
//ms
void delay(uint z)
{
	int x,y;
	for(x = 0; x < z; x++)
		for(y=0;y<110;y++);	
}

void Led_Pipeline_1() //先左再右逐个亮起,不熄灭;再从右到左逐个熄灭;

{
		//方法五:
		led = 0XFF;
		delay(1);
		led = 0XFE;  //1
		delay(1);
		led = 0XFD;  //2
		delay(1);
		led = 0XFB;  //3
		delay(1);
		led = 0XF7;  //4
		delay(1);
		led = 0XEF;  //5
		delay(1);
		led = 0XDF;  //6
		delay(1);
		led = 0XBF;  //7
		delay(1);
		led = 0X7F;  //8
		delay(1);
		led = 0XFF;
		delay(1);
}

void Led_Pipeline_2() //先左再右逐个亮起,不熄灭;再从右到左逐个熄灭;
{
		//	方法六:

		P1 = temp;

    delay(1);

    temp = _crol_(temp,1);
}

void main()
{   

	temp = 0xfe;

	while(1)

	{
		Led_Pipeline_1();

		Led_Pipeline_2();
	}

}
实验效果图:

img

2、见图一。通过AT89C51 单片机控制8 个发光二极管发光,循环实现亮点由上到下移动1 次(间隔时间为0.2S),由下到上移动1 次(间隔时间为0.2S),闪烁1 次(即先全亮0.1S,再全灭0.1S)。

电路连接图:

img

代码:

#include "reg52.h"

#include "intrins.h"

#define uint unsigned int  //无符号整型

#define uchar unsigned char //无符号字符型

#define led P1	//对整个P2端口进行操作

uchar temp;

//ms

void delay(uint z)

{

	int x,y;

	for(x = 0; x < z; x++)

		for(y=0;y<110;y++);	

}

void Led_Pipeline_1() //先左再右逐个亮起,不熄灭;再从右到左逐个熄灭;
{

		//	方法六:

	int i;

	for(i=0;i<7;i++)

	{

		P1 = temp;

		 delay(100);

    temp = _crol_(temp,1);}

	for(i=0;i<7;i++)

	{

		P1 = temp;

		 delay(100);

    temp = _cror_(temp,1);

	} 

}

void main()
{   
	temp = 0xfe;
	while(1)
	{
		Led_Pipeline_1();}

}

实验效果图:

img

img

img

3、用蜂鸣器发出固定电话回音声音。见图三。

固定电话回音声音:450Hz,通1秒断4秒。(1秒时间内,输出频率450Hz信号;另外四秒无声音)

电路连接图:

img

流程图:

img

代码:

#include "reg52.h"

#define uchar unsigned char

#define uint  unsigned int
sbit BUZZ = P1^5;
void OpenBuzz(uint freq); 
void StopBuzz();
void delay_ms(uint xms);
uint reload;					 //计算所需定时器重载值
void main()
{
	TMOD|=0x01;
	EA=1;
	while(1)
	{
		OpenBuzz(450);       //以4KHZ频率启动蜂鸣器
		delay_ms(1000);
		StopBuzz();         //停止蜂鸣器
		delay_ms(4000);
     }
}
void OpenBuzz(uint freq)
{
   reload = 65536 - (11059200/12)/(freq*2); 
   TH0 = reload/256;
   TL0 = reload%256;
   ET0 = 1;
   TR0 = 1;
}
void StopBuzz()
{
  ET0 = 0;
  TR0 = 0;
}

void Timer0() interrupt 1
{
	TH0 = reload/256;
	TL0 = reload%256;
	BUZZ = ~BUZZ;
} 
void delay_ms(uint xms)
{
	uint i,j;
	for(i=xms;i>0;i--)
		for(j=110;j>0;j--);

}

实验效果图:

img

4、 简易模拟交通灯img****(********自己作图********)****

​ 说明:东西向绿灯亮10秒,黄灯闪烁3次后红灯亮, 红灯亮后,南北向由红灯变为绿灯,15秒后南北向黄灯闪烁3次后变红灯,东西向变绿灯,如此重复。

电路连接图:

img

流程图:

img

代码:

#include "reg52.h"

#define uint unsigned int  //无符号整型

#define uchar unsigned char //无符号字符型

sbit red1 = P0^0;

sbit yellow1 = P0^1;

sbit green1 = P0^2;

sbit red2 = P0^3;

sbit yellow2 = P0^4;

sbit green2 = P0^5;

//ms
void delay_ms(uint z)
{
	int x,y;
	for(x = 0; x < z; x++)
		for(y=0;y<110;y++);	
}

void main()
{

	P1 = 0XFF;

	while(1)

	{

//		P1 = 0XFF;

//		delay_ms(1000);

//		P1 = 0;

//		delay_ms(1000);

		red2=0;

		red1=1;

		green1 = 0;

		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		green1 = 1;

		yellow1=0;

		delay_ms(100);

		yellow1=1;

		delay_ms(100);

		yellow1=0;
		delay_ms(100);
		yellow1=1;
		delay_ms(100);
		yellow1=0;
		delay_ms(100);
		yellow1=1;
		delay_ms(100);
		red1=0;
		red2=1;
		green2 = 0;
		delay_ms(1000);
		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		delay_ms(1000);

		green2 = 1;

		yellow2=0;

		delay_ms(100);

		yellow2=1;

		delay_ms(100);

		yellow2=0;

		delay_ms(100);

		yellow2=1;

		delay_ms(100);

		yellow2=0;

		delay_ms(100);

		yellow2=1;

		delay_ms(100);
	}

}

实验效果图:

img

img

img

img

img

五、提交实验报告写作内容要

请写出实验过程中曾出现的问题和你的解决方法,你对实验有何感想和体会?

一开始自我拟了一道题:做一个十字路口交通灯,带倒计时功能,有暂停功能,绿灯时长控制功能。且暂停时倒计时灯熄灭,十字路口红灯全亮;绿灯时长的控制由另一个单片机进行控制(串口通信)。

实验时:

①我先通过Proteus搭建一个只有十字路口交通灯的电路。搭建完电路后,通过代码编程,实现基本的交通灯功能。具体为按照四个路口方向逐次亮起红灯24秒,绿灯5秒,黄灯3秒。

②搞完交通灯的显示问题后,我去proteus中继续添加一部分电路,用于实现十字路口交通灯的倒计时的显示。这时发现单片机引脚不太够用,毕竟交通灯就占了12个引脚,若倒计时的显示全部直接用单片机的引脚作为控制,则要用到16个引脚。这明显(12+16=28)会用到P3口的引脚。但我又不想用P3口来做这些事,P3口我打算用于功能按键的控制。这时我想起动态数码管的位选其实可以用138译码器来进行,这样只需3个端口用于选择地址,而剩下的5个端口则省下来了。相关电路添加完毕后,我继续通过代码编程,实现基本的交通灯功能+倒计时功能。

③在单片机A中,加了个外部中断0,并在proteus中修改了对应电路。并通过在while(1)死循环中,用if….else….进行分支选择,成功把交通灯暂停功能添加上去了。

④在单片机B中,通过两个按键,并在代码中,实现了绿灯时长的加减,且通过串口发送给了单片机A中。至此完成了自拟题目的功能要求。

最后的最后就是,修改了一些小bug,例如增加了绿灯、红灯时长范围,防止绿灯时间过长等。并且在不影响功能的前提下,优化了下代码,尽量节约单片机的内存空间(虽说是实验而已,没必要,但还是要有一个好习惯),简化代码,使之既层次分明、通俗易懂,又简单直了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

行走的皮卡丘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值