前言
本篇文章属于学习笔记,来源于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