51单片机(一)

51单片机简明笔记(一)

这一系列blog主要用于记录51单片机的软件学习与部分硬件学习思路,保存代码与模版方便速查。

1概述

我的单片机型号是STC89C52RC,具体参数可见下表 查看参数 推测这个所谓程序空间指的是ROM 单片机简称MCU,是micro control unit的缩写,意为一个微型的计算机。 中央处理器(CPU):STC89C52RC的CPU是8051体系结构的核心,主要负责执行程序指令、数据处理、中断处理等任务。程序的编写使用C语言或汇编语言,通过编译器生成二进制可执行文件,然后通过下载工具将程序下载到STC89C52RC中。

存储器(FLASH):STC89C52RC具有64KB的Flash存储器,可以用来存储程序代码和数据。在编程时,需要将程序代码和数据存储到Flash中,以便单片机可以读取执行。

存储器(RAM):STC89C52RC具有256字节的RAM存储器,可以用来存储程序中的变量和中间结果。在编程时,需要定义变量并将其存储到RAM中,以便程序可以读写变量的值。

定时器/计数器(Timer):STC89C52RC具有3个定时器/计数器,可以用来产生定时中断、PWM波形输出等功能。在编程时,需要对定时器/计数器进行初始化配置,并编写中断服务程序来处理定时中断。

串口(UART):STC89C52RC具有一个串口,可以用来进行与外部设备的通信。在编程时,需要对串口进行初始化配置,并编写发送和接收函数来进行数据的传输。

IO口:STC89C52RC具有32个IO口,可以用来连接各种外部设备,如LED、LCD、按键、传感器等。在编程时,需要对IO口进行初始化配置,并编写IO口的读写函数来控制外部设备的状态。

中断控制器(INT):STC89C52RC具有中断控制器,可以用来管理各种中断源和中断服务程序。在编程时,需要对中断控制器进行初始化配置,并编写中断服务程序来处理中断事件。 原文链接:https://blog.csdn.net/m0_61107092/article/details/130212554

2 LED灯相关

基本思想 cpu控制寄存器(ram)控制高低电平

点亮一个led

1
2
3
4
5
6
#include <REGX52.H>
void main()
{
P2=0xFE; // 1111 1110

}

led闪烁(引入延时函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <REGX52.H>
#include <INTRINS.H>

void Delay100us() //@11.0592MHz
{
unsigned char i, j; //用unsigned 为了节约内存。

_nop_();
_nop_();
i = 2;
j = 15;
do
{
while (--j);
} while (--i);
}
void main()
{
while(1)
{
P2=0xFE; //1111 1110
Delay500ms();
P2=0xFF; //1111 1111
Delay500ms();
}
}

流水灯等等也是同样的道理。在单片机中main函数执行完一遍不会退出,而是会循环,因此想要终止在某一处,可以在main函数中加入一个while死循环。

3 独立按键控制

前置知识 1 控制八位灯中的某一位 采用这种写法P2_i=0/1 i从0取到7 0为低电平,1为高电平。 2 看电路图可知按键接口断开时为1 按下时为2 3 按键按下的抖动导致电位并不是平整的,需要通过软件或硬件实现消抖。 消除抖动是重点研究对象 消抖

控制一个LED

位运算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <REGX52.H>
#include <INTRINS.H>
void Delay(unsigned int times) //@11.0592MHz
{
while(times)
{
unsigned char i, j;

_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
times--;
}
}
void main()
{
if(P3_1==0)
{

Delay(20);
while(P3_1==0) Delay(1); //人手按下的速度是有限的,回弹也是如果判定还在按着按键,那么电位还不应该改变,继续截止。
P2_0=~P2_0;

}
}

独立按键控制LED移位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <REGX52.H>
#include <INTRINS.H>
void Delay(unsigned int times) //@11.0592MHz
{
while(times)
{
unsigned char i, j;

_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
times--;
}
}
unsigned char LEDNum;

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<<LEDNum);
}
if(P3_0==0)
{
Delay(20);
while(P3_0==0);
Delay(20);

if(LEDNum==0)
LEDNum=7;
else
LEDNum--;
P2=~(0x01<<LEDNum);
}
}
}

4 数码管显示

原理:参见 51单片机(三)数码管(超详细、必会!)_数码管abcdefg对应-CSDN博客

静态数码管显示数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <REGX52.H>


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(2,3);
while(1)
{

}
}

如若想要动态显示,只需要引入延时函数,在显示不同数字的操作之间加上一段延时即可。

5 模块化编程

几个图

6 矩阵键盘

我们有十六个按键,通过十六个独立通路实现对按键状态的检测是对IO口极大的浪费,因此为了减少I/O口的占用,通常将按键排列成矩阵形式。采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态。矩阵键盘扫(输入扫描)的原理:读取第1行(列)→读取第2行(列) →读取第3行(列) → ……,然后快速循环这个过程,最终实现所有按键同时检测的效果。这相当于我们读取了键盘的横纵坐标,因为每排(列)按键总是共用同一纵(横)坐标的,所以节省了资源。例如,要判断第一行S1、S2、S3、S4四个按键是否按下,则只需要先将P17接地,之后判断P13是否为0进而判断按键S1是否被按下,因为P17为低电平,若P13为低电平,则说明S1所在的电路导通了,即说明S1被按下,这与独立按键的原理一样。判断S2是否被按下,只需判断P12是否为0即可。要判断第一列S1、S5、S9、S13是否按下,可先将P13接地,然后判断P17、P16、P15、P14是否为0即可。代码实现矩阵按键数值显示 需要用到LCD1602.c文件(驱动程序)同时涉及到了之前独立按键控制LED灯的操作。

返回一个整形的“键盘函数”MatrixKey()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <REGX52.H>
#include "Delay.h"
* @brief 矩阵键盘读取按键键码
* @param 无
* @retval KeyNumber 按下按键的键码值
如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0
*/
unsigned char MatrixKey()
{
unsigned char KeyNumber=0;

P1=0xFF;
P1_3=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}

P1=0xFF;
P1_2=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}

P1=0xFF;
P1_1=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}

P1=0xFF;
P1_0=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}

return KeyNumber;
}

51单片机(一)
http://example.com/2024/01/21/EE/51单片机(一)/
作者
bradin
发布于
2024年1月21日
许可协议