51单片机学习笔记


零.序

基于郭天祥《新概念51单片机C语言教程》及B站江科大自动化协视频。

一.基础知识

1.二极管

1.1各种二极管

led 长正短负

各种二极管

1.2二极管工作原理

​ 二极管是一个由Р型半导体和N型半导体形成的PN结,在其交界面两侧形成空间电荷层,并建有自建电场。当不存在外加电压时,由于PN结两边载流子浓度差产生扩散电流和自建电场所引起的漂移电流相等而处于电平衡状态。
​ 当外界有正向电压偏置时,外界电场和自建电场的互相抑制作用使载流子的扩散电流增大引起正向电流。当外界有反向电压偏置时,外界电场和自建电场进一步加强,形成在一定反向电压范围内与反向偏置电压值无关的反向饱和电流。当外加的反向电压高到一定程度时,PN结空间电荷层中的电场强度达到临界值而产生载流子的倍增过程,进而产生大量电子空穴对,由此产生了数值很大的反向击穿电流,这称为二极管的击穿现象。

2.电容

2.1各种电容

各种电容

2.2电容作用

应用于电源电路,实现旁路、去耦、滤波和储能作用。

旁路电容是为本地器件提供能量的储能器件,使稳压器的输出均匀化,降低负载需求。

去耦电容起到一个电池的作用,满足驱动电路电流的变化,避免相互间的耦合干扰。

滤波,一般来说通高频阻低频,电容越大,阻抗越小。

储能型电容通过整流器收集电荷,并将存储的能量通过变换器引线传送至电源的输出端。

3.场效应管

3.1MOS管种类和结构

MOS管实物图

MOS管结构图

​ MOSFET 管可以被制造成增强型或耗尽型、P沟道或N沟道共4种类型,但实际应用的只有增强型的N沟道MOS管和增强型的Р沟道MOS管,所以通常提到NMOS和 PMOS指的就是这两种。对于这两种增强型MOS管,比较常用的是NMOS。原因是NMOS管导通电阻小,且容易制造。

3.2MOS管导通特性

​ NMOS 管的特性是,VGs大于一定的值就会导通,适合用于源极接地时的情况(低端驱动),只要栅极电压达到4~10V就可以导通。
​ PMOS 的特性是,VGs小于一定的值就会导通, 适合用于源极接Vcc时的情况(高端驱动)。

4.光耦

4.1光耦简介

光电耦合器亦称光电隔离器,简称光耦,是开关电源电路中常用的器件。

实物图1

实物图2

结构图

4.2光耦工作原理

​ 光耦以光为媒介传输电信号。它对输入、输出电信号有良好的隔离作用。
​ 光耦合器一般由三部分组成: 光的发射、光的接收及信号放大。输入的电信号驱动发光二极管(LED),使之发出一定波长的光,被光探测器接收而产生光电流,再经过进一步放大后输出。

5.蜂鸣器

5.1蜂鸣器介绍

蜂鸣器

5.2蜂鸣器结构原理

(1)压电式蜂鸣器
压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。当接通电源后(1.515V直流工作电压),多谐振荡器起振,输出1.5~2.5kHz 的音频信号,阻抗匹配器推动压电蜂鸣片发声。

(2)电磁式蜂鸣器
电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振荡器产生的音频电流信号通过电磁线圈,使电磁线圈产生磁场。振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。

​ 压电式蜂鸣器和电磁式蜂鸣器又各有两种结构:有源型和无源型。

​ 有源蜂鸣器内部带振荡源,所以只要一通电就会叫。而无源蜂鸣器内部不带振荡源,所以如果用直流信号驱动它时,无法令其鸣叫,必须用2kHz~5kHz的方波信号去驱动它。
​ 无论是有源型还是无源型,都可以通过单片机控制驱动信号来使它发出不同音调的声音,驱动方波的频率越高,音调就越高;驱动方波频率越低,音调也就越低。

6.继电器

6.1继电器结构

​ 继电器是当输入量(如电压、电流、温度等)达到规定值时,使被控制的输出电路导通或断开的电器。它可分为电气量(如电流、电压、频率、功率等)继电器及非电气量(如温度、压力、速度等)继电器两大类。

继电器实物图1

继电器实物图2

6.2继电器原理特性

​ 继电器是一种电子控制器件,它具有控制系统(又称输入回路)和被控制系统(又称输出回路),通常应用于自动控制电路中,它实际上是用较小的电流去控制较大电流的一种“自动开关”。故在电路中起着自动调节、安全保护、转换电路等作用。

7.直流稳压电源

直流稳压电源原理框图

​ 直流稳压电源是将交流电转变为稳定的、输出功率符合要求的直流电的设备。直流稳压电源通常由电源变压器、整流电路、滤波电路和稳压电路四部分组成。

其各部分的作用如下:
①电源变压器——将交流市电电压(220V)变换为符合整流需要的数值。
②整流电路——将交流电压变换为单向脉动直流电压。整流是利用二极管的单向导电性来实现的。
③滤波电路——将脉动直流电压中交流分量滤除,形成平滑的直流电压。滤波可利用电容、电感或电阻-电容来实现。
④稳压电路——其作用是当交流电网电压波动或负载变化时,保证输出直流电压稳定。简单的稳压电路可采用稳压管来实现,在稳压性能要求高的场合,可采用串联反馈式稳压电路(它包括基准电压、采样电路、放大电路和调整管等组成部分)。

7.1整流电路

​ 整流电路的功能是利用二极管的单向导电性将正弦交流电压转换成单向脉动电压。整流电路有单相整流和三相整流,有半波整流、全波整流、桥式整流等。
​ 下面分析整流电路时,为叙述简单,把二极管当做理想元件来处理,即认为它的正向导通电阻为零,而反向电阻为无穷大。

7.1.1单相桥式整流电路

单相桥式整流电路

​ 在电源电压uz的正、负半周内(设a端为正、b端为负时是正半周)电流通路用图中实线和虚线箭头表示。负载R上的电压uo的波形如图所示。电流的波形i。与u的波形相同。显然,它们都是单方向的全波脉动波形。

单相桥式整流电路波形图

7.1.2指标

输出电压的平均值公式1

直流电流

公式2

流经每个二极管的平均电流

公式3

二极管承受的最大反向电压

公式4

常见整流电路列表

7.2滤波电路

7.2.1电容滤波电路

​ 电容滤波电路是最简单的滤波器,它是在整流电路的负载上并联一个电容C。电容为带有正、负极性的大容量电容器,如电解电容、钼电容等。
​ 电容滤波是通过电容器的充电、放电来滤掉交流分量。图中,虚线波形为桥式整流的波形。并入电容C后,在u2>0时,D1,D3;导通,D2,D4截止,电源在向R供电的同时,又向C充电储能,由于充电时间常数很小(绕组电阻和二极管的正向电阻都很小),充电很快,输出电压uo随u2上升,当uc=√2u2,后,u2开始下降,u2<uc,t1t2时段内,D1D4全部反偏截止,由电容C向RL放电,由于放电时间常数较大,放电较慢,输出电压uo随uc按指数规律缓慢下降,如图中的ab实线段。b点以后,负半周电压 u2> uc,D1,D3,截止,D2,D4导通,C又被充电至c点,充电过程形成uo=u2的波形为bc实线段。c点以后,u2<uc,D1~D4又截止,C又放电,如此不断的充电、放电,使负载获得如图中实线所示的u波形。由波形可见,桥式整流接电容滤波后,输出电压的脉动程度大大减小。

电容滤波

7.3稳压电路

7.3.1并联型稳压电路

​ 并联型稳压电路是最简单的一种稳压电路。主要用于对稳压要求不高的场合,有时也作为基准电压源。因其稳压管Dz与负载电阻R并联而得名。

​ 引起电压不稳定的原因是交流电源电压的波动和负载电流的变化,而稳压管能够稳压的原理在于稳压管具有很强的电流控制能力。当保持负载R不变,Ui因交流电源电压增大而增大时,负载电压Uo也要增大,稳压管的电流急剧增大,因此电阻R上的压降急剧增加,以抵偿Ui的增加,从而使负载电压Uo保持近似不变。相反,Ui因交流电源电压降低而降低时,稳压过程与上述过程相反。
​ 如果保持电源电压不变,负载电流Io增大时,电阻R上的压降也增大,负载电压Uo因而下降,稳压管电流Iz急剧减小,从而补偿了Io的增大,使得通过电阻R的电流和电阻上的压降保持近似不变,因此负载电压Uo也就近似稳定不变。当负载电流减小时,稳压过程相反。
稳压管稳压电路

7.4集成稳压模块的使用

7.4.1三段固定式集成稳压模块实物图

三端固定式集成稳压模块实物图

7.4.2三段固定式集成稳压模块

​ 三端固定集成稳压模块有三个端子:输入端Ui、输出端Uo,和公共端COM。输入端接整流滤波电路,输出端接负载,公共端接输入、输出的公共连接点。其内部由采样、基准、放大、调整和保护等电路组成。保护电路具有过流、过热及短路保护功能。
​ 图为三端集成稳压器LM7805和LM7905作为固定输出电压的典型应用。正常工作时,输入、输出电压差为2~3V。C1为输入稳定电容,其作用是减小纹波、消振、抑制高频和脉冲干扰,它一般为0.1~1uF。C2为输出稳定电容,其作用是改善负载的瞬态响应,它一般为1uF。使用三端稳压器时要根据输出电流的大小选择加散热器,否则会由于过热而无法工作到额定电流。

典型应用

7.5串联开关型稳压电源

7.5.1串联开关型稳压电源工作原理

​ 串联反馈式稳压电路由于调整管工作在线性区,因此其管耗大、电源效率较低(40%~60%),有时还要配备庞大的散热装置。而串联开关型稳压电路调整管工作在开关状态,其具有管耗小、效率高(80%~90%)、稳压范围宽、滤波效果好等优点。

开关型稳压电源原理图

7.5.2串联开关型稳压电源工作过程

​ 开关型稳压电源电路原理框图如图所示。它是由调整管T、滤波电路LC、脉宽调制电路(PWM)和采样电路等组成。当ub为高电平时,调整管T饱和导通,输入电压Ui经滤波电感L加在滤波电容C和负载RL两端,在此期间,iL增大,L和C储能,二极管D反偏截止。当ub为低电平时,调整管T由导通变为截止,电感电流iL不能突变,iL经RL和续流二极管D衰减而释放能量,此时C也向RL放电,因此RL两端仍能获得连续的输出电压。

波形

​ 图中tob是调整管T的导通时间,toff是调整管T的截止时间,T=ton+toff是开关转换周期。显然,由于调整管T的导通与截止,使输入的直流电压Ui变成高频矩形脉冲电压Ue( Ud),经LC滤波得到输出电压。

公式5

​ 式中,q = ton/T称为脉冲波形的占空比,即一个周期持续脉冲时间ton与周期T之比值。由此可见,对于一定的Ui值,通过调节占空比即可调节输出电压Uo。
​ 上图电路是通过保持控制信号的周期T不变,而改变导通时间to来调节输出电压Uo的大小,这种电路称为脉宽调制型开关稳压电源(PWM);若保持控制信号的脉宽不变,只改变信号的周期T,同样也能使输出电压Uo发生变化,这就是频率调制型开关电源(PFM);若同时改变导通时间 ton和周期T,称为混合性开关稳压电源。

7.5.3稳压原理

​ 当输入电压波动或负载电流改变时,都将引起输出电压Uo的改变,在上图中,由于负反馈作用,电路能自动调整而使Uo基本维持不变。稳压过程如下:
当Ui↓→Uo↓→uf ↓ (uf<Uref)一uA为正值→ue输出高电平变宽(ton)↑一Uo↑。

当Ui↑→Uo↑ →uf↑t (uf>Uref)→uA为负值→ue输出高电平变窄(ton)↓→Uo↓。

​ 此时,uT,uB,uE的波形如图所示。

波形2

8.直流电机

8.1直流电机

直流电机实物图

8.2直流电机概述

​ 电动机简称电机,是使机械能与电能相互转换的机械,直流电机把直流电能变为机械能。激磁绕组及其所包围的铁芯组成的磁极为定子,带换向单元的电枢绕组和电枢铁芯结合构成直流电机的转子。

8.3直流电机基本工作原理

直流电机工作原理图

​ 从以上可以看到,要使线圈按照一定的方向旋转,关键问题是当导体从一个磁极范围转到另一个异性磁极范围时(也就是导体经过中性面后),导体中电流的方向也要同时改变,换向器和电刷就是完成这一任务的装置。许多线圈牢固地嵌在转子铁芯槽中,当导体中通过电流在磁场中因受力而转动时,就带动整个转子旋转,这就是直流电机的基本工作原理。

8.4直流电机的驱动

​ 用单片机控制直流电机时,需要加驱动电路,为直流电机提供足够大的驱动电流。通常有以下几种驱动电路:三极管电流放大驱动电路、电机专用驱动模块(如L298)和达林顿驱动器等。如果是驱动单个电机,并且电机的驱动电流不大时,我们可用三极管搭建驱动电路。如果电机所需要的驱动电流较大,可直接选用市场上现成的电机专用驱动模块。如果是读者自己学习电机原理及电路驱动原理使用,建议选用达林顿驱动器,它实际上是一个集成芯片,单块芯片同时可驱动8个电机,每个电机由单片机的一个IIO口控制,当需要调节直流电机转速时,使单片机的相应IO口输出不同占空比的PWM波形即可。
​ PWM是英文Pulse Width Modulation(脉冲宽度调制)的缩写,它是按一定规律改变脉冲序列的脉冲宽度,以调节输出量和波形的一种调制方式,我们在控制系统中最常用的是矩形波PWM信号,在控制时需要调节 PWM波的占空比。
​ 当用单片机IO口输出PWM信号时,可采用以下三种方法:
(1)利用软件延时。当高电平延时时间到时,对IO口电平取反变成低电平,然后再延时;当低电平延时时间到时,再对该IO口电平取反,如此循环就可得到PWM信号。
(2)利用定时器。控制方法同上,只是在这里利用单片机的定时器来定时进行高、低电平的翻转,而不用软件延时。
(3) 利用单片机自带的PWM控制器。STC12系列单片机自身带有PWM控制器,STC89系列单片机无此功能,其他型号的很多单片机也带有PWM控制器,如PIC单片机、AVR单片机等。

9.步进电机

9.1步进电机实物图

步进电机实物图

步进电机解剖图

9.2步进电机概述

​ 步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件。在非超载情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,即给电机加一个脉冲信号,电机则转过一个步距角。这一线性关系的存在,加上步进电机只有周期性的误差而无累积误差等特点,使得步进电机在速度、位置等控制领域的控制操作非常简单。虽然步进电机应用广泛,但它并不像普通的直流和交流电机那样在常规状态下使用,它必须由双环形脉冲信号、功率驱动电路等组成控制系统方可使用。

​ 步进电机分类
(1)永磁式(PM)。一般为二相,转矩和体积较小,步距角一般为7.5°或15°。
(2)反应式(VR)。一般为三相,可实现大转矩输出,步距角一般为1.5°,但噪声和振动都很大。
(3)混合式(HB)。指混合了永磁式和反应式的优点。它又分为二相和五相,二相步距角一般为1.8°,而五相步距角一般为0.72°。这种步进电机的应用最为广泛。

9.3步进电机工作原理

​ 步进电机是一种将电脉冲转换成相应角位移或线位移的电磁机械装置。它具有快速启、停能力,在电机的负荷不超过它能提供的动态转矩时,可以通过输入脉冲来控制它在一瞬间的启动或停止。步进电机的步距角和转速只和输入的脉冲频率有关,和环境温度、气压、振动无关,也不受电网电压的波动和负载变化的影响。因此,步进电机多应用在需要精确定位的场合。
(1)工作原理
​ 步进电机有三线式、五线式和六线式,但其控制方式均相同,都要以脉冲信号电流来驱动。假设每旋转一圈需要200个脉冲信号来励磁,可以计算出每个励磁信号能使步进电机前进1.8°,其旋转角度与脉冲的个数成正比。步进电动机的正、反转由励磁脉冲产生的顺序来控制。六线式四相步进电机是比较常见的,它的控制等效电路如图21.2.8所示。它有4条励磁信号引线A,A,B,B,通过控制这4条引线上励磁脉冲产生的时刻,即可控制步进电机的转动。每出现一个脉冲信号,步进电机只走一步。因此,只要依序不断送出脉冲信号,步进电机就能实现连续转动。

步进电机控制等效电路

(2)励磁方式

​ 步进电机的励磁方式分为全步励磁和半步励磁两种。其中全步励磁又有一相励磁和二相励磁之分;半步励磁又称一-二相励磁。假设每旋转一圈需要200个脉冲信号来励磁,可以计算出每个励磁信号能使步进电动机前进1.8°,简要介绍如下。
1.一相励磁——在每一瞬间,步进电机只有一个线圈导通。每送一个励磁信号,步进电机旋转1.8°,这是三种励磁方式中最简单的一种。
其特点是:精确度好、消耗电力小,但输出转矩最小,振动较大。如果以该方式控制步进电机正转,对应的励磁顺序如下表所示。若励磁信号反向传送,则步进电机反转。表中的1和0表示送给电机的高电平和低电平。

一相励磁顺序表

2.二相励磁——在每一瞬间,步进电动机有两个线圈同时导通。每送一个励磁信号,步进电机旋转1.8°。其特点是:输出转矩大,振动小,因而成为目前使用最多的励磁方式。如果以该方式控制步进电机正转,对应的励磁顺序见下表。若励磁信号反向传送,则步进电机反转。

二相励磁顺序表

3.—-二相励磁——为一相励磁与二相励磁交替导通的方式。每送一个励磁信号,步进电机旋转0.9°。
其特点是:分辨率高,运转平滑,故应用也很广泛。如果以该方式控制步进电机正转,对应的励磁顺序见下表。若励磁信号反向传送,则步进电机反转。

一二相励磁顺序表

9.4步进电机驱动

​ 步进电机的驱动可以选用专用的电机驱动模块,如 L298,FT5754等,这类驱动模块接口简单,操作方便,它们既可驱动步进电机,也可驱动直流电机。除此之外,还可利用三极管自己搭建驱动电路。另外,还有一种方法就是使用达林顿驱动器ULN2803,该芯片单片最多可一次驱动八线步进电机,当然如果只有四线或六线制的也是没有问题的。

9.5步进电机使用常见问题

(1)步进电机使用时出现振动大、失步或有声不转动等现象,为什么?
步进电机与普通交流电机有很大的差别,振动大或失步是常见的现象。产生的原因或解决方法有以下两点。
①控制脉冲——频率低速时是否处在共振点上(每个型号电机不同),高速时是否采用梯形或其他曲线加速,控制脉冲频率有无跳动(部分PLC机型)。
解决方法:调整控制脉冲频率或采用步进伺服专用控制器。
②驱动器——电机低速时,振动或失步,高速时正常;驱动电压过高。电机低速时正常,高速时失步;驱动电压过低。电机长时间低速运转无发热现象(电机正常工作时可高达80~90℃);驱动电流过小。电机工作时过热;驱动电流过大。
解决方法:调节驱动器电流、驱动电压或更换驱动器。

(2)步进电机控制为什么要采用梯形或其他加速方法?

​ 步进电机起步速度根据电机不同一般在150~250r/min,如果希望高于此速度运转就必须先用起步以下速度起步,逐渐加速至最高速度,运行一定距离后再逐渐减速至起步速度以下方可停止,否则会出现高速上不去或失步的现象。常见加速方法有分级加速、梯形加速和S字加速等。

(3)步进电机的外表温度允许达到多少?

​ 步进电机温度过高会使电机的磁性材料退磁,从而导致力矩下降及失步,因此电机外表允许的最高温度取决于不同电机磁性材料的退磁点。一般来讲,磁性材料的退磁点都在130℃以上,有的甚至高达200℃以上,所以步进电机外表温度在80~90℃完全正常。

(4)为什么步进电机的力矩会随转速的升高而下降?

​ 当步进电机转动时,电机各相绕组的电感将形成一个反向电动势,频率越高,反向电动势越大。在它的作用下,电机随频率(或速度)的增大而相电流减小,从而导致力矩下降。

(5) 为什么步进电机低速时可以正常运转,但若高于一定速度就无法启动并伴有啸叫声?

​ 步进电机有一个技术参数——空载启动频率,即步进电机在空载情况下能够正常启动的脉冲频率。如果脉冲频率高于该值,电机不能正常启动,可能发生失步或堵转。在有负载的情况下,启动频率应更低。如果要使电机达到高速转动,脉冲频率应该有加速过程,即启动频率较低,然后按一定加速度升到所希望的高频(电机转速从低速升到高速)。

(6)如何克服两相混合式步进电机在低速运转时的振动和噪声?
步进电机低速转动时振动和噪声大是其固有的缺点,一般可采用以下方法来克服:①如步进电机正好工作在共振区,可通过改变减速比等机械传动避开共振区。②采用带有细分功能的驱动器,这是最常用、最简便的方法。③换成步距角更小的步进电机,如三相或五相步进电机。④换成交流伺服电机,几乎可以完全克服振动和噪声,但成本较高。⑤在电机轴上加磁性阻尼器,市场上已有这种产品,但机械结构改变较大。

(7)细分驱动器的细分数是否能代表精度?

​ 步进电机的细分技术实质上是一种电子阻尼技术(请参考有关文献),其主要目的是减弱或消除步进电机的低频振动,提高电机的运转精度,它只是细分技术的一个附带功能。比如对于步距角为1.8°的两相混合式步进电机,如果细分驱动器的细分数设置为4,那么电机的运转分辨率为每个脉冲0.45°,电机的精度能否达到或接近0.45°,还取决于细分驱动器的细分电流控制精度等其他因素。不同厂家的细分驱动器的精度可能差别很大,细分数越大,精度越难控制。

(8)四相混合式步进电机与驱动器的串联接法和并联接法有什么区别?

​ 四相混合式步进电机一般由两相驱动器来驱动,因此连接时可以采用串联接法或并联接法将四相电机接成两相使用。串联接法一般在电机转速较低的场合使用,此时需要的驱动器输出电流为电机相电流的0.7倍,因而电机发热小;并联接法一般在电机转速较高的场合使用(又称高速接法),所需要的驱动器输出电流为电机相电流的1.4倍,因而电机发热较大。

(9)如何确定步进电机驱动器的直流供电电源?

①电压的确定。混合式步进电机驱动器的供电电源电压一般有一个较宽的范围(1248VDC),电源电压通常根据电机的工作转速和响应要求来选择。如果电机工作转速较高或响应要求较快,那么电压取值也高,但注意电源电压的纹波不能超过驱动器的最大输入电压,否则可能损坏驱动器。
②电流的确定。供电电源电流一般根据驱动器的输出相电流Ⅰ来确定。如果采用线性电源,电源电流一般可取I值的1.1
1.3倍;如果采用开关电源,电源电流一般可取I值的1.5~2.0倍。

(10)混合式步进电机驱动器的脱机信号FREE一般在什么情况下使用?

​ 当脱机信号 FREE为低电平时,驱动器输出到电机的电流被切断,电机转子处于自由状态(脱机状态)。在有些自动化设备中,如果在驱动器不断电的情况下要求直接转动电机轴(手动方式),就可以将FREE信号置低,使电机脱机,进行手动操作或调节。手动完成后,再将FREE信号置高,以继续自动控制。

(11)如何用简单的方法调整两相步进电机通电后的转动方向?

​ 只需将电机与驱动器接线的A+和A-(或B+和B-)对调即可。

(12)关于驱动器的细分原理及一些相关说明。

​ 在国外,对于步进系统,主要采用二相混合式步进电机及相应的细分驱动器。但在国内,广大用户对“细分”还不是特别了解,有些人认为,细分是为了提高精度,其实不然,细分主要是改善电机的运行性能,现说明如下:
​ 步进电机的细分控制是由驱动器精确控制步进电机的相电流来实现的,以二相电机为例,假如电机的额定相电流为3A,如果使用常规驱动器(如常用的恒流斩波方式)驱动该电机,电机每运行一步,其绕组内的电流将从0突变为3A或从3A突变到0,相电流的巨大变化,必然会引起电机运行的振动和噪声。如果使用细分驱动器,在10细分状态下驱动该电机,电机每运行一微步,其绕组内的电流变化只有0.3A而不是3A,且电流是以正弦曲线规律变化,这样就大大改善了电机的振动和噪声,因此性能上的优点才是细分的真正优点。由于细分驱动器要精确控制电机的相电流,所以对驱动器有相当高的技术和工艺要求,成本亦会较高。注意,国内有一些驱动器采用“平滑”来取代细分,有的亦称为细分,但这不是真正的细分,望广大用户一定要分清两者的本质不同:
“平滑”并不精确控制电机的相电流,只是把电流的变化率变缓一些,所以“平滑”并不产生微步,而细分的微步是可以用来精确定位的。
电机的相电流被平滑后,会引起电机力矩的下降,而细分控制不但不会引起电机力矩的下降,相反,力矩会有所增加。

10舵机

10.1舵机概述

​ 舵机英文称Servo,也称伺服机。其特点是结构紧凑、易安装调试、控制简单、大扭力、成本较低等。舵机的主要性能取决于最大力矩和工作速度(一般是以秒/60°为单位)。它是一种位置伺服的驱动器,适用于那些需要角度不断变化并能够保持的控制系统。在机器人机电控制系统中,舵机控制效果是性能的重要影响因素。舵机能够在微机电系统和航模中作为基本的输出执行机构,其简单的控制和输出使得单片机系统很容易与之接口。

10.2舵机工作原理

舵机引线示意图

​ 在航模遥控系统中,控制信号由接收机的通道进入信号调制芯片,获得直流偏置电压。它的内部有一个基准电路,产生周期为20ms、宽度为1.5ms 的基准信号,并将获得的直流偏置电压和电位器的电压比较,获得电压差输出。最后,将电压差的正、负输出到电机驱动芯片决定电机的正、反转。当电机转速一定时,通过级联减速齿轮带动电位器旋转,使电压差为0,电机停止转动。舵机的控制信号也是PWM信号,利用占空比的变化改变舵机的位置。下图为舵机输出转角与输入信号脉冲宽度的关系, 其脉冲宽度在0.5~2.5ms变化时, 舵机输出轴转角在0°~180°变化。

舵机输出转角与输入信号脉冲宽度的关系

二.单片机概述

单片机,英文Micro Controller Unit,简称MCU,内部集成了CPU、RAM、ROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能。单片机的任务是信息采集(依靠传感器)、处理(依靠CPU)和硬件设备(例如电机,LED等)的控制。

命名规则

单片机内部结构图

单片机最小系统,或者称为最小应用系统,是指用最少的元件组成的单片机可以工作的系统。 对51系列单片机来说,最小系统一般应该包括:单片机、晶振电路、复位电路。

单片机输出与输入为TTL电平,其中高电平为+5V,低电平为0V。计算机的串口为RS-232C电平,其中高电平为-12V,低电平为+12V。单片机上电,默认都是高电平。

三.C51代码编写基础知识

进制转换

数据类型

数据运算

基本语句

模块化编程

.c文件:函数、变量的定义

.h文件:可被外部调用的函数、变量的声明

任何自定义的变量、函数在调用前必须有定义或声明(同一个.c)

使用到的自定义函数的.c文件必须添加到工程参与编译

使用到的.h文件必须要放在编译器可寻找到的地方(工程文件夹根目录、安装目录、自定义)

sfr(special function register):特殊功能寄存器声明

例:sfr P0 = 0x80;

声明P0口寄存器,物理地址为0x80

sbit(special bit):特殊位声明

例:sbit P0_1 = 0x81; 或 sbit P0_1 = P0^1;

声明P0寄存器的第1位

可位寻址/不可位寻址:在单片机系统中,操作任意寄存器或者某一位的数据时,必须给出其物理地址,又因为一个寄存器里有8位,所以位的数量是寄存器数量的8倍,单片机无法对所有位进行编码,故每8个寄存器中,只有一个是可以位寻址的。对不可位寻址的寄存器,若要只操作其中一位而不影响其它位时,可用“&=”、“|=”、“^=”的方法进行位操作

三.独立按键

​ 对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动。

按键抖动

利用延时进行去抖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void main()
{
while(1)
{
if(P3_1==0) //检测k1是否按下
{
Delay(20); //延时去抖
while(P3_1==0); //等待按键释放
Delay(20); //延时去抖

P2_0=~P2_0; //LED1亮灭
}
}
}
1
2
3
4
5
6
7
8
9
10
11
unsigned char Key()
{
unsigned char KeyNumber=0;

if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}

return KeyNumber;
}

四.数码管

4.1数码管基础知识

数码管内部原理图

​ 有共阴极和共阳极两种方式。

四位一体

4.2数码管静态显示

​ 当多位数码管应用于某一系统时,它们的“位选”是可独立控制的,而“段选”是连接在一起的,我们可以通过位选信号控制哪几个数码管亮,而在同一时刻,位选选通的所有数码管上显示的数字始终都是一样的,因为它们的段选是连接在一起的,所以送入所有数码管的段选信号都是相同的,那么它们显示的数字必定一样,数码管的这种显示方法叫做静态显示。

数码管与单片机连接图

​ TX-1C实验板上使用的数码管为共阴极,图中,最上面一排是6个单位数码管,可以看到所有数码管的阳极,即标有a,b,c,d,e, f,g, h的引脚全部连接在一起,然后与下面的U1元件73HC573锁存器的数据输出端相连,锁存器的数据输入端连接单片机的PO口,PO口同时加了上拉电阻。数码管中WE1,WE2,WE3,WE4,WE5,WE6是它们的位选端,每一个数码对应一个位选端,与下面U2元件74HC573的数据输出端的低6位相连,U2的数据输入端也连接到单片机的PO口。两个锁存器的锁存端分别与单片机的P2.6和P2.7相连,用单片机可以控制锁存器的锁存端,进而控制锁存器的数据输出,这种分时控制的方法便可方便地控制任意数码管显示任意数字。

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
**********************************************************************

程序功能: 让TX-1C学习板的第一个数码管静态的显示数字3

**********************************************************************/
#include <reg51.h>

sbit dula=P2^6; //段选信号的锁存器控制
sbit wela=P2^7; //位选信号的锁存器控制

void main()
{
dula=0;
wela=0;

P0=0x4f; //数字“3”的代码
dula=1;
dula=0;

P0=0xfe; //选中第一个数码管
wela=1;
wela=0;

while(1);
}

4.3数码管动态显示

​ 所谓动态扫描显示,即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示,而实际上多位数码管是一位一位轮流显示的,只是轮流的速度非常快,人眼已经无法分辨出来。

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
**********************************************************************

程序功能: 让TX-1C学习板的六位数码管同时显示数字05

**********************************************************************/
#include <reg51.h>

sbit dula=P2^6; //段选信号的锁存器控制
sbit wela=P2^7; //位选信号的锁存器控制

unsigned char code wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
//数码管各位的码表
unsigned char code duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d};
//0-5的码表
void delay(unsigned int i)
{
unsigned int m,n;
for(m=i;m>0;m--)
for(n=90;n>0;n--);
}

void main()
{
unsigned char num;
while(1)
{
for(num=0;num<6;num++)
{
P0=wei[num];
wela=1;
wela=0;

P0=duan[num];
dula=1;
dula=0;
delay(2); //时间间隔短,这是关键(所谓的同时显示,只是间隔较短而已,利用人眼的余辉效应,觉得每个数码管都一直在亮)。
}
}
}

五.矩阵键盘

​ 独立键盘与单片机连接时,每一个按键都需要单片机的一个I/O口,为了节省IO口线,我们引入矩阵键盘。
​ 将16个按键排成4行4列,第一行将每个按键的一端连接在一起构成行线,第一列将每个按键的另一端连接在一起构成列线,这样便一共有4行4列共8根线,我们将这8根线连接到单片机的8个IO口上,通过程序扫描键盘就可检测16个键.用这种方法我们也可实现3行3列9个键、5行5列25个键、6行6列36个键等。
​ 无论是独立键盘还是矩阵键盘,单片机检测其是否被按下的依据都是一样的,也就是检测与该键对应的IO口是否为低电平。独立键盘有一端固定为低电平,单片机写程序检测时比较方便。而矩阵键盘两端都与单片机IO口相连,因此在检测时需人为通过单片机I/O口送出低电平。检测时,先送一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平(这时我们又确定了行数),则我们便可确认当前被按下的键是哪一行哪一列的,用同样方法轮流送各列一次低电平,再轮流检测一次各行是否变为低电平,这样即可检测完所有的按键,当有键被按下时便可判断出按下的键是哪一个键。当然我们也可以将行线置低电平,扫描列是否有低电平。这就是矩阵键盘检测的原理和方法。

矩阵键盘连接图

六.定时器

定时器

STC89C52的T0和T1均有四种工作模式:

模式0:13位定时器/计数器

模式1:16位定时器/计数器(常用)

模式2:8位自动重装模式

模式3:两个8位计数器

定时器0的模式1

左边时钟,中间计数,右边中断 65535

七.中断

​ 引起CPU中断的根源,称为中断源,中断源向CPU提出中断请求,CPU暂时中断原来的事务A,转去处理事件B,对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。实现上述中断功能的部件称为中断系统(中断机构)。

52单片机一共有6个中断源,它们的符号、名称及产生的条件分别解释如下:

INTO—外部中断0,由P3.2端口线引入,低电平或下降沿引起。

INT1—外部中断1,由 P3.3端口线引入,低电平或下降沿引起。T0—定时器/计数器О中断,由T0计数器计满回零引起。

T1—定时器/计数器1中断,由T1计数器计满回零引起。

T2—定时器/计数器⒉中断,由T2计数器计满回零引起。

TI / RI—串行口中断,串行端口完成一帧字符发送/接收后引起。

中断号

定时器和中断系统

定时器相关寄存器

​ 单片机在使用中断功能时,通常需要设置两个与中断有关的寄存器:中断允许寄存器IE和中断优先级寄存器IP。

中断允许寄存器IE

EA一全局中断允许位。

EA=1,打开全局中断控制,在此条件下,由各个中断控制位确定相应中断的打开或关闭。

EA=0,关闭全部中断。

–—无效位。

ET2一定时器/计数器②中断允许位。ET2= 1,打开T2中断。

ET2=0,关闭T2中断。

ES一串行口中断允许位。

ES = 1,打开串行口中断。

ES =0,关闭串行口中断。

ET1一定时器/计数器1中断允许位。

ET1 = 1,打开T1中断。

ET1 =0,关闭T1中断。

EX1一外部中断1中断允许位。

EX1=1,打开外部中断1中断。

EX1=0,关闭外部中断1中断。

ET0一定时器/计数器О中断允许位。

ET0=1,打开T0中断。

ET0=0,关闭T0中断。

EX0一外部中断0中断允许位。EX0=1,打开外部中断О中断。EX0=0,关闭外部中断0中断。

中断优先级寄存器IP

–—无效位。

PS一串行口中断优先级控制位。

PS = 1,串行口中断定义为高优先级中断。

PS =0,串行口中断定义为低优先级中断。

PT1一定时器/计数器1中断优先级控制位。

PT1=1,定时器/计数器1中断定义为高优先级中断。

PT1 =0,定时器/计数器1中断定义为低优先级中断。

PX1一外部中断1中断优先级控制位。
PX1= 1,外部中断1定义为高优先级中断。

PX1=0,外部中断1定义为低优先级中断。

PT0一定时器/计数器0中断优先级控制位。
PT0= 1,定时器/计数器0中断定义为高优先级中断。

PT0=0,定时器/计数器0中断定义为低优先级中断。

PX0一外部中断0中断优先级控制位。

PX0=1,外部中断0定义为高优先级中断。

PX0=0,外部中断0定义为低优先级中断。

7.2定时器中断

​ 单片机在使用定时器或计数器功能时,通常需要设置两个与定时器有关的寄存器:定时器/计数器工作方式寄存器TMOD与定时器/计数器控制寄存器TCON。

定时器工作方式寄存器TMOD

TMOD的高4位用于设置定时器1,低4位用于设置定时器0,对应4位的含义如下:

GATE一门控制位。

GATE=0,定时器/计数器启动与停止仅受TCON寄存器中 TRX ( X=0,1)来控制。

GATE=1,定时器/计数器启动与停止由TCON寄存器中TRX(X=0,1 )和外部中断引脚( INTO或 INT1)上的电平状态来共同控制。

c/T一定时器模式和计数器模式选择位。

c/T=1,为计数器模式;C/T=o,为定时器模式。

M1MO一工作方式选择位。

每个定时器/计数器都有4种工作方式,它们由M1MO设定,对应关系如下表所示。

定时器的4种工作方式

定时器控制寄存器

定时器控制寄存器TCON

TF1一定时器1溢出标志位。
当定时器1计满溢出时,由硬件使TF1 置1,并且申请中断。进入中断服务程序后,由硬件自动清0。需要注意的是,如果使用定时器的中断,那么该位完全不用人为去操作,但是如果使用软件查询方式的话,当查询到该位置1后,就需要用软件清0.
TR1一定时器1运行控制位。
由软件清0关闭定时器1。当GATE=1,且INT1为高电平时,TR1置1启动定时器1;当GATE=O时,TR1 置1启动定时器1。
TF0一定时器0溢出标志,其功能及操作方法同TF1。

TR0一定时器0运行控制位,其功能及操作方法同TR1。

IE1一外部中断1请求标志。
当IT1=0时,为电平触发方式,每个机器周期的S5P2采样INT1引脚,若INT1脚为低电平,则置1,否则IE1清0。
当IT1=1时,INT1为跳变沿触发方式,当第一个机器周期采样到INT1为低电平时,则IE1置1。IE1=1,表示外部中断1正在向CPU申请中断。当CPU响应中断,转向中断服务程序时,该位由硬件清0。
IT1一外部中断1触发方式选择位。
IT1=0,为电平触发方式,引脚 INT1上低电平有效。
IT1=1,为跳变沿触发方式,引脚INT1上的电平从高到低的负跳变有效。

IE0—外部中断0请求标志,其功能及操作方法同IE1。
IT0一外部中断0触发方式选择位,其功能及操作方法同IT1。

7.2.2定时器0的工作方式1: 16位定时器

​ 方式1的计数位数是16位,对T0来说,由TL0寄存器作为低8位、TH0寄存器作为高8位,组成了16位加1计数器,其逻辑结构框图如下图所示。

定时器0方式1逻辑结构图

​ 当GATE=0,TR0=1时,TL0便在机器周期的作用下开始加1计数,当TL0计满后向TH0进一位,直到把TH0也计满,此时计数器溢出,置TF0为1,接着向CPU申请中断,接下来CPU进行中断处理。在这种情况下,只要TR0为1,那么计数就不会停止。这就是定时器0的工作方式1的工作过程。

​ 接下来讲解如何计算定时器的初值问题。定时器一旦启动,它便在原来的数值上开始加1计数,若在程序开始时,我们没有设置TH0和 TL0,它们的默认值都是0,假设时钟频率为12MHz,12个时钟周期为一个机器周期,那么此时机器周期就是1us,计满TH0和 TL0就需要2l6-1个数,再来一个脉冲计数器溢出,随即向CPU申请中断。因此溢出一次共需65536us,约等于65.5ms,如果我们要定时50ms 的话,那么就需要先给TH0和TL0装一个初值,在这个初值的基础上计50000个数后,定时器溢出,此时刚好就是50ms中断一次,当需定时1s时,我们写程序时当产生20次50ms 的定时器中断后便认为是1s,这样便可精确控制定时时间了。要计50000个数时,TH0和TL0中应该装入的总数是65536-50000=15536,把15536对256求模: 15536/256=60装入TH0中,把15536对256求余:15536%256=176装入TL0中。
以上就是定时器初值的计算方法,总结后得出如下结论:当用定时器的方式1时,设机器周期为Ty,定时器产生一次中断的时间为t,那么需要计数的个数N=t / Tcy,装入THX和TLX中的数分别为
THX=(65536-N)/256,TLX=(65536-N)%256
要计算机器周期Tcy,就需要知道系统时钟频率,也就是单片机的晶振频率,TX-1C实验板上时钟频率为11.0592MHz,那么机器周期为12×(1/11059200)~1.09us,若 t=50ms,那么N =50 000/1.09=45872,这是晶振在11.0592MHz下定时50ms时初值的计算方法,当晶振为12MHz时,计算起来就比较方便了,用同样方法可算得N=50000。

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
void Timer0Init(void)
{
TMOD &= 0xF0; //把TMOD的低四位清零,高四位保持不变
TMOD |= 0x01; //把TMOD的最低位置1,高四位保持不变
TL0 = (65535-45872)/256; //装初值11.0592M晶振定时50ms数为45872
TH0 = (65535-45872)%256; //
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1; //开定时器0中断
EA=1; //开总中断
PT0=0; //中断优先级
}

void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = (65535-45872)/256; //装初值11.0592M晶振定时50ms数为45872
TH0 = (65535-45872)%256;
T0Count++; //T0Count每加1次判断一次是否到20次
if(T0Count>=20) //如果到了20次,说明1秒时间到
{
T0Count=0; //然后把T0Count清0重新再计20次

}
}

八.串口

8.1串口概述

​ 串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。

​ 单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。

​ 51单片机内部自带UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),可实现单片机的串口通信。

简单双向串口通信有两根通信线(发送端TXD和接收端RXD)

TXD与RXD要交叉连接

当只需单向的数据传输时,可以直接一根通信线

当电平标准不一致时,需要加电平转换芯片

串口硬件电路

8.2电平标准

​ 电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:

TTL电平:+5V表示1,0V表示0

RS232电平:-3-15V表示1,+3+15V表示0

RS485电平:两线压差+2+6V表示1,-2-6V表示0(差分信号)

8.3常见通信接口比较

常见通信接口比较

此外还有:CAN、USB等。

全双工:通信双方可以在同一时刻互相传输数据

半双工:通信双方可以互相传输数据,但必须分时复用一根数据线

单工:通信只能有一方发送到另一方,不能反向传输

异步:通信双方各自约定通信速率

同步:通信双方靠一根时钟线来约定通信速率

总线:连接各个设备的数据传输线路(类似于一条马路,把路边各住户连接起来,使住户可以相互交流)。

8.4 51单片机的UART

STC89C52有1个UART

STC89C52的UART有四种工作模式:

模式0:同步移位寄存器

模式1:8位UART,波特率可变(常用)

模式2:9位UART,波特率固定

模式3:9位UART,波特率可变

8.4串口参数及时序图

波特率:串口通信的速率(发送和接收各数据位的间隔时间)

检验位:用于数据验证

停止位:用于数据帧间隔

串口参数数据格式

串行口基本结构

SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器

串口和串口中断系统

8.5波特率

​ 单片机或计算机在串口通信时的速率用波特率表示,它定义为每秒传输二进制代码的位数,即1波特=1位/秒,单位是 bps (位/秒)。如每秒钟传送240个字符,而每个字符格式包含10位(1个起始位、1个停止位、8个数据位),这时的波特率为10位×240个/秒=2400 bps。

​ 在串行通信中,收、发双方对发送或接收数据的速率要有约定。通过编程可对单片机串行口设定为4种工作方式,其中方式0和方式2的波特率是固定的,而方式1和方式3的波特率是可变的,由定时器T1的溢出率来决定。
​ 串行口的4种工作方式对应三种波特率。由于输入的移位时钟的来源不同,所以各种方式的波特率计算公式也不相同,以下是4种方式波特率的计算公式。
方式0的波特率 =fosc/12。

方式1的波特率 = (2^SMOD /32) x(T1溢出率)。

方式2的波特率 = (2^SMOD/64)×fosc 。

方式3的波特率=(2^SMOD /32)×(T1溢出率)。

​ 式中,fosc为系统晶振频率,通常为12MHz或11.0592MHz;SMOD是PCON寄存器的最高位;T1溢出率即定时器T1溢出的频率。T1溢出率就是T1定时器溢出的频率,只要算出T1定时器每溢出一次所需的时间T,那么T的倒数1/T就是它的溢出率。

【例】已知串口通信在串口方式1下,波特率为9600bps,系统晶振频率为11.0592MHz,求TL1和TH1中装入的数值是多少?
解:

​ 设所求的数为X,则定时器每计256-X个数溢出一次,每计一个数的时间为一个机器周期,一个机器周期等于12个时钟周期,所以计一个数的时间为12/11.0592MHz (s),那么定时器溢出一次的时间为[256-X]x12/11.0592MHz (s),T1的溢出率就是它的倒数,方式1的波特率= (2^SMOD /32)x(T1溢出率),这里我们取SMOD=0,则2^SMOD=1,将已知的数代入公式后得9600=(1/32)x11059200/[256-X]×12,求得X=253,转换成十六进制为0xFD。上面若将SMOD置1的话,那么X的值就变成250了。可见,在不变化X值的状态下,SMOD由0变1后,波特率便增加一倍。

8.6串行口控制寄存器SCON

​ 串行口控制寄存器SCON在特殊功能寄存器中,字节地址为98H,可位寻址,SCON用以设定串行口的工作方式、接收/发送控制以及设置状态标志等。单片机复位时SCON全部被清0。其各位的定义如表所示。

串行口控制寄存器SCON

SM0,SM1一工作方式选择位。

​ 串行口有4种工作方式,它们由SMO,SM1设定,对应关系如表所示。

串行口工作方式

SM2—多机通信控制位。
SM2主要用于方式2和方式3。当接收机的SM2=1时,可以利用收到的RB8来控制是否激活RI (RB8=0时不激活RI,收到的信息丢弃;RB8= 1时收到的数据进入SBUF,并激活RI,进而在中断服务中将数据从SBUF读走)。当SM2=0时,不论收到的RB8是0还是1,均可以使收到的数据进入SBUF,并激活RI (即此时RB8不具有控制RI激活的功能)。通过控制SM2,可以实现多机通信。在方式0时,SM2必须是0。在方式1时,若SM2=1,则只有接收到有效停止位时,RI 才置1。
REN一允许串行接收位。
REN=1:允许串行口接收数据;REN=0:禁止串行口接收数据。

TB8—方式2,3中发送数据的第9位。
在方式2或方式3中,是发送数据的第9位,可以用软件规定其作用。可以用做数据的奇偶校验位,或在多机通信中,作为地址帧/数据帧的标志位。在方式0和方式1中,该位未用。
RB8—方式2,3中接收数据的第9位。
在方式2或方式3中,是接收数据的第9位,可作为奇偶校验位或地址帧/数据帧的标志位。在方式1时,若SM2=0,则RB8是接收到的停止位。
TI一发送中断标志位。
在方式0时,当串行发送第8位数据结束时,或在其他方式,串行发送停止位的开始时,由内部硬件使TI置1,向CPU发出中断申请。在中断服务程序中,必须用软件将其清0,取消此中断申请。
RI一接收中断标志位。
在方式0时,当串行接收第8位数据结束时,或在其他方式,串行接收停止位的中间时,由内部硬件使RI置1,向CPU发出中断申请。也必须在中断服务程序中,用软件将其清0,取消此中断申请。

1
2
3
4
5
6
7
8
9
10
11
12
13
//串口初始化
void UART_Init()
{
SCON=0x40; //8位数据,可变波特率
PCON |= 0x80; //使能波特率倍速位
TMOD &= 0x0F; //设置定时器模式 清除定时器1模式位
TMOD |= 0x20; //设置定时器1为8位自动重装方式
TL1 = 0xF3; //设置定时初值
TH1 = 0xF3; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
//串口向电脑发送一个数据
unsigned char Sec;

void main()
{
UART_Init(); //
while(1)
{
UART_SendByte(Sec); //
Sec++; //
Delay(1000); //
}
}

电脑通过串口控制LED

1
2
3
4
5
6
7
8
9
10
11
12
13
void UART_Init()
{
SCON=0x50;
PCON |= 0x80;
TMOD &= 0x0F;
TMOD |= 0x20;
TL1 = 0xF3;
TH1 = 0xF3;
ET1 = 0;
TR1 = 1;
EA=1;
ES=1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"

void main()
{
UART_Init();
while(1)
{

}
}

void UART_Routine() interrupt 4
{
if(RI==1)
{
P2=~SBUF;
UART_SendByte(SBUF);
RI=0;
}
}

九.LED点阵屏

点阵屏

点阵屏2

LED点阵屏的结构类似于数码管,只不过是数码管把每一列的像素以“8”字型排列而已。

LED点阵屏与数码管一样,有共阴和共阳两种接法,不同的接法对应的电路结构不同。

LED点阵屏需要进行逐行或逐列扫描,才能使所有LED同时显示。

十.DS1302实时时钟

10.1DS1302实时时钟概述

DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能。

RTC(Real Time Clock):实时时钟,是一种集成电路,通常称为时钟芯片。

DS1302引脚定义及电路

DS1302内部结构图

DS1302寄存器定义

10.2时序定义

DS1302时序定义

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
void DS1302_Init(void)
{
DS1302_CE=0;
DS1302_SCLK=0;
}

void DS1302_WriteByte(unsigned char Command,Data)
{
unsigned char i;
DS1302_CE=1;
for(i=0;i<8;i++)
{
DS1302_IO=Command&(0x01<<i);
DS1302_SCLK=1;
DS1302_SCLK=0;
}
for(i=0;i<8;i++)
{
DS1302_IO=Data&(0x01<<i);
DS1302_SCLK=1;
DS1302_SCLK=0;
}
DS1302_CE=0;
}

unsigned char DS1302_ReadByte(unsigned char Command)
{
unsigned char i,Data=0x00;
Command|=0x01;
DS1302_CE=1;
for(i=0;i<8;i++)
{
DS1302_IO=Command&(0x01<<i);
DS1302_SCLK=0;
DS1302_SCLK=1;
}
for(i=0;i<8;i++)
{
DS1302_SCLK=1;
DS1302_SCLK=0;
if(DS1302_IO){Data|=(0x01<<i);}
}
DS1302_CE=0;
DS1302_IO=0;
return Data;
}

十一.蜂鸣器

蜂鸣器是一种将电信号转换为声音信号的器件,常用来产生设备的按键音、报警音等提示信号。

蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器。

有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定。

无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音。

蜂鸣器驱动电路

十二.AT24C02及I^2C总线

12.1AT24C02概述

存储器介绍

AT24C02是一种可以实现掉电不丢失的存储器,可用于保存单片机运行时想要永久保存的数据信息

存储介质:E2PROM

通讯接口:I2C总线

容量:256字节

AT24C02

AT24C02引脚及应用电路

12.2 I2C总线概述

I2C总线(Inter IC BUS)是由Philips公司开发的一种通用数据总线。

两根通信线:SCL(Serial Clock)、SDA(Serial Data)。

同步、半双工,带数据应答。

​ 通用的I2C总线,可以使各种设备的通信标准统一,对于厂家来说,使用成熟的方案可以缩短芯片设计周期、提高稳定性,对于应用者来说,使用通用的通信协议可以避免学习各种各样的自定义协议,降低了学习和应用的难度。

12.3 I2C电路规范

​ 所有I2C设备的SCL连在一起,SDA连在一起。

​ 设备的SCL和SDA均要配置成开漏输出模式。

​ SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右。

​ 开漏输出和上拉电阻的共同作用实现了“线与”的功能,此设计主要是为了解决多机通信互相干扰的问题。

12.4 I2C时序结构

I2C时序结构

发送一个字节

接收一个字节

应答

发送一帧数据

​ 主机发送启动信号后,再发出寻址信号。器件地址有7位和10位两种,这里只介绍7位地址寻址方式。寻址信号由一个字节构成,高7位为地址位,最低位为方向位,用以表明主机与从器件的数据传送方向。方向位为0,表明主机接下来对从器件进行写操作;方向位为1,表明主机接下来对从器件进行读操作。

​ 主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,如果相同,则认为自己正被主机寻址,根据R/W位将自己确定为发送器或接收器。
​ 从机的地址由固定部分和可编程部分组成。在一个系统中可能希望接入多个相同的从机,从机地址中可编程部分决定了可接入总线该类器件的最大数目。如一个从机的7位寻址位有4位是固定位,3位是可编程位,这时仅能寻址8个同样的器件,即可以有8个同样的器件接入到该I2C总线系统中。

接收一帧数据

先发送再接收数据帧

![字节写 随机读](../images/51单片机学习笔记/字节写 随机读.png)

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
53
54
55
56
57
58
59
60
#include <REGX52.H>

sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;

void I2C_Start(void)
{
I2C_SDA=1;
I2C_SCL=1;
I2C_SDA=0;
I2C_SCL=0;
}

void I2C_Stop(void)
{
I2C_SDA=0;
I2C_SCL=1;
I2C_SDA=1;
}

void I2C_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
I2C_SDA=Byte&(0x80>>i);
I2C_SCL=1;
I2C_SCL=0;
}
}

unsigned char I2C_ReceiveByte(void)
{
unsigned char i,Byte=0x00;
I2C_SDA=1;
for(i=0;i<8;i++)
{
I2C_SCL=1;
if(I2C_SDA){Byte|=(0x80>>i);}
I2C_SCL=0;
}
return Byte;
}

void I2C_SendAck(unsigned char AckBit)
{
I2C_SDA=AckBit;
I2C_SCL=1;
I2C_SCL=0;
}

unsigned char I2C_ReceiveAck(void)
{
unsigned char AckBit;
I2C_SDA=1;
I2C_SCL=1;
AckBit=I2C_SDA;
I2C_SCL=0;
return AckBit;
}
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
#include <REGX52.H>
#include "I2C.h"

#define AT24C02_ADDRESS 0xA0

void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS);
I2C_ReceiveAck();
I2C_SendByte(WordAddress);
I2C_ReceiveAck();
I2C_SendByte(Data);
I2C_ReceiveAck();
I2C_Stop();
}

unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
unsigned char Data;
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS);
I2C_ReceiveAck();
I2C_SendByte(WordAddress);
I2C_ReceiveAck();
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS|0x01);
I2C_ReceiveAck();
Data=I2C_ReceiveByte();
I2C_SendAck(1);
I2C_Stop();
return Data;
}

十三.DS18B20温度传感器

13.1 DS18B20

DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点。

测温范围:-55°C 到 +125°C。

通信接口:1-Wire(单总线)。

其它特征:可形成总线结构、内置温度报警功能、可寄生供电。

DS18B20

DS18B20引脚及驱动电路

13.2单总线介绍

单总线(1-Wire BUS)是由Dallas公司开发的一种通用数据总线。

一根通信线:DQ。

异步、半双工。

单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线。

13.3单总线电路规范

设备的DQ均要配置成开漏输出模式。

DQ添加一个上拉电阻,阻值一般为4.7KΩ左右。

若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路。

13.4单总线时序结构

单总线初始化

![单总线 发送一位](../images/51单片机学习笔记/单总线 发送一位.png)

![单总线 接收一位](../images/51单片机学习笔记/单总线 接收一位.png)

单总线发送接收一个字节

DS18B20操作流程

DS18B20数据帧

温度存储格式

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <REGX52.H>

sbit OneWire_DQ=P3^7;

unsigned char OneWire_Init(void)
{
unsigned char i;
unsigned char AckBit;
EA=0;
OneWire_DQ=1;
OneWire_DQ=0;
i = 247;while (--i); //Delay 500us
OneWire_DQ=1;
i = 32;while (--i); //Delay 70us
AckBit=OneWire_DQ;
i = 247;while (--i); //Delay 500us
EA=1;
return AckBit;
}

void OneWire_SendBit(unsigned char Bit)
{
unsigned char i;
EA=0;
OneWire_DQ=0;
i = 4;while (--i); //Delay 10us
OneWire_DQ=Bit;
i = 24;while (--i); //Delay 50us
OneWire_DQ=1;
EA=1;
}

unsigned char OneWire_ReceiveBit(void)
{
unsigned char i;
unsigned char Bit;
EA=0;
OneWire_DQ=0;
i = 2;while (--i); //Delay 5us
OneWire_DQ=1;
i = 2;while (--i); //Delay 5us
Bit=OneWire_DQ;
i = 24;while (--i); //Delay 50us
EA=1;
return Bit;
}

void OneWire_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
OneWire_SendBit(Byte&(0x01<<i));
}
}

unsigned char OneWire_ReceiveByte(void)
{
unsigned char i;
unsigned char Byte=0x00;
for(i=0;i<8;i++)
{
if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
}
return Byte;
}

十四.LCD1602

14.1LCD1602概述

LCD1602(Liquid Crystal Display)液晶显示屏是一种字符型液晶显示模块,可以显示ASCII码的标准字符和其它的一些内置特殊字符,还可以有8个自定义字符。

显示容量:16×2个字符,每个字符为5*7点阵。

常见液晶显示屏

LCD1602引脚及驱动电路

LCD1602内部结构图

LCD1602内部RAM映射图

​ 当我们向图中的00~0F、404F地址中的任一处写入显示数据时,液晶都可立即显示出来,当写入到1027或50~67地址处时,必须通过移屏指令将它们移入可显示区域方可正常显示。

14.2时序结构

LCD1602写数据或指令

LCD1602字符型液晶显示模块指令集

LCD1602操作流程

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <REGX52.H>

sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_E=P2^7;
#define LCD_DataPort P0

void LCD_Delay() //@12.000MHz 1ms
{
unsigned char i, j;

i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}

void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_E=1;
LCD_Delay();
LCD_E=0;
LCD_Delay();
}

void LCD_WriteData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_E=1;
LCD_Delay();
LCD_E=0;
LCD_Delay();
}

void LCD_Init(void)
{
LCD_WriteCommand(0x38);
LCD_WriteCommand(0x0C);
LCD_WriteCommand(0x06);
LCD_WriteCommand(0x01);
}

void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
else
{
LCD_WriteCommand(0x80|(Column-1)+0x40);
}
}

void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}

void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}

int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}

void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData('0'+Number/LCD_Pow(10,i-1)%10);
}
}

void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
unsigned char i;
unsigned int Number1;
LCD_SetCursor(Line,Column);
if(Number>=0)
{
LCD_WriteData('+');
Number1=Number;
}
else
{
LCD_WriteData('-');
Number1=-Number;
}
for(i=Length;i>0;i--)
{
LCD_WriteData('0'+Number1/LCD_Pow(10,i-1)%10);
}
}

void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
unsigned char SingleNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingleNumber=Number/LCD_Pow(16,i-1)%16;
if(SingleNumber<10)
{
LCD_WriteData('0'+SingleNumber);
}
else
{
LCD_WriteData('A'+SingleNumber-10);
}
}
}

void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData('0'+Number/LCD_Pow(2,i-1)%2);
}
}

十五.直流电机驱动PWM

15.1概述

​ 直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极,当电极正接时,电机正转,当电极反接时,电机反转。

​ 直流电机主要由永磁体(定子)、线圈(转子)和换向器组成。

电机驱动电路

15.2PWM介绍

​ PWM(Pulse Width Modulation)即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速、开关电源等领域。

PWM重要参数:

​ 频率 = 1 / TS 占空比 = TON / TS 精度 = 占空比变化步距。

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
//LED呼吸灯
#include <REGX52.H>

sbit LED=P2^0;

void Delay(unsigned int t)
{
while(t--);
}

void main()
{
unsigned char Time,i;
while(1)
{
for(Time=0;Time<100;Time++)
{
for(i=0;i<20;i++)
{
LED=0;
Delay(Time);
LED=1;
Delay(100-Time);
}
}
for(Time=100;Time>0;Time--)
{
for(i=0;i<20;i++)
{
LED=0;
Delay(Time);
LED=1;
Delay(100-Time);
}
}
}
}

产生PWM方法

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
#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Timer0.h"

sbit Motor=P1^0;

unsigned char Counter,Compare;
unsigned char KeyNum,Speed;

void main()
{
Timer0_Init();
while(1)
{
KeyNum=Key();
if(KeyNum==1)
{
Speed++;
Speed%=4;
if(Speed==0){Compare=0;}
if(Speed==1){Compare=50;}
if(Speed==2){Compare=75;}
if(Speed==3){Compare=100;}
}
}
}

void Timer0_Routine() interrupt 1
{
TL0 = 0x9C;
TH0 = 0xFF;
Counter++;
Counter%=100;
if(Counter<Compare)
{
Motor=1;
}
else
{
Motor=0;
}
}

十六.A/D D/A

16.1概述

AD(Analog to Digital):模拟-数字转换,将模拟信号转换为计算机可操作的数字信号。

DA(Digital to Analog):数字-模拟转换,将计算机输出的数字信号转换为模拟信号。

AD/DA转换打开了计算机与模拟信号的大门,极大的提高了计算机系统的应用范围,也为模拟信号数字化处理提供了可能。

硬件电路模型

AD转换通常有多个输入通道,用多路选择开关连接至AD转换器,以实现AD多路复用的目的,提高硬件利用率。

AD/DA与单片机数据传送可使用并口(速度快、原理简单),也可使用串口(接线少、使用方便)。

可将AD/DA模块直接集成在单片机内,这样直接写入/读出寄存器就可进行AD/DA转换,单片机的IO口可直接复用为AD/DA的通道。

![AD DA](../images/51单片机学习笔记/AD DA.png)

DA原理

AD原理

16.2性能指标

分辨率:指AD/DA数字量的精细程度,通常用位数表示。例如,对于5V电源系统来说,8位的AD可将5V等分为256份,即数字量变化最小一个单位时,模拟量变化5V/256=0.01953125V,所以,8位AD的电压分辨率为0.01953125V,AD/DA的位数越高,分辨率就越高。

转换速度:表示AD/DA的最大采样/建立频率,通常用转换频率或者转换时间来表示,对于采样/输出高速信号,应注意AD/DA的转换速度。

16.3 XPT2046

​ XPT2046是一款4线制电阻式触摸屏控制器,内含12位分辨率125KHz转换速率逐步逼近型A/D转换器。XPT2046支持从1.5V到5.25V的低电压I/0接口。XPT2046能通过执行两次A/D转换查出被按的屏幕位置,除此之外,还可以测量加在触摸屏上的压力。内部自带⒉2.5V参考电压,可以作为辅助输入、温度测量和电池监测之用,电池监测的电压范围可以从O0V到6V。XPT2046片内集成有一个温度传感器。在2.7V的典型工作状态下,关闭参考电压,功耗可小于0.75mW。XPT2046采用微小的封装形式:TSSOP-16,QFN-16和VFBGA一48。工作温度范围为-40℃~+85℃。与ADS7846、TSC2046、AK4182A完全兼容。

XPT2046时序

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
#include <REGX52.H>
#include <INTRINS.H>

sbit XPY2046_DIN=P3^4;
sbit XPY2046_CS=P3^5;
sbit XPY2046_DCLK=P3^6;
sbit XPY2046_DOUT=P3^7;

unsigned int XPT2046_ReadAD(unsigned char Command)
{
unsigned char i;
unsigned int Data=0;
XPY2046_DCLK=0;
XPY2046_CS=0;
for(i=0;i<8;i++)
{
XPY2046_DIN=Command&(0x80>>i);
XPY2046_DCLK=1;
XPY2046_DCLK=0;
}
for(i=0;i<16;i++)
{
XPY2046_DCLK=1;
XPY2046_DCLK=0;
if(XPY2046_DOUT){Data|=(0x8000>>i);}
}
XPY2046_CS=1;
return Data>>8;

十七.红外遥控(外部中断)

17.1概述

红外遥控是利用红外光进行通信的设备,由红外LED将调制后的信号发出,由专用的红外接收头进行解调输出

通信方式:单工,异步

红外LED波长:940nm

通信协议标准:NEC标准

红外遥控硬件电路

•空闲状态:红外LED不亮,接收头输出高电平

•发送低电平:红外LED以38KHz频率闪烁发光,接收头输出低电平

•发送高电平:红外LED不亮,接收头输出高电平

基本发送与接收

NEC编码


文章作者: RickyLove
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 RickyLove !
  目录