IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 单片机实验记录 -> 正文阅读

[嵌入式]单片机实验记录

单片机实验

1、实验1 基本输入输出实验

题目:在Proteus环境下,设计基于51单片机(采用AT89C51)控制电路。P3.2和P3.3口线接两个按钮开关K0、K1,P1口和P2口接了两个共阴极LED显示器。编程实现:开始显示数字50,定义K0和K1分别为
+1 和 -1 键,即按K0显示的数字是 +1,按K1显示的数字是 -1。当显示数字 +1 到99后(或显示数字 -1 到0后),恢复显示数字初值50。K0和K1的管理采用查询的方式。

代码:

#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit K0=P3^2;
sbit K1=P3^3;
uchar data i;			//定一个RAM单元
uchar data dir_buf[2];	//显示缓存区
uchar code dirtable[18]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};  //显示表
void delay(uint xms)	//延时函数
{
	uint t1,t2;
	for(t1=0;t1<xms;t1++)
	for(t2=0;t2<120;t2++);
}
void display()			 //显示函数
{
	P1=dirtable[dir_buf[0]];   //P2口显示
	P2=dirtable[dir_buf[1]];   //P1口显示
}
void key()				 //按键管理函数
{
	uchar key1;
	K0=1;K1=1;			 //读按键前先写1
	key1=P3;			 //读按键值
	key1=key1&0x0c;		 //屏蔽掉无用位
	while(key1!=0x0c)	 //判断是否有按键按下
	{
		delay(6);		 //去抖动
		key1=P3;		 //再读
		key1=key1&0x0c;
		while(key1!=0x0c)  //再次判断是否有按键按下
		{
			if(K0==0)	  //K0按下的时候加1
				i=i+1;
			else
				i=i-1;
			K0=1;K1=1;	  
			key1=P3;
			key1=key1&0x0c;
			while(key1!=0x0c)	 //判断按键是否抬起
			{
				key1=P3;
				key1=key1&0x0c;
			}
		}
		
	}
}
void main()
{
	i=50;
	while(1)
	{
		if(i>99 || i<0)
		{
			i=50;
		}
		else
		{
			key();				//调用按键管理
			dir_buf[0]=i/10;	//十位
			dir_buf[1]=i%10;	//个位
			display();
		}
	}
}

电路图:
在这里插入图片描述

实验2 并行I/O口应用设计实验

题目要求:设计用两个开关S1、S2控制P1.0引脚实现蜂鸣器报警的程序,要求如下: (1)开关S1、S2分别接到P3.0、P3.1引脚上。
(2)蜂鸣器接到P1.0引脚上。 (3)开关S1闭合发出频率为1kHz的声音,发声时间约为1s。
(4)开关S2闭合发出频率为500Hz的声音,发声时间约为0.5s。 提示: (1)假设单片机系统时钟频率为12MHz。
(2)采用软件延时。
(3)在Proteus中,可以使用的蜂鸣器有两种,分别是SOUNDER和BUZZER,实验前请查阅资料了解蜂鸣器的使用方法。

代码:

#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit S1=P3^0;
sbit S2=P3^1;
sbit sourder=P1^0;
uchar mask=0x03;
uint t3,t4;
void delay(uint xms)	//延时函数
{
	uint t1,t2;
	for(t1=0;t1<xms;t1++)
	for(t2=0;t2<110;t2++);
}
void delay_time(uint times)
{
	uint i;
	for(i=0;i<times;i++);
}
void play(times)        //根据不同的频率进行播放的函数
{
	sourder=1;
	delay_time(times);
	sourder=0;
	delay_time(times);
}
void keyspan()				 //按键管理函数
{
	uchar key;
	S1=1;S2=1;			 		//读按键前先写1
	key=P3;			 			//读按键值
	key=key&mask;		 //屏蔽掉无用位
	while(key!=mask)	 //判断是否有按键按下
	{
		delay(6);		 //去抖动
		key=P3;		 //再读
		key=key&mask;
		while(key!=mask)  //再次判断是否有按键按下
		{
			if(S1==0)				//S1按下的时候加1
			{	
				for(t3=0;t3<1000;t3++)	   //频率为1000hz,发声时间为1s
					play(62);                //0.5ms延时来获取1khz的频率(高低电平之间的转换延时)
			}
			else
			{
				for(t4=0;t4<250;t4++)     //频率为500hz,发声时间为0.5s
					play(125);							//1ms的延时来获取500hz的频率(高低电平之间的转换延时)
			}
			S1=1;S2=1;	  
			key=P3;
			key=key&mask;
			while(key!=mask)	 //判断按键是否抬起
			{
				key=P3;
				key=key&mask;
			}
		}
	}
}
void main()
{
	sourder=0;
	while(1)
	{
		keyspan();
	}
}

电路图:
在这里插入图片描述

实验3 中断应用实验

本实验为租车里程测量模拟计算实验,要求如下:
假设出租车车轮转1圈产生2个负脉冲,轮胎周长为2m。试测量并显示出租车的行驶里程,测量与显示范围0~999999米。设计硬件电路并编写程序。(车轮转动信号通过中断方式获取)
设置一个按键S1,控制出租车行驶里程显示的启动和清零。(用中断方式控制)
【提示】
(1)行驶里程显示可以使用7段六位共阴级数码管(7SEG-MPX6-CC)或7段六位共阳级数码管(7SEG-MPX6-CA)。
(2)可以用Proteus中的虚拟仪器“SIGNAL GENERATOR(信号发生器)”(见右图)作为外部中断输入信号,模拟车轮转动产生的脉冲信号。
(3)实验前查阅资料,了解出租车里程计算和计价器计价原理。

代码:

#include<reg51.h>
#define uchar unsigned char
#define ulong unsigned long
unsigned char code table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数字显示的代码表(0~9)
bit flag = 0;      					//里程计数开关(0停止并清零,1启动)
ulong s = 0;   							//里程计量(满999999后清零)
uchar odometer[6];					//里程表
ulong c[7]= {1,10,100,1000,10000,100000,1000000}; 	//进行每位的值计算
void delay(uchar xms)//延时函数
{
	uchar i,j;
	for(i=0;i<xms;i++)
		for(j=0;j<110;j++);
}
void display()  //显示函数
{
	int bitcode,i;
	// odometer [0] = (s%10)/1;					//第6位
	// odometer [1] = (s%100)/10;				//第5位
	// odometer [2] = (s%1000)/100; 			//第4位
	// odometer [3] = (s%10000)/1000;		//第3位
	// odometer [4] = (s%100000)/10000;  //第2位
	// odometer [5] = (s%1000000)/100000;//第1位
	for(i=0;i<6;i++)              //找到规律一次性初始化各个位
	{
		odometer[i] = (s%c[i+1])/c[i];
	}
	bitcode=0xfe;
	for(i=5;i>=0;i--)
	{
		P2=bitcode;
		P1=table[odometer[i]];
		delay(1);
		bitcode=(bitcode<<1)| 0x01;			
	} 
}
void interupt_0(void) interrupt 0 //信号中断控制
{
	if(flag==1)
	{
		s++;
		if(s>999999)
			s=0;
	}
}
void interupt_1(void) interrupt 2 //按钮S1中断控制
{
	if(flag==0)           //启动
	{
		flag=~flag;
	}
	else
	{
		s=0;                //清零
		flag=~flag;
	}
	
}
void main(void)
{
	IT0 = 1;              //外部中断0
	IT1 = 1;							//外部中断1
	EA = 1;								//中断允许
	EX1 = 1;						
	EX0 = 1;
	PX1 = 1;						
	while(1)
	{
		display();
	}
}

电路图:
在这里插入图片描述

实验4 定时器应用实验

本实验为“秒表设计”实验,即用单片机定时/计数器设计一个秒表。具体要求如下:
(1)秒表显示格式为“0000”,前两位为秒(s),计时到60s清0,后两位为百分之一秒,计到100即清0并且使前2位加1。
(2)设置两个按键K1和K2,其中,K1控制秒表的“启动/暂停”(即按一次“启动”,再按一次“暂停”),K2控制秒表“清零”,按键的同时要显示按键状态值(设“启动”、“暂停”和“清零”三种按键状态值分别为1、2、3)。要求K1和K2按中断方式工作。
【提示】
秒表显示和按键状态值显示可以使用7段六位共阴级数码管(7SEG-MPX6-CC)或7段六位共阳级数码管(7SEG-MPX6-CA),显示功能分配见下图。
在这里插入图片描述

代码:

分析:

在这个实验中,我使用的是工作方式1,因为要求是百分之一秒来进行计时,故0.01s=10ms.故需要最大定时时间大于10ms的方式。(当然也可以使用方式0,思路是:让定时器5ms中断一次,可以设定一个计中断次数的值n,当中断两次即10ms,使秒表的百分位加1同时将n重新赋值为1),使用方式1的时候,让定时器10ms中断一次同时将百分位加1即可。
方式1:定时初值计算:计数初值 = 65536– 10ms / ( 12MHz×12 )=65536-10000=55536。

#include<reg51.h>
#define uchar unsigned char
#define ulong unsigned long
unsigned char code table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数字显示的代码表(0~9)
int count;              									//led显示 1 启动  2 暂停 3 清零
bit isStart;                              //开始 暂停标志位 0 开始 1 暂停
ulong s = 0;  														//秒表计时整体时间
uchar time[6];														//经过运算后显示管各位的数值
ulong c[7]= {1,10,100,1000,10000,100000,1000000}; 	//进行每位的值计算
void delay(uchar xms)											//延时函数
{
	uchar i,j;
	for(i=0;i<xms;i++)
		for(j=0;j<110;j++);
}
void display()  													//显示函数
{
	uchar bitcode,i;
	for(i=0;i<6;i++)              					//找到规律一次性初始化各个位
	{
		time[i] = (s%c[i+1])/c[i];
	}
	time[5]=count;					//将显示管的最高显示位设置位启动、暂停和清零的状态值
	bitcode=0xdf;
	for(i=0;i<6;i++)
	{
		P2=bitcode;
		P1=table[time[i]];
		delay(1);
		if(i==4)
		{
			bitcode=0xfd;						//当在显示管从左往右看的第二位的时候,重新赋值。
		}
		bitcode=(bitcode>>1)|0x82;	//每次都不选显示管从左往右看的第二位(即不进行选通位选段)	
	} 
}
void timer0() interrupt 1 							//定时器0
{   
	TR0=0;                     						//停止T0
	if(isStart==0)
	{
		TH0=(65536-10000)/256;
		TL0=(65536-10000)%256;  						//T0初始化
		s++;
		if(s>6000)
		{
			s=0;
		}
	}
	else if(isStart==1)
	{
		TR0=0;
	}
	TR0=1;
}

void my_int0(void) interrupt 0
{
	if(isStart==0)           				//启动
	{
		isStart=1;
		count=2;
	}
	else if(isStart==1)							//暂停
	{
		isStart=0;
		count=1;
	}
}
void my_int1(void) interrupt 2
{
		s=0;                			//清零
		count=3;
		isStart=1;
}
int main()
{
	TMOD=0x01;
	TH0=(65536-10000)/256;
	TL0=(65536-10000)%256;  	 //T0初始化
	EA=1;
	ET0=1;           					//IE定时器允许
	TR0=1;            				//启动定时器
	
	IT0 = 1;                	//外部中断0
	IT1 = 1;							  	//外部中断1
	EX1 = 1;						
	EX0 = 1;
	isStart=1;								//开始,计时器暂停。
	count=2;
	while(1)
	{
			display();      	 	
	}
}

电路图:
在这里插入图片描述

实验5 计数器应用实验

编写程序实现:用定时器/计数器T0监视一生产线(用逻辑触发器模拟),每产生10个工件,发出一个包装命令(即由P1.0引脚输出一个正脉冲),同时记录其箱数并将当前的箱数值显示在LED显示器上(显示到100后清0)。

分析 计数器工作方式选择及计数初值计算分析 因为题目中要求需要自动装箱,且10次装一次,故需要选取能自动装值的。
方式2的特点:初始化时把计数初值分别装入TL0和TH0中,当计数溢出时,由预置计数器自动给计数器TH0重新装初值。 初值计算:计数初值 =
256 – N ;即计数初值=256-10=246

代码:

#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//数码表

sbit Single=P1^0;  	//装箱脉冲信号
sbit s0=P3^0;				//十位显示器位选
sbit s1=P3^1;				//个位显示器位选

uint count=0;				//装箱个数计数器

void delay(uchar xms)	//延时函数
{
	uchar i,j;
	for(i=0;i<xms;i++)
		for(j=0;j<110;j++);
}
void display()
{
	P2=table[count/10];	//装箱数的十位数
	s0=1;s1=0;					//选择十位显示器
	delay(1);
	s0=0;s1=0;
	
	P2=table[count%10];	//装箱数的个位数
	s0=0;s1=1;					//选择个位数
	delay(1);
	s0=0;s1=0;
}
void count0() interrupt 1	//T0当作计数器
{
	count=count+1;			//累计装箱数
	if(count==100)			//做溢出处理
		count=0;
	Single=1;						//装箱控制信号
	delay(1);
	Single=0;
}
void main()
{

	count=0;
	Single=0;
	TMOD=0x06;
	TH0=TL0=256-10;      //使用方式2,初值可以自动装入8位定时器/计数器中
	EA=1;
	ET0=1;
	TR0=1;
	while(1)
	{
		display();
	}
}

电路图:
在这里插入图片描述
实验结果:
(1)程序刚开始运行
在这里插入图片描述
(2)产生了10个工件,进行一次包装
在这里插入图片描述
(3)第99次装箱,即产生了990个工件
在这里插入图片描述

实验6 D/A转换实验

波形发生器设计。

  1. 功能要求 (1)有4个功能键,分别用来选择输出:三角波、梯形波、方波和正弦波。 (2)按下某个功能键,进入中断,在中断程序中查询,确定按下的是哪个功能键,并输出对应的波形。
    (3)有一个2位的数码管显示器,显示功能号01、02、03、04,分别代表输出三角波、梯形波、方波和正弦波。
  2. 设计任务 (1)完成单片机最小系统电路设计。 (2)完成按键电路设计。 (3)完成D/A转换及接口电路的设计。 (4)完成显示电路设计。

代码:

#include<reg51.h>
#include<absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define DAC0832 XBYTE[0x7fff]
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//数码表

sbit s0=P3^0;				//十位显示器位选
sbit s1=P3^1;				//个位显示器位选

sbit KEY1=P2^0; //三角波
sbit KEY2=P2^1; //梯形波
sbit KEY3=P2^2; //方波
sbit KEY4=P2^3; //正弦波

code uchar sintab[]={0x7f,0x8a,0x95,0xa0,0xab,0xb5,0xbf,0xc8,
					0xd1,0xd9,0xe1,0xe8,0xee,0xf3,0xf7,0xfb,0xfd,0xff,0xff};

uint count=0;		//功能键标志(01、02、03、04,分别代表输出三角波、梯形波、方波和正弦波)
uint cou=0;		
//延时函数
void delay(uchar xms)
{
	uchar t1,t2;
	for(t1=1;t1<xms;t1++)
		for(t2=1;t2<120;t2++);
}
void display()
{
	P1=table[count/10];	//十位数
	s0=1;s1=0;					//选择十位显示器
	delay(1);
	s0=0;s1=0;
	
	P1=table[count%10];	//个位数
	s0=0;s1=1;					//选择个位数
	delay(1);
	s0=0;s1=0;
}
//三角波
void Triangle()
{
	uchar i = 0;
	while(1)
	{
		if(KEY1==0)
		{
			for(i=0;i<255;i++)
				{DAC0832=i;display();}       //从0开始到FEH(上升阶段)
			for(i=255;i>0;i--)
				{DAC0832=i;display();}			//从FEH开始到0(下降阶段)
		}
		else
		{
			break;
		}
	}
}

//梯形波
void Trapezoidal()
{
	uchar i = 0;
	while(1)
	{
		if(KEY2==0)
		{
			for(i=255;i>0;i--)
				{DAC0832=i;display();}       
			for(i=0;i<255;i++)
				{DAC0832=0;display();}
			for(i=0;i<255;i++)
				{DAC0832=i;display();}
		}
		else
		{
			break;
		}
	}
}

//方波
void square()
{
	uchar i = 0;
	while(1)
	{
		if(KEY3==0)
		{
			for(i=0;i<100;i++)
				{DAC0832=255;display();}
			for(i=0;i<100;i++)
				{DAC0832=0;display();}
		}
		else
		{
			break;
		}
	}
}
//正弦波
void sin()
{
	uchar i = 0;
	while(1)
	{
		if(KEY4==0)
		{
			for(i=0;i<18;i++)
				{DAC0832 = sintab[i];display();}     //第1个1/4周期
			
			for(i=18;i>0;i--)
				{DAC0832 = sintab[i];display();}     //第2个1/4周期
			
			for(i=0;i<18;i++)
				{DAC0832 = ~sintab[i];display();}     //第3个1/4周期
			
			for(i=18;i>0;i--)
				{DAC0832 = ~sintab[i];display();}     //第4个1/4周期
		}
		else
		{
			break;
		}
	}
}
	
void bo()
{
	if(count==01)
	{
		Triangle();
	}
	if(count==02)
	{
		Trapezoidal();
	}
	if(count==03)
	{
		square();
	}
	if(count==04)
	{
		sin();
	}
}

void int0_interrupt(void) interrupt 0 using 3//外部中断0
{	
	EX0=0;//关中断
	if(KEY1==0) {count=01;}
	if(KEY2==0) {count=02;}
	if(KEY3==0) {count=03;}
	if(KEY4==0) {count=04;}
	EX0=1;//开中断
}
void main()
{
	IT0=1;//INT0下降沿中断
	EX0=1;
	EA=1;
	while(1)
	{
		bo();
	}
}

电路图:
在这里插入图片描述

实验结果:
(1)三角波
在这里插入图片描述
(2)梯形波
在这里插入图片描述
(3)方波
在这里插入图片描述
(4)正弦波
在这里插入图片描述

实验7 A/D转换实验

直流数字电压表的设计与实现。

  1. 功能要求 数字电压表(DigitalVoltmeter)简称DVM,它是采用数字化测量技术,把连续的模拟量转换成不连续、离散的数字形式并加以显示的仪表。要求使用AT89C51单片机,采用动态显示的方式,把8通道模数转换器ADC0808/0809采样的电压值的大小经单片机处理后由数码管显示出来,量程为0
    ? 5V,显示格式为X.XXX。
  2. 设计任务 (1)完成单片机最小系统电路设计。 (2)完成A/D转换及接口电路的设计。 (3)完成显示电路设计。

代码:

#include<reg51.h>
#include<absacc.h>
#define uint unsigned int
#define uchar unsigned char
#define ADC0809 XBYTE[0x78ff]
sbit P33=P3^3;
sbit P26=P2^6;
sbit P25=P2^5;
sbit P24=P2^4;
sbit P23=P2^3;
uchar code table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//普通数字显示的代码表(0~9)
uchar code numdep[10]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};//带小数点的数字显示的代码表(0~9)
uchar vdata;	//输出的数字电压值 
int c[5]= {10000,1000,100,10,1}; 	//进行每位的值计算
int t[4];	//经过运算后显示管各位的数值
//延时函数
void delay(uchar xms)
{
	uchar i,j;
	for(i=0;i<xms;i++)
		for(j=0;j<60;j++);
}
//显示函数
void display()
{
	uchar i;
	float dv;
	int s=0;                
	dv=0.0196078431373*vdata;  //将数字电压值转换成模拟电压值(5/255=0.0196078431373)   
	s=(int)(dv*1000);				   //具有一定格式的电压值(例如2.0133...转化为2013)
	for(i=0;i<4;i++)           //找到规律一次性初始化各个位
	{
		t[i] = (s%c[i])/c[i+1];
	}
	for(i=0;i<4;i++) 
	{
		if(i==0)
		{
			P26=0;P25=1;P24=1;P23=1;
			P1=numdep[t[i]];
		}
		if(i==1)
		{
			P26=1;P25=0;P24=1;P23=1;
			P1=table[t[i]];
		}
		if(i==2)
		{
			P26=1;P25=1;P24=0;P23=1;
			P1=table[t[i]];
		}
		if(i==3)
		{
			P26=1;P25=1;P24=1;P23=0;
			P1=table[t[i]];
		}			
		delay(1);
	}	
}
void interrupt_1() interrupt 2
{
	vdata=ADC0809;
	ADC0809=0;
}
void main()
{
	EA=1;EX1=1;IT1=1;
	vdata=0;
	ADC0809=0;
	while(1)
	{
		display();
	}
}

电路图:
在这里插入图片描述
实验结果:
(1)显示1.450V
在这里插入图片描述
(2)显示2.450V
在这里插入图片描述
(3)显示3.901V
在这里插入图片描述

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-06-14 22:50:26  更:2022-06-14 22:50:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 1:56:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码