单片机笔记全集(1)

 本文为博主 LED-执棋困局,csdn原创首发。希望看完后能对你有所帮助,不足之处请指正!一起交流学习,共同进步!
> 发布人:LED-执棋困局
> 欢迎你为独创博主LED-执棋困局点赞❤❤❤+关注👍+收藏🌹+评论☺。

系列专栏:CSDN-单片机学习系列🎁
> 我的格言是:“尽最大努力,做最好的自己!💪
版权声明:本文为CSDN博主「LCD-执棋困局」的原创文章,CSDN独一份。

如需转载,还请通知一声噢⚠!
————————————————
版权声明:本文为CSDN博主「LCD-执棋困局」的原创文章,转载请附上原文出处链接及本声明。

本文介绍一些常用基本元件。

目录

一、LED灯

1.1基本理论1

1.2流水灯

1.2.1一步步法

1.2.2数组法

1.2.3库函数法

二、数码管

2.1基本理论2

2.2数码管模块

2.3数码管显示服务函数

三、按键

3.1基本理论3

3.2按键扫描

3.3线反转法

3.4中断法

一、LED灯

1.1基本理论1

LCD灯由一个二极管组成,通常LED灯一端接地GND/电源,另一端接I/O口(最好接个电阻,以防LED灯烧坏)。二极管一端是阳极,另一端是阴极,所以多个LCD灯接法有两种:共阴极接法和共阳极接法。

共阳极接法,LED灯要导通(发亮),接IO口那端要是低电平(0),另一端接电源。共阴极接法,LCD灯要导通(发亮),接IO口那端要是高电平(1),另一端接地GND。

以8个LED灯为例,采用共阳极接法(IO口接P2),若要让第一个灯亮,则P1^0=0,其他引脚为1,即1111 1110(0xfe)。

1.2流水灯

实现流水灯编码有3种方法,分别是一步步法、数组法、库函数法。

1.2.1一步步法

这个不常用,就是一步一步写出来。简单来说,第一个灯亮,接着第二个灯亮,又接着是第三个灯亮,……,第八个灯亮。

P2=0xfe;

delay(200);

P2=0xfd;

delay(200);

P2=0xfb;

delay(200);

P2=0xf7;

delay(200);

1.2.2数组法

将流水灯二进制存储,利用for语句实现流水灯功能。

unsigned char a[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf 0xbf,0x7f};

while(1)

{

    unsigned chari;

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

    {

           P2=a[i];

           delay(200);

    }

}

1.2.3库函数法

#include<intrins.h> //含_crol_()和_cror_()函数

while(1)

{

    static unsigned char temp;

   temp=0xfe;

    P2=temp;

    temp=_crol_(temp,1);  //temp循环左移1位

}

二、数码管

2.1基本理论2

数码管内部由LED和电阻组成,接法可以分为共阳极接法和共阴极接法(接法同上)。数码管线码[abcdefg、dp(用于显示小数)]用于显示字符,位码用于控制显示第几个数码管。数码管线码相当于LED的接IO端,位码相当于LED的公共端。

数码管类型很多,如带:的数码管、带小数点的数码管等。

参考下图(以共阳极接法为例,则线码=1亮,=0不亮),若要显示字符2,则线码abdeg要亮,即:

dp  g  f  e  d  c  b  a

0    1   0  1   1  0  1   1        0x5b

cd9787152a094ce0bffd11b842403dad.jpg

 数码管显示有四个步骤:

位码→线码→延时1ms→消隐(线码=0)

若要用定时器定时1ms延时,需要将消隐移动到第一步。

另外,可以设置缓冲区,方便显示字符的修改,并定义数组用于存储数码管可以显示的字符。

2.2数码管模块

display.c

#include "display.h"

unsigned char code leddata[]={
	              0x3F, //0
	              0x06, //1
                  0x5B, //2
	              0x4F, //3
	              0x66, //4																																																																		
	              0x6D, //5
	              0x7D, //6
	              0x07, //7
	              0x7F, //8
	              0x6F, //9
	              0x77, //A																																																																							
	              0x7C, //B
	              0x39, //C
	              0x5E, //D
	              0x79, //E
	              0x71, //F
	              0x76, //H
	              0x38, //L
	              0x37, //n
                  0x3E, //u	
	              0x73, //P																																																																	
	              0x5C, //o
	              0x40, //-
	              0x00  //熄灭
                             };//数码管段码表

unsigned char LEDBuf[]={8,8,8,8};//缓冲区
unsigned char code PLACE_COOE[]={0xfe,0xfd,0xfb,0xf7};//位码
/******************************************************************************************
函数名:display
功能:数码管显示函数
参数:无
返回值:无
******************************************************************************************/
void display()
{
	unsigned char i;
	IO_DIG=leddata[LEDBuf[i]];//段码
	IO_PLACE=PLACE_COOE[i];//位码
	delay(1);//延时1ms
	IO_DIG=0x00;//消隐
    i++;
	if(N==i)
		i=0;
}

定时器定时1ms时数码管模块:

#include "display.h"

unsigned char code leddata[]={
	              0x3F, //0
	              0x06, //1
                  0x5B, //2
	              0x4F, //3
	              0x66, //4																																																																		
	              0x6D, //5
	              0x7D, //6
	              0x07, //7
	              0x7F, //8
	              0x6F, //9
	              0x77, //A																																																																							
	              0x7C, //B
	              0x39, //C
	              0x5E, //D
	              0x79, //E
	              0x71, //F
	              0x76, //H
	              0x38, //L
	              0x37, //n
                  0x3E, //u	
	              0x73, //P																																																																	
	              0x5C, //o
	              0x40, //-
	              0x00  //熄灭
                             };//数码管段码表

unsigned char LEDBuf[]={0,0,0,0};//缓冲区
unsigned char code PLACE_COOE[]={0xfe,0xfd,0xfb,0xf7};//位码
/******************************************************************************************
函数名:display
功能:数码管显示函数
参数:无
返回值:无
******************************************************************************************/
void display()
{
	static unsigned char i=0;
	switch(i)
	{
		case 0:
			IO_DIG=0x00;//消隐
			IO_DIG=leddata[LEDBuf[0]];//段码
	        IO_PLACE=PLACE_COOE[0];//位码
            i++;
		  break;
		case 1:
			IO_DIG=0x00;//消隐
			IO_DIG=leddata[LEDBuf[1]];//段码
	        IO_PLACE=PLACE_COOE[1];//位码
            i++;
		  break;
		case 2:
			IO_DIG=0x00;//消隐
			IO_DIG=leddata[LEDBuf[2]];//段码
	        IO_PLACE=PLACE_COOE[2];//位码
            i++;
		  break;
		case 3:
			IO_DIG=0x00;//消隐
			IO_DIG=leddata[LEDBuf[3]];//段码
	        IO_PLACE=PLACE_COOE[3];//位码
            i=0;
		  break;
	}
}
/***********************************************************
函数名:Timer0_Init
参  数:无
返回值:无
***********************************************************/
void Timer0_Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	ET0=1;            //定时器0中断开关打开
	TF0 = 0;				  //清除TF0标志
	TR0 = 1;				  //定时器0开始计时
}

void T0_timer() interrupt 1 //实现数码管的动态刷新
{
	TR0=0;            //暂时关闭定时器T0
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	display();        //数码管显示函数
	TR0=1;            //再次打开定时器T0
}

display.h

#ifndef __DISPLAY_H__
#define __DISPLAY_H__

#include <reg51.h>
#include "delay.h"

#define IO_DIG   P0 //段码IO
#define IO_PLACE P2 //位码IO

#define N 4 //数码管个数

unsigned char code leddata[];//变量声明
extern unsigned char LEDBuf[];

void display();//数码管显示函数声明

#endif

2.3数码管显示服务函数

参考2.2模块,若要显示一个四位数,可以计算出每一位并赋给缓冲区,从而在屏幕中显示这四位数。

unsigned char temp=1234;

dis_service()

{

    LEDbuf[0]=temp/1000;

    LEDbuf[1]=temp/100%10;

    LEDbuf[0]=temp/10%10;

    LEDbuf[0]=temp%10;

}

三、按键

3.1基本理论3

按键种类很多,从插入方式,可分为贴片式和插入式。从功能上,可分为一键单义、一键二义、一键多义(一按键多功能)。

按键如何接呢?通常是一端接地,另一端接到IO口。

按键按下时,会有抖动现象,严重影响功能的实现,所以要进行消抖。消抖有两种方法,分别是硬件消抖、软件消抖。硬件消抖外接电路,软件就是利用延时法进行消抖,如下图所示。

376dd00a2197431dabeb569c1003159b.png

3.2按键扫描

如何判断按键按下被按下呢?主要有行列扫描、中断法。

行列扫描,可以分为行扫描、列扫描。行扫描就是键盘一端列接地,逐行进行扫描,当按下按键时,接IO口的另一端连通地,由高电平变成低电平,松开键盘时,断开地,低电平又变回高电平,依据此原理,可以判断出哪个按键被按下,列扫描同理,键盘一端行接地,另一端接IO口。

步骤:(1)判断是否按下(2)延时5ms-10ms(3)再次判断是否按下(4)等待松开

代码如下:

#include "key.h"//独立键盘头文件
#include "delay.h"//延时头文件

/******************************************************************************************
函数名:key
功能:  独立键盘函数
参数:  无
返回值:unsigned char
******************************************************************************************/
unsigned char key()//独立键盘按键函数
{
	unsigned char temp=0;
//方法1:
	/*if(key1==0)//判断是否按下键盘
	{
		delay(10);//消抖
		if(key1==0)//再次判断是否按下键盘
		{
			temp=1;//键盘按下,中间值temp赋为1
		}while(key1==0);//松手等待
	}
	if(key2==0)
	{
		delay(10);
		if(key2==0)
		{
			temp=2;
		}while(key2==0);
	}
	if(key3==0)
	{
		delay(10);
		if(key3==0)
		{
			temp=3;
		}while(key3==0);
	}
	if(key4==0)
	{
		delay(10);
		if(key4==0)
		{
			temp=4;
		}while(key4==0);
	}*/

//方法2:

	if(key1==0||key2==0||key3==0||key4==0)
	{
		delay(10);
		if(key1==0||key2==0||key3==0||key4==0)
		{
			if(key1==0)
				temp=1;
			if(key2==0)
				temp=2;
			if(key3==0)
				temp=3;
			if(key4==0)
				temp=4;
		}while(key1==0||key2==0||key3==0||key4==0);
	}
	return temp;//返回中间值
}

3.3线反转法

常见与矩阵键盘。先将行输出(0),列端输入(1),利用按下按键时,一端接地(0),接IO口的另一端(1)连通地,由高电平变成低电平,松开键盘时,断开地,低电平又变回高电平原理,计算出temp,接着行输入(1),列输出(0),再次利用该原理,计算出temp2,最后计算出temp+temp2的结果,这个结果就是这个按键独有的编码。

代码如下:key_scan.c

#include "key_scan.h"//独立键盘头文件
#include "delay.h"//延时头文件

/******************************************************************************************
函数名:key
功能:  独立键盘函数
参数:  无
返回值:unsigned char
******************************************************************************************/
unsigned char key_scan()//独立键盘按键函数
{
	unsigned char temp,temp2;
	static unsigned char keynum=20;
	KEYPIO=0xf0;//1为输入 0位输出 令高4位为1 低4位为0
	temp=KEYPIO;
	if(temp!=0xf0)//判断是否按下按键
	{
		delay(10);//消抖延时10ms
		if(temp!=0xf0)//再次判断是否按下按键
		{
			temp=KEYPIO&0xf0;//确定行
			KEYPIO=0x0f;//反转
			temp2=KEYPIO&0x0f;//确定列
		}
	}
	switch(temp+temp2)
	{
		case 0xee:keynum=1;break;
		case 0xed:keynum=2;break;
		case 0xeb:keynum=3;break;
		case 0xe7:keynum=4;break;
		case 0xde:keynum=5;break;
		case 0xdd:keynum=6;break;
		case 0xdb:keynum=7;break;
		case 0xd7:keynum=8;break;
		case 0xbe:keynum=9;break;
		case 0xbd:keynum=0;break;
		case 0xbb:keynum=10;break;
		case 0xb7:keynum=11;break;
		case 0x7e:keynum=12;break;
		case 0x7d:keynum=13;break;
		case 0x7b:keynum=14;break;
		case 0x77:keynum=15;break;
		default:break;
	}
	return keynum;
}

key_scan.h

#ifndef __KEY_SCAN_H__
#define __KEY_SCAN_H__

#include <reg51.h>//51头文件

#define KEYPIO P3 //矩阵键盘两端所接的IO口

unsigned char key_scan();//独立键盘函数声明

#endif

3.4中断法

以at89c51单片机为例,有2个外部中断,引脚分别为INT0、INT1。一般初始化时,要打开允许外部中断开关EX0/EX1和总中断EA,同时设置触发方式IT0/IT1,外部中断0的入口编号为0,外部中断1的入库编号为2。

代码如下:

void EX1_init()
{
	IT1=1;//下降沿触发
	EA=1;//开启总中断
	EX1=1;//开启外部中断1
}

void time1() interrupt 2 //中断服务函数--外部中断1
{
	switch(P2&0x0f)//判断哪个按键按下
	{
		case 0x0e:
			num++;if(num>9999) num=0;//实现加法运算
		  break;
		case 0x0d:
			num--;if(num>9999) num=9999;//实现减法运算
		  break;
		case 0x0b:
			num=0;//实现清0
		  break;
		case 0x07:
			num=8888;//数码管显示8888
		  break;
		default:break;
	}
}

本次学习了单片机三大基本元件,分别介绍了它们的原理和代码解析,下文将继续讲述单片机的知识全集,我们敬请期待!!!

 ——————————————————————————————————————————

本次介绍了三大元件,同时提供模块代码和原理,帮助大家理解相关编码思路。

hi!我是博主LED-执棋困局🔥,喜欢或期待更好作品的,可以关注一下我LED-执棋困局🙏🙏🙏,我们一起进步,另外欢迎大家的点评😊!!!

关注博主:点击支持——LED-执棋困局
———————————————————————————————————————————

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值