嵌入式入门之51单片机

前言

本篇文章属于学习笔记,来源于B站教学视频,相关代码工程请从源地址自行下载。这位Up讲解得很好,适合同学们一起学习,在这里推荐给大家。本文为个人学习笔记,只能做参考,细节方面建议观看视频,肯定受益匪浅。
51单片机入门教程-2020版 程序全程纯手打 从零开始入门

一.环境搭建

1.开发软件:keil5C51。可自行到官网下载。(注意要下51单片机版本)
请添加图片描述
2、烧录软件stc-isp
请添加图片描述
3.开发板:普中A2标准板。请添加图片描述

二.单片机介绍

单片机(Single-Chip Microcomputer)是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。从上世纪80年代,由当时的4位、8位单片机,发展到现在的300M的高速单片机。

历史

单片机的发展先后经历了4位、8位、16位和32位等阶段。8位单片机由于功能强,被广泛用于工业控制、智能接口、仪器仪表等各个领域,8位单片机在中、小规模应用场合仍占主流地位,代表了单片机的发展方向,在单片机应用领域发挥着越来越大的作用。 80年代初,Intel公司推出了8位的MCS-51系列的单片机。

51单片机的部件

MCS-51单片机的逻辑部件,包括一个8位CPU及片内振荡器、 80514B掩膜ROM、87514KBEPROM、8031无ROM、特殊功能寄存器SFR128BRAM、定时器/计数器T0及T1、并行I/O接口:P0、P1、P2、P3;串行接口:TXD、RXD;中断系统:INT0,INT1。

51单片机的命名规则

请添加图片描述

51单片机结构

请添加图片描述
请添加图片描述

STC89C52系列单片机最小系统

请添加图片描述

二.操作LED

1.LED的硬件原理图

通过下面的图,我们可以看到LED正极接着电源,那我们可以控制P2的八根引脚的高低电压来控制电路的导通从而控制LED的亮灭。并且通过串联电阻来限流,避免LED烧坏。而单片机需要通过CPU控制寄存器的值,进而通过驱动器加大控制力度,由控制电路输出高低电平(对应寄存器1/0)。因此,程序需要在对应的寄存器上写1或0,即可控制LED的亮灭。

请添加图片描述
请添加图片描述

2.控制LED代码。

//LED D1亮
#include <REGX52.H>

void main()
{
   
	//P2=0xEE;//1111 1110
	while()
	{
   
		P2=0xEE;//1111 1110
	}
}
//延时500ms控制LED灯闪烁
#include <REGX52.H>
#include <INTRINS.H>
void Delay500ms()		//@11.0592MHz
{
   
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
   
		do
		{
   
			while (--k);
		} while (--j);
	} while (--i);
}


void main()
{
   
	
	while(1)
	{
   
		P2=0xFE;
		Delay500ms();
		P2=0xFF;
		Delay500ms();
	}
}
//流水灯
#include <REGX52.H>
#include <intrins.h>
void Delay500ms()		//@11.0592MHz
{
   
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
   
		do
		{
   
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
   	
	while(1)
	{
   
		P2=0xFE;//1111 1110
		Delay500ms();
		P2=0xFD;//1111 1101
		Delay500ms();
		P2=0xFB;//1111 1011
		Delay500ms();
		P2=0xF7;//1111 0111
		Delay500ms();
		P2=0xEF;//1110 1111
		Delay500ms();
		P2=0xDF;//1101 1111
		Delay500ms();
		P2=0xBF;//1011 1111
		Delay500ms();
		P2=0x7F;//0111 1111
		Delay500ms();
	}
}
//LED流水灯升级(控制延时时间)
#include <REGX52.H>
#include <intrins.h>
void Delay1ms(unsigned int xms)		//@11.0592MHz
{
   
	while(xms){
   
		unsigned char i, j;

		_nop_();
		_nop_();
		_nop_();
		i = 11;
		j = 190;
		do
		{
   
			while (--j);
		} while (--i);
		xms--;
 }
}

void main()
{
   
	while(1)
	{
   
		P2=0xFE;//1111 1110
		Delay1ms(500);
		P2=0xFD;//1111 1101
		Delay1ms(500);
		P2=0xFB;//1111 1011
		Delay1ms(500);
		P2=0xF7;//1111 0111
		Delay1ms(500);
		P2=0xEF;//1110 1111
		Delay1ms(500);
		P2=0xDF;//1101 1111
		Delay1ms(500);
		P2=0xBF;//1011 1111
		Delay1ms(500);
		P2=0x7F;//0111 1111
		Delay1ms(500);
	}
}

//按位与控制LED循环亮灭
#include <REGX52.H>
#include <intrins.h>
void Delay500ms()		//@11.0592MHz
{
   
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
   
		do
		{
   
			while (--k);
		} while (--j);
	} while (--i);
}
void main()
{
   
	while(1)
	{
   
		P2=0xFF;
		Delay500ms();
		while(P2!=0)
		{
   
			
			P2=(P2<<1);
			Delay500ms();
		}
		//P2=0xFF;
    }
}

请添加图片描述
请添加图片描述

三.独立按键控制LED灯亮灭

1.独立按键原理图

四个按键都接地,按下时导通,四根引线是则处于低电位。
请添加图片描述

2.按键的抖动。

因为按键的抖动,消除抖动可以在编写代码是延时抖动时间,使他处于稳点位置。
请添加图片描述

3.按键控制led的代码。

//按键控制LED
#include <REGX52.H>
void main()
{
   
	//P2=0xFE;
	//P2_0=1;
	while(1)
	{
   
		if(P3_1==0){
   
			P2_0=0;
		}
		else{
   
			P2_0=1;
		}
	}
	
}
//按键控制led状态
#include <REGX52.H>

void Delay1ms(unsigned int xms)		//@11.0592MHz
{
   
	while(xms)
	{
   
		unsigned char i, j;

		i = 2;
		j = 199;
		do
		{
   
			while (--j);
		} while (--i);
		xms--;
     }
}

void main()
{
   
	while(1)
	{
   
		if(P3_1==0)
		{
   
			Delay1ms(20);
			while(P3_1==0);
			Delay1ms(20);
			
			P2_0=~P2_0;
		}
	}
}
//按键控制led二进制亮灭
#include <REGX52.H>
void Delay(unsigned int xms)		//@11.0592MHz
{
   
	while(xms--)
	{
   
		unsigned char i, j;
		i = 2;
		j = 199;
		do
		{
   
			while (--j);
		} while (--i);
    }
}

void main(){
   
	
	unsigned char LEDNum = 0;
	while(1)
	{
   
		if(P3_1==0)
		{
   
			Delay(20);
			while(P3_1==0);
			Delay(20);
			LEDNum++;
			P2 = ~LEDNum;
		}
	}	
}
//按键控制led移位
#include <REGX52.H>
void Delay(unsigned int xms)		//@11.0592MHz
{
   
	while(xms--)
	{
   
		unsigned char i, j;
		i = 2;
		j = 199;
		do
		{
   
			while (--j);
		} while (--i);
    }
}

void main(){
   
	
	unsigned char LEDNum = 0;
	P2 = ~0x01;
	//unsigned char LEDNum2 = 0;
	while(1)
	{
   
		if(P3_1==0)
		{
   
			Delay(20);
			while(P3_1==0);
			Delay(20);
			  LEDNum++;
			if(LEDNum>7)
				LEDNum=0;
			 //LEDNum++;
			P2 = ~(0x01<<LEDNum);
			//LEDNum1++;
		}
		if(P3_0==0)
		{
   
			Delay(20);
			while(P3_0==0);
			Delay(20);
			if(LEDNum==0)
				LEDNum=7;
			else
				 LEDNum--;
			P2 = ~(0x01<<LEDNum);
		}
	}	
}

四.静态数码管

1.单个数码管引脚定义

数码管的接法,有共阳和共阴之分。共阴时,拉高电压即可点亮。共阳时,拉低电平点亮。
请添加图片描述

2.开发板四位一体的数码管引脚

请添加图片描述

3.74HC138译码器原理图

请添加图片描述

4.动态数码管模块原理图

请添加图片描述

5.静态数码管模块代码

//
#include <REGX52.H>
const unsigned char NixieTable[]={
   0x3F,0x06,0x5B,
	                           0x4F,0x66,0x6D,
		                       0x7D,0x07,0x7F,0x6F};

void Nixie(unsigned char Location,Number)
{
   
	switch(Location)
	{
   
		case 1:
			P2_4=1;P2_3=1;P2_2=1;break;
		case 2:
			P2_4=1;P2_3=1;P2_2=0;break;
		case 3:
			P2_4=1;P2_3=0;P2_2=1;break;
		case 4:
			P2_4=1;P2_3=0;P2_2=0;break;
		case 5:
			P2_4=0;P2_3=1;P2_2=1;break;
		case 6:
			P2_4=0;P2_3=1;P2_2=0;break;
		case 7:
			P2_4=0;P2_3=0;P2_2=1;break;
		case 8:
			P2_4=0;P2_3=0;P2_2=0;break;
			
	}
	P0 = NixieTable[Number];
	
}



void main()
{
   
//	const unsigned char NixieTable[]={0x3F,0x06,0x5B,
//	                           0x4F,0x66,0x6D,
//		                       0x7D,0x07,0x7F,0x6F};
//注意:函数传参都是拷贝过去的。
	
	while(1)
	{
   
		Nixie(3,2);
	}
	
	
}

6.动态数码管模块代码

消影是因为位选和段选显示数据窜位。加了一个延时函数并且位选清零。

#include <REGX52.H>

const unsigned char NixieTable[]={
   0x3F,0x06,0x5B,
	                           0x4F,0x66,0x6D,
		                       0x7D,0x07,0x7F,0x6F};

void Delay(unsigned int xms)		//@11.0592MHz
{
   
	while(xms--)
	{
   
		unsigned char i, j;
		i = 2;
		j = 199;
		do
		{
   
			while (--j);
		} while (--i);
    }
}

void Nixie(unsigned char Location,Number)
{
   
	switch(Location)
	{
   
		case 1:
			P2_4=1;P2_3=1;P2_2=1;break;
		case 2:
			P2_4=1;P2_3=1;P2_2=0;break;
		case 3:
			P2_4=1;P2_3=0;P2_2=1;break;
		case 4:
			P2_4=1;P2_3=0;P2_2=0;break;
		case 5:
			P2_4=0;P2_3=1;P2_2=1;break;
		case 6:
			P2_4=0;P2_3=1;P2_2=0;break;
		case 7:
			P2_4=0;P2_3=0;P2_2=1;break;
		case 8:
			P2_4=0;P2_3=0;P2_2=0;break;
			
	}
	P0 = NixieTable[Number];
	Delay(1);
	P0=0x00;
	
}



void main()
{
   
//	const unsigned char NixieTable[]={0x3F,0x06,0x5B,
//	                           0x4F,0x66,0x6D,
//		                       0x7D,0x07,0x7F,0x6F};
//注意:函数传参都是拷贝过去的。
	
	while(1)
	{
   
		Nixie(1,1);
		//Delay(100);
		Nixie(2,2);
		//Delay(100);
		Nixie(3,3);
		//Delay(100);
		
	}
	
	
}

7.数码管驱动方式。

单片机直接扫描: 硬件设备简单,但会耗费大量的单片机CPU时间。
专用驱动芯片: 内部自带显存、扫描电路,单片机只需告诉它显示什么即可。

五.模块化编程和LCD1602调试工具

1.模块化编程

请添加图片描述
模块化编程框架
请添加图片描述
请添加图片描述
C语言预编译
请添加图片描述

2.LCD1602调试工具

请添加图片描述

六.矩阵键盘

1.矩阵键盘介绍

请添加图片描述

2.扫描的概念

请添加图片描述

3.准双向口输出简图

请添加图片描述

4.矩阵键盘模块原理图

读取第一行然后快速循环扫描,也可以按列扫描。
例:当P1_7 = 0是相当于接地,当S1按下时候,强上拉使P1_3低电压输入数据为0,即P1_3=0。
请添加图片描述

5.代码块示例

MartixKey.c

#include <REGX52.H>
#include "Delay.h"

unsigned char MartixKey()
{
   
	unsigned char KeyNum=0;
	
		P1 = 0xFF;
		P1_7=0;
	    if(P1_3==0){
   Delay(20);while(P1_3==0);Delay(20);KeyNum=1;}
		if(P1_2==0){
   Delay(20);while(P1_2==0);Delay(20);KeyNum=2;}
		if(P1_1==0){
   Delay(20);while(P1_1==0);Delay(20);KeyNum=3;}
		if(P1_0==0){
   Delay(20);while(P1_0==0);Delay(20);KeyNum=4;}
		
		P1 = 0xFF;
		P1_6=0;
	    if(P1_3==0){
   Delay(20);while(P1_3==0);Delay(20);KeyNum=5;}
		if(P1_2==0){
   Delay(20);while(P1_2==0);Delay(20);KeyNum=6;}
		if(P1_1==0){
   Delay(20);while(P1_1==0);Delay(20);KeyNum=7;}
		if(P1_0==0){
   Delay(20);while(P1_0==0);Delay(20);KeyNum=8;}
		
		P1 = 0xFF;
		P1_5=0;
	    if(P1_3==0){
   Delay(20);while(P1_3==0);Delay(20);KeyNum=9;}
		if(P1_2==0){
   Delay(20);while(P1_2==0);Delay(20);KeyNum=10;}
		if(P1_1==0){
   Delay(20);while(P1_1==0);Delay(20);KeyNum=11;}
		if(P1_0==0){
   Delay(20);while(P1_0==0);Delay(20);KeyNum=12;}
		
		P1 = 0xFF;
		P1_4=0;
	    if(P1_3==0){
   Delay(20);while(P1_3==0);Delay(20);KeyNum=
  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值