51单片机:与15系列的区别---最简单的几个模块

51单片机:与15系列的区别---最简单的几个模块,第1张

自从蓝桥杯省赛完成之后,就开始准备学习51单片机。相对于蓝桥杯比赛所用的板子来说,这个单片机还是有所不同的。在管脚,阴阳极上有些区分。因此,开贴做笔记记录一下。

首先介绍几个最为基础的模块。这几个模块改动都不大,原理也相近类似。

目录

一、LED灯

二、蜂鸣器

三、数码管

四、独立按键

五、矩阵按键

一、LED灯

根据原理图,可以看到LED1是P20管脚,与15系列的相同,将其置1就是亮起,置0就是熄灭。写法与15系列的单片机有些类似。

在LED灯的循环点亮的程序,与15单片机也相同。由于移位之后自动补0(亮起),所以我们要通过取反的程序来写。

 

拓展:左移右移通过库函数实现流水灯

我们需要调用另一个头文件:#include “intrins.h”,

在这里面,_cror_函数是右移;_crol_函数是左移。

注意:此函数与我们自己写的移位语句不同的是:移位语句左右移位之后,丢掉的位自动补0;而这两个函数在移位之后,移出去的位将会补在数的后面

对于这两个函数的使用:_crol_(要移动的变量,移动几位)

例如:LED=_crol_(LED,1); 我们要提前规定LED的值是0XFE,从0XFE向左开始逐渐移动1位。(后面的数字改成2之后,就是移动两位,隔一个灯移动一次)。

程序:LED灯循环,间隔1秒。

#include "reg52.h"
#include "intrins.h"

#define uchar unsigned char
#define uint unsigned int
	
#define LED		P2//采用宏定义的方法,将P2端口进行定义

uchar i=0;

void Delayms(uint ms);//1毫秒 

void main()
{
	while(1)
	{
		LED=0XFE;
		for(i=0;i<8;i++)
		{
			LED=_crol_(LED,1);
			Delayms(1000);
		}
	}
}

void Delayms(uint ms)//1毫秒延时函数
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=115;j>0;j--);
}
二、蜂鸣器

有源蜂鸣器:内部频率不可改变,因此音色不可改变(15单片机上的,此类蜂鸣器控制简单,只需要置1或置0即可关闭或打开)。

无源蜂鸣器:可改变内部频率、改变音色(改变延时的时间);改变占空比(改变声音大小)。(51单片机上的,需要持续输出波形才可以使用蜂鸣器)。

通过原理图可以看出,与蜂鸣器相连接的是五线四项步进电机里的P25口。打开蜂鸣器:让蜂鸣器输出持续的波形信号(时刻发生改变);关闭蜂鸣器:让蜂鸣器输出高或低的脉冲信号(不改变)

波形信号的频率:1.5—5KHZ;我们可以使用频率1KHZ的,周期T=1ms(500微秒高电平,500微秒低电平)。

注意:蜂鸣器响的时间由i和延时的时间共同控制。

           延时的时间越长,声音就越低沉;延时的时间越短,声音就越尖细。

            占空比越大,声音越大。

程序:可改变占空比来改变蜂鸣器声音大小   延时程序复制的stc软件里的。

#include "reg52.h"

#define uchar unsigned char
#define uint unsigned int
	
sbit BEEP=P2^5;

uint i=2000;

void delay_10us(uint ten_us);//延时10微秒程序


void delay_10us(uint ten_us)//延时10微秒程序
{
	while(ten_us--);
}

void main()
{
	uint i=2000;//控制蜂鸣器发出声音的时间,
	            //蜂鸣器响的时间由i和延时的时间共同控制
	while(1)
	{
		while(i--)
		{
			BEEP=0;//蜂鸣器低电平
			delay_10us(10);
			BEEP=1;//蜂鸣器高电平
			delay_10us(190);
		}
		i=0;BEEP=0;//关闭蜂鸣器
	}
}
三、数码管

1、共阳共阴极数码管:

共阳极数码管是指将所有发光二极管的阳极接到一起形成公共极(COM)的数码管,共阳极数码管在应用时应将公共极 COM 接到+5V(低电平点亮)

共阴极数码管(本单片机)是指将所有发光二极管的阴极接到一起形成公共极(COM)的数码管,共阴极数码管在应用时应将公共极 COM 接到地线GND上。(高电平点亮)

所以这个板子上的数码管显示与15系列的正好相反。

2、74HC245芯片和74HC138芯片

   要学会阅读芯片手册。

      74HC245芯片是有个DIR管脚的,该管脚控制了电流的输出方向,高电平的时候是从A-B输出的;低电平是从B-A输出的。我们需要的是高电平。

      74HC138芯片俗称38译码器,三个输入端(A0、A1、A2),8个输出端(Y0、Y1、Y2、Y3、Y4、Y5、Y6、Y7)。通过阅读芯片手册中的真值表来了解如何通过输入端控制输出端(即控制哪个数码管位选的打开)。

真值表如下:L是低电平,H是高电平。当8个端口为低电平的时候,该数码管的位选就会打开。

 

注意:LED8和Y7都表示的板子上最左边第一个数码管。

LSA、LSB、LSC是对38译码器的三个输入管脚的定义,用来控制数码管的位选。

在显示一个数码管之后,就要对数码管进行消隐的 *** 作(让段选为0X00),目的是让数码管的显示更加清晰,清除数码管底部的暗红色痕迹。

程序:8个数码管依次显示1-8

#include 

#define uchar unsigned char
#define uint unsigned int
	
#define SMG_duanxuan   P0//对整个P0端口进行定义 用宏定义
                         //是对整个段选端口进行定义
/**********************定义38译码器的输入管脚**************/

sbit LSA=P2^2;//对单个管脚进行定义用sbit
sbit LSB=P2^3;
sbit LSC=P2^4;

uchar code tab[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,0X40,0X00};//0-9,横线,关闭
uchar Smg[8]={0};
uchar Smg_num=0;

void Delayms(uint ms);//1毫秒延时
void Smg_display();//数码管显示函数

void main()
{
	while(1)
	{
		Smg_display();
	}
}

void Smg_display()//数码管显示函数
{
	uchar Smg_num=0;
	
	for(Smg_num=0;Smg_num<8;Smg_num++)
	{
		switch(Smg_num)
		{
			case 0:LSA=1;LSB=1;LSC=1;break;//数码管1
			case 1:LSA=0;LSB=1;LSC=1;break;
			case 2:LSA=1;LSB=0;LSC=1;break;
			case 3:LSA=0;LSB=0;LSC=1;break;
			case 4:LSA=1;LSB=1;LSC=0;break;
			case 5:LSA=0;LSB=1;LSC=0;break;
			case 6:LSA=1;LSB=0;LSC=0;break;
			case 7:LSA=0;LSB=0;LSC=0;break;//数码管8
		}
		SMG_duanxuan=tab[Smg[Smg_num]];
		//P0=tab[Smg[Smg_num]];//直接控制P0口也行
		Smg[0]=1;Smg[1]=2;Smg[2]=3;Smg[3]=4;Smg[4]=5;Smg[5]=6;Smg[6]=7;Smg[7]=8;
		Delayms(1);
		SMG_duanxuan=0X00;//消隐,让数码管的显示更加清晰
	}
}

void Delayms(uint ms)//1毫秒延时
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=114;j>0;j--);
}
四、独立按键

I/O口作为输入的实例   按键按下,I/O口为低电平。

按键的抖动:通常是5-10ms的范围,所以无论是按下还是松手,我们都要进行一个软件延时。一般延时5毫秒即可。

         

 

在这里要注意的是,不同于15单片机的地方在于按键的顺序,P31管脚是按键1,P30管脚是按键2.

程序:按下第一个按键,LED1亮起;按下第二个按键,LED2亮起;按下第三个按键,数码管1显示8;按下第四个按键,数码管2显示8;

#include 

#define uchar unsigned char
#define uint unsigned int

uchar code tab[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,0X40,0X00};//0-9,横线,关闭
uchar Smg[8]={2,1,10,0,6,10,8,8};
uchar Smg_num=0;
	
/******************对4个独立按键的管脚进行定义*********************/

sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;

/******************对LED灯进行定义*********************/

sbit LED1=P2^0;
sbit LED2=P2^1;

/******************定义38译码器的输入管脚*******************/

sbit LSA=P2^2;   //对单个管脚进行定义用sbit
sbit LSB=P2^3;
sbit LSC=P2^4;
#define SMG_duanxuan   P0//对整个P0端口进行定义 用宏定义
                         //是对整个段选端口进行定义

void Keyscan();
void Smg_display();//数码管显示函数
void Delayms(uint ms);//1毫秒延时

void main()
{
	
	while(1)
	{
		Smg_display();
		Keyscan();
	}
}

void Smg_display()//数码管显示函数
{
	uchar Smg_num=0;
	
	for(Smg_num=0;Smg_num<8;Smg_num++)
	{
		switch(Smg_num)
		{
			case 0:LSA=1;LSB=1;LSC=1;break;//数码管1
			case 1:LSA=0;LSB=1;LSC=1;break;
			case 2:LSA=1;LSB=0;LSC=1;break;
			case 3:LSA=0;LSB=0;LSC=1;break;
			case 4:LSA=1;LSB=1;LSC=0;break;
			case 5:LSA=0;LSB=1;LSC=0;break;
			case 6:LSA=1;LSB=0;LSC=0;break;
			case 7:LSA=0;LSB=0;LSC=0;break;//数码管8
		}
		SMG_duanxuan=tab[Smg[Smg_num]];
		//P0=tab[Smg[Smg_num]];
		Delayms(1);
		SMG_duanxuan=0X00;//消隐,让数码管的显示更加清晰
	}
}

void Keyscan()
{
	if(KEY1==0)
	{
		Delayms(5);//软件消抖
		if(KEY1==0)
		{
			LED1=0;
		}
		while(!KEY1);//软件消抖
	}
	else if(KEY2==0)
	{
		Delayms(5);
		if(KEY2==0)
		{
			LED2=0;
		}
		while(!KEY2);
	}
	else if(KEY3==0)
	{
		Delayms(5);
		if(KEY3==0)
		{
			Smg[0]=8;
		}
		while(!KEY3);
	}
	else if(KEY4==0)
	{
		Delayms(5);
		if(KEY4==0)
		{
			Smg[1]=8;
		}
		while(!KEY4);
	}
}

void Delayms(uint ms)//1毫秒延时
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=114;j>0;j--);
}
五、矩阵按键

根据原理图,我们可以看出我们可以看出:矩阵按键的管脚在P10—P17,

我们宏定义矩阵按键的管脚          #define KEYSCAN16   P1

程序的架构与15系里的基本类似,第一列是:让P1=0XF7,判定第一列是否被下,进行消抖检测,再次判断是否被按下,根据P1的值来进行程序的实现,抬手消抖。

不同之处在于列数和行数的表示方法有所不同,

第一列:0XF7;第二列:0XFB;第三列:0XFD,第四列:0XFE。

检测这一列中第几行被按下:第一行:0X7列;第二行:0XB列 第三行:0XD列;第四行:0XE列。

程序:

void Keyscan16()
{
	KEYSCAN16=0XF7;
	if(KEYSCAN16!=0XF7)
	{
		Delayms(5);
		if(KEYSCAN16!=0XF7)
		{
			switch(KEYSCAN16)
			{
				case 0X77:Smg[0]=1;break;
				case 0XB7:Smg[1]=2;break;
				case 0XD7:Smg[2]=3;break;
				case 0XE7:Smg[3]=4;break;
			}		
			while(KEYSCAN16!=0XF7);
		}
	}
	
	KEYSCAN16=0XFB;
	if(KEYSCAN16!=0XFB)
	{
		Delayms(5);
		if(KEYSCAN16!=0XFB)
		{
			switch(KEYSCAN16)
			{
				case 0X7B:Smg[4]=5;break;
				case 0XBB:Smg[5]=6;break;
				case 0XDB:Smg[6]=7;break;
				case 0XEB:Smg[7]=8;break;
			}		
			while(KEYSCAN16!=0XFB);
		}
	}
	
	KEYSCAN16=0XFD;
	if(KEYSCAN16!=0XFD)
	{
		Delayms(5);
		if(KEYSCAN16!=0XFD)
		{
			switch(KEYSCAN16)
			{
				case 0X7D:Smg[0]=6;break;
				case 0XBD:Smg[1]=6;break;
				case 0XDD:Smg[2]=6;break;
				case 0XED:Smg[3]=6;break;
			}		
			while(KEYSCAN16!=0XFD);
		}
	}
	
	KEYSCAN16=0XFE;
	if(KEYSCAN16!=0XFE)
	{
		Delayms(5);
		if(KEYSCAN16!=0XFE)
		{
			switch(KEYSCAN16)
			{
				case 0X7E:Smg[0]=8;break;
				case 0XBE:Smg[1]=8;break;
				case 0XDE:Smg[2]=8;break;
				case 0XEE:Smg[3]=8;break;
			}		
			while(KEYSCAN16!=0XFE);
		}
	}
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1295390.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-10
下一篇 2022-06-10

发表评论

登录后才能评论

评论列表(0条)

保存