51单片机

单片机集成了,CPU,内储存器,外储存器,等电脑设备是一个小型的计算机。可以控制一些硬件设备的运行,体形小耗能低。

概念

单片机含有端口,端口又含有引脚。例如:STC89C52RC型号的单片机有五个端口,P0,P1,P2,P3,P4

一个端口又有8个引脚,P0.0~P4.8。

单片机通过控制电压的高低来控制硬件设备的运行。LED的起始电压是5V,单片机控制输出5V高电平,就没有电流通过,灯灭,反之灯亮。

在编写程序中:

定义端口

1
sfr P0 = 0x80

其中sfr是special function register特殊功能寄存器的意思,P0是变量名0x80是该组端口的位置。

在STC89C52RC型号的单片机中五个端口位置如下:

端口 位置
0 0x80
1 0x90
2 0xA0
3 0xB0
4 0xe8

以上可以由一个内置文件引入include “reg52.h”

定义好端口后还需要定义引脚

1
sbit P0.0 = P0^0

keil

keil是一个编写工具,内置了各种库。

打开keil点击project=>new uvision project=>intel=>8052AH

设置输出十六进制文件:点击配置目标选项,点output选项勾选Create HEX File,配置路径select folder listing.

模块化编程

要想控制复杂的硬件运行就需要对单片机进行程序编写。第一步是对项目进行模块化,就是把不同的文件分好类。

{history:output:hex16project:keilreadme:src{dev:,,sys:config.hmain.c\begin{cases} history:历史文件\\ output:输出文件hex16进制文件\\ project:keil工程文件\\ readme:说明文件\\ src\begin{cases} dev:外接模块的控制程序,蜂鸣器,显示器等\\ sys:配置文件config.h\\ main.c \end{cases} \end{cases}

config.h:包含reg52.h等一些文件,定义引脚引用名称

dev:外接模块有*.h和*.c两种文件

  • *.h中声明*.c中需要的函数名,提供给main.c以便include
  • *.c中包含config.h和*.h,编写函数

main.c:主文件,实现模块之间的连接

在keil目录中右键添加几个文件,右击manage project item添加刚刚的模块文件

点击配置目标选项,点output和listing,配置路径select folder listing.再配置C51的include paths 添加src ,dev,sys

程序编写

延时

在stc-isp中找到软件延时计算器,系统频率是11.0592指令集是STC-Y1,复制代码,进行编译此时会出现一个错误,需要引入头文件#include “intrins.h”

独立按键

默认没有按下是高电平,按下是低电平。机械按键都会有一个抖动,前沿抖动,闭合,后沿抖动。这两个抖动会导致按键出现重复高低电平的变化,应该消除抖动,抖动一般是15ms。

config.h

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
/******************************************************************************/
// 包含头文件
/******************************************************************************/
#include "reg52.h"
#include "intrins.h"

/******************************************************************************/
// 类型定义
/******************************************************************************/
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
typedef signed char int8;
typedef signed int int16;
typedef signed long int32;

/******************************************************************************/
// P4端口定义,位置再在上表中由定义
/******************************************************************************/
sfr P4 = 0xe8;

/******************************************************************************/
// KEY引脚配置
/******************************************************************************/
sbit key1 = P1^0; //up

delay.c

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
/******************************************************************************/
// 包含头文件
/******************************************************************************/
#include "config.h"
#include "delay.h"


/******************************************************************************/
// 函数名称:Delay15ms
// 输入参数:无
// 输出参数:无
// 函数功能:15ms
// 晶振频率:11.0592M
/******************************************************************************/
void Delay15ms()
{
uint8 i, j;

i = 27;
j = 226;
do
{
while (--j);
} while (--i);
}

delay.h

1
2
3
4
/******************************************************************************/
// 延时函数声明
/******************************************************************************/
void Delay15ms();

这里.h文件就是delay.c的头文件主要是声明函数,delay.c里的所有函数都在这里声明,其他文件只要引入delay.h就可以调用delay.c的函数了。

key.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void Key_Up_Press(void){
bit flag = 1; //定义标记
key1=1; //赋予初始值
if(!key1){ //判断是否按下开关
Delay15ms(); //跳过前沿抖动
if(!key1){ //再次确认是否还是按下
while(!key1); //等待松开
Delay15ms(); //跳过后沿抖动
while(!key1); //确定松开
flag = 0; //改变标记位
}
}
return flag; //返回标记
}

解释:

  • 定义标记flag主要是记录开关是否被触发过。
  • 赋予初始值是因为key正常状体默认是高电平所以是1
  • 判断是否按下开关,如果按下开光则key变成0,!key=1判断语句执行
  • 跳过前沿抖动,防止误判发生
  • 再次确认这个步骤的意思是闭合状态,不加也没什么影响,加上更可靠
  • 等待松开,如果松开key变成1,!key=0跳出循环
  • 跳过后沿抖动,防止误判发生
  • 确定松开,如果确实是松开直接跳出循环
  • 改变标记,提供给调用函数判断进行执行下一步命令

key.h

1
bit Key_Up_Press(void);   //判断按键1是否按下

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/******************************************************************************/
// 包含头文件
/******************************************************************************/
#include "config.h"
#include "key.h"
#include "delay.h"

/******************************************************************************/
// main函数
/******************************************************************************/
int main(void){
while(1){
if(!Key_Up_Press())led1=~led1; //up -> led1 toggle
}
}

如果按键被按下过Key_Up_Press()=0,!Key_Up_Press()=1,执行后面的命令。