51单片机基础
51单片机基础
学习时间:2022年11月6日
学习来源:江科大自化协
1 开发工具
Keil5
:Keil C51
是美国Keil Software
公司出品的51系列兼容单片机C语言软件开发系统。Keil提供了包括C编译器、宏汇编、链接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(μVision
)将这些部分组合在一起。
下载地址:https://www.keil.com/download/product/
STC-ISP:STC-ISP 是一款单片机下载编程烧录软件,是针对STC系列单片机而设计的,可下载STC89系列、12C2052系列和12C5410等系列的STC单片机,使用简便。
2 单片机和开发板介绍
2.1 单片机
单片机(Single-Chip Microcomputer)是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。
从上世纪80年代,由当时的4位、8位单片机,发展到现在的300M的高速单片机。
单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。相当于一个微型的计算机,和计算机相比,单片机只缺少了I/O设备。概括的讲:一块芯片就成了一台计算机。
2.2 51单片机
51单片机是对兼容英特尔8051指令系统的单片机的统称。51单片机广泛应用于家用电器、汽车、工业测控、通信设备中。
- 主要产品:
Intel
(英特尔):80C31、80C51、87C51,80C32、80C52、87C52等;Atmel
(艾特梅尔):89C51、89C52、89C2051,89S51(RC),89S52(RC)等;- Philips(飞利浦)、华邦、Dallas(达拉斯)、Siemens(西门子)等公司的许多产品;
STC
(宏晶):STC89C51、STC90C51、STC11系列、STC15系列、STC8系列等。
STC89C52单片机
- 所属系列:51单片机系列
- 公司:STC公司(宏晶),中国公司
- 位数:8位
- RAM:512字节
- ROM:8K(Flash)
- 工作频率:12MHz(本开发板使用)
命名规则
内部结构
STC89C52系列单片机的内部结构框图如下图所示。STC89C52单片机中包含中央处理器(CPU)、程序存储器(Flash)、数据存储器(SRAM)、定时/计数器、UJART串口、I/O接口、EE-PROM、看门狗等模块。STC89C52系列单片机几平包含了数据采集和控制中所需的所有单元模块,可称得上一个片上系统。
2.3 开发板
原理图
注:我的自用开发板(STC89C52 RC
):
3 LED
3.1 点亮一个LED
3.1.1 新建工程
- 在Keil5中新建一个工程:搜索
AT89C52
(采用的是Atmel),然后选择否
,不生成启动文件。
- 新建C源代码文件
- 编写初始代码
1 | void main() { |
- 构建
build
项目
3.1.2 LED介绍
发光二极管(Light Emitting Diode
)
简称:LED
用途:照明、广告灯、指引灯、屏幕
上图:左正右负。
原理图
简单的原理:单片机的CPU通过向IO口写入值(1高电平5v,0低电平0v),来控制硬件电路的高低电平。
- LED模块
从上图可知,LED模块引出的管脚编号从P20~P27,共8个管脚,控制8个LED
- 单片机核心
从上图可知,LED的P20~P27
管脚连接至单片机CPU的P2.0~P2.7
管脚。因此通过控制51单片机核心中的P2特殊功能寄存器的每一位的值,来控制输出到LED的P20~P27
管脚的电平高低。
例如,如果P2.0
的值设置为1,代表高电平,此时LED灭(两端没有电压差);相反设置为0,代表低电平,此时LED亮。
3.1.3 代码实现
这里让P20(芯片寄存器为P2,位号为P2.0)对应的LED亮,其他LED灭。
1 |
|
头文件REGX52.H
包含了AT89X52
芯片的寄存器变量(仅列出部分):
1 | /*-------------------------------------------------------------------------- |
然后构建,生成相应的hex
十六进制文件
3.1.4 烧录
- 相应设置:
打开程序文件:选择项目下构建好的hex
十六进制文件,然后下载。
关闭单片机,再进行冷启动(单片机在冷启动时加载程序),之后即可发现LED亮。
程序改进
单片机上电后,会执行main函数:
1 |
|
执行到第三行后,LED亮,之后从main函数退出,cpu会再次执行main函数,到第三行,LED亮,如此反复,此时cpu会不断操作P2寄存器。
改进:
1 |
|
cpu执行至第4行进入死循环,此时P2 = 0xFE;
,LED一直亮,且cpu不会再操作P2寄存器。
3.2 LED闪烁
效果:让LED以1s为周期闪烁。新建一个工程。
代码实现
1 |
|
3.3 LED流水灯
效果:LED逐一亮灭。
代码实现
1 |
|
代码优化:修改延时代码,接受一个参数n来控制熄灭的时间。
1 | // n为延时的时间,单位ms |
4 独立按键
4.1 介绍
轻触按键:相当于是一种电子开关,按下时开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开。
电路原理图
- 独立按键模块:例如,按下K1时,P31接地为低电平(0),使得cpu的P3寄存器的该位为0;反之为1。
- cpu:接至
P3
寄存器
4.2 控制LED亮灭
效果:按下按键K1(注意编号为P31
),LED D1(编号P20
)亮,松开按键K1,LED D1灭。
REGX52.H
头文件中,不仅定义了8位寄存器的变量(以sfr
修饰),还定义了针对8位寄存器每1位的单独变量(以sbit
修饰),例如:
1 | /*------------------------------------------------ |
代码实现
1 |
|
4.3 控制LED状态
效果:按一下按键K1,LED D1亮,再按一下,LED灭
按键的抖动:对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动。
消抖有两种策略:
- 硬件消抖:在电路中加入电容
- 软件消抖:加入延时函数
代码实现
1 |
|
4.4 控制LED显示二进制
效果:每按一次K1,LED按照二进制递增的顺序进行亮灭。
实现代码
1 |
|
上述程序:
- 第一次按下时,
LEDNum=0000 0001
,取反为LEDNum=1111 1110
,并赋值给P2,使得最后一位(P2_0)的LED亮。 - 第二次按下时,
LEDNum=0000 0010
,取反为LEDNum=1111 1101
,并赋值给P2,使得P2_1的LED亮。 - 以此类推
4.5 控制LED移位
效果:每按一次K1,LED从低位到高位,一次移动一位亮。每按一次K2,LED从高位到低位,一次移动一位亮。
- P2寄存器需要的变化:
1111 1110
—>1111 1101
—>1111 1011
…
- 取反后相应的变化:
0000 0001
—>0000 0010
—>0000 0100
…- 即
0000 0001
向左进行移位,按多少次,就移动多少位
代码实现
1 |
|
5 数码管
5.1 静态数码管显示
5.1.1 概述
LED数码管:数码管是一种简单、廉价的显示器,是由多个发光二极管封装在一起组成“8”字型的器件。
一位数码管
分为共阴极COM连接和共阳极GRN连接两种连接方式:
- 引脚连接
以共阳极(上面的下图)为例,3和8号引脚接至正极,A号LED负极引脚编号为7,以此类推。
多位数码管
也分为共阴极连接和共阳极连接两种连接方式:
5.1.2 电路原理图
- 动态数码管模块
其中74HC245是一个双向数据缓冲器,端口是一一对应的关系,作用是提供驱动能力(如果去掉,则P传过来的信号直接当做驱动,给LED的阳极供电,反之,加上缓冲器后,P传过来的信号只是当做控制信号,即使很微弱也能区分相对的正负,之后再由74HC245的VCC直接给LED提供电源驱动,使得LED更亮)。DIR
控制数据流向,高电平为从左到右(右边读左边),低电平从右到左(左边读右边),图中DIR
接电源,则上电后为右边读左边,有的单片机该端口接的是跳线帽Jxx
。
- 74H138译码器
输入端:P22~P24
,高位到低位:CBA
输出端Y0~Y7
使能端G1~G2
:单片机上电就使能。
例如,输入CBA为101
(二进制),换算成十进制为5
,则选中Y5
使能,其余失效。
5.1.3 代码实现
效果:点亮LED6,并显示6
代码实现
1 |
|
程序解析:
- 在译码器中,LED6对应Y5,因此输入端二进制应该为
101
abcdefg(dp)
亮的为acdefg
,因此LED段码为:0111 1101
,对应十六进制0x7D
代码优化
构造一个函数Nixie
,接收参数控制哪个LED亮,以及亮的数字
1 |
|
5.2 动态数码管显示
所谓动态显示,是指多个数码管同时亮起,实际上从电路原理图来看,在确定的某一时刻,只能有一个数码管亮(译码器只能送一个确定的值来决定位选);但是单片机执行指令速度很快,人眼具有视觉暂留,因此看起来像是多个数码管同时亮了起来。
数码管显示通常以位选 段选 位选 段选...
的顺序来执行,其中,位选是选择哪一个数码管亮,段选是数码管中的LED哪些亮,以形成一个数字或某种形状。
1 | void main() { |
消隐:单片机执行速度很快,以位选 段选 位选 段选...
的顺序执行时,段选码可能会窜到位选码的位置上,导致错误。在数码动态显示过程中,若进行位选切换时没有对上一位显示的内容进行清空,则会导致当前数码管中出现上一片内容的余影,从而使显示模糊,影响了整个显示效果。
解决方法:在数码管位选信号切换前,先向段传送“不亮”字型码,然后在进行切换和正常传递新段码。
实现代码
1 |
|
数码管驱动方式:
- 单片机直接扫描:硬件设备简单,但会耗费大量的单片机CPU时间
- 专用驱动芯片:内部自带显存、扫描电路,单片机只需告诉它显示什么即可
6 模块化编程和LCD
6.1 简介
传统方式编程:所有的函数均放在main.c
里,若使用的模块比较多,则一个文件内会有很多的代码,不利于代码的组织和管理,而且很影响编程者的思路。
模块化编程:把各个模块的代码放在不同的.c
文件里,在.h
文件里提供外部可调用函数的声明,其它.c
文件想使用其中的代码时,只需要#include "XXX.h"
文件即可。使用模块化编程可极大的提高代码的可阅读性、可维护性、可移植性等。
注意事项:
- .c文件:函数、变量的定义
- .h文件:可被外部调用的函数、变量的声明
- 任何自定义的变量、函数在调用前必须有定义或声明(同一个.c)
- 使用到的自定义函数的.c文件必须添加到工程参与编译
- 使用到的.h文件必须要放在编译器可寻找到的地方(工程文件夹根目录、安装目录、自定义)
6.2 预编译
C语言的预编译以#
开头,作用是在真正的编译开始之前,对代码做一些处理(预编译)。
预编译 | 意义 |
---|---|
#include <REGX52.H> |
把REGX52.H 文件的内容搬到此处 |
#define PI 3.14 |
定义PI,将PI替换为3.14 |
#define ABC |
定义ABC |
#ifndef __XX_H__ |
如果没有定义__XX_H__ |
#endif |
与#ifndef ,#if 匹配,组成“括号” |
此外还有#ifdef
,#if
,#else
,#elif
,#undef
等
6.3 模块化实现
需求:将延时函数和数码管显示的函数模块化。
- 项目结构:
代码实现
Delay.c
和Delay.h
1 | void Delay(unsigned int n) { |
1 |
|
Nixie.c
和Nixie.h
1 |
|
1 |
|
main.c
1 |
|
6.4 LCD1602调试工具
6.4.1 原理图
使用LCD1602
液晶屏作为调试窗口,提供类似printf函数的功能,可实时观察单片机内部数据的变换情况,便于调试和演示。
本视频提供的LCD1602代码属于模块化的代码,使用者只需要知道所提供函数的作用和使用方法就可以很容易的使用LCD1602。
函数 | 作用 |
---|---|
LCD_Init(); |
初始化 |
LCD_ShowChar(1,1,'A'); |
显示一个字符 |
LCD_ShowString(1,3,"Hello"); |
显示字符串 |
LCD_ShowNum(1,9,123,3); |
显示十进制数字 |
LCD_ShowSignedNum(1,13,-66,2); |
显示有符号十进制数字 |
LCD_ShowHexNum(2,1,0xA8,2); |
显示十六进制数字 |
LCD_ShowBinNum(2,4,0xAA,8); |
显示二进制数字 |
1 |
|
1 |
|
电路原理图
- LCD1602接口
- cpu
由图可知,LCD的八个引脚LCD D0 ~ LCD D7
与cpu的P0寄存器的P0 ~ P7
相连
6.4.2 代码示例
1 |
|
7 矩阵键盘
7.1 简介
在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式。
采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态。
扫描
- 数码管扫描(输出扫描) 原理:显示第1位→显示第2位→显示第3位→……,然后快速循环这个过程,最终实现所有数码管同时显示的效果
- 矩阵键盘扫描(输入扫描) 原理:读取第1行(列)→读取第2行(列) →读取第3行(列) → ……,然后快速循环这个过程,最终实现所有按键同时检测的效果
以上两种扫描方式的共性:节省I/O口。
7.2 原理图
矩阵按键
通过原理图可知,P17~P14
连接按键的左端,P13~P10
连接按键的右端
- 按行扫描:
- 扫描第一行:给定
P17~P14
为0111
,当P13~P10
的哪一位为0,则S1~S4
对应的被按下。例如P13
为0,则S1
被按下。 - 扫描第二行:给定
P17~P14
为1011
,当P13~P10
的哪一位为0,则S5~S8
对应的被按下。例如P13
为0,则S5
被按下。 - 以此类推
- 扫描第一行:给定
- 按列扫描:
- 扫描第一列:给定
P13~P10
为0111
,当P17~P14
的哪一位为0,则S1,S5,S9,S13
对应的被按下。 - 以此类推
- 扫描第一列:给定
单片机核心
7.3 矩阵键盘
效果:采用列扫描;按下一个按键,在LCD显示屏上显示按键的序号。
可以为头文件新建一个模板(代码片段):
MatrixKey.c
和头文件
1 |
|
1 |
|
main.c
1 |
|
7.4 密码锁
效果:S1~S9
定义为输入的数字,S10
为0,S11
为确认,S12
为取消。
- 代码实现
1 |
|
8 定时器
8.1 简介
8.1.1 定时器资源
定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。
定时器作用:
- 用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作
- 替代长时间的Delay,提高CPU的运行效率和处理速度(不让CPU空转)
定时器个数:3个(T0
、T1
、T2
),T0和T1与传统的51单片机兼容,T2是此型号单片机增加的资源。
注意:定时器的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有51单片机所共有的。
8.1.2 框图
定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号,每隔“一秒”,计数单元的数值就增加一,当计数单元数值增加到“设定的闹钟提醒时间”时,计数单元就会向中断系统发出中断申请,产生“响铃提醒”,使程序跳转到中断服务函数中执行。
8.1.3 工作模式
STC89C52的T0
和T1
均有四种工作模式:
- 模式0:13位定时器/计数器
- 模式1:16位定时器/计数器(常用)
- 模式2:8位自动重装模式
- 模式3:两个8位计数器
工作模式1的框图
SYSclk
:系统时钟,即晶振周期,本开发板上的晶振为12MHz。然后可进行12分频和6分频两种,12分频使得时钟脉冲的频率变为1MHz(每1μs,计数加1),6分频使其变为2MHz。
T0 PIN
:计数器功能。C/T非
是计数器(Counter
)和定时器(Timer
)的功能选择开关。若为低电平,则定时器功能选通,否则是计数器功能。
计数单元有两个字节寄存器组成,TL0表示低8位,TH0表示高8位,最大可表示的数为65535;当左侧时钟脉冲每过来一次,计数单元加1,直到最大值,使得标志位TF0为true,触发中断系统。
下方的TR0
、GATE
和INT0
是控制位,控制定时器或计数器开启。
8.1.4 中断系统
中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。
当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后,再回到原来被中断的地方,继续原来的工作,这样的过程称为中断。实现这种功能的部件称为中断系统,请示CPU中断的请求源称为中断源。
微型机的中断系统一般允许多个中断源,当几个中断源同时向CPU请求中断,要求为它服务的时候,这就存在CPU优先响应哪一个中断源请求的问题。通常根据中断源的轻重缓急排队,优先处理最紧急事件的中断请求源,即规定每一个中断源有一个优先级别。CPU总是先响应优先级别最高的中断请求。
STC89C51RC/RD+系列单片机提供了8个中断请求源,它们分别是∶外部中断0(INT0
)、定时器0中断、外部中断1(INT1
)、定时器1中断、串口(UART
)中断、定时器2中断、外部中断2(INT2
)、外部中断3(INT3
)。所有的中断都具有4个中断优先级。
注意:中断的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的中断资源,例如中断源个数不同、中断优先级个数不同等等。
如果使用C语言编程,中断查询次序号就是中断号,例如:
8.1.5 相关寄存器
寄存器是连接软硬件的媒介。在单片机中寄存器就是一段特殊的RAM存储器(特殊功能寄存器sfr
详见补充知识1.4节存储
),一方面,寄存器可以存储和读取数据,另一方面,每一个寄存器背后都连接了一根导线,控制着电路的连接方式。寄存器相当于一个复杂机器的“操作按钮”。
定时器/计数器相关寄存器
中断寄存器
① TCON控制
对定时器T0或T1的控制寄存器:
- TF∶定时器/计数器溢出标志。T1被允许计数以后,从初值开始加1计数。当最高位产生溢出时由硬件置1,向CPU请求中断,一直保持到CPU响应中断时,才由硬件清0
- TR:定时器的运行控制位。该位由软件置位和清零。当
GATE=0,TR1=1
时就允许T1开始计数,TR1=0时禁止T1计数。
② TMOD模式
定时和计数功能由特殊功能寄存器TMOD的控制位C/T
进行选择,TMOD寄存器的各位信息如下表所列。
可以看出,2个定时/计数器有4种操作模式,通过TMOD的M1和M0选择。
③ IE中断允许
8.2 LED间隔闪烁
效果:通过LED隔一秒闪烁一次。
初始化定时器
假设要让定时器0以模式1(16位定时)工作:
TMOD
- GATE=0,C/T=0,M1=0,M0=1
TCON
- 初值计算:
0~65535
,每隔1μs计数加1,总共计时65535μs;64535距离计数器差值为1000,所以计时为1ms; - TH=64535/256,TL=64535%256;也可以使用工具生成定时器代码
- TR0=1:允许T0开始计数
- 初值计算:
初始化中断系统
初始化值:ET0=1(T0溢出中断控制),EA=1(总中断控制),PT0=0(优先级设为最低级,也可以不设置,默认为0)
代码实现
注:这里使用了STC-ISP
的定时器计算器生成的代码
1 |
|
说明:
- 第17行定时器初始化后开始计时,main程序进入while循环。
- 到达1ms时,定时器产生中断,cpu进入中断子程序,重新给定时器赋初值(让定时器以1ms定时),T0Count++(1000时就是1s);
- 中断子程序执行完毕,又进入main程序继续执行(仍处于在while循环中);
- 到达1ms时,定时器产生中断,cpu进入中断子程序,重新给定时器赋初值,T0Count++;
- 以此类推…(当T0Count=1000时,进入if语句,刷新T0Count,让LED灯状态取反)
注意:在main函数的while循环里并未显式调用中断子程序,这一步是由定时器引起的中断让cpu自动做出的调用。
代码改造——模块化
Timer0.c
和Timer0.h
1 |
|
1 |
|
main.c
1 |
|
注:T0Count需要有static
修饰,详见C语言学习笔记的12.1.6 块作用域的静态变量(静态无链接)
。
8.3 按键控制LED流水灯
效果:通过按键控制LED流水灯的方向。
代码实现
Key.c
和头文件
1 |
|
1 |
|
作用:返回按下按键的序号
main.c
1 |
|
8.4 定时器时钟
效果:LCD显示屏1s递增
代码实现
1 |
|
9 串口通信
9.1 简介
串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。
51单片机内部自带UART(Universal Asynchronous Receiver Transmitter
,通用异步收发器),可实现单片机的串口通信。
硬件电路
- 简单双向串口通信有两根通信线(发送端TXD和接收端RXD)
- TXD与RXD要交叉连接
- 当只需单向的数据传输时,可以直接一根通信线
- 当电平标准不一致时,需要加电平转换芯片
电平标准
电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:
- TTL电平:+5V表示1,0V表示0
- RS232电平:
-3~-15V
表示1,+3~+15V
表示0 - RS485电平:两线压差
+2~+6V
表示1,-2~-6V
表示0(差分信号)
常用通信接口
名称 | 引脚定义 | 通信方式 | 特点 |
---|---|---|---|
UART | TXD 、RXD |
全双工、异步 | 点对点通信 |
I²C | SCL、SDA | 半双工、同步 | 可挂载多个设备 |
SPI | SCLK、MOSI、MISO、CS | 全双工、同步 | 可挂载多个设备 |
1-Wire | DQ | 半双工、异步 | 可挂载多个设备 |
此外还有:CAN、USB等。
9.2 单片机的UART
9.2.1 工作模式
STC89C52有1个UART;
STC89C52的UART有四种工作模式:
- 模式0:同步移位寄存器
- 模式1:8位UART,波特率可变(常用)
- 模式2:9位UART,波特率固定
- 模式3:9位UART,波特率可变
9.2.2 串口参数
- 波特率:串口通信的速率(发送和接收各数据位的间隔时间)
- 检验位:用于数据验证,对于9位数据格式,
RB8/TB8
为检验位 - 停止位:用于数据帧间隔
先发低位,再发高位:
9.2.3 串口模式图
- SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器。
- T1溢出率(T1定时器)用来控制波特率。
- 最左侧的箭头为内部的总线。
SMOD
用于控制波特率是否加倍
9.2.4 串口和中断
两个中断经过了或门,如果其中有一个中断了,就可通过或门输出1中断。
9.2.5 相关寄存器
其中:SCON
的SM0
和SM1
用于确定串口的工作方式:
9.3 串口向电脑发送数据
效果:串口每秒向电脑发送按秒递增的数据。
代码实现
- 可以通过
STC-ISP
的波特率计算器来获取串口初始化代码
- 串口初始化和发送模块
1 |
|
TI
:发送中断请求标志位。在方式0,当串行发送数据第8位结束时,由内部硬件自动置位,即TI=1
,向主机请求中断,响应中断后必须用软件复位,即TI=0
。
1 |
|
- 主函数
1 |
|
9.4 电脑向串口发送数据
SCON
寄存器的第4位REN
位:允许/禁止串行接收控制位。由软件置位REN,即REN=1
为允许串行接收状态,可启动串行接收器RxD,开始接收信息。软件复位REN,即REN=0,则禁止接收。因此需要置为1;- 启动串口中断
ES
:ES=1
- 接收中断请求标志位:在方式0,当串行接收到第8位结束时由内部硬件自动置位
RI=1
,向主机请求中断,响应中断后必须用软件复位,即RI=0
。在其他方式中,串行接收到停止位的中间时刻由内部硬件置位,即RI=1,必须由软件复位,即RI=0。
代码实现
UART.c
1 |
|
main.c
1 |
|
9.5 波特率计算
定时器1的初始值为:
1 | TL1 = 0xF4; |
则计数256 - 244 = 12
个数就溢出一次(配置的是定时器1的8位自动重装,因此到达8位最大值256时就溢出);
对于11.0592MHz
的晶振,设定在12T
的模式下(12分频)时,实际的晶振频率为0.9216MHz
,所以计数1次需要1/0.9216μs
(MHz对应μs),大约为1.085069444444444μs
,则计数12次为13.02083333333333μs
,对应的溢出频率为0.0768MHz
;
如果设置了波特率加倍(SMOD=1
,即没有除以2),则T1溢出率(0.0768MHz
)到达发送/接收控制器的频率为0.0768MHz/16=0.0048MHz
,即4800Hz
,即为波特率。
10 LED点阵屏
10.1 简介
LED点阵屏由若干个独立的LED组成,LED以矩阵的形式排列,以灯珠亮灭来显示文字、图片、视频等。LED点阵屏广泛应用于各种公共场合,如汽车报站器、广告屏以及公告牌等。
LED点阵屏分类:
- 按颜色:单色、双色、全彩
- 按像素:
8*8
、16*16
等(大规模的LED点阵通常由很多个小点阵拼接而成)
显示原理
- 单色LED点阵
- 双色LED点阵
LED点阵屏的结构类似于数码管,只不过是数码管把每一列的像素以“8”字型排列而已;
LED点阵屏与数码管一样,有共阴和共阳两种接法,不同的接法对应的电路结构不同;
LED点阵屏需要进行逐行或逐列扫描,才能使所有LED同时显示;
电路图
DPa~DPh
选择的是从下到上的行P00~P07
选择的是从右到左的列
74HC595
74HC595是串行输入并行输出的移位寄存器(串转并),可用3根线输入串行数据,8根线输出并行数据,多片级联后,可输出16位、24位、32位等,常用于IO口扩展。
OE非
:74HC595芯片使能端,非表示低电平使能,因此需要将J24跳线帽接在2和3号位,让OE端接地使能;RCLK
:上升沿锁存,接P35口;P35口由0转1(上升沿)时,将串行输入缓存送至并行输出端(QA至QH口);SRCLK
:上升沿移位,接P36口;P36口由0转1(上升沿)时,将输入进行移位;SER
:串行输入口,接P34口QA~QH
:并行输出口QH'
:用于多片级联,接在下一片74HC595
的串行输入口SER
上
芯片内部图如下:
10.2 点阵显示图形
效果:在LED点阵屏上显示对角线
代码实现
MatrixLED
1 |
|
1 |
|
main
1 |
|
11 实时时钟
11.1 简介
12 蜂鸣器
12.1 简介
蜂鸣器是一种将电信号转换为声音信号的器件,常用来产生设备的按键音、报警音等提示信号。
蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器
- 有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定
- 无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音
一般的,蜂鸣器电路图表示:
12.2 驱动电路
- 三极管驱动
例如上图中,通过NPN型三极管Q1进行驱动。当基极接高电平时,三极管导通,此时蜂鸣器工作,反之不工作。
- 集成电路驱动
上图,蜂鸣器负极引出引脚为BEEP
,该引脚接至ULN2003
芯片的12号引脚,如下图所示:
其中ULN2003
是一个单片高电压、高电流的达林顿晶体管阵列集成电路,主要用于继电器驱动器、字锤驱动器、灯驱动器、显示驱动器、线路驱动器和逻辑缓冲器。
由上图可知,通过P25
IO口取反控制OUT5
的输出,进而控制蜂鸣器的工作状态,即P25
口输入1,取反为0输出到OUT5
,使得蜂鸣器工作,输入0则不工作。
12.3 音符和频率
12.4 蜂鸣器播放提示音
效果:按下独立按键,蜂鸣器播放提示音。
代码实现
Buzzer.h
1 |
|
Buzzer.c
1 |
|
main.c
1 |
|
12.5 蜂鸣器播放音乐
13 AT24C02(I2C)
补充知识
1 单片机原理(基础)
主要参考资料:电光耗子皮卡皮
1.1 单片机的三大发展阶段
- SCM:(
Single Chip Micro computer
),单片微型计算机阶段。寻求最佳单片状态的嵌入式体系结构。最具代表性的产品是Intel的8位MCS-51
系列单片机。
- MCU:(
Micro Controller Unit
),微控制器阶段。集成各种外围电路与接口电路的能力。
- SOC:(
System on Chip
),SoC是一个有专用目标的集成电路,包含完整系统并嵌入软件的全部内容。
1.2 基础框架结构
以MCS-51
为例。
SCM:将通用微计算机基本功能部件集成在一块芯片上构成的一种专用微机系统。
SCM = CPU+OSC+ROM+RAM+I/O+INTERRUPT+TIME/COUNTER+UART+BUS EXTENDER
- 1个8位中央处理器
CPU
- 4KB片内程序存储器
ROM
,相当于计算机的硬盘 - 256字节数据存储器
RAM
,相当于计算机的内存 - 4个8位并行
I/O
口 - 5个中断源
INT
- 2个16位定时器/计数器
T/C
- 1个全双工串行口
UART
- 可扩展64KB ROM和RAM 的总线
1.3 CPU
CPU是单片机的核心。CPU(中央处理器)分为控制器和运算器两部分。
1.3.1 控制器
- 控制器的用途:统一指挥和控制各单元协调工作
- 控制器的任务: 从ROM中取出指令—->译码—->执行指令
- 控制器的组成:
- 程序计数器(Program Counter -
PC
) : 指向下一条指令的首地址,ROM存储单元的地址指针(引导程序运行),可修改,让程序跳转运行复位时:PC初值=0 --> 复位后程序从0开始运行
。 - 指令寄存器(nstruction Register -
IR
) : 8位寄存器,暂存指令,等待译码 - 指令译码器(Instruction Decoder -
ID
) : 将指令寄存器的指令进行译码,转为可执行的电信号再通过定时器电路将其执行 - 数据指针寄存器 (Data Pointer -
DPTR
) : 指向ROM或RAM存储单元的地址指针(引导数据传送),DPTR是专门为16位(或者小于16位)的外部RAM或者外部ROM准备用于读取和写入的。
- 程序计数器(Program Counter -
1.3.2 运算器
略
1.4 存储
1.4.1 存储空间
- 普林斯顿结构:RAM和ROM统一编址
- 哈佛结构:RAM和ROM独立编址,51单片机采用哈佛结构。
因此单片机共有4个物理存储空间:片内RAM,片内ROM,片外RAM和片外ROM,3个逻辑存储空间:片内片外ROM统一编址。
1.4.2 程序存储器ROM
作用:存放程序,表格或常数,掉电不丢失。
- EA = 1时,4 KB以内的地址在片内ROM,大于4KB的地址在片外ROM中 (图中折线),两者共同构成64KB空间。
- EA = 0时,片内ROM被禁用,全部64KB地址都在片外ROM中 (图中直线)
1.4.3 数据存储器RAM
地址
在单片机、计算机系统里面,内存为了定位(为了能够找到每一个内存空间),把每一个空间都编上一个序号,那么内存编号的那个号码我们就叫地址,地址编号通常以十六进制的数字表示。
存储器系统中,给字节编号就叫字节地址,给二进制位编号就叫位地址。
①区:共有32个字节地址:
00H ~ 1FH
,每个字节地址都有一个寄存器名称(R0 ~ R7
),32个字节地址被分为4组(第0~第3组);CPU在一个时刻,只能选一组工作寄存器组,通过程序状态字寄存器PSW
的RS1
和RS0
来控制选组,不设置的话默认选择第0组,剩下的三组则用作数据存储器。②区:共有16个字节地址:
20H ~ 2FH
,合计16 * 8 = 128
个位地址,可以用字节地址或位地址进行寻址。
③区:共有80个字节地址,没有位地址,也没有寄存器名称,此区可作为堆栈区和中间数据存储区使用。
特殊功能寄存器区
SFR
:Special Function Register
,承担着单片机内部资源的管理工作。
示例
直接寻址:通过把地址定义一个名称后,修改在该地址的内存空间的内容。
1 | Sbit P0_0 = 80H; // 把80H编号的位空间取一个名称P0_0,定义一个名称P0_0 |
Sfr
:特殊寄存器字节定义指令
Sbit
:位地址定义指令
1.5 单片机引脚
P1.0 ~ P1.7
:1-8脚,准双向IO口,P1端口P3.0 ~ P3.7
:10-17脚,带复用功能,P3端口P2.0 ~ P2.7
:21-28脚,高八位数据总线,P2端口P0.0 ~ P0.7
:39-32脚,低八位数据总线,P0端口
引脚分类
- 电源及晶振引脚(4)
- 控制引脚(4)
- 端口引脚(32)
1.6 IO口
1.6.1 基本元器件
① 二极管
具有单向导电性能, 即给二极管阳极加上正向电压时,二极管导通。 当给阳极和阴极加上反向电压时,二极管截止。 因此,二极管的导通和截止,则相当于开关的接通与断开。二极管就是由一个PN结加上相应的电极引线及管壳封装而成的。
- N型半导体:硅原子外层带4个负电子,多个硅原子连接,外层形成稳定的8电子结构,因此纯净的硅晶体不导电。为了能使其导电,在硅晶体中掺杂了磷原子,磷原子多余的一个电子成为自由电子,使其能够导电。因为自由电子带负电,因此称为N型半导体,即
Negative
。
- P型半导体:在硅晶体中掺杂硼原子,硼原子周围缺少一个电子,形成空穴,吸引负电子,对外显正电,因此称为P型半导体,即
Postive
。
- PN结:采用不同的掺杂工艺,通过扩散作用,将P型半导体与N型半导体制作在同一块半导体(通常是硅或锗)基片上,在它们的交界面就形成空间电荷区称为PN结。
- 由P区引出的电极称为阳极,N区引出的电极称为阴极。因为PN结的单向导电性,二极管导通时电流方向是由阳极通过管子内部流向阴极。
电场方向和电子的受力方向相反:
当正极接P端时,自由电子可以和空穴复合,形成电流。反之则不行。正(电源正极)接正(P端Positive),负接负。
② 三极管
用电控制的开关分为三极管和mos管,实际上后两者的功能不仅限于电路的开闭,还有放大等作用。
三极管:通过电流控制电路开闭
- NPN:NPN型三极管是指由两块N型半导体中间夹着一块P型半导体所组成的三极管。可以看成两个二极管的P端连接在一起。
三极管由两个PN结构成,共用的一个电极成为三极管的基极(用字母B表示——B取自英文Base),其他的两个电极分别称为集电极(用字母C表示——C取自英文Collector,收集)和有箭头的发射极(用字母E表示—— E取自英文Emitter,发射)。基区和发射区之间的结成为发射结,基区和集电区之间的结成为集电结。
集电区掺杂浓度(自由电子数量多)最高,发射区次之,基区(空穴数量较少)最低且最薄。
不论将电源接至集电极或发射极,三极管均不能导通。
如果给BE极也加上电源(正接正,负接负):
发射区的电子向基区的空穴复合,但是只有少部分能够复合成功,形成基极电流B->E
。
而大部分负电子被吸引到了集电区,形成集电极电流C->E
,也就是三极管的输出电流。
基区做得很薄,是为了让发射区的电子更容易进入集电区。
功能:用 B-E 的电流 (IB) 控制 C-E 的电流 (IC),如果B-E没有电流,则C-E断;如果B接高,则B-E有电流,C-E通。
- PNP:用 E-B 的电流 (IB) 控制 E-C 的电流(IC),E极电位最高,且正常放大时通常C极电位最低,即VC<VB<VE;如果B接低,则通。
③ mos管
mos管:通过电压控制电路开闭。全称金属氧化物半导体场效应晶体管(Metal Oxide Semiconductor Field Effect Transistor
),简写为MOSFET,再次简写为MOS。
- N沟道mos管:由NPN构成,给两块N型半导体引出两个金属电极,分别作为mos管的漏极和源极。如果像下面这样直接连接并不会导通,因为NPN实际上构成了两个方向相反的二极管。
电路符号:图中箭头的方向是N沟道电子的流动方向。
为了让其导通,在P区添加了一层很薄的二氧化硅绝缘层,上覆盖一个金属板,形成栅极。给栅极也接上电(正极),栅极就会排斥空穴,吸引电子。电压越大,吸引的电子就越多,直到累计到一定数量时,在两个N型半导体之间形成了N沟道。此时可以将其看成一整块N型半导体。
mos管特性:
- 栅极的输入阻抗非常高,因为有红色的绝缘层的存在,造成其输入电阻可达上亿欧姆。所以它的输入几乎不取电流。
- 栅极容易被静电击穿
总结:漏极D接正极,源极S接负极,栅极G正电压时,导电沟道建立
- P沟道mos管:漏极D接负极,源极S接正极,栅极G负电压时,导电沟道建立
口诀:P下N上:NPN和Nmos,通过高电位导通;PNP和Pmos通过低电位导通
④ 三态门
E接高电平导通,相当于NPN型的三极管。N上
⑤ 触发器
触发器具有记忆存储功能,由门电路组成。这里简单介绍D触发器。
- 正边沿D触发器
- D:输入;Q输出;CLK:时钟脉冲
- 只有在时钟脉冲CLK上升沿到来的时刻,才采样D端的输入信号,来改变Q的输出状态,而在其他时刻,D和Q是隔离的。
- 负边沿D触发器:
D触发器广泛用于数字信号的锁存输出。
1.6.2 拉电流和灌电流
拉电流和灌电流是衡量电路输出驱动能力(注意:拉、灌都是对芯片输出端而言的,所以是驱动能力)的参数。
由于数字电路的输出只有高、低(0,1)两种电平值,高电平输出时,一般是输出端对负载提供电流,其提供电流的数值叫“拉电流”;
低电平输出时,一般是输出端要吸收负载的电流,其吸收电流的数值叫“灌(入)电流”。
对于大多数的逻辑电路(数字电路和单片机),输出拉电流的能力较弱,一般只有几毫安(<5mA
),而输出灌电流的能力较强,一般为5~10mA
。
一般情况下,在需要一定电流驱动的情况下,通常将驱动负载使用“灌电流”比较合适(例如LED),对于只是提供“开关信号”或者基本不需要电流驱动的情况下,使用“拉电流”比较合适。
1.6.3 上拉和下拉
上拉电阻和下拉电阻:上拉电阻和下拉电阻都是电阻元器件,所谓上拉电阻就是接电源正极,下拉的就是接负极或地。
上拉就是将不确定的信号通过一个电阻钳位在高电平,上拉电阻其实和上拉电压并没有太大关系,它的主要作用是补全电路,起限流和负载的作用。
下拉同理,也是将不确定的信号通过一个电阻钳位在低电平。
上拉电阻解析
如上图所示,当上拉电阻位于单片机内部时。若B没有电流,则三极管断开,IO输出位高电平(该端口没有接负载,为开路电压;或者没有电流,压降为0);若B有电流,则三极管导通接地,相当于IO口直接接地,输出低电平。
将上拉电阻移动到单片机外部,此时单片机会将IO端口设计成开漏输出或开集电极状态。所以芯片的内部已经集成了上拉电阻,则外部电路不需要添加上拉电阻。上拉电阻通常用在IO的输出口上。
总结上拉电阻起到的作用:
- 在三极管导通的时候(单片机内部控制电路输出高电平),它起到一个虚假的负载,防止因为正负极直接短路造成的线材发热或烧毁三极管,因为此时电源直接通过三极管接地。
- 在三极管不通的时候,为后面的用电器提供限流的保险服务,在实际应用中,会防止后面的用电器功率或负载过大,烧毁前面的供电部分电路。这个作用跟保险丝几乎一样。
1.6.4 输出模式
① 推挽输出
上面的三极管是NPN型三极管,下面的三极管是PNP型三极管,请留意控制端、输入端和输出端。
当Vin电压为V+时,上面的N型三极管控制端有电流输入,Q3导通,于是电流从上往下通过,提供电流给负载。
经过上面的N型三极管提供电流给负载(Rload),这就叫「推」,此时的电流就是拉电流。
当Vin电压为V-时,下面的三极管有电流流出,Q4导通,有电流从上往下流过。
经过下面的P型三极管提供电流给负载(Rload),这就叫「挽」,此时的电流为灌电流。
② 开漏输出
首先介绍开集输出:开集的意思,就是集电极C一端什么都不接,直接作为输出端口。
如果要用这种电路带一个负载,比如一个LED,必须接一个上拉电阻:当Vin没有电流,Q5断开时,LED亮。当Vin流入电流,Q5导通时,LED灭。
开漏电路,就是把上图中的三极管换成场效应管(MOSFET)。
1.6.5 IO口结构
STC89C51RC/RD系列单片机所有I/O口均有3种工作类型∶
- 准双向口/弱上拉(标准8051输出模式)
- 仅为输入(高阻)
- 开漏输出功能。
STC89C51RC/RD+系列单片机的P1/P2/P3上电复位后为准双向口/弱上拉模式,P0口上电复位后是开漏输出。P0口作为总线扩展用时,不用加上拉电阻,作为I/O口用时,需加10K-4.7K上拉电阻。
① 准双向P1口
准双向P1口:8个相同结构电路,组成P1特殊功能寄存器(90H
)
P1_n
= 1个锁存器(D触发器) + 1个场效应管驱动器(N沟道mos管) + 2个三态门缓冲器
- 单片机执行向P1口写数据指令时,P1口工作于输出方式,例如
P1 = 0x12
。如下图,内部总线写入1,经过锁存器的Q非
口出来为0,此时mos管截止,电源vcc经过R上拉电阻向P1口出,为高电平,注意读锁存器为0,使三态门2不放行。
- 当单片机执行从P1口读取数据并存到变量val指令时,P1口工作于读引脚方式,例如
val = P1
。但是mos管如果处于导通的情况下,会出现P1口读取不准确,可能走mosV接地那部分电路,因此要在读引脚前先执行一条写1指令强迫V截止,引脚P1电平便不会读错,所以P1口作为输入口是有条件的,要先让MOS管截止。而作为输出口是无条件的,因此,P1口被称为准双向口。
- 当单片机执行
读-改-写
类指令时,P1口工作于读锁存器方式。如P1++;
。Q端电平经过三态门2读入内部总线(得到P1的原始值),然后在运算器中进行+1运算,然后结果重新写到Q端(下一个上升沿,同时也输出到P1.n)。 - 读锁存器与读引脚的效果是不同的,读锁存器是为了获得前次的锁存值,而读引脚则是为了获得引脚上的当前值。
② 复用口P3口
P3口:8个相同结构电路,组成P3特殊功能寄存器(B0H
)
P3.n
= 1个锁存器 + 1个mos + 2个三态门 + 1个与非门
P3口比P1口多了一个与非门,且与非门接在Q输出端上。
- 通用IO口:当第二输出功能端置为1时,那么与非门相当于非门,即Q变为Q非,然后接在mos管上,此时P3功能与P1功能相同,作为通用IO口;
- 第二输出功能:当锁存器置为1时,那么与非门相当于非门,此时通过第二输出功能来输出。例如下图,第二输出功能为1,则输出为1;
- 第二输入功能:当锁存器置为1,第二输出功能置为1,那么与非门输出0,P3引脚输入则走第二输入功能引脚。
③ 高八位拓展地址总线P2口
P2口:8个相同结构电路,组成P2特殊功能寄存器(A0H
)
P2 = 1个锁存器 + 2个三态门 + 1个mos + 两路开关 + 非门
通用IO:系统将控制器置为0,两路开关打到锁存器端,Q经过非门为Q非,此时与P1口相同。
控制端置为1,用作外部地址总线(16位地址总线的高8位)
④ 低八位拓展地址总线P0口
P0 = 1个锁存器 + 2个三态门 + 2个mos + 两路开关 + 与门 + 非门
- 通用IO:系统会将控制端置0,两路开关打到锁存器端,而V2连接的与门一端由控制端输入 (0与任何数都等于0),所以一直高阻态,因此当作输出时需要自行接上拉电阻。数据输入时,CPU自动使地址/数据端一1,控制端一0,故分时复用方式为无条件的真双向口
总结
P0-P3 口都可作为准双向通用IO口,其中只有 P0 口需要外接上拉电阻;在需要扩展片外设备时,P2 口可作为其地址线接口,P0 口可作为其地址线/数据线复用接口,此时它是真正的双向口。
1.7 时钟电路
单片机需要时钟信号才能正常运行,时钟信号是脉冲信号的一种,周期固定,占宽比1:1的矩形脉冲波。时钟电路就是通过其他元器件综合来形成时钟信号(单片机的心跳)来提供给单片机,那么据上述可知,提供给单片机时钟信号即可让单片机运行起来。
下面是两种实现方式:
- 晶振时钟:通过外部晶振电路来获取时钟信号,电容用于起振
- 脉冲时钟:外部从XTAL2引脚输入时钟信号
1.8 复位
在微机系统中,为了保证电路的稳定可靠运行,复位电路是必不可少的一部分,复位电路的首要功能是通电复位。使单片机恢复原始默认状态的操作,通俗来讲,复位就是把你写的程序从第一步开始运行,类似一键重播功能。
P0~P3复位默认是FFH
,也就是默认全高电平。