前要:本笔记为初学者上b站江科大自化协的51单片机入门教程P1-P12所得笔记,包含单片机简介和LED、独立按键、数码管相关内容。
目录
1.1.什么是单片机以及为什么要学单片机?51是什么?
2-1点亮一个LED
2.2LED闪烁
2.3流水灯
3.1独立按键控制LED亮灭
3.2独立按键控制LED状态
3.3独立按键控制LED显示二进制
3.4独立按键控制LED的移位
4-1静态数码管显示
4-2动态数码管显示(多位显示的原理就是动态模糊)
1. 单片机介绍与WHY要学单片机
单片机,Micro Controller Unit ,简称MCU。
内部集成了CPU,RAM,ROM,定时器,中断系统,通讯接口等一系列电脑的常用硬件功能
单片机的任务是信息收集(依靠传感器),处理(依靠CPU),和硬件设备(eg.电机,LED等)的控制。
那WHY要学单片机?
单片机算是个袖珍版计算机,成本低、体积小,结构简单,在各种生活、工业领域大有所用,(eg.各种带智能的东西,都加入了单片机;红绿灯)同时,学习单片机是了解计算机原理和结构的最佳选择。
注:WHY叫51牌单片机呢?51单片机是指80年代Intel开发的8051单片机内核的统称,就是因为这个“8051”有个51,所以凡是与“8051”内核一样的单片机都统称为51系列单片机。
2.51单片机的基础信息
如图在淘宝选择,然后得到了牌子名为STC89C52RC 401-PD1P40
所属系列:51单片机系列
公司;STC公司
位数:8位
RAM:512字节//随机,易掉,内存,又称运行内存
ROM:8K (flash)//只读,相当于仓库,存储
工作频率:12MHZ
3.STC89C52系列的命名规则
4.STC89C52的内部结构和原理图
5.使用单片机前需要的软硬件设备
一台不错的电脑、以及
一.四步走(初始化代码——敲代码——保存代码——运行代码)
1.初始化代码
a.进K5,建文件,设型号
建一个新工程是先新建一个文件夹(方便保存工程文件并查找),再起名其文件为任意名(固定Project是个好主意)
型号输AT89C52RC(因为K5没与STC合作,但AT厂所做和STC类似,所以用AT就行)
b..导入C语言
右键Source Group1,选C,名main(不必纠结,起一个固定的就行)
//c.使用C之前的一些了解和调整(往后四步走就不包此了)
//左上角三个按钮分别是编译 建立 所有文件重新编译和建立
2.敲代码
a.输入目录
右键选择
b,开敲
c,用F7 (建立)检查是否No error以及No wrong
3.保存代码
在
处点OUTPUT,点create HEXfik(每建立一个工程都有这样)
然后F7重装即保存
4.运行代码
打开Lsp,设好芯片型号STC89C52RC(以后不用再设),打开程序文件(在文件夹的Object文件夹中),下载/安装,双击单片机按扭键重启
二.关于LED
1.LED介绍——发光二极管
内部小三角形表示正级VCC
大梯形表示负极GND
2.开发版中的LED
VCC表正级(高电频) ,高电频用1表示
GND表负极 (低点频),低电频用0表示
开发版的原 理图
CPU通过配置这些控制的寄存器,来控制硬件电路,硬件电路来完成我们想要完成的功能。
三.点亮一盏灯
结合LED的原理图
如点亮第一盏
就是让P2中P2-7为0 是也就是1111 1110 (注意代码是从p27到P20)
就给P2(P大写!)寄存器输入此2进制码,但由于k5无法直接识别二进制码,要转化为16进制码
口诀 四位一格 8421 10以上A到F
然后就按代码四步走运行即可
#include
void main()
{
P2=0xFE; //1111 1110
while(1)
{
}
}
常规代码四部走 其中代码内部:
1.用
void main()
{
P2=0XFE;
P2=0XFF;//1111 1111
}
但我们发现 P2只会闪一下 因为这里P2值无法再变为亮 所以用循环while(1){}来是指循环
实现闪烁
void main()
{
while(1)
{
P2=0XFE;
P2=0XFF;//1111 1111
}
}
2.
但我们发现 这样反倒约等于没闪 因为代码运行太快 人眼看不见闪烁
所以要设延时
3.how调——总思路:在亮和灭后面各加延时500ms(0.5s)
在stc软件找到延时计算机——设定时长度为500ms 系统频率为12MHZ,指令集为stcy——点击复制代码——copy到main前作为函数——完善代码(去掉_nop_)——将Delay 500ms ();放到开与关后即可
#include
#include
void Delay500ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
i = 4;
j = 205;
k = 187;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
while(1)
{
P2=0XFE;
Delay500ms();
P2=0XFF;//1111 1111
Delay500ms();
}
}
1.将闪烁的代码打一遍之后,copy down P2,然后更改0的位置,再转16进制即可
#include
#include
void Delay500ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
i = 4;
j = 205;
k = 187;
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();
}
}
2.改进(不想总是为了改变延长时间而去一直要复制代码)
设万能代码——弄Delay1ms的函数——加入变量xms作为参数加入Delay1ms()中,再j加上while(xms){延时一秒的代码;xms--;} ——这样就完成了Delay1ms的代码
然后在main中使用Delay(100);就行。
#include
void Delay1ms(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while (xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
while(1)
{
P2=0xFE;//1111 1110
Delay1ms(1000);
P2=0xFD;//1111 1101
Delay1ms(1000);
P2=0xFB;//1111 1011
Delay1ms(100);
P2=0xF7;//1111 0111
Delay1ms(100);
P2=0xEF;//1110 1111
Delay1ms(100);
P2=0xDF;//1101 1111
Delay1ms(100);
P2=0xBF;//1011 1111
Delay1ms(100);
P2=0x7F;//0111 1111
Delay1ms(100);
}
}
1.独立按键的介绍
2.版中的独立按键
按键在上电时默认高电频,按下变低电频,再松手变回高电频。
3.如何控制呢?
#include
void main()
{
while (1)
{
if (P3_2==0 )
{
P2_0=0;
}
else
{
P2_0=1;
}
}
}
远程操纵灯和按键的方法就是代码的链接
4.一些备用知识——C51:51中的C语言
具体的C知识见C的笔记,这里将概述放出:
1.C51数据类型;
2.C51数据运算
算术:+-*/%=
判断:>,>=,<,<=,==,!=
逻辑:
&& 逻辑与
|| 逻辑或
! 逻辑非
位运算:(C中少见)
<< 按位左移
>> 按位右移
& 按位与
| 按位或
^ 按位异或
~ 按位取反
3.c51基本语句
任何复杂程序均可由3种关系组成
选择;if switch case(强制选择,多重判断)
循环:while;for(可以控制循环次数)
顺序:直接写
1.按键的抖动和消抖
对于机械按键而言,当机械触点断开、闭合时,
2.为什么要消抖
我们平时按按钮,其实一般都是电脑按下不操作,松手才操作。所以得消抖
#include
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
P2_0=~P2_0;
}
}
1.加入.按键控制的函数
2.本想X+1 然后取反输出实现二进制
但是这样
1111 1111+1=0000 0000 ~0000 0000=1111 1111 出现了自循环
所以要引一个参数来操作
#include
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while (xms--){
i = 2;
j = 239;
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;
}
}
}
1.常规初始化 导入和修改Delay函数,加上独立按键板块
2.核心代码
a.设寄存器
b.探讨how移位(单按键) 运用取反和<<
#include
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while (xms--){
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
unsigned char LEDNum=0;
void main()
{
P2=~0x01;
while(1)
{
if(P3_1==0)
{
Delay(20);
while (P3_1==0);
Delay(20);
LEDNum++;
if (LEDNum>=8)
{
LEDNum=0;
}
P2=~(0x01<
c.双按键 运用--和<<
#include
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while (xms--){
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
unsigned char LEDNum=0;
void main()
{
P2=~0x01;
while(1)
{
if(P3_1==0)
{
Delay(20);
while (P3_1==0);
Delay(20);
LEDNum++;
if (LEDNum>=8)
{
LEDNum=0;
}
P2=~(0x01<
1.数码管介绍
2.数码管引脚定义
1个里8个灯(共阴或者共阳 意思是八个灯接在同一个阴极或者阳极)
a.如何一个管亮出一个数字 对应的地方亮就行 如
亮6,就是AEFDCG亮, B为灭
b.四位一体的数码管
c.动态数码管——视觉暂留效应(先不解释,往后看)
3.数码管原理图(含138和74H245)
a.我们是共阴极——LED1-8都连在同一个阴极,调整的就是调阳极
b.138译码器
就是选择LED灯的东西,CBA的十进制代码和Y的2进制代码对应,通过输入CBA代码,选择哪盏或者哪些LED亮
c.74HC245双向数据缓冲器
用处:简单理解成原封不动送P0到LCD
d.里面的电容器 ——稳定电源供电
e,限流电阻
总结:选LED口(挑一个灯亮)——给段码(亮灯里面的哪些部分)——亮
4.铺垫——C51知识(同理,主要还是看C的笔记,这里只写作用)
a.数组:数组的目的是通过数组名加索引号简单快捷的操作大量数据。
b.子函数:子函数的目的是实现代码的复用和优化程序结构。
5.如何在数码管上一个灯显示数字6呢?
1.让灯通电 2.让灯显示六
3.使用子函数优化,使得所输位置和所需数字即可显示
#include
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()
{
NiXie(1,3);
while (1)
{
}
}
目的:123位分别显示1 2 3
1.常规初始化和单数字的代码
2.补上代码:复制P0——单数字代码进while(不断扫描,因为P0在不断变,不扫描无法显示)——加延时——感受延时变短的动态模糊(200ms——20ms——0)——然而去掉之后会有影子
影子何来?
在位选 段选 位选 段选 的衔接下 代码出现了重叠影
3.所以要用延时和清0来消影
#include
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while (xms--){
i = 2;
j = 239;
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()
{
while (1)
{
NiXie(1,1);
// Delay(20);
NiXie(2,2);
// Delay(20);
NiXie(3,3);
// Delay(20);
}
}
4.数码管驱动方式