Size: px
Start display at page:

Download ""

Transcription

1 51 单片机 C 语言 基础程序设计 zicreate.com Jason 编著 - 51 系列单片机 C 语言编程 - 单片机常用外围器件应用总结

2

3 目录第一部分 :51 系列 AT89S52 单片机 C 语言程序设计 第 1 章 AT89S52 单片机硬件介绍 AT89S52 单片机引脚分布图 功能特性描述 AT89S52 单片机的主要性能参数 引脚功能说明 存储器结构 AT89S51 及 AT89S2051 单片机引脚分布图 AT89S52 单片机选型表 AT89S52 单片机型号标识解析 AT89S52 单片机封装信息 AT89S52 单片机最小系统 第 2 章 AT89S52 单片机常用功能寄存器总结 程序状态寄存器 PSW 电源控制寄存器 PCON 定时器 0 1 方式控制寄存器 TMOD 定时器 0 1 控制寄存器 TCOD 定时器 2 控制寄存器 T2COD 中断允许寄存器 IE 中断优先级寄存器 IP 串行口控制寄存器 SCON 辅助寄存器 AUXR 辅助寄存器 1 AUXR 第 3 章 51 系列单片机汇编指令集 汇编指令 第 4 章 51 系列单片机 C 语言编程基础 ANSI C 和 Keil C C51 的数据类型 C51 的存储器类型 C51 的存储器模式 C51 常用的库函数 C51 的基本语句 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 AT89S52 单片机的通用 I/O 口 C 语言编程 AT89S52 单片机的 I/O 口

4 5.1.2 AT89S52 单片机控制 LED 流水灯 AT89S52 单片机控制蜂鸣器 AT89S52 单片机控制 DC5V 继电器 AT89S52 单片机的中断系统介绍 AT89S52 单片机的外部中断 C 语言编程 AT89S52 单片机外部中断相关功能寄存器 AT89S52 单片机外部中断 C 语言编程实例 AT89S52 单片机的定时 / 计数器 C 语言编程 与定时 / 计数器相关的功能寄存器 定时 / 计数器中断 C 语言编程实例 AT89S52 单片机的异步串行通信编程 与串行异步通信相关的功能寄存器 串行异步通信 C 语言编程实例 第 6 章 AT89S52 单片机扩展功能 C 语言编程 LED 数码管显示 LCD1602 显示 LCD12864 显示 独立键盘输入 矩阵键盘输入 A/D 和 D/A 转换 第 7 章 AT89S52 单片机控制系统应用实例设计 AT89S52 单片机控制的模拟交通灯系统设计 基于 AT89S52 单片机及 DS18B20 温度传感器的测温系统设计 数码管显示 LCD1602 液晶显示 基于 AT89S52 单片机及 DS1302 的多功能时钟系统设计 第二部分 : 单片机常用外围器件 第 1 章常用电子元器件 电阻器 电容器 二极管 三极管 常用开关 蜂鸣器 继电器 接口器件

5 1.9 纽扣电池 第 2 章常用数字逻辑电路 常用 74HC 系列器件表 HC 系列逻辑门电路 双路可再触发单稳多谐振荡器 74HC 译码器 / 多路分配器 74HC138/74HC139/74HC 路 2 输入多路选择器 74HC 位串进并出移位寄存器 74HC 位并进串出移位寄存器 74HC 三态输出的 8 路正反相缓冲器 / 线路驱动器 74HC244 74HC 三态输出的 8 路总线收发器 74HC 路 D 型上升沿触发器 74HC 三态输出的 8 路 D 型锁存器 74HC373/74HC 三态输出锁存的 8 位移位寄存器 74HC 第 3 章显示器件 LED 数码管 LCD1602 液晶 LCD12864 液晶 第 4 章通信相关器件 RS232 总线接口芯片 MAX RS485 总线接口芯片 MAX PT2262/PT2272 遥控编解码电路 第 5 章 A/D 和 D/A 转换相关器件 A/D 转换器件 D/A 转换器件 第 6 章电源相关器件 电源器件的选型 三端稳压器 LM78M05 LM78L05 L 三端稳压器 LM 三端稳压器 AMS 第 7 章传感器相关器件 数字温度传感器 DS18B20 温度 时钟芯片 DS

6

7 第一部分 :51 系列 AT89S52 单片机 C 语言程序设计 第 1 章 AT89S52 单片机硬件介绍 AT89S52 单片机是美国 ATMEL 公司生产的低功耗, 高性能 CMOS 8 位单片机, 片内含有 8kb 的可系统编程的 Flash 只读程序存储器, 器件采用 ATMEL 公司的高密度 非易失性存储技术生产, 兼容标准 8051 指令系统及引脚 在单芯片上, 拥有灵巧的 8 位 CPU 和在系统可编程 Flash, 使得 AT89S52 为众多嵌入式控制应用系统提供高灵活 超有效的解决方案 1.1 AT89S52 单片机引脚分布图 a) 40 引脚塑料双列直插式封装 (PDIP) b) 44 引脚塑料无引线芯片载体封装 (TQFP) c) 42 引脚塑料双列直插式封装 (PDIP) d) 44 引脚薄型四方扁平封装 (PLCC) 图 1-1:AT89S52 引脚分布及封装图 - 1 -

8 1.2 功能特性描述 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 AT89S52 具有以下标准功能 :8k 字节 Flash,256 字节 RAM,32 位 I/O 口线, 看门狗定时器,2 个数据指针, 三个 16 位定时器 / 计数器, 一个 6 向量 2 级中断结构, 全双工串行口, 片内晶振及时钟电路 另外, AT89S52 可降至 0Hz 静态逻辑操作, 支持 2 种软件可选择节电模式 空闲模式下,CPU 停止工作, 允许 RAM 定时器 / 计数器 串口 中断继续工作 掉电保护方式下,RAM 内容被保存, 振荡器被冻结, 单片机一切工作停止, 直到下一个中断或硬件复位为止 1.3 AT89S52 单片机的主要性能参数 与 MCS-51 产品指令系统完全兼容 8k 字节在线系统编程 (ISP) Flash 闪速存储器 1000 次擦写周期 V 的工作电压范围 全静态工作模式 :0Hz-33MHz 三级程序加密锁 字节内部 RAM 32 个可编程 I/O 口线 1.4 引脚功能说明 3 个 16 位定时 / 计数器 6 个中断源 全双工串行 UART 通道 低功耗空闲和掉电模式 中断可从空闲模式唤醒系统 看门狗 (WDT) 及双数据指针 掉电标识和快速编程特性 灵活的在线系统编程 (ISP 一字节或页写模式 ) P0 口 :P0 口是一组 8 位漏极开路型双向 I/O 口, 也即地址 / 数据总线复用口 作为输出口用时, 每位能驱动 8 个 TTL 逻辑门电路, 对端口写 1 可作为高阻抗输入端用 在访问外部数据存储器或程序存储器时, 这组口线分时转换地址 ( 低 8 位 ) 和数据总线复用, 在访问期间激活内部上拉电阻 在 Flash 编程时, P0 口接收指令字节, 而在程序校验时, 输出指令字节, 校验时, 要求外接上拉电阻 P1 口 :P1 是一个带内部上拉电阻的 8 位双向 I/O 口,P1 的输出缓冲级可驱动 ( 吸收或输出电流 )4 个 TTL 逻辑门电路 对端口写 1, 通过内部的上拉电阻把端口拉到高电平, 此时可作输入口 作输入口使用时, 因为内部存在上拉电阻, 某个引脚被外部信号拉低时会输出一个电流 (In) Flash 编程和程序校验期间 P 1 接收低 8 位地址 此外,P1.0 和 P1.2 分别作定时器 / 计数器 2 的外部计数输入 (P1.0/T2) 和时器 / 计数器 2 的触发输入 (P1.1/T2EX), 具体如下表所示 引脚 表 1-1: P1 口第二功能 第二功能 P1.0 T2 ( 定时器 / 计数器 T2 的外部计数输入 ), 时钟输出 P1.1 T2EX( 定时器 / 计数器 T2 的捕捉 / 重载触发信号和方向控制 ) P1.5 MOSI( 在系统编程用 ) P1.6 MISO( 在系统编程用 ) P1.7 SCK ( 在系统编程用 ) P2 口 :P2 是一个带有内部上拉电阻的 8 位双向 I/O 口,P2 的输出缓冲级可驱动 ( 吸收或输出电流 )4 个 TTL 逻辑门电路 对端口写 1, 通过内部的上拉电阻把端口拉到高电平, 此时可作输入口, 作输入口使用时, 因为内部存在上拉电阻, 某个引脚被外部信号拉低时会输出一个电流 (In) 在访问外部程序存储器或 16 位地址的外部数据存储器 ( 例如执行 指令 ) 时,P2 口送出高 8 位地址数据 在访问 8 位地址的外部数据存储器 ( 如执行 指令 ) 时,P2 口线卜的内容 ( 也即特殊功能寄存器 (SFR) 区中 P2 寄存器的内容 ), 在整个访问期间不改变 Flash 编程或校验时,P2 亦接收高位地址和其它控制信号 P3 口 :P3 口是一组带有内部上拉电阻的 8 位双向 I/O 口 P3 口输出缓冲级可驱动 ( 吸收或输出电流 )4 个 TTL 逻辑门电路 对 P3 口写入 1 时, 它们被内部上拉电阻拉高并可作为输入端口 作输入端时, 被外部拉低的 P3 口将用上拉电阻输出电流 (In) P3 口除了作为一般的 I/O 口线外, 更重要的用途是它的第二功能 P3 口还接收一些用于 Flash 闪速存储器编程和程序校验的控制信号 引脚 表 1-2: P3 口第二功能 P3.0 RXD ( 串行口输入 ) 第二功能 - 2 -

9 第一章 AT89S52 单片机硬件介绍 P3.1 TXD ( 串行口输出 ) P3.2 INT 0 ( 外部中断 0 输入 ) P3.3 INT 1 ( 外部中断 1 输入 ) P3.4 T0 ( 定时 / 计数器 0 的外部输入 ) P3.5 T1 ( 定时 / 计数器 1 的外部输入 ) P3.6 WR ( 片外数据存储器 I/O 口写选通 ) P3.7 RD ( 片外数据存储器 I/O 口读写选通 ) RST: 复位输入 当振荡器工作时,RST 引脚出现两个机器周期以上高电平将使单片机复位 WDT 溢出将使该引脚输出高电平, 设置 SFR AUXR 的 DISRTO 位 ( 地址 8EH) 可打开或关闭该功能 DISRTO 位缺省为 RESET 输出高电平打开状态 ALE/ PROG : 当访问外部程序存储器或数据存储器时,ALE( 地址锁存允许 ) 输出脉冲用于锁存地址的低 8 位字节 即使不访问外部存储器,ALE 仍以时钟振荡频率的 1/6 输出固定的正脉冲信号, 囚此它可对外输出时钟或用于定时目的 要注意的是 : 每当访问外部数据存储器时将跳过一个 ALE 脉冲 对 Flash 存储器编程期间, 该引脚还用于输入编程脉冲 ( PROG ) 如有必要, 可通过对特殊功能寄存器 (SFR) 区中的 8EH 单元的 D0 位置位, 可禁正 ALE 操作 该位置位后, 只有一条 MOVX 和 MOVC 指令 ALE 才会被激活 此外, 该引脚会被微弱拉高, 单片机执行外部程序时, 应设置 ALE 无效 PSEN : 程序储存允许 ( PSEN ) 输出是外部程序存储器的读选通信号, 当 AT89S51 由外部程序存储器取指令 ( 或数据 ) 时, 每个机器周期两次 PSEN 有效, 即输出两个脉冲 当访问外部数据存储器, 没有两次有效的 PSEN 信号 EA /VPP: 外部访问允许 欲使 CPU 仅访问外部程序存储器 ( 地址为 0000H-FFFFH), EA 端必须保持低电平 ( 接地 ) 需注意的是 : 如果加密位 LB1 被编程, 复位时内部会锁存 EA 端状态 如果 EA 端为高电平 ( 接 Vcc 端 ),CPU 则执行内部程序存储器中的指令 Flash 存储器编程时, 该引脚加上 +12 V 的编程电压 Vpp XTAL1: 振荡器反相放大器及内部时钟发生器的输入端 XTAL2: 振荡器反相放大器的输出端 1.5 存储器结构 特殊功能寄存器 : 特殊功能寄存器 (SFR) 的地址空间映象如表 1-3 所示 并不是所有的地址都被定义了 片上没有定义的地址是不能用的 读这些地址, 一般将得到一个随机数据 ; 写入的数据将会无效 用户不应该给这些未定义的地址写入数据 1 由于这些寄存器在将来可能被赋予新的功能, 复位后, 这些位都为 0 表 1-3: 特殊功能寄存器 (SFR) 的地址空间 序号地址符号复位值说明 1 80H P0 FFH P0 口锁存寄存器 2 81H SP 07H 堆栈指针 3 82H DP0L 00H 数据指针 DPTR0 低 8 位 4 83H DP0H 00H 数据指针 DPTR0 高 8 位 5 84H DP1L 00H 数据指针 DPTR1 低 8 位 6 85H DP1H 00H 数据指针 DPTR1 高 8 位 7 87H PCON 0XXX0000B 电源控制寄存器 8 88H TCON 00H 定时 / 计数器 0 和 1 的控制寄存器 9 89H TMOD 00H 定时 / 计数器 0 和 1 的模式寄存器 10 8AH TL0 00H 定时 / 计数器 0 低 8 位 - 3 -

10 11 8BH TL1 00H 定时 / 计数器 1 低 8 位 12 8CH TH0 00H 定时 / 计数器 0 高 8 位 13 8DH TH1 00H 定时 / 计数器 1 高 8 位 14 8EH AUXR XXX0 0XX0B 辅助寄存器 15 90H P1 FFH P1 口锁存寄存器 16 98H SCON 00H 串行口控制寄存器 17 99H SBUF XXXX XXXXB 串行数据缓冲寄存器 18 0A0H P2 FFH P2 口锁存寄存器 19 0A2H AUXR1 XXXX XXX0B 辅助寄存器 A6H WDTRST XXXX XXXXB WDT 复位寄存器 21 0A8H IE 0X B 中断允许控制寄存器 22 0B0H P3 FFH P3 口锁存寄存器 23 0B8H IP XX B 中断优先级控制寄存器 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 24 0C8H T2CON 00H 定时 / 计数器 2 控制寄存器 25 0C9H T2MOD XXXX XX00B 定时 / 计数器 2 模式寄存器 26 0CAH RCAP2L 00H 定时 / 计数器 2 捕捉 / 重装寄存器低 8 位 27 0CBH RCAP2H 00H 定时 / 计数器 2 捕捉 / 重装寄存器高 8 位 28 0CCH TL2 00H 定时 / 计数器 2 低 8 位 29 0CDH TH2 00H 定时 / 计数器 2 高 8 位 30 0D0H PSW 00H 程序状态字 31 0E0H ACC 00H 累加器 32 0F0H B 00H B 寄存器 中断寄存器 : 各中断允许控制位于 IE 寄存器,5 个中断源的中断优先级控制位于 IP 寄存器 双时钟指针寄存器 : 为更方便地访问内部和外部数据存储器, 提供了两个 16 位数据指针寄存器 : DP0 位于 SFR( 特殊功能寄存器 ) 区块中的地址 82H, 83H 和 DP1 位于地址 84H, 85H, 当 SFR 中辅助寄存器 1 AUXR1 的位 DPS=0 选择 DP0, 而 DPS=1 则选择 DP1 用户应在访问相应的数据指针寄存器前初始化 DPS 位 电源空闲标志 : 电源空闲标志 (POF) 在特殊功能寄存器 SFR 中 PCON 的第 4 位 (PCON.4, 电源打开时 POF 置 1, 它可由软件设置睡眠状态并不为复位所影响 程序存储器 : 如果 EA 引脚接地 (GND), 全部程序均执行外部存储器 在 AT89S51, 假如 EA 接至 Vcc( 电源 +), 程序首先执行地址从 0000H-1FFFH (8KB) 内部程序存储器, 而执行地址为 2000H-FFFFH (60KB) 的外部程序存储器 如图 1-2 数据存储器 :AT89S51 的具有 256 字节的内部 RAM, 这 128 字节可利用直接或间接寻址方式访问, 堆栈操作可利用间接寻址方式进行,128 字节均可设置为堆栈区空间 如图 1-2 看门狗定时器 (WDT):WDT 是为了解决 CPU 程序运行时可能进入混乱或死循环而设置, 它由一个 14 位计数器和看门狗复位 SFR (WDTRST) 构成 外部复位时,WDT 默认为关闭状态, 要打开 WDT, 用户必须按顺序将 01EH 和 0E1H 写到 WDTRST 寄存器 (SFR 地址为 OA6H), 当启动了 WDT, 它会随晶体振荡器在每个机器周期计数, 除硬件复位或 WDT 溢出复位外没有其它方法关闭 WDT, 当 WDT 溢出, 将使 RSF 引脚输出高电平的复位脉冲 定时 / 计数器 0 和定时 / 计数器 1: 定时器 0 和 1 都是一个 16 位定时 / 计数器 定时 / 计数器 2: 定时器 2 是一个具有 16 位自动重装或捕获能力的定时 / 计数器 ww.zicreate.com - 4 -

11 第一章 AT89S52 单片机硬件介绍 图 1-2: 存储器地址分布图 1.6 AT89S51 及 AT89S2051 单片机引脚分布图 AT89S2051 单片机引脚分布图 : PDIP/SOIC 图 1-3:AT89S51 及 AT89S2051 单片机引脚分布与封装图 - 5 -

12 1.7 AT89S52 单片机选型表 表 1-4 AT89S52 单片机选型表 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 表 1-5 AT89S52 单片机封装形式 1.8 AT89S52 单片机型号标识解析 1. 后缀的数字部分, 表示支持的最高系统时钟 例 :AT89S52-24PU, 24 表示可支持最高为 24MHz 的系统时钟 2. 后缀第一个字母, 表示封装 P :DIP 封装, A :TQFP 封装, J :PLCC 封装 例 :AT89S52-24PU, P 表示 DIP 封装 3. 后缀最后一个字母, 表示应用级别 C : 商业级, I : 工业级 ( 有铅 ) U 工业级 ( 无铅 ) 例 :AT89S52-24PU, U 表示无铅工业级 AT89S52-24PI, I 表示有铅工业级 1.9 AT89S52 单片机封装信息 ww.zicreate.com - 6 -

13 第一章 AT89S52 单片机硬件介绍 图 1-4 AT89S52 单片机封装信息 1.8 AT89S52 单片机最小系统如图 1-5 所示, 即为 AT89S52 单片机最小系统 有晶振电路 上电复位按键复位电路 下载口电路组成 图 1-5 AT89S52 单片机最小系统原理图 - 7 -

14 2.1 程序状态寄存器 PSW 第 2 章 AT89S52 单片机常用功能寄存器总结 表 2-1 程序状态寄存器 PSW D7 D6 D5 D4 D3 D2 D1 D0 Cy AC F0 RS1 RS0 OV -- P Cy: 在算术运算中它可作为进位标志位, 有进借位时,Cy 被硬件置 1, 否则被硬件清 0 在位运算中, 它作累加器使用, 在位传送 位与和位或等位操作中, 都要使用进位标志位 AC: 辅助进位标志位 进行加法或减法操作低 4 位向高四位有进借位时,AC 被硬件置 1, 否则被硬件清 0 在进行十进制调整指令时, 将借助 AC 状态进行判断 F0: 用户标志位 RS1 RS0: 工作寄存器组选择位 该两位通过软件置 0 或 1 来选择当前工作寄存器 如表 2-2 所示 表 2-2 设置工作寄存器组 RS1 RS0 寄存器组 R0 ~ R7 的物理地址 组 00H ~ 07H 组 08H ~ 0FH 组 10H ~ 17H 组 18H ~ 1FH OV: 溢出标志位 当执行算术指令时, 在带符号的加减运算中,OV=1 表示有溢出 ( 或借位 ) 反之, OV=0 表示运算正确, 即无溢出产生 P: 奇偶校验标志位 用以表示累加器 A 中 1 的个数的奇偶性 若累加器中 1 的个数为奇数则 P=1, 否则 P=0 2.2 电源控制寄存器 PCON 表 2-3 电源控制寄存器 PCON D7 D6 D5 D4 D3 D2 D1 D0 SMOD POF GF1 GF0 PD IDL SMOD: 波特率倍增位 POF: 电源空闲标志 GF1 GF0: 通用标志位 PD: 掉电方式控制位, 当 PD=1 时, 则进入掉电方式 IDL: 待机方式控制位, 当 IDL =1 时, 则进入掉电方式 2.3 定时器 0 1 方式控制寄存器 TMOD 表 2-4 定时器 0 1 方式控制寄存器 TMOD D7 D6 D5 D4 D3 D2 D1 D0 GATE C/T M1 M0 GATE C/T M1 M0 T1 T0 GATE: 门控位 当 GATE=0 时, 只利用控制位 TR0 或 TR1 来控制定时器的启停 当 GATE=1 时, 定时器的启停由外部中断引脚和控制位 TR0 或 TR1 来共同控制 C/T : 功能选择位 当 C/T =0 时, 设定为定时器工作方式 当 C/T =1 时, 设定为计数器工作方式 M1 M0: 工作模式控制位 表 2-5 定时器 0 1 工作模式设定 M1 M0 工作方式功能简述 0 0 模式 0 13 位计数器,TLi 只用低 5 位 0 1 模式 1 16 位计数器 1 0 模式 2 8 位自动重装计数器 仅 TLi 作为计数器,THi 的值不变 TLi 溢出, THi 中的值自动装入 TLi 中. 1 1 模式 3 T0 分为两个独立的 8 位计数器 - 8 -

15 第二章 AT89S52 单片机常用功能寄存器总结 计数初值的计算 : Tc 计数值 其中 Tc是定时时间, T T p p 12 f osc 是机器周期 f Tc 计数初值 X M 计数值 M M (TC fosc) / 12 T 2.4 定时器 2 方式控制寄存器 T2MOD p osc 是振荡频率 表 2-6 定时器 2 方式控制寄存器 T2MOD D7 D6 D5 D4 D3 D2 D1 D T2OE DCED T2OE: 定时器 2 输出允许位 DCED: 置 1 后, 定时器 2 可配置成向上 / 向下计数 2.5 定时器 0 1 控制寄存器 TCOD 表 2-7 定时器 0 1 控制寄存器 TCOD D7 D6 D5 D4 D3 D2 D1 D0 TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 TF1 TF0: 分别为定时器 1 和定时器 0 的溢出标志 溢出后由硬件置 1, 并申请中断 TR1 TR0: 分别为定时器 1 和定时器 0 的启停控制位 置 1 启动, 清 0 停止 IE1 IE0: 外部中断请求标志位 外部中断有中断请求时, 由硬件置 1 响应中断后由硬件清 0 IT1 IT0: 外部中断触发方式位 设置为 0 时为电平触发, 设置为 1 时为边沿触发 2.6 定时器 2 控制寄存器 T2COD 表 2-8 定时器 2 控制寄存器 T2COD D7 D6 D5 D4 D3 D2 D1 D0 TF2 EXF2 RCLK TCLK EXEN2 TR2 C/ T 2 CP/ RL 2 TF2: 定时器 2 溢出标志位 必须软件清 0 当 RCLK=1 或 TCLK=1 时 TF2 不用置位 EXF2: 定时器 2 外部标志位 EXEN2=1 时,T2EX 上的负跳变而出现捕捉或重载时,EXF2 会被硬件置位 定时器 2 打开,EXF2=1 时, 将引导 CPU 执行定时器 2 中断程序 EXF2 必须如见清 0 在向下 / 向上技术模式 (DCEN=1) 下 EXF2 不能引起中断 RCLK: 串行口接收数据时钟标志位 若 RCLK=1, 串行口将使用定时器 2 溢出脉冲作为串行口工作模式 1 和 3 的串口接收时钟 ;RCLK=0, 将使用定时器 1 计数溢出作为串口接收时钟 TCLK: 串行口发送数据时钟标志位 若 TCLK=1, 串行口将使用定时器 2 溢出脉冲作为串行口工作模式 1 和 3 的串口发送时钟 ;TCLK=0, 将使用定时器 1 计数溢出作为串口发送时钟 EXEN2: 定时器 2 外部允许标志位 当 EXEN2=1 时, 如果定时器 2 没有用作串行时钟,T2EX(P1.1) 的负跳变见引起定时器 2 捕捉和重载 若 EXEN2=0, 定时器 2 将视 T2EX 端的信号无效 TR2: 开始 / 停止控制定时器 2 TR2=1, 定时器 2 开始工作 C/ T 2 : 定时器 2 定时 / 计数选择标志位 C/ T 2 =0, 定时 ;C/ T 2 =1, 外部事件计数 ( 下降沿触发 ) CP/ RL 2 : 捕捉 / 重载选择标志位 当 EXEN2=1 时,CP/ RL2 =1,T2EX 出现负脉冲, 会引起捕捉操作 ; 当定时器 2 溢出或 EXEN2=1 时 T2EX 出现负跳变, 都会出现自动重载操作 CP/ RL2 =0 将引起 T2EX 的负脉冲 当 RCKL=1 或 TCKL=1 时, 此标志位无效, 定时器 2 溢出时, 强制做自动重载操作 2.7 中断允许寄存器 IE 表 2-9 中断允许寄存器 IE D7 D6 D5 D4 D3 D2 D1 D0 EA -- ET2 ES ET1 EX1 ET0 EX0 EA: 当 EA=1 时 CPU 开总中断, 当 EA=0 时 CPU 关总中断 ET2 ET1 ET0: 定时器中断允许控制位 为 1 时允许中断 EX1 EX0: 外部中断中断允许控制位 为 1 时允许外部中断 - 9 -

16 ES: 串行口中断允许控制位 为 1 时允许中断 2.8 中断优先级寄存器 IP 表 2-10 中断优先级寄存器 IP 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 D7 D6 D5 D4 D3 D2 D1 D PT2 PS PT1 PX1 PT0 PX0 PT2 PT1 PT0: 定时器优先级设定位 置 1 时为高优先级 PX1 PX0: 外部中断优先级设定位 置 1 时为高优先级 PS: 串行口中断优先级设定位 置 1 时为高优先级 2.9 串行口控制寄存器 SCON 表 2-11 串行口控制寄存器 SCON D7 D6 D5 D4 D3 D2 D1 D0 SM0 SM1 SM2 REN TB8 RB8 TI RI SM0 SM0: 串行通信方式选择位 表 2-12 设置串行通信方式 SM0 SM1 工作方式 功能说明 波特率 0 0 方式 0 同步移位寄存器方式 f osc / 方式 1 10 位异步通信方式 可变, 由定时器控制 1 0 方式 2 11 位异步通信方式 f osc /32 或 f osc / 方式 3 11 位异步通信方式 可变, 由定时器控制 SM2: 多机通信控制位 置 1 时多机通信, 主要用于方式 2 和方式 3 置 0 时是单机对单机通信 REN: 接收控制位 0 即禁止接收 1 允许接收 TB8: 发送数据第 9 位 RB8: 接收数据第 9 位 TI: 发送中断标志位, 发送完一帧由硬件置 1, 发送前必须用软件复位 RI: 接收中断标志位, 接收完一帧由硬件置 1, RI 也用软件复位 波特率计算 : SMOD 方式 0 和方式 2 的波特率波特率 fosc (/ 64/ 2 ) 方式 1 和方式 3 的波特率 SMOD 溢出周期 定时时间 256 X fosc 波特率 T1的溢出率 (/ 32 / 2 ) 1/ 溢出周期 波特率 SMOD SMOD 2 fosc 2 fosc X X 2.10 辅助寄存器 AUXR 表 2-13 辅助寄存器 AUXR 12 SMOD 2 fosc 计数初值 X 波特率 D7 D6 D5 D4 D3 D2 D1 D WDIDLE DISRTO DISALE WDIDLE: 空闲模式下 WDT 使能标志位 0 空闲模式下,WDT 继续计数 1 空闲模式下,WDT 停止计数 DISRTO: 复位输出标志位 0 看门狗 (WDT) 定时结束,Reset 输出高电平 1 Reset 只有输入 DISALE:ALE 使能标志位 0 ALE 以 1/6 晶振频率输出信号 1 ALE 只有在执行 MOVX 或 MOVC 指令时激活 2.11 辅助寄存器 1 AUXR1 表 2-14 辅助寄存器 1 AUXR1 D7 D6 D5 D4 D3 D2 D1 D DPS DPS: 数据指针选择位 0 选择 DPTR 寄存器 DP0L 和 DP0H, 1 选择 DPTR 寄存器 DP1L 和 DP1H ww.zicreate.com

17 第二章 AT89S52 单片机常用功能寄存器总结

18 第 3 章 51 系列单片机汇编指令集 3.1 汇编指令 表 系列单片机汇编指令表 助记符指令说明字节数周期数 ( 数据传递类指令 ) MOV A,Rn 寄存器传送到累加器 1 1 MOV A,direct 直接地址传送到累加器 2 1 MOV A,@Ri 累加器传送到外部 RAM(8 地址 ) 1 1 MOV A,#data 立即数传送到累加器 2 1 MOV Rn,A 累加器传送到寄存器 1 1 MOV Rn,direct 直接地址传送到寄存器 2 2 MOV Rn,#data 累加器传送到直接地址 2 1 MOV direct,rn 寄存器传送到直接地址 2 1 MOV direct,direct 直接地址传送到直接地址 3 2 MOV direct,a 累加器传送到直接地址 2 1 MOV direct,@ri 间接 RAM 传送到直接地址 2 2 MOV direct,#data 立即数传送到直接地址 3 2 直接地址传送到直接地址 1 2 直接地址传送到间接 RAM 2 1 立即数传送到间接 RAM 2 2 MOV DPTR,#data16 16 位常数加载到数据指针 3 1 MOVC A,@A+DPTR 代码字节传送到累加器 1 2 MOVC A,@A+PC 代码字节传送到累加器 1 2 MOVX A,@Ri 外部 RAM(8 地址 ) 传送到累加器 1 2 MOVX A,@DPTR 外部 RAM(16 地址 ) 传送到累加器 1 2 累加器传送到外部 RAM(8 地址 ) 1 2 助记符 指令说明 字节数 周期数 累加器传送到外部 RAM(16 地址 ) 1 2 PUSH direct 直接地址压入堆栈 2 2 POP direct 直接地址弹出堆栈 2 2 XCH A,Rn 寄存器和累加器交换 1 1 XCH A, direct 直接地址和累加器交换 2 1 XCH 间接 RAM 和累加器交换 1 1 XCHD 间接 RAM 和累加器交换低 4 位字节 1 1 ( 算术运算类指令 ) INC A 累加器加 INC Rn 寄存器加 INC direct 直接地址加 间接 RAM 加 INC DPTR 数据指针加 DEC A 累加器减 DEC Rn 寄存器减 DEC direct 直接地址减

19 第三章 51 系列单片机汇编指令集 间接 RAM 减 MUL AB 累加器和 B 寄存器相乘 1 4 DIV AB 累加器除以 B 寄存器 1 4 DA A 累加器十进制调整 1 1 ADD A,Rn 寄存器与累加器求和 1 1 ADD A,direct 直接地址与累加器求和 2 1 ADD A,@Ri 间接 RAM 与累加器求和 1 1 ADD A,#data 立即数与累加器求和 2 1 ADDC A,Rn 寄存器与累加器求和 ( 带进位 ) 1 1 ADDC A,direct 直接地址与累加器求和 ( 带进位 ) 2 1 ADDC A,@Ri 间接 RAM 与累加器求和 ( 带进位 ) 1 1 ADDC A,#data 立即数与累加器求和 ( 带进位 ) 2 1 SUBB A,Rn 累加器减去寄存器 ( 带借位 ) 1 1 SUBB A,direct 累加器减去直接地址 ( 带借位 ) 2 1 SUBB A,@Ri 累加器减去间接 RAM( 带借位 ) 1 1 SUBB A,#data 累加器减去立即数 ( 带借位 ) 2 1 ( 逻辑运算类指令 ) ANL A,Rn 寄存器 与 到累加器 1 1 ANL A,direct 直接地址 与 到累加器 2 1 ANL A,@Ri 间接 RAM 与 到累加器 1 1 ANL A,#data 立即数 与 到累加器 2 1 ANL direct,a 累加器 与 到直接地址 2 1 ANL direct, #data 立即数 与 到直接地址 3 2 ORL A,Rn 寄存器 或 到累加器 1 2 ORL A,direct 直接地址 或 到累加器 2 1 ORL A,@Ri 间接 RAM 或 到累加器 1 1 ORL A,#data 立即数 或 到累加器 2 1 助记符 指令说明 字节数 周期数 ORL direct,a 累加器 或 到直接地址 2 1 ORL direct, #data 立即数 或 到直接地址 3 1 XRL A,Rn 寄存器 异或 到累加器 1 2 XRL A,direct 直接地址 异或 到累加器 2 1 XRL A,@Ri 间接 RAM 异或 到累加器 1 1 XRL A,#data 立即数 异或 到累加器 2 1 XRL direct,a 累加器 异或 到直接地址 2 1 XRL direct, #data 立即数 异或 到直接地址 3 1 CLR A 累加器清零 1 2 CPL A 累加器求反 1 1 RL A 累加器循环左移 1 1 RLC A 带进位累加器循环左移 1 1 RR A 累加器循环右移 1 1 RRC A 带进位累加器循环右移 1 1 SWAP A 累加器高 低 4 位交换 1 1 ( 控制转移类指令 )

20 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 相对 DPTR 的无条件间接转移 1 2 JZ rel 累加器为 0 则转移 2 2 JNZ rel 累加器为 1 则转移 2 2 CJNE A,direct,rel 比较直接地址和累加器, 不相等转移 3 2 CJNE A,#data,rel 比较立即数和累加器, 不相等转移 3 2 CJNE Rn,#data,rel 比较寄存器和立即数, 不相等转移 2 2 比较立即数和间接 RAM, 不相等转移 3 2 DJNZ Rn,rel 寄存器减 1, 不为 0 则转移 3 2 DJNZ direct,rel 直接地址减 1, 不为 0 则转移 3 2 NOP 空操作, 用于短暂延时 1 1 ACALL add11 绝对调用子程序 2 2 LCALL add16 长调用子程序 3 2 RET 从子程序返回 1 2 RETI 从中断服务子程序返回 1 2 AJMP add11 无条件绝对转移 2 2 LJMP add16 无条件长转移 3 2 SJMP rel 无条件相对转移 2 2 ( 布尔指令 ) CLR C 清进位位 1 1 CLR bit 清直接寻址位 2 1 SETB C 置位进位位 1 1 SETB bit 置位直接寻址位 2 1 CPL C 取反进位位 1 1 CPL bit 取反直接寻址位 2 1 ANL C,bit 直接寻址位 与 到进位位 2 2 ANL C,/bit 直接寻址位的反码 与 到进位位 2 2 ORL C,bit 直接寻址位 或 到进位位 2 2 助记符 指令说明 字节数 周期数 ORL C,/bit 直接寻址位的反码 或 到进位位 2 2 MOV C,bit 直接寻址位传送到进位位 2 1 MOV bit, C 进位位位传送到直接寻址 2 2 JC rel 如果进位位为 1 则转移 2 2 JNC rel 如果进位位为 0 则转移 2 2 JB bit,rel 如果直接寻址位为 1 则转移 3 2 JNB bit,rel 如果直接寻址位为 0 则转移 3 2 JBC bit,rel 直接寻址位为 1 则转移并清除该位 2 2 助记符 指令说明 ( 伪指令 ) ORG DB DW EQU DATA 指明程序的开始位置定义数据表定义 16 位的地址表给一个表达式或一个字符串起名给一个 8 位的内部 RAM 起名 ww.zicreate.com

21 第三章 51 系列单片机汇编指令集 XDATA BIT END 给一个 8 位的外部 RAM 起名给一个可位寻址的位单元起名指出源程序到此为止 ( 指令中的符号标识 ) Rn 工作寄存器 R0-R7 Ri 工作寄存器 R0 和 间接寻址的 8 位 RAM 单元地址 (00H-FFH) #data8 8 位常数 #data16 16 位常数 addr16 16 位目标地址, 能转移或调用到 64KROM 的任何地方 addr11 11 位目标地址, 在下条指令的 2K 范围内转移或调用 Rel 8 位偏移量, 用于 SJMP 和所有条件转移指令, 范围 -128~+127 Bit 片内 RAM 中的可寻址位和 SFR 的可寻址位 Direct 直接地址, 范围片内 RAM 单元 (00H-7FH) 和 80H-FFH $ 指本条指令的起始位置

22 第 4 章 51 系列单片机 C 语言编程基础 4.1 ANSI C 和 Keil C C51 与标准 C 语言基本相同, 只有 Keil C51 扩展的一些数据类型不一样 表 4-1 ANSI C 中的关键字 关键字 用途 说明 auto 存储种类说明 用于说明局部变量, 缺省值为此 break 程序语句 退出最内层循环 case 程序语句 switch 语句中的选择项 char 数据类型说明 单字节整形数或字符型数据 const 存储类型说明 在程序执行过程中不可更改的常量值 continue 程序语句 转向下一次循环 default 程序语句 switch 语句中的失败选择项 do 程序语句 构成 do..while 结构 double 数据类型说明 双精度浮点数 else 程序语句 构成 if..else 选择语句 enum 数据类型说明 枚举 extern 存储种类说明 在其他程序模块中说明了的全局变量 float 数据类型说明 单精度浮点数 for 程序语句 构成 for 循环结构 goto 程序语句 构成 goto 转移结构 if 程序语句 构成 if..else 选择语句 int 数据类型说明 基本整型 long 数据类型说明 长整型数 register 存储种类说明 使用 cpu 内部寄存器的变量 return 程序语句 函数返回 short 数据类型说明 短整型数 signed 数据类型说明 有符号数, 二进制数据的最高位为符号位 sizeof 运算符 计算表达式或数据类型的字节数 static 存储种类说明 静态变量 struct 数据类型说明 结构类型数据 switch 程序语句 构成 switch 选择结构 typedef 数据类型说明 重新进行数据类型定义 union 数据类型说明 联合数据类型 unsigned 数据类型说明 无符号数据 void 数据类型说明 无类型数据 volatile 数据类型说明 该变量在程序执行中可被隐含的改变 while 程序语句 构成 while 和 do..while 结构 表 4-2 keil C51 中扩展的关键字 关键字 用途 说明 bit 位标量声明 声明一个位标量或位类型的函数 sbit 位标量声明 声明一个可位寻址的变量 sfr 特殊功能寄存器声明 声明一个特殊功能寄存器 sfr16 特殊功能寄存器声明 声明一个 16 位的特殊功能寄存器

23 第 4 章 51 系列单片机 C 语言编程基础 data 存储器类型说明直接寻址的内部数据存储器 bdata 存储器类型说明可位寻址的内部数据存储器 idata 存储器类型说明间接寻址的内部数据存储器 pdata 存储器类型说明分页寻址的外部数据存储器 xdata 存储器类型说明外部数据存储器 code 存储器类型说明程序存储器 interrupt 中断函数说明定义一个中断函数 reentrant 再入函数说明定义一个再入函数 using 寄存器组定义定义芯片的工作寄存器 4.1 C51 的数据类型 表 4-3 C51 的数据类型 数据类型长度值域 位型 bit 1 字节 0 或 1 字符型 signed char 1 字节 -128~+127 整形 unsigned char 1 字节 0~255 signed int 2 字节 ~ unsigned int 2 字节 0~65535 signed long 4 字节 ~ unsigned long 4 字节 0~ 实型 float 4 字节 ±1.176E-38~±3.40E+38 指针型 访问 SFR 的数据类型 data/idata/pdata 1 字节 1 字节地址 code/xdata 2 字节 2 字节地址 通用指针 3 字节其中 1 字节为存储器类型编码,2,3 字节为地址偏移量 sbit 1 位 0 或 1 sfr 1 字节 0~255 sfr16 2 字节 0~65535 编译的数据类型 ( 如结构 ) 包含上表所列的数据类型 由于 51 系列是 8 位机, 因而不存在字节校准问题 这意味着数据结构成员是顺序放置的 数据类型的转换 : 当计算结果隐含着另外一种数据类型时, 数据类型可以自动进行转换, 例如, 将一个位变量赋给一个整型变量时, 位型值自动转换为整型值, 有符号变量的符号也能自动进行处理 这些转换也可以用 C 语言的标准指令进行人工转换 4.2 C51 的存储器类型 C51 编译器完全支持 8051 微处理器及其系列的结构, 可完全访问 MCS-51 硬件系统所有部分 每个变量可准确地赋予不同的存贮器类型 (data,idata,pdata,xdata,code) 访问内部数据存贮器 (idata) 要比访问外部数据存贮器 (xdata) 相对要快一些, 因此, 可将经常使用的变量置于内部数据存贮器中, 而将较大及很少使用的数据单元置于外部数据存贮器中 存储器类型 data bdata idata pdata xdata code 1)DATA 区 表 4-4 C51 的存储器类型 描述 直接寻址内部数据存贮器, 访问变量速度最快 (128bytes) 可位寻址内部数据存贮器, 允许位与字节混合访问 (16 bytes) 间接寻址内部数据存贮器, 可访问全部地址空间 (256bytes) 分页 (256bytes) 外部数据存贮器, 由操作码 访问 外部数据存贮器 (64K), 由 访问 代码数据存贮器 (64K), 由 访问

24 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 对 DATA 区的寻址是最快的, 所以应该把使用频率高的变量放在 DATA 区, 由于空间有限, 必须注意使用 DATA 区,DATA 区除了包含程序变量外, 还包含了堆栈和寄存器组 DATA 区 unsigned char data system_status=0; unsigned int data unit_id[2]; char data inp_string[16]; float data outp_value; mytype data new_var; 在 SMALL 存储模式下, 未说明存储器类型时, 变量默认被定位在 DATA 区 标准变量和用户自定义变量都可以存储在 DATA 区, 只要不超过 DATA 区的范围 因为 C51 使用默认的寄存器组传递参数, 至少失去了 8B 另外要定义足够大的堆栈空间, 当内部堆栈溢出的时候, 程序会产生莫名其妙的错误, 实际原因是 80C51 系列单片机没有硬件报错机制, 堆栈溢出只能以这种方式表示出来 2)BDATA 区当在 DATA 区的位寻址区定义变量, 这个变量就可进行位寻址, 并且声明位变量 这对状态寄存器来说十分有用, 因为它可以单独使用变量的每一位, 而不一定要用位变量名引用位变量 下面是一些在 BDATA 区中声明变量和使用位变量的例子 unsigned char bdata status_byte; unsigned int bdata status_word; unsigned long bdata status_dword; sbit stat_flag=status_byte^4; if(status_word^15) stat_flag=1; 编译器不允许在 BDATA 区中定义 float 和 double 类型的变量, 如果想对浮点数的每位寻址, 可以通过包含 float 和 long 的联合实现 typedef union /* 定义联合类型 */ unsigned long lvalue; /* 长整型 32 位 */ float fvalue; /* 浮点数 32 位 */ bit_float; /* 联合名 */ bit_float bdata myfloat; /* 在 BDATA 区中声明联合 */ sbit float_ld=myfloat.lvalue^31; /* 定义位变量名 */ 3)IDATA 区 IDATA 区也可以存放使用比较频繁的变量, 使用寄存器作为指针进行寻址 在寄存器中设置 8 位地址进行间接寻址, 与外部存储器寻址比较, 它的指令执行周期和代码长度都比较短 unsigned char idata system_status=0; unsigned int idata unit_id[2]; char idata inp_string[16]; float idata outp_value; 4)PDATA 和 XDATA 区在这两个区声明变量和在其他区的语法是一样的,PDATA 区只有 256B, 而 XDATA 区可达 65536B, 举例如下 unsigned char xdata system_status=0; unsigned int pdata unit_id[2]; char xdata inp_string[16]; float pdata outp_value; 对 PDATA 和 XDATA 的操作是相似的, 对 PDATA 区寻址比对 XDATA 区寻址要快, 因为对 PDATA 区寻址只需要装入 8 位地址, 而对 XDATA 区寻址需装入 16 位地址 所以尽量把外部数据存储在 PDATA ww.zicreate.com

25 第 4 章 51 系列单片机 C 语言编程基础 区中, 对 PDATA 和 XDATA 寻址要使用 MOVX 指令, 需要 2 个处理周期 5)CODE 区 CODE 区即 80C51 的程序代码区, 所以代码区的数据是不可改变的,80C51 的代码区不可重写 一般代码区中可存放数据表, 跳转向量和状态表, 对 CODE 区的访问和对 XDATA 区的访问的时间是一样的, 代码区中的对象在编译时初始化, 否则就得不到想要的值 下面是代码区的声明例子 unsigned int code unit_id[2]=0x1234, 0x89ab; unsigned char code uchar_data[16] =0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15; 如果在变量说明时略去存贮器类型标志符, 编译器会自动选择默认的存贮器类型 默认的存贮器类型进一步由控制指令 SMALL COMPACT 和 LARGE 限制 例如 : 如果声明 char charvar, 则默认的存贮器模式为 SMALL,charvar 放在 data 存贮器 ; 如果使用 COMPACT 模式, 则 charvar 放入 idata 存贮区 ; 在使用 LARGE 模式的情况下,charvar 被放入外部存贮区或 xdata 存贮区 4.3 C51 的存储器模式 C51 编译器允许采用三种存储模式 : 小编译模式 SMALL 紧凑编译模式 COMPACT 大编译模式 LARGE 一个变量的存储器模式确定了变量在内存中的地址空间 在 SMALL 模式下, 该变量在 80C51 单片机的内部 RAM 中 ; 在 COMPACT 和 LARGE 模式下, 该变量在 80C51 单片机的外部 RAM 中 同样一个函数的存储器模式确定了函数的参数和局部变量在内存中的地址空间 在 SMALL 模式下, 函数的参数和局部变量在 80C51 单片机的内部 RAM 中 ; 在 COMPACT 和 LARGE 模式下, 函数的参数和局部变量在 80C51 单片机的外部 RAM 中 存贮器模式决定了自动变量和默认存贮器类型, 参数传递区和无明确存贮区类型的说明 在固定的存贮器地址变量参数传递是 C51 的一个标准特征, 在 SMALL 模式下参数传递是在内部数据存贮区中完成的 LARGRE 和 COMPACT 模式允许参数在外部存贮器中传递 C51 同时也支持混合模式, 例如在 LARGE 模式下生成的程序可将一些函数分页放入 SMALL 模式中从而加快执行速度 存贮器模式 SMALL COMAPCT LARGE 表 4-4 C51 的存储器模式 描述 参数及局部变量放入可直接寻址的内部寄存器 ( 最大 128bytes, 默认存贮器类型是 DATA) 参数及局部变量放入分页外内部存贮区 ( 最大 256bytes, 默认存贮器类型是 PDATA) 参数及局部变量直接放入外部数据存贮器 ( 最大 64K, 默认存贮器类型是 XDATA) SMALL,COMPACT,LARGE 这些指令控制存贮器模式选择 存贮器模式对不同的变量定义有所影响 SMALL: 所有函数和过程变量及局部数据段被定义在 8051 系统内部数据存贮器, 因此以这种模式访问数据对象是非常有效的 这种模式的缺点是地址空间有限 COMPACT: 所有函数和过程变量及局部数据段被定义在 8051 系统外部数据存贮器中, 这个存贮区可达 256 字节 (1 页 ) 这种模式使用访问外部数据存贮器的简洁形式 (@R0/R1) LARGE: 所有变量和局部变量数据段定义在 8051 系统的外部数据存贮器中, 可访问达 64K 字节的地址空间 因此, 它需要通过数据指针 (DPTR), 这是一种效率不高的数据访问形式 注意 : 调用子程序的栈始终放在内部存贮器中 4.4 C51 常用的库函数 C51 软件包的库包含标准的应用程序, 每个函数都在相应的头文件 (.h) 中有原型声明 如果使用库函数, 必须在源程序中用预编译指令定义与该函数相关的头文件 ( 包含了该函数的原型声明 ) 例如 : #include<at89x52.h> #include<intrins.h> 如果省掉头文件, 编译器则期望标准的 C 参数类型, 从而不能保证函数的正确执行 1.regxx.h/AT89X52.h: 访问 SFR 和 SFR-BIT 地址文件 reg51.h,reg52.h 和 reg552.h 允许访问 8051 系列的 SFR 和 SFR-bit 的地址, 这些文件都包含 #include 指令, 并定义了所需的所有 SFR 名以寻址 8051 系列的外围电路地址, 对于 8051 系列中其它一些器件, 用户可用文件编辑器很容易地产生一个.h 文件

26 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 2. intrins.h: 内部函数函数名 :_crol_,_irol_,_lrol_ 原型 :unsigned char _crol_(unsigned char val,unsigned char n); unsigned int _irol_(unsigned int val,unsigned char n); unsigned int _lrol_(unsigned int val,unsigned char n); 功能 :_crol_,_irol_,_lrol_ 以位形式将 val 左移 n 位, 该函数与 8051 RLA 指令相关, 上面几个函数不同于参数类型 函数名 :_cror_,_iror_,_lror_ 原型 :unsigned char _cror_(unsigned char val,unsigned char n); unsigned int _iror_(unsigned int val,unsigned char n); unsigned int _lror_(unsigned int val,unsigned char n); 功能 :_cror_,_iror_,_lror_ 以位形式将 val 右移 n 位, 该函数与 8051 RRA 指令相关, 上面几个函数不同于参数类型 函数名 :_nop_ 原型 :void _nop_(void); 功能 :_nop_ 产生一个 NOP 指令, 该函数可用作 C 程序的时间比较 C51 编译器在 _nop_ 函数工作期间不产生函数调用, 即在程序中直接执行了 NOP 指令 函数名 :_testbit_ 原型 :bit _testbit_(bit x); 功能 :_testbit_ 产生一个 JBC 指令, 该函数测试一个位, 当置位时返回 1, 否则返回 0 如果该位置为 1, 则将该位复位为 的 JBC 指令即用作此目的 _testbit_ 只能用于可直接寻址的位 ; 在表达式中使用是不允许的 3. math.h: 数学函数函数名 :abs,cabs,fabs,labs 原型 :extern int abs(int va1); extern char cabs(char val); extern float fabs(float val); extern long labs(long val); 功能 :abs 决定了变量 val 的绝对值, 如果 val 为正, 则不作改变返回 ; 如果为负, 则返回相反数 这四个函数除了变量和返回值的数据不一样外, 它们功能相同 函数名 :exp,log,log10 原型 :extern float exp(float x); extern float log(float x); extern float log10(float x); 功能 :exp 返回以 e 为底 x 的幂,log 返回 x 的自然数 (e= ),log10 返回 x 以 10 为底的数 函数名 :sqrt 原型 :extern float sqrt(float x); 功能 :sqrt 返回 x 的平方根 函数名 :rand,srand 原型 :extern int rand(void); extern void srand(int n); 功能 :rand 返回一个 0 到 之间的伪随机数 srand 用来将随机数发生器初始化成一个已知 ( 或期望 ) 值, 对 rand 的相继调用将产生相同序列的随机数 函数名 :cos,sin,tan 原型 :extern float cos(flaot x); extern float sin(flaot x); ww.zicreate.com

27 第 4 章 51 系列单片机 C 语言编程基础 extern flaot tan(flaot x); 功能 : cos 返回 x 的余弦值 Sin 返回 x 的正弦值 tan 返回 x 的正切值, 所有函数变量范围为 -π/ 2~+π/2, 变量必须在 ±65535 之间, 否则会产生一个 NaN 错误 函数名 :acos,asin,atan,atan2 原型 :extern float acos(float x); extern float asin(float x); extern float atan(float x); extern float atan(float y,float x); 功能 : acos 返回 x 的反余弦值,asin 返回 x 的正弦值,atan 返回 x 的反正切值, 它们的值域为 -π /2~+π/2 atan2 返回 x/y 的反正切, 其值域为 -π~+π 函数名 :cosh,sinh,tanh 原型 :extern float cosh(float x); extern float sinh(float x); extern float tanh(float x); 功能 : cosh 返回 x 的双曲余弦值 ;sinh 返回 x 的双曲正弦值 ;tanh 返回 x 的双曲正切值 函数名 : fpsave,fprestore 原型 :extern void fpsave(struct FPBUF *p); extern void fprestore (struct FPBUF *p); 功能 : fpsave 保存浮点子程序的状态 fprestore 将浮点子程序的状态恢复为其原始状态, 当用中断程序执行浮点运算时这两个函数是有用的 4. stdlib.h: 标准函数函数名 : atof 原型 : extern double atof(char *s1); 功能 : atof 将 s1 串转换为浮点值并返回它 输入串必须包含与浮点值规定相符的数 C51 编译器对数据类型 float 和 double 相同对待 函数名 : atol 原型 : extern long atol(char *s1); 功能 : atol 将 s1 串转换成一个长整型值并返回它 输入串必须包含与长整型值规定相符的数 函数名 : atoi 原型 : extern int atoi(char *s1); 功能 : atoi 将 s1 串转换为整型数并返回它 输入串必须包含与整型数规定相符的数 5. absacc.h: 绝对地址访问函数名 : CBYTE,DBYTE,PBYTE,XBYTE 原型 : #define CBYTE((unsigned char *)0x50000L) #define DBYTE((unsigned char *)0x40000L) #define PBYTE((unsigned char *)0x30000L) #define XBYTE((unsigned char *)0x20000L) 功能 : 上述宏定义用来对 8051 地址空间作绝对地址访问, 因此, 可以字节寻址 CBYTE 寻址 CODE 区,DBYTE 寻址 DATA 区,PBYTE 寻址 XDATA 区 ( 通过 命令 ),XB YTE 寻址 XDATA 区 ( 通过 命令 ) 例 : 下列指令在外存区访问地址 0x1000 xval=xbyte[0x1000]; XBYTE[0X1000]=20; 通过使用 #define 指令, 用符号可定义绝对地址, 如符号 X10 可与 XBYTE[0x1000] 地址相等 :#defi ne X10 XBYTE[0x1000] 函数名 : CWORD,DWORD,PWORD,XWORD

28 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 原型 : #define CWORD((unsigned int *)0x50000L) #define DWORD((unsigned int *)0x40000L) #define PWORD((unsigned int *)0x30000L) #define XWORD((unsigned int *)0x20000L) 功能 : 这些宏与上面相似, 只是它们指定的类型为 unsigned int 通过灵活的数据类型, 所有地址空间都可以访问 4.5 C51 的基本语句一 if 语句用 if 语句可以构成分支结构 它根据给定的条件进行判断, 以决定执行某个分支程序段 C 语言的 if 语句有三种基本形式 1. 第一种形式为基本形式 :if if( 表达式 ) 语句其语义是 : 如果表达式的值为真, 则执行其后的语句, 否则不执行该语句 2. 第二种形式为 : if-else if( 表达式 ) 语句 1; else 语句 2; 其语义是 : 如果表达式的值为真, 则执行语句 1, 否则执行语句 2 3. 第三种形式为 if-else-if 形式前二种形式的 if 语句一般都用于两个分支的情况 当有多个分支选择时, 可采用 if-else-if 语句, 其一般形式为 : if( 表达式 1) 语句 1; else if( 表达式 2) 语句 2; else if( 表达式 3) 语句 3; else if( 表达式 m) 语句 m; else 语句 n; 其语义是 : 依次判断表达式的值, 当出现某个值为真时, 则执行其对应的语句 然后跳到整个 if 语句之外继续执行程序 如果所有的表达式均为假, 则执行语句 n 然后继续执行后续程序 二 switch 语句 C 语言还提供了另一种用于多分支选择的 switch 语句, 其一般形式为 : switch( 表达式 ) case 常量表达式 1: 语句 1; case 常量表达式 2: 语句 2; case 常量表达式 n: 语句 n; default : 语句 n+1; 其语义是 : 计算表达式的值 并逐个与其后的常量表达式值相比较, 当表达式的值与某个常量表达 ww.zicreate.com

29 第 4 章 51 系列单片机 C 语言编程基础 式的值相等时, 即执行其后的语句, 然后不再进行判断, 继续执行后面所有 case 后的语句 如表达式的值与所有 case 后的常量表达式均不相同时, 则执行 default 后三 while/do while 语句 while 语句的一般形式为 : while( 表达式 ) 语句其中表达式是循环条件, 语句为循环体 while 语句的语义是 : 计算表达式的值, 当值为真 ( 非 0) 时, 执行循环体语句 do-while 语句的一般形式为 : do 语句 while( 表达式 ); 这个循环与 while 循环的不同在于 : 它先执行循环中的语句, 然后再判断表达式是否为真, 如果为真则继续循环 ; 如果为假, 则终止循环 因此, do-while 循环至少要执行一次循环语句 四 for 语句在 C 语言中,for 语句使用最为灵活, 它完全可以取代 while 语句 它的一般形式为 : for( 表达式 1; 表达式 2; 表达式 3) 语句它的执行过程如下 : 1) 先求解表达式 1 2) 求解表达式 2, 若其值为真 ( 非 0), 则执行 for 语句中指定的内嵌语句, 然后执行下面第 3) 步 ; 若其值为假 (0), 则结束循环, 转到第 5) 步 3) 求解表达式 3 4) 转回上面第 2) 步继续执行 5) 循环结束, 执行 for 语句下面的一个语句 for 语句最简单的应用形式也是最容易理解的形式如下 : for( 循环变量赋初值 ; 循环条件 ; 循环变量增量 ) 语句循环变量赋初值总是一个赋值语句, 它用来给循环控制变量赋初值 ; 循环条件是一个关系表达式, 它决定什么时候退出循环 ; 循环变量增量, 定义循环控制变量每循环一次后按什么方式变化 这三个部分之间用 ; 分开 五 break 和 continue 语句 break 语句通常用在循环语句和开关语句中 当 break 用于开关语句 switch 中时, 可使程序跳出 switch 而执行 switch 以后的语句 ; 如果没有 break 语句, 则将成为一个死循环而无法退出 break 在 switch 中的用法已在前面介绍开关语句时的例子中碰到, 这里不再举例 当 break 语句用于 do-while for while 循环语句中时, 可使程序终止循环而执行循环后面的语句, 通常 break 语句总是与 if 语句联在一起 即满足条件时便跳出循环 注意 : 1) break 语句对 if-else 的条件语句不起作用 2) 在多层循环中, 一个 break 语句只向外跳一层 continue 语句的作用是跳过循环本中剩余的语句而强行执行下一次循环 continue 语句只用在 for while do-while 等循环体中, 常与 if 条件语句一起使用, 用来加速循环

30 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 5.1 AT89S52 单片机的通用 I/O 口 C 语言编程 AT89S52 单片机的 I/O 口 1.AT89S52 单片机 I/O 口功能表 5-1 AT89S52 单片机 I/O 口功能 端口 引脚位置 第一功能 第二功能 符号功能符号功能 P0 39~32 P0.0~P0.7 通用 I/O 口 AD0~AD7 地址 / 数据总线低 8 位 P1 1 P1.0 T2 定时器 / 计数器 T2 的外部计数输入, 时钟输出 2 P1.1 T2EX 定时器 / 计数器 T2 的捕捉 / 重载触发信号和方向控制 3~5 P1.2~P1.4 通用 I/O 口 6 P1.5 MOSI 主机 (master) 输出 从机 (slave) 输入 7 P1.6 MISO 主机 (master) 输出 从机 (slave) 输入 8 P1.7 SCK 串行时钟信号 P2 21~28 P2.0~P2.7 通用 I/O 口 A8~A15 地址总线高 8 位 P3 10 P3.0 RXD 串行口输入 11 P3.1 TXD 串行口输出 12 P3.2 INT 0 外部中断 0 输入 13 P3.3 通用 I/O 口 INT 1 外部中断 1 输入 14 P3.4 T0 定时 / 计数器 0 的外部输入 15 P3.5 T1 定时 / 计数器 1 的外部输入 16 P3.6 WR 片外数据存储器 I/O 口写选通 17 P3.7 RD 片外数据存储器 I/O 口读写选通 2.AT89S52 单片机 I/O 端口的驱动能力 89S52 直接驱动负载时每个端口可驱动的最大灌电流负载 (IOL) 为 10mA; 每组端口 8 个引脚的总灌电流负载驱动能力为 P0 口 26 ma,p1~p3 口每组 15 ma;4 组 (P0,P1,P2,P3) 端口 32 个引脚的总灌电流负载驱动能力为 71 ma 89S52 驱动其他器件时,P0 口可驱动 8 个 LS TTL 负载, 其他端口可驱动 4 个 LS TTL 负载 外部端口用做通用 I/O 口时, 应当注意以下问题 : 由于 P0 口用做 I/O 口时为 OC 输出, 输出 1 时实际为开路状态, 如果需要驱动 CMOS 或 TTL 器件, 必须接上拉电阻 许多单片机系统中 89S52 的 P0 口旁都有一只 9 脚排阻, 它一般都是 P0 口的上拉电阻 端口用做输入时, 必须先向端口写 1 系统复位后所有外部端口状态为 AT89S52 单片机控制 LED 流水灯 AT89S52 控制 LED 流水灯的电路图如图 5-1 所示 AT89S52 控制 LED 流水灯的 C 语言程序如下所示 : /********************************************************************** * 程序名 ; LED 流水灯实验 ( 晶振 MHZ) * 功 能 : LED 灯从上至下依次点亮,1 秒循环一遍 十秒后从下至上依次点亮 * 1 秒循环一遍 如此循环往复 * 编程者 : ZPZ * 编程时间 :2008/10/4 **********************************************************************/ #include<reg52.h> // 包含头文件 #include <intrins.h> #define LED_Data P2 // 定义 LED 数据端口 #define uchar unsigned char // 宏定义

31 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 sbit smg1=p1^0; // 定义数码管端口 sbit smg2=p1^1; uchar a=0xfe,num0=0,num1=0,ge=0,shi=0;// 定义变量 uchar table[10]=0xc0,0xf9,0xa4,0xb0,0x99, // 定义显示段码表 0x92,0x82,0xf8,0x80,0x90; 图 5-1 LED 流水灯电路图 /********************************** 函数名 :delay 功能 : 延时 1ms 左右参数 :z 返回值 : 无 ***********************************/ void delay(uchar z) // 延时 1ms 左右 unsigned char j,k ; for (j=z;j>0;j--) for(k=120;k>0;k--); /********************************** 函数名 :timer0_init 功能 :T0 初始化函数参数 :f 返回值 : 无 ***********************************/ void timer0_init(bit f) TMOD=0x01; // 定时器 0 工作在方式 1 TH0=0x1f; // 定时器赋初值 62.5ms TL0=0x00; ET0=1; // 开 T0 中断 EA=1; // 开总中断

32 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 TR0=f; //f 为 1 启动定时器 0, 为 0 禁止定时器 0 /********************************** 函数名 :display 功能 : 显示函数参数 :qian,bai,shi,ge 返回值 : 无 ***********************************/ void display(uchar shi,uchar ge) smg1=0; // 选通第一个数码管 smg2=1; // 关断另一个 P0=table[ge];// 个位送显示 delay(5); smg1=1; smg2=0; P0=table[shi];// 十位送显示 delay(5); /********************************** 函数名 :main 功能 : 主函数参数 : 无返回值 : 无 ***********************************/ void main() bit i=0; // 定义一个位变量 smg1=1; // 熄灭数码管 smg2=1; LED_Data = 0xff; // 熄灭所有 LED 灯 timer0_init(1); // 初始化定时器 0 while(1) // 主循环 if(num0>15) // 定时 1 秒到时个位加 1 num0=0; ge++; if(ge>9) // 如果各位大于 9, 个位清 0 十位加 1 ge=0; shi++; if(shi>5) shi=0; i=~i; display(shi,ge); if(num1>1) num1=0; if(i==0) a=_crol_(a,1); if(i==1) a=_cror_(a,1); LED_Data=a; // 如果十位大于 5, 十位清 0,LED 灯反向循环点亮 // 使 LED 循环左移 // 使 LED 循环右移 // 点亮相应的 LED 灯

33 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 /********************************** 函数名 :timer0 功能 : 定时器 0 中断函数参数 : 无返回值 : 无 ***********************************/ void timer0() interrupt 1 TH0=0x1f; // 重赋初值 TL0=0x00; num0++; //num0 加 1 num1++; //num1 加 AT89S52 单片机控制蜂鸣器 AT89S52 控制蜂鸣器的电路图如图 5-2 所示 图 5-2 AT89S52 控制蜂鸣器电路图 AT89S52 控制蜂鸣器的 C 语言程序如下所示 : /********************************************************************** * 程序名 ; 蜂鸣器实验 ( 晶振 MHZ) * 功能 : 蜂鸣器响 1s 停 1s * 编程者 : ZPZ * 编程时间 :2008/9/4 **********************************************************************/ #include<reg52.h> // 包含头文件 #define uchar unsigned char // 宏定义 #define uint unsigned int sbit buzzer=p3^3; // 定义数码管端口 uchar num=0; /********************************** 函数名 :timer0_init 功能 :T0 初始化函数参数 :f 返回值 : 无 ***********************************/ void timer0_init(bit f) TMOD=0x01; // 定时器 0 工作在方式 1 TH0=0x3c; // 定时器赋初值 50ms TL0=0xb0; ET0=1; // 开 T0 中断 EA=1; // 开总中断 TR0=f; //f 为 1 启动定时器 0, 为 0 禁止定时器

34 /********************************** 函数名 :main 功能 : 主函数参数 : 无返回值 : 无 ***********************************/ void main() buzzer=1; // 关蜂鸣器 timer0_init(1); // 初始化定时器 0 while(1); // 无限循环等待中断 /********************************** 函数名 :timer0 功能 : 定时器 0 中断函数参数 : 无返回值 : 无 ***********************************/ void timer0() interrupt 1 TH0=0x3c; // 重赋初值 TL0=0xb0; num++; //num 加 1 if(num>20) // 定时 1s num=0; buzzer=~buzzer; // 蜂鸣器响 1s 停 1s AT89S52 单片机控制 DC5V 继电器 AT89S52 控制继电器的电路图如图 5-3 所示 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 ww.zicreate.com 图 5-3 AT89S52 控制继电器电路图 AT89S52 控制继电器的 C 语言程序如下所示 : /********************************************************************** * 程序名 ; 继电器控制实验 * 功能 :K1 按下继电器吸合,K2 按下继电器断开 * 编程者 :ZPZ * 编程时间 :2008/9/10 **********************************************************************/ #include<reg52.h> // 包含头文件

35 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 #define uchar unsigned char // 宏定义 #define uint unsigned int sbit key1=p3^2; // 定义键盘口 sbit key2=p3^3; sbit relay=p3^0; // 定义继电器控制口 /********************************** 函数名 :delay 功能 : 延时 1ms 左右参数 :z 返回值 : 无 ***********************************/ void delay(uint z) uint i,j; // 定义局部变量 for(i=z;i>0;i--) // 循环 for(j=120;j>0;j--); // 循环 /******************************************* 函数名 : key_scan() 功能 : 键盘扫描函数参数 : 无返回值 : 无 /********************************************/ void key_scan() if(key1==0) // 判断 k1 是否按下 delay(10); // 延时消抖 if(key1==0) // 再次判断 k1 是否按下 relay=0; // 继电器吸合 while(key1==0); // 判断 k1 是否松开 if(key2==0) // 判断 k2 是否按下 delay(10); // 延时消抖 if(key2==0) // 再次判断 k2 是否按下 relay=1; // 继电器断开 while(key2==0); // 判断 k2 是否松开 /******************************************* 函数名 : main 功能 : 主函数参数 : 无返回值 : 无 /********************************************/ void main() relay=1; // 断开继电器 while(1) key_scan(); // 键盘扫描

36 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 5.2 AT89S52 单片机的中断系统介绍中断源就是向 CPU 发出中断请求的来源 AT89S52 共有六个中断源 :2 个外部中断 (INT0 和 INT1) 3 个定时器中断 ( 定时器 0 1 和 2) 和 1 个串行中断 1. 外部中断外部中断包括外部中断 0 和外部中断 1 它们的中断请求信号分别由单片机引脚 INT 0 /P3.2 和 INT 1/P3.3 输入 外部中断请求有两种信号方式 : 电平方式和脉冲方式 电平方式的中断请求信号是低电平有效, 即只要在 INT 0 或 INT 1引脚上出现低电平时, 就激活外部中断标志 脉冲方式的中断请求信号则是脉冲的负跳变有效 在这种方式下, 在两个相邻机器周期内, INT 0 或 INT 1引脚电平状态发生变化, 即在第一个机器周期内位为高电平, 第二个机器周期内为低电平, 就激活外部中断标志 2. 内部定时和外部计数中断单片机芯片内部有三个定时器 / 计数器, 对脉冲信号进行计数 若脉冲信号为内部振荡器输出的脉冲 ( 机器周期信号 ), 则计数脉冲的个数反映了时间的长短, 称为定时方式 若脉冲信号为来自 T0/P3.4 T1/P3.5 T2/P1.0 的外部脉冲信号, 则计数脉冲的个数仅仅反映外部脉冲输入的多少, 称为计数方式 当定时器 / 计数器发生溢出 ( 计算器状态由 FFFFH 再加 1, 变为 0000H 状态 ),CPU 查询到单片机内部硬件自动设置的一个溢出标志位为 1 时, 便激活中断 定时方式中断由单片机芯片内部发生, 不需要在芯片外部设置引入端 计数方式中断外部输入脉冲 ( 负跳变 ) 引起, 脉冲加在引脚 T0/P3.4 T1/P3.5 T2/P1.0 端 3. 串行中断串行中断是为串行通信的而需要设置的 当串行口发送完或接收完一帧信息时, 单片机内部硬件便自动串行发送或接收中断标志位置 1 当 CPU 查询到这些标志位为 1 时, 便激活串行中断 串行中断是由单片机内部自动发生的, 不需要在芯片外设置引入脚 4. 中断矢量地址 ww.zicreate.com 表 5-2 中断源及其对应的矢量地址 中断源中断标志位中断矢量地址 外部中断 0( INT 0 ) IE0 0003H 定时器 0(T0) 中断 TF0 000BH 外部中断 1( INT 1) IE1 0013H 定时器 1(T1) 中断 TF1 001BH 串行口中断 定时器 2(T2) 中断 发送中断 接收中断 T2 溢出中断 T2EX 中断 TI RI TF2 EXF2 0023H 002BH 由于两个相邻的中断服务程序入口地址间隔仅为 8 字节, 一般的中断服务程序是容纳不下的 通常是在相应的中断服务程序入口地址中放一条长跳转指令 LJMP, 这样就可以转到 64KB 的任何可用区域了 若在 2KB 范围内转移, 则可存放 AJMP 指令 由于 0003H~002BH 是中断矢量地址区, 因此, 单片机应在程序入口地址 0000H 处放一条无条件转移指令 ( 如 LJMP XXXXH), 转到指定的主程序地址 5. 中断优先级中断优先级只有高低两级, 所以在工作过程中必然会有两个或两个以上中断源处于同一中断优先级 若出现这种情况, 内部中断系统对各中断源的处理遵循以下两条基本原则 : 1) 低优先级中断可以被高优先级中断所中断, 反之不能 ; 2) 一种中断 ( 不管是什么优先级 ) 一旦得到响应, 与它同级的中断不能再中断它 当 CPU 同时收到几个同一优先级的中断请求时,CPU 将按自然优先级顺序确定应该响应哪个中断请

37 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 求 其自然优先级排列如下 : 中断源外部中断 0 定时器 0 中断外部中断 1 定时器 1 中断串行口中断定时器 2 中断 同级自然优先级最高级 最低级 6. 中断系统的 C 语言编程基础 AT89S52 的中断系统十分重要,C51 编译器允许在 C 语言源程序中声明中断和编写中断服务程序, 从而减轻了采用汇编程序编写中断服务程序的繁琐程度 通过使用 interrupt 关键字来实现 定义中断服务程序的一般格式如下 : void 函数名 ( ) interrupt n [using m] 关键字 interrupt 后面的 n 是中断号,n 的取值范围 :0~31 编译程序从 8n+3 处产生中断向量, 即在程序存储器 8n+3 地址处形成一条长跳转指令, 转向中断号 n 的中断服务程序 中断号对应着 IE 寄存器中的使能位, 即 :IE 寄存器中的 0 位对应着外部中断 0, 相应的外部中断 0 的中断号是 0 中断号 0~ 5 对应中断源的关系如表所示 表 5-3 中断号和中断源的对应关系 中断号中断源中断向量 0 外部中断 H 1 定时器 0 000BH 2 外部中断 H 3 定时器 1 001BH 4 串行口 0023H 5 定时器 2 002BH using m 指明该中断服务程序所对应的工作寄存器组, 取值范围 :0~3 指定工作寄存器组的缺点是所有被中断调用的过程都必须使用同一个寄存器组, 否则参数传递会发生错误 通常不设定 using m, 除非保证中断程序中未调用其他子程序 使用 C51 编写中断服务程序, 程序员无需关心 ACC B DPH DPL PSW 等寄存器的保护,C51 编译器会根据上述寄存器的使用情况在目标代码中自动增加压栈和出栈 5.3 AT89S52 单片机的外部中断 C 语言编程 AT89S52 单片机外部中断相关功能寄存器与外部中断相关的功能寄存器如下 : 中断允许寄存器 IE D7 D6 D5 D4 D3 D2 D1 D0 EA -- ET2 ES ET1 EX1 ET0 EX0 EA: 当 EA=1 时 CPU 开总中断, 当 EA=0 时 CPU 关总中断 EX1 EX0: 外部中断允许控制位 为 1 时允许外部中断 中断优先级寄存器 IP D7 D6 D5 D4 D3 D2 D1 D PT2 PS PT1 PX1 PT0 PX0 PX1 PX0: 外部中断优先级设定位 置 1 时为高优先级

38 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 定时器 0 1 控制寄存器 TCOD D7 D6 D5 D4 D3 D2 D1 D0 TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 IT1 IT0: 外部中断触发方式位 设置为 0 时为电平触发, 设置为 1 时为边沿触发 AT89S52 单片机外部中断 C 语言编程实例 AT89S52 单片机外部中断电路原理图如图 5-4 所示 : ww.zicreate.com 图 5-4 外部中断的电路原理图 AT89S52 单片机外部中断 C 语言程序如下所示 : /********************************************************************** * 程序名 : 外部中断实验 ( 晶振 MHZ) * 功能 : 当按键 k1 按下触发外部中断 0, 数码管开始显示 00~99 加计数, 当按下 * k2 时, 数码管开始显示 99~00 减计数 * 编程者 :ZPZ * 编程时间 :2008/9/14 **********************************************************************/ #include<at89x52.h> // 包含头文件 #define uchar unsigned char // 宏定义 #define uint unsigned int #define data_bus P0 // 定义显示数据口 char counter=0; // 定义一个全局变量 uchar t_f=0; // 定义全局变量用于定时 1s bit f=0; // 数加 1 数减 1 转换标志位 f=0 加计数,f=1 减计数 sbit wei1=p1^1; // 定义位选口

39 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 sbit wei2=p1^0; sbit k1=p3^2; // 定义中断口 sbit k2=p3^3; uchar code table[]= 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,;// 定义显示断码表 0~9 /***************************************** 函数名 :delay 功能 : 延时 1ms 左右参数 :z 返回值 : 无 ******************************************/ void delay(uint z) uint i,j; // 定义局部变量 for(i=z;i>0;i--) // 循环 for(j=120;j>0;j--); // 循环 /***************************************** 函数名 :int0_1_init 功能 : 延时 1ms 左右参数 :z 返回值 : 无 ******************************************/ void int0_1_init() PX0=1; //int0 中断为高优先级 PX1=0; //int1 中断为低优先级 PT1=0; // 定时器 1 为低优先级 EX0=1; // 开 int0 中断 EX1=1; // 开 int1 中断 EA=1; // 开总中断 IT0=1; //int0 边沿触发 IT1=1; //int1 边沿触发 /***************************************** 函数名 :timer1_init 功能 : 定时器 1 初始化参数 :f 返回值 : 无 ******************************************/ void timer1_init(bit f) TMOD=0x10; // 定时器 1 工作在方式 1 TH1=0x3c; // 初值 30ms TL1=0xb0; ET1=1; // 开定时器 1 中断 EA=1; // 开总中断 TR1=f; //f=1 启动定时器 1,f=0 关闭定时器 1 /***************************************** 函数名 :display 功能 : 显示函数参数 :shi,ge 返回值 : 无 *******************************************/ void display(uchar shi,uchar ge) wei1=0; wei2=1; // 选通第一个数码管关断另一个 data_bus=table[shi]; // 送要显示的段码

40 delay(2); wei2=0; wei1=1; data_bus=table[ge]; delay(2); 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 // 选通第二个数码管 / 关断另一个 // 送要显示的段码 /******************************************* 函数名 : main 功能 : 主函数参数 : 无返回值 : 无 /*******************************************/ void main () int0_1_init(); // 初始化外部中断 timer1_init(1); // 初始化定时器 1 while(1) // 主循环 display(counter/10,counter%10); // 显示键值 /******************************************* 函数名 : int0 功能 : 外部中断 0 中断函数参数 : 无返回值 : 无 /*******************************************/ void int0() interrupt 0 using 0 f=0; //f 清 0 减计数 /******************************************* 函数名 : int1 功能 : 外部中断 1 中断函数参数 : 无返回值 : 无 /*******************************************/ void int1() interrupt 2 using 2 f=1; //f 置 1 加计数 /******************************************* 函数名 : timer1 功能 : 定时器 1 中断函数参数 : 无返回值 : 无 /*******************************************/ void timer1() interrupt 3 using 3 TH1=0x3c; // 定时器重赋初值 TL1=0xb0; t_f++; //t_f 加 1 加到 20 定时 1s if(t_f==20) t_f=0; //1s 时间到 t_f 清 0 if(f==0) // 如果 f=0 加计数 ww.zicreate.com

41 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 counter++; if(counter>99) counter=0; else // 否则减计数 counter--; if(counter<0) counter=99; 5.4 AT89S52 单片机的定时 / 计数器 C 语言编程 与定时 / 计数器相关的功能寄存器中断允许寄存器 IE D7 D6 D5 D4 D3 D2 D1 D0 EA -- ET2 ES ET1 EX1 ET0 EX0 EA: 当 EA=1 时 CPU 开总中断, 当 EA=0 时 CPU 关总中断 ET2 ET1 ET0: 定时器中断允许控制位 为 1 时允许中断 中断优先级寄存器 IP D7 D6 D5 D4 D3 D2 D1 D PT2 PS PT1 PX1 PT0 PX0 PT2 PT1 PT0: 定时器优先级设定位 置 1 时为高优先级 定时器 0 1 方式控制寄存器 TMOD D7 D6 D5 D4 D3 D2 D1 D0 GATE C/T M1 M0 GATE C/T M1 M0 T1 T0 GATE: 门控位 当 GATE=0 时, 只利用控制位 TR0 或 TR1 来控制定时器的启停 当 GATE=1 时, 定时器的启停由外部中断引脚和控制位 TR0 或 TR1 来共同控制 C/T : 功能选择位 当 C/T =0 时, 设定为定时器工作方式 当 C/T =1 时, 设定为计数器工作方式 M1 M0: 工作模式控制位 表 5-4 定时器 0 1 工作模式设定 M1 M0 工作方式功能简述 0 0 模式 0 13 位计数器,TLi 只用低 5 位 0 1 模式 1 16 位计数器 1 0 模式 2 8 位自动重装计数器 仅 TLi 作为计数器,THi 的值不变 TLi 溢出, THi 中的值自动装入 TLi 中. 1 1 模式 3 T0 分为两个独立的 8 位计数器 计数初值的计算 : Tc 计数值 其中 Tc是定时时间, T T p p 12 f osc 是机器周期 f Tc 计数初值 X M 计数值 M M (TC fosc) / 12 T 定时器 2 方式控制寄存器 T2MOD p osc 是振荡频率 D7 D6 D5 D4 D3 D2 D1 D T2OE DCED T2OE: 定时器 2 输出允许位 DCED: 置 1 后, 定时器 2 可配置成向上 / 向下计数

42 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 定时器 0 1 控制寄存器 TCOD D7 D6 D5 D4 D3 D2 D1 D0 TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 TF1 TF0: 分别为定时器 1 和定时器 0 的溢出标志 溢出后由硬件置 1, 并申请中断 TR1 TR0: 分别为定时器 1 和定时器 0 的启停控制位 置 1 启动, 清 0 停止 定时器 2 控制寄存器 T2COD D7 D6 D5 D4 D3 D2 D1 D0 TF2 EXF2 RCLK TCLK EXEN2 TR2 C/ T 2 CP/ RL 2 TF2: 定时器 2 溢出标志位 必须软件清 0 当 RCLK=1 或 TCLK=1 时 TF2 不用置位 EXF2: 定时器 2 外部标志位 EXEN2=1 时,T2EX 上的负跳变而出现捕捉或重载时,EXF2 会被硬件置位 定时器 2 打开,EXF2=1 时, 将引导 CPU 执行定时器 2 中断程序 EXF2 必须如见清 0 在向下 / 向上技术模式 (DCEN=1) 下 EXF2 不能引起中断 RCLK: 串行口接收数据时钟标志位 若 RCLK=1, 串行口将使用定时器 2 溢出脉冲作为串行口工作模式 1 和 3 的串口接收时钟 ;RCLK=0, 将使用定时器 1 计数溢出作为串口接收时钟 TCLK: 串行口发送数据时钟标志位 若 TCLK=1, 串行口将使用定时器 2 溢出脉冲作为串行口工作模式 1 和 3 的串口发送时钟 ;TCLK=0, 将使用定时器 1 计数溢出作为串口发送时钟 EXEN2: 定时器 2 外部允许标志位 当 EXEN2=1 时, 如果定时器 2 没有用作串行时钟,T2EX(P1.1) 的负跳变见引起定时器 2 捕捉和重载 若 EXEN2=0, 定时器 2 将视 T2EX 端的信号无效 TR2: 开始 / 停止控制定时器 2 TR2=1, 定时器 2 开始工作 C/ T 2 : 定时器 2 定时 / 计数选择标志位 C/ T 2 =0, 定时 ;C/ T 2 =1, 外部事件计数 ( 下降沿触发 ) CP/ RL 2 : 捕捉 / 重载选择标志位 当 EXEN2=1 时,CP/ RL2 =1,T2EX 出现负脉冲, 会引起捕捉操作 ; 当定时器 2 溢出或 EXEN2=1 时 T2EX 出现负跳变, 都会出现自动重载操作 CP/ RL2 =0 将引起 T2EX 的负脉冲 当 RCKL=1 或 TCKL=1 时, 此标志位无效, 定时器 2 溢出时, 强制做自动重载操作 定时 / 计数器中断 C 语言编程实例 AT89S52 单片机定时 / 计数器中断电路原理图如图所示 : ww.zicreate.com

43 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 图 5-5 定时器中断的电路原理图 AT89S52 单片机定时 / 计数器中断 C 语言程序实例如下所示 : /********************************************************************** * 程序名 ; 时钟实验 1 * 功能 : 数码管通过动态扫描显示时间, 时间可设定, 调整时间时时钟不走 ; * 定时器 0 用于设定 1s 定时, 定时器 1 用于设定调节时间时时间的闪烁 ; * k1 用于进入和退出时间调节模式,k2 时间加 1,k3 时间减 1 * 编程者 : ZPZ * 编程时间 :2008/10/9 **********************************************************************/ #include<reg52.h> // 包含头文件 #define uint unsigned int // 变量类型宏定义 #define uchar unsigned char sbit led=p2^7; // 定义 LED 等端口 sbit key1=p2^0; // 定义键盘端口 sbit key2=p2^1; sbit key3=p2^2; uchar num=0,temp=0,count=0; // 定义全局变量 uchar aa; uchar hour,min,sec; uchar code table[]=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90;// 定义显示断码表 ( 共阳 ) /***************************************** 函数名 :delay 功能 : 延时 1ms 左右参数 :z 返回值 : 无 ******************************************/ void delay(uint z) uint i,j; for(i=z;i>0;i--) for(j=120;j>0;j--); // 定义局部变量 // 循环 // 循环 /***************************************** 函数名 :display 功能 : 显示函数参数 :a,b,c,d,e,f,aa 返回值 : 无 *******************************************/ void display(uchar a,uchar b,uchar c,uchar d,uchar e,uchar f,uchar aa) if(num==1)p1=0x01&aa;p0=a;delay(2);elsep1=0x01;p0=a;delay(2); // 时的十位显示 if(num==1)p1=0x02&aa;p0=b;delay(2);elsep1=0x02;p0=b;delay(2); // 时的个位显示 if(num==2)p1=0x04&aa;p0=c;delay(2);elsep1=0x04;p0=c;delay(2); // 分的十位显示 if(num==2)p1=0x08&aa;p0=d;delay(2);elsep1=0x08;p0=d;delay(2); // 分时的个位显示 if(num==3)p1=0x10&aa;p0=e;delay(2);elsep1=0x10;p0=e;delay(2); // 秒时的十位显示 if(num==3)p1=0x20&aa;p0=f;delay(2);elsep1=0x20;p0=f;delay(2); // 秒时的个位显示 /***************************************** 函数名 :read_key 功能 : 读按键函数参数 : 无返回值 : 无 *******************************************/ void read_key()

44 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 if(key1==0) // 如果 K1 按下 delay(10); // 延时消抖 if(key1==0) // 再次判断 K1 是否按下 while(1) //K1 若按下进入时间调节主循环 if(key1==0) // 在调节主循环中判断 K1 是否按下 led=0; // 有按键按下点亮 LED 灯 delay(10); // 延时消抖 if(key1==0) // 再次判断 K1 是否按下 num++; //K1 若按下, 按一次 num 值加 1 if(num>3)num=0;break; // 如果 num 值大于 3 则 num 值清 0, 退出循环 while(~key1); // 送按键消抖 led=1; // 按键松开熄灭 LED 灯 if(key2==0) // 判断 K2 是否按下 led=0; delay(10); if(key2==0) if(num==1)hour++;if(hour==24)hour=0;// 小时加 1 if(num==2)min++;if(min==60)min=0;// 分钟加 1 if(num==3)sec++;if(sec==60)sec=0;// 秒加 1 while(~key1); led=1; if(key3==0) // 判断 K3 是否按下 led=0; delay(10); if(key3==0) if(num==1)hour--;if(hour==0)hour=23; // 小时减 1 if(num==2)min--;if(min==0)min=59; // 分钟减 1 if(num==3)sec--;if(sec==59)sec=59; // 秒减 1 while(~key1); led=1; if(count<=15) // 调节时间时, 实现要调节的时间闪烁 display(table[hour/10],table[hour%10],table[min/10], table[min%10],table[sec/10],table[sec%10],0xff); if(count>15) display(table[hour/10],table[hour%10],table[min/10], table[min%10],table[sec/10],table[sec%10],0x00); while(~key1); ww.zicreate.com

45 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 /***************************************** 函数名 :time_change 功能 : 时间调整函数参数 : 无返回值 : 无 *******************************************/ void time_change() read_key(); // 判断是那一个按键按下 // 如果定时器 0 定时 1s 到 if(temp>=20) temp=0; //temp 清 0 sec++; // 秒加 1 if(sec>=60) // 如果秒 >=60 分加 1 sec=0; min++; if(min>=60) // 如果 >=60 时加 1 min=0; hour++; if(hour>24) // 如果时 >24 时清 0 hour=0; /***************************************** 函数名 :timer_init 功能 : 定时器初始化参数 :f 返回值 : 无 ******************************************/ void timer_init(bit f) TMOD=0x11; // 定时器 0/1 均工作在方式 1 TH0=0x3c; // 定时器 0 赋初值 50ms TL0=0xb0; TH1=0x3c; // 定时器 1 赋初值 50ms TL1=0xb0; EA=1; // 开总中断 ET0=1; // 开定时器 0 中断 ET1=1; // 开定时器 1 中断 TR0=f; //f=1 启动定时器 0,f=0 关闭定时器 0 TR1=f; //f=1 启动定时器 1,f=0 关闭定时器 1 /******************************************* 函数名 : main 功能 : 主函数参数 : 无返回值 : 无 /*******************************************/ void main()

46 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 P2=0xff; hour=12; // 设定时间初值 min=59;sec=50;aa=0xff; //aa 赋 0xff timer_init(1); // 定时器初始化 while(1) // 主循环 time_change(); // 调节时间 display(table[hour/10],table[hour%10],table[min/10],table[min%10],table[sec/10],table[sec%10],0xff);// 送显示 /******************************************* 函数名 : timer0 功 能 : 定时器 0 中断函数 参 数 : 无 返回值 : 无 /*******************************************/ void timer0() interrupt 1 using 1 TH0=0x3c; // 重赋初值 50ms TL0=0xb0; temp++; //temp 加 1 /******************************************* 函数名 : timer1 功 能 : 定时器 1 中断函数 参 数 : 无 返回值 : 无 /*******************************************/ void timer1() interrupt 3 using 3 TH1=0x3c; // 重赋初值 50ms TL1=0xb0; count++; //count 加 1 if(count>=20) // 如果 1s 时间到 count 清 0 count=0; 5.5 AT89S52 单片机的异步串行通信编程 与串行异步通信相关的功能寄存器 AT89S52 单片机的串行口具有两条独立的数据线 发送端 TXD 和接收端 RXD, 它允许数据同时 往两个相反的方向传输 一般通信时发送数据由 TXD 端输出, 接收数据由 RXD 端输入 AT89S52 单片 机的串行口既可以用于网络通信, 亦可实现串行异步通信, 还可以用作同步移位寄存器 如果在串行口 的输入输出引脚上加上电平转换器, 就可方便地构成标准的 RS-232 接口 AT89S52 单片机的串行接口 是一个全双工通信接口, 它有两个物理上独立的接收 发送缓冲器 SBUF, 可以同时发送和接收数据 但是发送缓冲器只能写入, 不能读出 ; 接收缓冲器只能读出, 不能写入 两个缓冲器共用一个地址 (99H) 在完成串行口初始化后, 发送数据时, 采用 MOV SBUF,A 指令, 将要发送的数据写入 SBUF, 则 CPU 自动启动和完成串行数据的输出 ; 接收数据时, 采用 MOV A,SBUF 指令,CPU 就自动将接收到 的数据从 SBUF 中读出 控制 AT89S52 单片机串行接口的控制寄存器有两个 特殊功能寄存器 SCON 和 PCON, 用以设置 串行端口的工作方式 接收 / 发送的运行状态 接收 / 发送数据的特征 数据传输率的大小, 以及作为运 行的中断标志等, 其格式如下. 串行口控制寄存器 SCON SCON 的字节地址是 98H, 位地址 ( 由低位到高位 ) 分别是 98H 一 9FH SCON 的格式如下 : D7 D6 D5 D4 D3 D2 D1 D0 SM0 SM1 SM2 REN TB8 RB8 TI RI ww.zicreate.com

47 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 SM0 SM0: 串行通信方式选择位 SM2: 多机通信控制位 置 1 时多机通信, 主要用于方式 2 和方式 3 置 0 时是单机对单机通信 REN: 接收控制位 0 即禁止接收 1 允许接收 TB8: 发送数据第 9 位 RB8: 接收数据第 9 位 TI: 发送中断标志位, 发送完一帧由硬件置 1, 发送前必须用软件复位 RI: 接收中断标志位, 接收完一帧由硬件置 1, RI 也用软件复位 波特率计算 : SMOD 方式 0 和方式 2 的波特率波特率 fosc (/ 64/ 2 ) 方式 1 和方式 3 的波特率用定时器 1 产生的波特率 波特率 T1的溢出率 /( 32 / 2 SMOD 12 ) 1/ 溢出周期溢出周期 定时时间 256 X f 波特率 32 f 12 其中,fosc 是振荡器的频率,UART 为通用异步接收和发送器的英文缩写 下面对这 4 种工作模式作进一步介绍 1. 方式 0 当设定 SM1 SM0 为 00 时, 串行口工作于方式 0, 它又叫同步移位寄存器输出方式 在方式 0 下, 数据从 RXD(P3.0) 端串行输出或输入, 同步信号从 TXD(P3.1) 端输出, 发送或接收的数据为 8 位, 低位在前, 高位在后, 没有起始位和停止位 数据传输率固定为振荡器的频率 1/12, 也就是每一机器周期传送一位数据 方式 0 可以外接移位寄存器, 将串行口扩展为并行口, 也可以外接同步输入 / 输出设备 执行任何一条以 SBUF 为目的的寄存器指令, 就开始发送 2. 方式 1 当设定 SM1 SM0 为 01 时, 串行口工作于方式 1 方式 1 为数据传输率可变的 8 位异步通信方式, 由 TXD 发送,RXD 接收, 一帧数据为 10 位,1 位起始位 ( 低电平 ),8 位数据位 ( 低位在前 ) 和 1 位停止位 ( 高电平 ) 数据传输率取决于定时器 1 或 2 的溢出速率 (1/ 溢出周期 ) 和数据传输率是否加倍的选择位 SMOD 对于有定时器 / 计数器 2 的单片机, 当 T2CON 寄存器中 RCLK 和 TCLK 置位时, 用定时器 2 作为接收和发送的数据传输率发生器, 而 RCLK=TCLK=0 时, 用定时器 1 作为接收和发送的数据传输率发生器 两者还可以交叉使用, 即发送和接收采用不同的数据传输率 类似于模式 0, 发送过程是由执行任何一条以 SBUF 为目的的寄存器指令引起的 3. 方式 2 当设定 SM0 SM1 二位为 10 时, 串行口工作于方式 2, 此时串行口被定义为 9 位异步通信接口 SMOD SMOD 2 osc 2 fosc 用定时器 1 产生的波特率 波特率 T 2的溢出率 / X X 溢出速率 其中 (RCAP2H,RCAP2L) 为 16 位寄存器的初值 2 16 f osc SMOD 2 fosc 计数初值 X 波特率 osc 2 (RCAP 2H, RCAP 2L) AT89S52 单片机可以通过软件设置串行口控制寄存器 SCON 中 SM0(SCON.7) 和 SMl(SCON.6) 来指定串行口的 4 种工作方式 串行口操作模式选择如表 5-5 所示 表 5-5 设置串行通信方式 SM0 SM1 工作方式功能说明波特率 0 0 方式 0 同步移位寄存器方式 f osc / 方式 1 10 位异步通信方式 可变, 由定时器控制 1 0 方式 2 11 位异步通信方式 f osc /32 或 f osc / 方式 3 11 位异步通信方式 可变, 由定时器控制

48 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 采用这种方式可接收或发送 11 位数据, 以 11 位为一帧, 比方式 1 增加了一个数据位, 其余相同 第 9 个数据即 D8 位用作奇偶校验或地址 / 数据选择, 可以通过软件来控制它, 再加特殊功能寄存器 SCON 中的 SM2 位的配合, 可使 MCS-51 单片机串行口适用于多机通信 发送时, 第 9 位数据为 TB8, 接收时, 第 9 位数据送入 RB8 方式 2 的数据传输率固定, 只有两种选择, 为振荡率的 1/64 或 1/32, 可由 PCON 的最高位选择 4. 方式 3 当设定 SM0 SM1 二位为 11 时, 串行口工作于方式 3 方式 3 与方式 2 类似, 唯一的区别是方式 3 的数据传输率是可变的 而帧格式与方式 2 一样为 11 位一帧 所以方式 3 也适合于多机通信 电源控制寄存器 PCON PCON 的字节地址为 87H, 无位地址, 其格式如下 :PCON 是为在 CMOS 结构的 MCS-51 单片机上实现电源控制而附加的, 对于 CMOS 结构的 MCS-51 系列单片机, 除了第 7 位外, 其余都是虚设的 与串行通信有关的也就是第 7 位, 称作 SMOD, 它的用处是使数据传输率加倍 D7 D6 D5 D4 D3 D2 D1 D0 SMOD POF GF1 GF0 PD IDL SMOD: 数据传输率加倍位 在计算串行方式 1,2,3 的数据传输率时 ;0 表示不加倍 ;1 表示加倍 其余有效位说明如下 除了以上两个控制寄存器外, 中断允许寄存器 IE 中的 ES 位也用来作为串行 I/O 中断允许位 当 ES =1, 允许串行 I/O 中断 ; 当 ES=0, 禁止串行 I/O 中断 中断优先级寄存器 IP 的 PS 位则用作串行 I/O 中断优先级控制位 当 PS=1, 设定为高优先级 ; 当 PS =0, 设定为低优先级 中断允许寄存器 IE D7 D6 D5 D4 D3 D2 D1 D0 EA -- ET2 ES ET1 EX1 ET0 EX0 EA: 当 EA=1 时 CPU 开总中断, 当 EA=0 时 CPU 关总中断 ET2 ET1 ET0: 定时器中断允许控制位 为 1 时允许中断 ES: 串行口中断允许控制位 为 1 时允许中断 中断优先级寄存器 IP D7 D6 D5 D4 D3 D2 D1 D PT2 PS PT1 PX1 PT0 PX0 PT2 PT1 PT0: 定时器优先级设定位 置 1 时为高优先级 PS: 串行口中断优先级设定位 置 1 时为高优先级 定时器 2 控制寄存器 T2CON D7 D6 D5 D4 D3 D2 D1 D0 TF2 EXF2 RCLK TCLK EXEN2 TR2 C/ T 2 CP/ RL 2 TF2: 定时器 2 溢出标志位 必须软件清 0 当 RCLK=1 或 TCLK=1 时 TF2 不用置位 EXF2: 定时器 2 外部标志位 EXEN2=1 时,T2EX 上的负跳变而出现捕捉或重载时,EXF2 会被硬件置位 定时器 2 打开,EXF2=1 时, 将引导 CPU 执行定时器 2 中断程序 EXF2 必须如见清 0 在向下 / 向上技术模式 (DCEN=1) 下 EXF2 不能引起中断 RCLK: 串行口接收数据时钟标志位 若 RCLK=1, 串行口将使用定时器 2 溢出脉冲作为串行口工作模式 1 和 3 的串口接收时钟 ;RCLK=0, 将使用定时器 1 计数溢出作为串口接收时钟 TCLK: 串行口发送数据时钟标志位 若 TCLK=1, 串行口将使用定时器 2 溢出脉冲作为串行口工作模式 1 和 3 的串口发送时钟 ;TCLK=0, 将使用定时器 1 计数溢出作为串口发送时钟 EXEN2: 定时器 2 外部允许标志位 当 EXEN2=1 时, 如果定时器 2 没有用作串行时钟,T2EX(P1.1) 的负跳变见引起定时器 2 捕捉和重载 若 EXEN2=0, 定时器 2 将视 T2EX 端的信号无效 TR2: 开始 / 停止控制定时器 2 TR2=1, 定时器 2 开始工作 C/ T 2 : 定时器 2 定时 / 计数选择标志位 C/ T 2 =0, 定时 ;C/ T 2 =1, 外部事件计数 ( 下降沿触发 ) CP/ RL 2 : 捕捉 / 重载选择标志位 当 EXEN2=1 时,CP/ RL2 =1,T2EX 出现负脉冲, 会引起捕捉操作 ; ww.zicreate.com

49 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 当定时器 2 溢出或 EXEN2=1 时 T2EX 出现负跳变, 都会出现自动重载操作 CP/ RL2 =0 将引起 T2EX 的负脉冲 当 RCKL=1 或 TCKL=1 时, 此标志位无效, 定时器 2 溢出时, 强制做自动重载操作 定时器 0 1 控制寄存器 TCON D7 D6 D5 D4 D3 D2 D1 D0 TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 TF1 TF0: 分别为定时器 1 和定时器 0 的溢出标志 溢出后由硬件置 1, 并申请中断 TR1 TR0: 分别为定时器 1 和定时器 0 的启停控制位 置 1 启动, 清 0 停止 IE1 IE0: 外部中断请求标志位 外部中断有中断请求时, 由硬件置 1 响应中断后由硬件清 0 IT1 IT0: 外部中断触发方式位 设置为 0 时为电平触发, 设置为 1 时为边沿触发 定时器 2 方式控制寄存器 T2MOD D7 D6 D5 D4 D3 D2 D1 D T2OE DCED T2OE: 定时器 2 输出允许位 DCED: 置 1 后, 定时器 2 可配置成向上 / 向下计数定时器 0 1 方式控制寄存器 T2MOD D7 D6 D5 D4 D3 D2 D1 D0 GATE C/ T M1 M0 GATE C/ T M1 M0 T1 T0 GATE: 门控位 当 GATE=0 时, 只利用控制位 TR0 或 TR1 来控制定时器的启停 当 GATE=1 时, 定时器的启停由外部中断引脚和控制位 TR0 或 TR1 来共同控制 C/ T : 功能选择位 当 C/ T =0 时, 设定为定时器工作方式 当 C/ T =1 时, 设定为计数器工作方式 M1 M0: 工作模式控制位 表 5-6 定时器 0 1 工作模式设定 M1 M0 工作方式功能简述 0 0 模式 0 13 位计数器,TLi 只用低 5 位 0 1 模式 1 16 位计数器 1 0 模式 2 8 位自动重装计数器 仅 TLi 作为计数器,THi 的值不变 TLi 溢出, THi 中的值自动装入 TLi 中. 1 1 模式 3 T0 分为两个独立的 8 位计数器 计数初值的计算 : Tc 计数值 其中 Tc是定时时间, T T p p 12 f osc 是机器周期 f Tc 计数初值 X M 计数值 M M (TC fosc) / 12 T p osc 是振荡频率 数据传输率的确定 : 串行口每秒钟发送 ( 或接收 ) 的位数就是数据传输率 对方式 0 来说, 数据传输率已固定成 fosc/12, 随着外部晶振的频率不同, 数据传输率亦不相同 常用的 fosc 有 12MHz 和 6MHz, 所以数据传输率相应为 和 bit/s 在此方式下, 数据将自动地按固定的数据传输率发送 / 接收, 完全不用设置 对方式 2 而言, 数据传输率的计算式为 2SMOD fosc/64 当 SMOD=0 时, 数据传输率为 fm/64; 当 SMOD=1 时, 数据传输率为 fosc/32 在此方式下, 程控设置 SMOD 位的状态后, 数据传输率就确定了, 不需要再作其他设置 对方式 1 和方式 3 来说, 数据传输率和定时器 1 的溢出率有关, 定时器 1 的溢出率为 : 定时器 1 的溢出率 = 定时器 1 的溢出次数 / 秒方式 1 和方式 3 的数据传输率计算式为 : 2 SMOD /32 T1 溢出率

50 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 根据 SMOD 状态位的不同, 数据传输率有 Tl/32 溢出率和 T1/16 溢出率两种 由于 T1 溢出率的设置是方便的, 因而数据传输率的选择将十分灵活 前已叙及, 定时器 Tl 有 4 种工作方式, 为了得到其溢出率, 而又不必进入中断服务程序, 往往使 T1 设置在工作方式 2 的运行状态, 也就是 8 位自动加入时间常数的方式 表 5-7 常用数据传输率设置方法 数据传输率 /Hz fosc/mhz SMOD 定时器 1 方式 0 最大 :1M 方式 2 最大 :375k 方式 1 3:62.5k 4.8k 2.4k 1.2k 19.2k 9.6k 9.6k 4.8k 2.4k 1.2k 串行异步通信 C 语言编程实例 X C/T 方式重新装入值 X X X X X X FFH F3H F3H F6H FDH FDH FAH FAH F4H E8H 0FEEH ww.zicreate.com

51 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 图 5-6 串行通信电路原理图 /********************************************************************** * 程序名 ; 单片机与电脑串行通信 ( 晶振 MHZ) * 功能 : 当按键 1 按下单片机向电脑发送 10 串字符, 单片机接收到得字符在 1602 * 上的第二行显示, 当发送数据时,1602 的第一行显示 Data Sending... * 数据发送完,1602 上显示 send over * 编程者 :ZPZ * 编程时间 :2008/11/14 **********************************************************************/ #include<reg52.h> // 包含头文件 #include<intrins.h> #define uchar unsigned char // 宏定义 #define uint unsigned int #include "lcd_1602.h" // 包含 lcd_1602.h 头文件 sbit key1=p3^2; // 定义键盘口 uchar code table1[]="data Sending... "; // 定义要显示的数组 uchar code table2[]=" send over "; uchar send_data[]="welcome to zpz.cublog.cn\n";// 定义要发送的数组 /******************************************* 函数名 :delay 功能 : 延时 1ms 左右参数 :z 返回值 : 无 ********************************************/

52 void delay(uint z) uint i,j; // 定义局部变量 for(i=z;i>0;i--) // 循环 for(j=120;j>0;j--); // 循环 /******************************************* 函数名称 : baud_rate_init 功能 : 比特率设置函数 (9600) 参数 : 无返回值 : 无 /********************************************/ void baud_rate_init() TMOD=0x20; // 工作在方式 2 TH1=0xfd; // 波特率 9600 TL1=0xfd; SM0=1; //SCON=0xd8 工作在方式 3 SM1=1; SM2=0; // 单机通信 REN=1; // 允许接收 TB8=1; // 发送数据第 9 位为 1 RB8=0; // 接收数据第 9 位为 0 TI=0; // 清 0 发送中断标志位 RI=0; // 清 0 接收中断标志位 PCON=0x00; //SMOD=0 TR1=1; // 启动定时器 1 EA = 1 ; // 开总中断 /******************************************* 函数名 : send_str() 功能 : 发送字符串参数 : 无返回值 : 无 /********************************************/ void send_str(uchar *str) uchar i; // 定义一个局部变量 for(i=0;str[i]!='\0';i++) // 逐个发送自字节数据 SBUF=str[i]; // 将一位数据收发送缓冲器 while(ti==0); // 等待发送完成 TI=0; // 发送完成后软件将 TI 清 0 /******************************************* 函数名 : receive_char() 功能 : 发送一个字符参数 : 无返回值 : 无 /********************************************/ uchar receive_char() uchar i; // 定义一个局部变量 if(ri==1); // 判断是否有数据要接收 RI =0; //RI 清 0 后开始接收数据 i=sbuf; // 从接收缓冲器中读取数据 return(i); // 返回接收的数据 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计

53 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 /******************************************* 函数名 : key_scan() 功 能 : 键盘扫面函数 参 数 : 无 返回值 : 无 /********************************************/ void key_scan(uchar z) uchar a; if(key1==0) // 判断 k1 是否按下 delay(10); // 延时消抖 if(key1==0) // 再次判断 k1 是否按下 lcd_1602_gotoxy(1,0x00); // 指定第一行显示的首地址 lcd_1602_printf(table1,16) ; // 在第一行显示 for(a=0;a<z;a++) //z 是要发送字符串的遍数 send_str(send_data); // 发送字符串 lcd_1602_gotoxy(1,0x00); // 指定第一行显示的首地址 lcd_1602_printf(table2,16); while(key1==0); // 判断 k1 是否松开 /******************************************* 函数名称 : main 功 能 : 主函数 参 数 : 无 返回值 : 无 /********************************************/ void main() uchar dis; // 定义变量 dis baud_rate_init(); // 波特率设置 lcd_1602_init(); //LCD1602 初始化 while(1) // 主循环 key_scan(10); // 扫描键盘发送数据 lcd_1602_gotoxy(2,0x00); // 指定第二行显示的首地址 dis=receive_char(); // 存储接收到得数据 lcd_1602_write(1,dis); // 在 1602 上显示接收到的数据 /********************************************************************** * 程序名 ; lcd_1602_h * 功能 : LCD1602 的 c51 编程头文件 * 编程者 : ZPZ * 编程时间 :2008/9/12 **********************************************************************/ #ifndef lcd_1602_h #define lcd_1602_h #define uchar unsigned char // 变量类型宏定义 #define uint unsigned int #define data_port P0 // 定义数据口

54 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 sbit lcde=p1^0; // 定义使能端口 sbit lcdrw=p1^1; // 定义读写端口 sbit lcdrs=p1^2; // 定义数据命令选择端口 /******************************************* 函数名称 : lcd_1602_delay 功能 : 1602 延时子函数参数 : z 返回值 : 无 /********************************************/ void lcd_1602_delay(uint z) uint j,k; // 定义局部变量 for(j=z;j>0;j--) for(k=20;k>0;k--); /******************************************* 函数名称 : lcd_1602_write 功能 : 1602 写命令 / 数据函数参数 : f "0" 写命令,"1" 写数据. c 是命令或数据返回值 : 无 /********************************************/ void lcd_1602_write(bit f,uchar c) lcdrw=0; // 写选通 lcdrw 为 "0" 是向 lcd1602 写, 为 "1" 是读 lcdrs=f; // 写数据或命令选通端 "0" 写命令,"1" 写数据 data_port=c; // 把数据或命令送入数据口 lcd_1602_delay(2); // 延时 400μs 左右 lcde=1; //lcde 端给一个脉冲 lcd_1602_delay(5); lcde=0; lcd_1602_delay(2); // 延时 /******************************************* 函数名称 : lcd_1602_read 功能 : 1602 读数据函数参数 : d 返回值 : 无 /********************************************/ /*uchar lcd_1602_read(uchar d) lcdrw=1; // 读选通 lcdrs=1; lcd_1602_delay(2); lcde=1; lcd_1602_delay(2); d=data_port; lcd_1602_delay(2); lcde=0; lcd_1602_delay(2); return d; */ /******************************************* 函数名称 : lcd_1602_init 功能 : 1602 初始化函数参数 : 无返回值 : 无 ww.zicreate.com

55 第 5 章 AT89S52 单片机典型功能部件 C 语言编程 /********************************************/ void lcd_1602_init() lcde=0; lcd_1602_write(0,0x38); // 设置显示模式,16*2 显示,5*7 点阵,8 位数据接口 lcd_1602_write(0,0x0c); // 写入开显示 不显示光标 光标不闪烁命令 lcd_1602_write(0,0x01); // 写清屏命令 lcd_1602_write(0,0x06); // 写一个字符, 地址指针加一, 光标加一 /******************************************* 函数名称 : lcd_1602_gotoxy 功能 : 1602 显示坐标函数参数 : x"1" 表示第一行 "2" 表示第二行 y 地址 返回值 : 无 /********************************************/ void lcd_1602_gotoxy(uchar x, uchar y) if(x==1) lcd_1602_write(0,0x80 y); if(x==2) lcd_1602_write(0,(0x80+0x40) y); /******************************************* 函数名称 : lcd_1602_printf 功能 : 1602 写显示函数参数 : f "0" 在第一行显示,"1" 在第二行显示返回值 : 无 /********************************************/ void lcd_1602_printf(uchar *str,uchar num) uchar i; for (i=0;i<num;i++) lcd_1602_write(1,*str); str++; lcd_1602_delay(5); /******************************************* 函数名称 : lcd_1602_move_left 功能 : 1602 全屏左移函数参数 : 返回值 : 无 /********************************************/ /*void lcd_1602_move_left() uchar num; for(num=0;num<16;num++) */ #endif lcd_1602_write(0,0x18); lcd_1602_delay(1000); // 在第一行定位显示地址 // 在第二行定位显示地址 // 全屏左移命令

56 第 6 章 AT89S52 单片机扩展功能 C 语言编程 6.1 LED 数码管显示七段 LED 显示器需要由驱动电路驱动 在七段 LED 显示器中, 共阳极显示器, 用低电平驱动 ; 共 阴极显示器, 用高电平驱动 点亮显示器有静态和动态两种方式 数码管的详细使用说明请参看第四章 单片机常用外围器件 1. 数码管静态显示 所谓静态显示, 就是当显示器显示某一字符时, 相应段的发光二极管恒定地导通或截止 图 5-1 为 一个四位静态 LED 显示器电路 该电路各位可独立显示, 只要在该位的段选线上送相应的段码, 该位就 能保持响应的显示字符 这种显示方法的每一位都需要有一个 8 位输出口控制 静态显示器的优点是显示稳定, 在发光二极管导通电流一定的情况下显示器的亮度高, 控制系统在 运行过程中, 仅仅在需要更新显示内容时,CPU 才执行一次显示更新子程序, 这样大大节省了 CPU 的 时间, 提高了 CPU 的工作效率 ; 缺点是位数较多时, 所需的 I/O 口太多, 硬件开销太大 图 6-1 四位静态 LED 显示电路 例如在 AT89S52 上扩展多片串行输人并行输出的移位寄存器 74LS164 作为静态显示器接口, 图 5-2 给出了 8 位共阳极静态显示器的逻辑接口 图 6-2 串行扩展静态共阳数码管显示电路

57 第 6 章 AT89S52 单片机扩展功能 C 语言编程 静态显示程序如下 : /********************************************************************** * 程序名 ; 数码管静态显示实验 ( 晶振 MHZ) * 功能 : 数码管静态显示 0000~9999 * 编程者 : ZPZ * 编程时间 :2008/9/4 **********************************************************************/ #include<reg52.h> // 包含 reg52.h 头文件 #define uint unsigned int // 宏定义 #define uchar unsigned char uint counter=0; // 定义一个无符号整形变量 uchar t0_1s=0; // 定义一个无符号字符型变量 uchar code table[]= 0xc0,0xf9,0xa4,0xb0,0x99, 0x92,0x82,0xf8,0x80,0x90;// 定义断码表 0~9( 共阳 ) sbit dat=p1^0; // 定义数据端口 sbit clk=p1^1; // 定义时钟端口 /********************************** 函数名 :delay 功能 : 延时 1ms 左右参数 :z 返回值 : 无 ***********************************/ void delay(uint z) uint i,j; // 定义局部变量 for(i=z;i>0;i--) // 循环 for(j=110;j>0;j--); // 循环 /********************************** 函数名 :write_byte 功能 : 向 74ls164 写入一个字节参数 :z 返回值 : 无 ***********************************/ void write_byte(uchar z) uchar i,num; // 定义局部变量 num=table[z]; // 将码表值送给变量 num for(i=0;i<8;i++) // 循环 8 次送一个字节到数据口 clk=0; // 给时钟信号线低电平 dat=num&0x80 ; // 送数据 clk=1; // 给时钟信号线高电平 num<<=1; //num 左移一位后送给 num /********************************** 函数名 :timer0_init 功能 :T0 初始化函数参数 :f 返回值 : 无 ***********************************/ void timer0_init(bit f) TMOD=0x01; // 定时器 0 工作在方式 1 TH0=0x3c; // 定时器赋初值 50ms TL0=0xb0;

58 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 ET0=1; // 开 T0 中断 EA=1; // 开总中断 TR0=f; //f 为 1 启动定时器 0, 为 0 禁止定时器 0 /********************************** 函数名 :display 功能 : 显示函数参数 : 无返回值 : 无 ***********************************/ void display() write_byte(counter%10); // 送个位显示 write_byte(counter%100/10); // 送十位显示 write_byte(counter%1000/100); // 送百位显示 write_byte(counter/1000); // 送千位显示 /********************************** 函数名 :main 功能 : 主函数参数 : 无返回值 : 无 ***********************************/ void main() timer0_init(1); // 定时器 0 初始化 while(1) // 主循环 display(); // 调用显示函数 delay(25); // 延时 /********************************** 函数名 :timer0 功能 : 定时器 0 中断函数参数 : 无返回值 : 无 ***********************************/ void timer0() interrupt 1 TH0=0x3c; // 重新赋初值 TL0=0xb0; t0_1s+=1; // 变量 t0_1s 加 1 if(t0_1s==20) // 中断 20 次定时 1s t0_1s=0; // 变量 t0_1s 清 0 counter+=1; //counter 加 1 if(counter==9999) // 如果 counter=9999 counter 清 0 counter=0; 2. 数码管动态显示 所谓动态显示就是一位一位地轮流点亮各位显示器 ( 扫描 ), 对于显示器的每一位而言, 每隔一段时 间点亮一次 在同一时刻只有一位显示器在工作 ( 点亮 ), 利用人眼的视觉暂留效应和发光二极管熄灭时 的余辉效应, 看到的却是多个字符 同时 显示 显示器亮度既与点亮时的导通电流有关, 也与点亮时间和间隔时间的比例有关 调整电流和时间参 ww.zicreate.com

59 第 6 章 AT89S52 单片机扩展功能 C 语言编程 数, 可实现亮度较高较稳定的显示 图 6-3 动态扫描显示电路图 (74HC573 锁存驱动 )

60 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 图 6-4 动态扫描共阴数码管显示电路图 ( 三极管驱动 ) 图 5-3 图 5-4 均为 4 位动态 LED 显示器电路 其中段选线占用一个 I/O 口, 控制各位 LED 显示器所 显示的字形 ( 称为段码或字形口 ); 位选线需要一个 I/O 口, 控制显示器公共极电位 ( 称为位码或字位口 ) 动态显示器的优点是节省硬件资源, 成本较低 但在控制系统运行过程中, 要保证显示器正常显示, CPU 必需每隔一段时间执行一次显示子程序, 占用 CPU 大量时间, 降低了 CPU 的工作效率, 同时显示 亮度较静态显示器低 动态显示程序如下 : /********************************************************************** * 程序名 ; 数码管动态扫描显示实验 ( 晶振 MHZ) * 功能 : 数码管动态扫描显示 0000~9999( 共阴数码管 ) * 编程者 : ZPZ * 编程时间 :2008/9/4 **********************************************************************/ #include<reg52.h> // 包含 reg52.h 头文件 #define uint unsigned int // 宏定义 #define uchar unsigned char #define data_bus P0 // 定义数据口 P0 uint counter=0; // 定义一个无符号整形变量 uchar t0_1s=0; // 定义一个无符号字符型变量 uchar code table[]= 0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f;// 定义断码表 0~9( 共阴 ) sbit wei1=p1^0; // 定义位选口 sbit wei2=p1^1; sbit wei3=p1^2; sbit wei4=p1^3; /********************************** 函数名 :delay 功能 : 延时 1ms 左右 ww.zicreate.com

61 第 6 章 AT89S52 单片机扩展功能 C 语言编程 参数 :z 返回值 : 无 ***********************************/ void delay(uint z) uint i,j; // 定义局部变量 for(i=z;i>0;i--) // 循环 for(j=110;j>0;j--); // 循环 /********************************** 函数名 :timer0_init 功能 :T0 初始化函数参数 :f 返回值 : 无 ***********************************/ void timer0_init(bit f) TMOD=0x01; // 定时器 0 工作在方式 1 TH0=0x3c; // 定时器赋初值 50ms TL0=0xb0; ET0=1; // 开 T0 中断 EA=1; // 开总中断 TR0=f; //f 为 1 启动定时器 0, 为 0 禁止定时器 0 /********************************** 函数名 :display 功能 : 显示函数参数 :qian,bai,shi,ge 返回值 : 无 ***********************************/ void display(uint qian,uint bai,uint shi,uint ge) wei1=0; // 选通第一个数码管 wei2=1; // 关断其它三个 wei3=1; wei4=1; data_bus=table[qian]; // 送要显示的段码 delay(2); wei2=0; wei1=1;wei3=1;wei4=1; data_bus=table[bai]; delay(2); wei3=0; wei1=1;wei2=1;wei4=1; data_bus=table[shi]; delay(2); wei4=0; wei1=1; wei2=1;wei3=1; data_bus=table[ge]; delay(2); /********************************** 函数名 :main 功能 : 主函数参数 : 无返回值 : 无 ***********************************/ void main() timer0_init(1); // 定时器 0 初始化

62 while(1) // 主循环 display(counter/1000,counter%1000/100,counter%100/10,counter%10); /********************************** 函数名 :timer0 功能 : 定时器 0 中断函数参数 : 无返回值 : 无 ***********************************/ void timer0() interrupt 1 TH0=0x3c; // 重新赋初值 TL0=0xb0; t0_1s+=1; // 变量 t0_1s 加 1 if(t0_1s==20) // 中断 20 次定时 1s t0_1s=0; // 变量 t0_1s 清 0 counter+=1; //counter 加 1 if(counter==9999) // 如果 counter=9999 counter 清 0 counter=0; 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 // 调用显示函数 6.2 LCD1602 显示如图 5-5 为 LCD1602 显示电路 LCD1602 的详细使用说明请参看第四章单片机常用外围器件 ww.zicreate.com

63 第 6 章 AT89S52 单片机扩展功能 C 语言编程 图 6-5 LCD1602 显示电路 LCD1602 显示程序如下 : /********************************************************************** * 程序名 ; LCD1602 显示实验 ( 晶振 MHZ) * 功能 : 该实验 1602 液晶显示实验, 两行字符会从右至左逐渐进入整个屏幕 * 编程者 : ZPZ * 编程时间 :2008/9/14 **********************************************************************/ #include<reg52.h> // 包含头文件 #include<intrins.h> #define uchar unsigned char // 宏定义 #define uint unsigned int #include "lcd_1602.h" // 包含 lcd_1602.h 头文件 uchar num; // 定义变量 num uchar table[]="welcome to"; // 将要显示的数存入数组 uchar table2[]="zpz.cublog.cn"; /******************************************* 函数名称 : main 功能 : 主函数参数 : 无返回值 : 无 /********************************************/ void main() lcd_1602_init(); lcd_1602_gotoxy(1,0x13); // 指定第一行显示的首地址 lcd_1602_printf(table,10); lcd_1602_gotoxy(2,0x52); lcd_1602_printf(table2,13); lcd_1602_move_left();// 全屏左移 while(1); // 指定第二行显示的首地址 /********************************************************************** * 程序名 ; lcd_1602_h * 功能 : LCD1602 的 c51 编程头文件 * 编程者 : ZPZ * 编程时间 :2008/9/12 **********************************************************************/ #ifndef lcd_1602_h #define lcd_1602_h #define uchar unsigned char // 变量类型宏定义 #define uint unsigned int #define data_port P0 // 定义数据口 sbit lcde=p1^0; // 定义使能端口 sbit lcdrw=p1^1; // 定义读写端口 sbit lcdrs=p1^2; // 定义数据命令选择端口 /******************************************* 函数名称 : lcd_1602_delay 功 能 : 1602 延时子函数 参 数 : z 返回值 : 无 /********************************************/ void lcd_1602_delay(uint z) uint j,k; for(j=z;j>0;j--) // 定义局部变量

64 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 for(k=20;k>0;k--); /******************************************* 函数名称 : lcd_1602_write 功能 : 1602 写命令 / 数据函数参数 : f "0" 写命令,"1" 写数据. c 是命令或数据返回值 : 无 /********************************************/ void lcd_1602_write(bit f,uchar c) lcdrw=0; // 写选通 lcdrw 为 "0" 是向 lcd1602 写, 为 "1" 是读 lcdrs=f; // 写数据或命令选通端 "0" 写命令,"1" 写数据 data_port=c; // 把数据或命令送入数据口 lcd_1602_delay(2); // 延时 400μs 左右 lcde=1; //lcde 端给一个脉冲 lcd_1602_delay(5); lcde=0; lcd_1602_delay(2); // 延时 /******************************************* 函数名称 : lcd_1602_read 功能 : 1602 读数据函数参数 : d 返回值 : 无 /********************************************/ /*uchar lcd_1602_read(uchar d) lcdrw=1; lcdrs=1; lcd_1602_delay(2); lcde=1; lcd_1602_delay(2); d=data_port; lcd_1602_delay(2); lcde=0; lcd_1602_delay(2); return d; // 读选通 */ /******************************************* 函数名称 : lcd_1602_init 功能 : 1602 初始化函数参数 : 无返回值 : 无 /********************************************/ void lcd_1602_init() lcde=0; lcd_1602_write(0,0x38); lcd_1602_write(0,0x0c); lcd_1602_write(0,0x01); lcd_1602_write(0,0x06); /******************************************* 函数名称 : lcd_1602_gotoxy 功能 : 1602 显示坐标函数参数 : x"1" 表示第一行 "2" 表示第二行 y 地址 返回值 : 无 /********************************************/ // 设置显示模式,16*2 显示,5*7 点阵,8 位数据接口 // 写入开显示 不显示光标 光标不闪烁命令 // 写清屏命令 // 写一个字符, 地址指针加一, 光标加一

65 第 6 章 AT89S52 单片机扩展功能 C 语言编程 void lcd_1602_gotoxy(uchar x, uchar y) if(x==1) lcd_1602_write(0,0x80 y); if(x==2) lcd_1602_write(0,(0x80+0x40) y); /******************************************* 函数名称 : lcd_1602_printf 功能 : 1602 写显示函数参数 : f "0" 在第一行显示,"1" 在第二行显示返回值 : 无 /********************************************/ void lcd_1602_printf(uchar *str,uchar num) uchar i; for(i=0;i<num;i++) lcd_1602_write(1,*str); str++; lcd_1602_delay(5); /******************************************* 函数名称 : lcd_1602_move_left 功能 : 1602 全屏左移函数参数 : 返回值 : 无 /********************************************/ void lcd_1602_move_left() uchar num; for(num=0;num<16;num++) lcd_1602_write(0,0x18); lcd_1602_delay(1000); #endif 6.3 LCD12864 显示 LCD12864 的电路原理图如图 5-6 所示 : // 在第一行定位显示地址 // 在第二行定位显示地址 // 全屏左移命令

66 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 图 6-6 LCD12864 应用电路原理图 应用实例程序如下 /********************************************************************** * 程序名 ; lcd12864 * 功能 :lcd12864 显示校徽 校名图片及字符串 * 编程者 : ZPZ * 编程时间 :2009/8/5 **********************************************************************/ #include<at89x52.h> // 包含 AT89X52.h 头文件 #include<intrins.h> // 包含 intrins.h 头文件 #define uchar unsigned char // 变量类型宏定义 #define uint unsigned int #define LCD_Data P0 // 定义 LCD12864 的数据口 sbit LCD_RS=P1^2; // 并行的指令 / 数据选择信号端定义 sbit LCD_E=P1^0; // 并行的使能信号端定义 sbit LCD_WR=P1^1; // 并行的读写选择信号端定义 /************ 校徽图片编码显示表 ************/ uchar code xiaohui[]= 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x07,0xF0,0x00,0x07,0xF0,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x0F,0x81,0x80,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x3E,0x0F,0x00,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x78,0x05,0x00,0x38,0x0F,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x01,0xF0,0x07,0x00,0x30,0x07,0xC0,0x00,0x00,0x00,0x00,0x00, ww.zicreate.com

67 第 6 章 AT89S52 单片机扩展功能 C 语言编程 0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0x80,0xF0,0x01,0xE0,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x07,0x94,0x07,0x80,0xE0,0x00,0xF0,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x0F,0x1C,0x04,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x0E,0x0E,0x00,0x7F,0x00,0x28,0x38,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x1C,0x1F,0x03,0xFF,0xF0,0xBC,0x1C,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x38,0x0B,0x1F,0xFF,0xFC,0xF0,0x0E,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x70,0x0C,0x3F,0xFF,0xFF,0x10,0x07,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x70,0x04,0xFF,0xFF,0xFF,0x80,0x07,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xE0,0x01,0xFF,0xEF,0xFF,0xC0,0x03,0x80,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xEC,0x03,0xFF,0xEF,0xFF,0xF0,0x01,0x80,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0xCC,0x07,0xFF,0xEF,0xFF,0xF0,0x05,0xC0,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0xCE,0x0F,0xFF,0xE7,0xFF,0xF8,0x7C,0xC0,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x03,0xB5,0x0F,0xFF,0xE3,0xFF,0xFD,0x78,0xE0,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x03,0x90,0xDF,0xFF,0xF0,0xFF,0xFF,0xF8,0xE0,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x03,0x0E,0xBF,0xFF,0xF8,0x3F,0xFE,0xC0,0x60,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x07,0x00,0x3F,0xFF,0xFE,0x0F,0xFF,0x00,0x70,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x07,0x00,0x7F,0xE7,0xE7,0x07,0xFF,0x00,0x70,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x06,0x00,0x7F,0xE3,0x87,0x81,0xFF,0x00,0x30,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x06,0x00,0x7F,0xE3,0x87,0xE0,0xFF,0x88,0x30,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x06,0x00,0x7F,0xE3,0x87,0xE0,0xFF,0x8F,0x38,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x0E,0x3C,0xFF,0xE3,0x87,0xF0,0x7F,0x8F,0x38,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x0E,0x14,0xFE,0xE3,0x87,0xF0,0x7F,0x8C,0x38,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x0E,0x3C,0xFF,0x23,0x87,0xF0,0x7F,0x8F,0x38,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x0E,0x04,0xFF,0xC3,0x87,0xF0,0x7F,0x8F,0x38,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x0E,0x38,0xFF,0xC3,0x87,0xF0,0xFF,0x8C,0x38,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x0E,0x3C,0xFF,0xC1,0x87,0xE0,0xFF,0x8F,0x38,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x0E,0x3C,0xFF,0xC0,0x07,0xC1,0xFF,0x81,0x38,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x0E,0x3C,0xFF,0xC2,0x00,0x03,0xFF,0x8E,0x38,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x0E,0x2C,0x7F,0xC3,0x80,0x07,0xFF,0x8F,0x38,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x06,0x1C,0x7F,0xC3,0x80,0x3F,0xFF,0x82,0x30,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x06,0x20,0x7F,0xC3,0x87,0xFF,0xFF,0x1E,0x30,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x07,0x1E,0x3F,0xC3,0x87,0xFF,0xFF,0x1E,0x70,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x07,0x1E,0x3F,0xC3,0x87,0xFF,0xFF,0x26,0x70,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x03,0x19,0x3F,0xC3,0x87,0xFF,0xFE,0x3C,0x60,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x03,0x8F,0x1F,0xC3,0x87,0xFF,0xFC,0x74,0xE0,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x03,0x8B,0x8F,0xC3,0x87,0xFF,0xFC,0x48,0xE0,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0xC7,0x0F,0xC3,0x87,0xFF,0xF8,0xE0,0xC0,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0xC0,0x07,0xF3,0x9F,0xFF,0xF0,0xE1,0xC0,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xE0,0x63,0xFF,0xFF,0xFF,0xE1,0x31,0x80,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xE0,0xE1,0xFF,0xFF,0xFF,0xC3,0x83,0x80,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x71,0xF8,0xFF,0xFF,0xFF,0x82,0xC7,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x70,0x3C,0x3F,0xFF,0xFF,0x0F,0x07,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x38,0x2A,0x0F,0xFF,0xFC,0x17,0x8E,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x1C,0x3E,0x83,0xFF,0xE0,0x7B,0x1C,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x0E,0x04,0xE0,0x3E,0x00,0x28,0x38,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x0F,0x0E,0xF8,0x00,0x03,0x38,0x78,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x07,0x83,0x9F,0x80,0x1F,0x00,0xF0,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x03,0xC0,0x92,0xFE,0xBA,0x81,0xE0,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x01,0xF0,0x33,0xDE,0xEB,0x83,0xC0,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x78,0x07,0x6E,0xAC,0x0F,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x6F,0xE0,0x3E,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x04,0x07,0xF0,0x00,0x07,0xF0,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; /************ 校名图片编码显示表 ************/

68 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 uchar code xiaoming[]= 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80, 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xE0, 0x00,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0, 0x00,0x00,0x7E,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x01,0xE0, 0x00,0x01,0xF0,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x03,0x80, 0x60,0x03,0xC0,0x00,0x1E,0x60,0x3C,0x07,0x00,0x00,0x00,0x1E,0x00,0x00,0x03,0x08, 0x78,0x07,0xF0,0x00,0x1D,0xE3,0xFC,0x1F,0x00,0x00,0x00,0x0F,0x00,0x00,0x06,0x7C, 0x3C,0x1F,0xB8,0x00,0x3F,0xE3,0xEC,0x7F,0x00,0x00,0x00,0x07,0x70,0x00,0x0F,0xFC, 0x3C,0x3F,0xB8,0x00,0x7F,0x60,0x18,0xFE,0x00,0x07,0x00,0x07,0xF8,0x03,0x3F,0xDC, 0x38,0x7E,0x70,0x03,0xFC,0xC0,0x3B,0xFC,0x00,0x3F,0xC0,0x07,0xF0,0x03,0xFF,0xB8, 0x00,0x6F,0xF0,0x07,0xF8,0xC0,0x73,0xB8,0x00,0xFF,0xC0,0x0F,0xE0,0x01,0xFF,0xF0, 0x00,0x1F,0xF0,0x06,0x7D,0xC0,0x70,0x30,0x00,0xFF,0x00,0x1F,0x80,0x04,0xFF,0xE0, 0x00,0x1F,0xF0,0x00,0xF9,0x80,0x76,0x30,0x00,0x1E,0x00,0x7F,0x00,0x07,0x7F,0x80, 0x00,0x1F,0xF0,0x01,0xF7,0x80,0x6E,0x70,0x00,0x3C,0x0F,0xFC,0x00,0x07,0xFF,0xE0, 0x30,0x3F,0x60,0x03,0xFF,0x80,0x6C,0x60,0x00,0x78,0x0F,0xF8,0x00,0x03,0xEF,0xE0, 0x38,0x1E,0x60,0x07,0xFD,0x80,0xFC,0x60,0x00,0xE0,0x0F,0x70,0x00,0x03,0x8F,0xC0, 0x38,0x06,0x60,0x1E,0x1B,0x80,0xF8,0xE0,0x00,0xF8,0x00,0xE1,0x80,0x03,0xBF,0x80, 0x3B,0x00,0x60,0x1C,0xFB,0x81,0xF0,0xE0,0x01,0xFE,0x01,0xE1,0xC0,0x00,0x76,0x00, 0x1B,0x00,0x60,0x70,0xFB,0x01,0xF0,0xE0,0x07,0xFE,0x01,0xC0,0xE0,0x00,0xE6,0x00, 0x1F,0x00,0x60,0x60,0x53,0x03,0xE0,0x60,0x1F,0xFC,0x03,0x80,0x78,0x01,0xC6,0x00, 0x1E,0x00,0x60,0x60,0xF3,0x03,0xC0,0xE0,0x3F,0xE0,0x07,0x00,0x7C,0x03,0x87,0x80, 0x1E,0x00,0x60,0x60,0x3F,0x07,0x80,0xE4,0x1F,0x80,0x0F,0x00,0xFC,0x27,0x1F,0x80, 0x0E,0x00,0x60,0xF0,0x1F,0x0F,0x80,0xFC,0x04,0x00,0x1E,0x01,0xF8,0xDE,0x3E,0x00, 0x06,0x00,0x60,0x60,0x0F,0x0F,0x00,0xF8,0x00,0x00,0x3C,0x03,0xE0,0xFC,0x76,0x00, 0x00,0x00,0x70,0x00,0x07,0x0E,0x00,0xE0,0x00,0x00,0xF0,0x03,0x00,0x78,0xFE,0x00, 0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xE0,0x00,0x00,0x70,0xFE,0x00, 0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x07,0x70,0x00,0x00,0xF0,0x18,0x00,0x06,0x00,0x40,0x77,0x02,0x00,0x00,0x40,0x00, 0x02,0x20,0x00,0x00,0x48,0x08,0x10,0x02,0x00,0x00,0x22,0x00,0x00,0x00,0x10,0x00, 0x02,0x25,0xA6,0xD0,0x49,0x8E,0xF9,0x1A,0xB4,0xCC,0x23,0xA7,0xF2,0xF6,0xFA,0xE0, 0x03,0xEA,0xD3,0x68,0x4A,0x4A,0x52,0xA3,0x5A,0x50,0x22,0xD2,0xA5,0x48,0x52,0x40, 0x02,0x2E,0x95,0x48,0x72,0x49,0x53,0xA2,0x52,0x50,0x22,0x92,0xA7,0x4C,0x51,0x40, 0x02,0x28,0x95,0x48,0x42,0x48,0x92,0x22,0x52,0x50,0x22,0x92,0xA4,0x42,0x50,0x80, 0x07,0x77,0xDB,0xEC,0xE1,0x9C,0x9D,0x9F,0x7B,0xEC,0x1D,0xDF,0x43,0xEC,0xFC,0x80, 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, 0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

69 第 6 章 AT89S52 单片机扩展功能 C 语言编程 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; /******************************************* 函数名称 : lcd12864_delay 功 能 : lcd12864 延时子函数 参 数 : z 返回值 : 无 /********************************************/ void lcd12864_delay(uint z) uint i,j; // 延时 1ms 左右 for(i=z;i>0;i--) for(j=120;j>0;j--); /******************************************* 函数名称 : lcd12864_delay 功 能 : lcd12864 忙等待函数 参 数 : 无 返回值 : 无 /********************************************/ void lcd12864_busywait() // 等待 LCD 就绪 uchar Status; // 定义一个局部变量 LCD_RS=0; // 数据选择信号拉低 LCD_WR=1; // 读写选择信号置 1 LCD_Data=0xFF; // 向 中写入 0xFF LCD_E=1; // 使能端拉高 Status=LCD_Data; // 将数据信息送状态变量 LCD_E=0; // 使能端拉低 while(status&0x80) // 若 忙等待 LCD_E=1; Status=LCD_Data; LCD_E=0; LCD_WR=0; // 读写选择信号置 0 /******************************************* 函数名称 : lcd12864_write_data 功 能 : 向 lcd12864 写数据函数 参 数 : 无 返回值 : 无 /********************************************/ void lcd12864_write_data( uchar Data ) // 向 LCD 写入一个字节的数据 lcd12864_busywait(); // 忙等待 LCD_RS=1; LCD_Data=Data; // 写一个字节数据 LCD_E=1; LCD_E=0; /******************************************* 函数名称 : lcd12864_write_data 功能 : 向 lcd12864 写数据函数参数 : 无返回值 : 无

70 /********************************************/ void lcd12864_write_command( uchar Command )// 向 LCD 写入一个字节的命令 lcd12864_busywait(); // 忙等待 LCD_RS=0; LCD_Data=Command; LCD_E=1; LCD_E=0; /******************************************* 函数名称 : change_address ww.zicreate.com // 写一个字节的命令 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 功能 : 改变地址, 实现了逐行显示参数 : StartAddress 返回值 : StartAddress /********************************************/ uchar change_address(uchar StartAddress) switch(startaddress) case 0x87:lcd12864_write_command(0x90);StartAddress=0x90;break;// 第一行显示完, 地址指向第二行首地址 case 0x8F:lcd12864_write_command(0x98);StartAddress=0x98;break;// 若第三行显示完, 地址指向第四行首地址 case 0x97:lcd12864_write_command(0x88);StartAddress=0x88;break;// 若第二行显示完, 地址指向第三行首地址 default:startaddress+=1; return StartAddress; /******************************************* 函数名称 : write_lcd12864 功能 : 在 lcd12864 显示一个字符串, 参数 : StartAddress 为起始地址 ; Size 为字符串大小 ;Size==0 时由程序自己判断字符串结束标志, 否则输出 Size 个字符, 不够则填充空格 ; Charactors 为要求输出的字符串 ; 返回值 : 无 /********************************************/ void write_lcd12864(uchar StartAddress,uchar Size,uchar Charactors[]) uchar *i=charactors; // 字符串的首地址 lcd12864_write_command(startaddress);// 写入首地址 if(!size) //Size 为 0 while(*i) lcd12864_write_data(*i); i++; if('\0'==*i) // 判断字符串结尾,*i 为 0 代表结束 break; // 到达字符串的末尾就跳出循环 lcd12864_write_data(*i);// 将要显示的字符串送显示 i++; StartAddress=change_address(StartAddress);// 若一行显示完就转向下一行显示 /*******************************************

71 第 6 章 AT89S52 单片机扩展功能 C 语言编程 函数名称 : photo_display 功能 : 图片显示函数参数 : 无返回值 : 无 /********************************************/ void photo_display(uchar *address) uint i=0; uchar count1,count2,count3,lcd_x,lcd_y; // 定义一些中间变量 lcd_x=0x80; // 上半屏 X 坐标首地址 for(count3=2;count3>0;count3--) // 先显示上半屏, 再显示下半屏 lcd_y=0x80; //Y 坐标首地址 for(count2=32;count2>0;count2--) //1 屏 32 行, 一位一行, 一行 16 列, 一个字节一列 lcd12864_write_command(0x34); // 扩充指令集动作 _nop_(); lcd12864_write_command(lcd_y); // 设定绘图 RAM 地址 _nop_(); lcd12864_write_command(lcd_x); // 设定绘图 RAM 地址 _nop_(); lcd12864_write_command(0x30); // 基本指令集动作 _nop_(); for(count1=16;count1>0;count1--,i++)// 送每一行 16 个字节 _nop_(); lcd12864_write_data(*(address+i)); _nop_(); lcd_y++; // 每送一行,Y 坐标加 1 lcd_x=0x88; // 下半屏 X 坐标首地址 lcd12864_write_command(0x36); _nop_(); lcd12864_write_command(0x30); /******************************************* 函数名称 : lcd12864_init 功能 : lcd12864 初始化函数参数 : 无返回值 : 无 /********************************************/ void lcd12864_init() // 扩充指令集动作, 开绘图显示 // 基本指令集动作 lcd12864_write_command(0x01); // 清屏 lcd12864_delay(150); lcd12864_write_command(0x30); // 功能设置 8 位界面, lcd12864_delay(150); lcd12864_write_command(0x0c); lcd12864_delay(150); lcd12864_write_command(0x06); lcd12864_delay(150); /******************************************* 函数名称 : main 功参 能 : 主函数数 : 无 // 显示开, 光标关, 反白显示 //DDRAM 地址自加

72 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 返回值 : 无 /********************************************/ void main() lcd12864_init(); while(1) lcd12864_write_command(0x01); // 清屏 photo_display(&xiaohui); // 显示校徽图片 lcd12864_delay(2000); // 延时 lcd12864_write_command(0x01); // 清屏 photo_display(&xiaoming); // 显示校名图片 lcd12864_delay(2000); // 延时 lcd12864_write_command(0x01); // 清屏 write_lcd12864(0x80,0," 张朋真 电子信息工程 zpz2005@139.com TEL: ");// 显示信息字符 lcd12864_delay(2000); // 延时 6.3 独立键盘输入 独立键盘的电路原理图如图 5-6 所示 : 独立键盘的 C 语言程序如下所示 : /********************************************************************** * 程序名 : 独立键盘实验 ( 晶振 MHZ) * 功 能 : 数码管上显示 00~99 按一下 K1 数值加 1, 按一下 K2 数值减 1 * 编程者 : ZPZ * 编程时间 :2008/9/14 **********************************************************************/ #include<reg52.h> // 包含头文件 #define uchar unsigned char // 宏定义 #define uint unsigned int #define data_bus P0 sbit wei1=p1^1; // 定义位选口 sbit wei2=p1^0; sbit key1=p3^2; // 定义键盘口 sbit key2=p3^3; uchar counter=0; // 定义一个全局变量 uchar code table[]= 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90;// 定义断码表 0~9 /******************************************* 函数名 :delay 功能 : 延时 1ms 左右 参数 :z 返回值 : 无 ********************************************/ void delay(uint z) uint i,j; // 定义局部变量 for(i=z;i>0;i--) // 循环 for(j=120;j>0;j--); // 循环 ww.zicreate.com

73 第 6 章 AT89S52 单片机扩展功能 C 语言编程 图 6-6 独立键盘的电路原理图 /******************************************* 函数名 : key_scan() 功能 : 键盘扫面函数参数 : 无返回值 : 无 /********************************************/ void key_scan() if(key1==0) // 判断 k1 是否按下 delay(10); // 延时消抖 if(key1==0) // 再次判断 k1 是否按下 if(counter>=99) // 如果 counter=99,counter 清 0 counter=0; counter++; // 如果 k1 按下 counter+1 while(key1==0); // 判断 k1 是否松开 if(key2==0) // 判断 k2 是否按下 delay(10); // 延时消抖 if(key2==0) // 再次判断 k2 是否按下

74 if(counter==0) // 如果 counter=0,counter=99 counter=99; counter--; // 如果 k2 按下 counter-1 while(key2==0); // 判断 k2 是否松开 /******************************************* 函数名 :display 功能 : 显示函数 参数 :shi,ge 返回值 : 无 ********************************************/ void display(uchar shi,uchar ge) wei1=0; wei2=1; // 选通第一个数码管关断另一个 data_bus=table[shi]; // 送要显示的段码 delay(2); wei2=0; wei1=1; // 选通第二个数码管 / 关断另一个 data_bus=table[ge]; // 送要显示的段码 delay(2); /******************************************* 函数名 : main 功 能 : 主函数 参 数 : 无 返回值 : 无 /********************************************/ void main() while(1) key_scan(); // 键盘扫面 display(counter/10,counter%10); // 送显示 6.4 矩阵键盘输入 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 4 4 矩阵键盘的电路原理图如图 5-7 所示 : 4 4 矩阵键盘的 C 语言程序 : /********************************************************************** * 程序名 ; 4 4 矩阵键盘实验 ( 晶振 MHZ) * 功能 : 当按键按下时, 数码管显示相应的键值 0~f * 编程者 : ZPZ * 编程时间 :2008/9/14 **********************************************************************/ #include<reg52.h> // 包含头文件 #define uchar unsigned char // 宏定义 #define uint unsigned int #define key_input P2 // 定义键盘口 #define data_bus P0 // 定义显示数据口 uchar key_value=0; // 定义一个全局变量 sbit wei1=p1^0; // 定义位选口 sbit wei2=p1^1; uchar code table[]= 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e;// 定义显示断码表 0~f ww.zicreate.com

75 第 6 章 AT89S52 单片机扩展功能 C 语言编程 图 矩阵键盘电路原理图 /********************************** 函数名 :delay 功能 : 延时 1ms 左右 参数 :z 返回值 : 无 ***********************************/ void delay(uint z) uint i,j; // 定义局部变量 for(i=z;i>0;i--) // 循环 for(j=120;j>0;j--); // 循环 /******************************************* 函数名 : key_scan() 功 能 : 键盘扫描函数 参 数 : 无 返回值 : 0 或 (~sccode)+(~recode) 键值编码 /********************************************/ uchar key_scan() uchar sccode,recode; // 定义两个局部变量 key_input=0xf0; // 键盘口高四位送 1, 低四位送 0 if((key_input&0xf0)!=0xf0) // 判断是否有按键按下 delay(10); // 延时 10ms 消抖 if((key_input&0xf0)!=0xf0) // 再次判断是否有按键按下 sccode=0xfe; // 把 0xfe 送 sccode while((sccode&0x10)!=0) key_input=sccode; // 逐次给低四位送

76 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 if((key_input&0xf0)!=0xf0) // 判断是哪一个按键按下 recode=(key_input&0xf0) 0x0f; return((~sccode)+(~recode)); // 返回键值编码 else sccode=(sccode<<1) 0x01; // 无按键按下扫描下一行 return(0); // 无按键按下返回 0 /********************************** 函数名 :display 功能 : 根据键值编码显示送显示相应键值函数参数 :buffer_key 返回值 : 无 ***********************************/ void display(uchar buffer_key) wei1=0; wei2=1; if(buffer_key==0x88) data_bus=table[0]; if(buffer_key==0x84) data_bus=table[1]; if(buffer_key==0x82) data_bus=table[2]; if(buffer_key==0x81) data_bus=table[3]; if(buffer_key==0x48) data_bus=table[4]; if(buffer_key==0x44) data_bus=table[5]; if(buffer_key==0x42) data_bus=table[6]; if(buffer_key==0x41) data_bus=table[7]; if(buffer_key==0x28) data_bus=table[8]; if(buffer_key==0x24) data_bus=table[9]; if(buffer_key==0x22) data_bus=table[10]; if(buffer_key==0x21) data_bus=table[11]; if(buffer_key==0x18) data_bus=table[12]; if(buffer_key==0x14) data_bus=table[13]; if(buffer_key==0x12) data_bus=table[14]; if(buffer_key==0x11) data_bus=table[15]; /******************************************* 函数名 : main 功能 : 主函数参数 : 无返回值 : 无 // 选通第一个数码管 // 关断另一个 // 如果键盘口值为 0x88, 送 0 显示 // 如果键盘口值为 0x84, 送 1 显示 // 如果键盘口值为 0x82, 送 2 显示 // 如果键盘口值为 0x81, 送 3 显示 // 如果键盘口值为 0x48, 送 4 显示 // 如果键盘口值为 0x44, 送 5 显示 // 如果键盘口值为 0x42, 送 6 显示 // 如果键盘口值为 0x41, 送 7 显示 // 如果键盘口值为 0x28, 送 8 显示 // 如果键盘口值为 0x24, 送 9 显示 // 如果键盘口值为 0x22, 送 a 显示 // 如果键盘口值为 0x21, 送 b 显示 // 如果键盘口值为 0x18, 送 c 显示 // 如果键盘口值为 0x14, 送 d 显示 // 如果键盘口值为 0x12, 送 e 显示 // 如果键盘口值为 0x11, 送 f 显示

77 第 6 章 AT89S52 单片机扩展功能 C 语言编程 /********************************************/ void main () while(1) key_value=key_scan(); // 读取键值编码 display(key_value); // 显示键值 6.5 A/D 和 D/A 转换 1. 基于 ADC0832 的 A/D 转换实例 图 6-8 ADC0832 转换电路图 ADC0832 的 A/D 转换的 C 语言程序 : /********************************************************************** * 程序名 ;ADC0832 A/D 转换实例 * 功能 ; 通过调节电位器使得输入到 ADC0832 得模拟量电压值发生变化,ADC0832 * 将转换成的数字量在数码管上以电压值的形式显示出来 * 编程者 ;ZPZ * 编程时间 ;2008/11/15 **********************************************************************/ #include<reg52.h> // 包含头文件 #include <intrins.h> #include "adc0832.h" #define uint unsigned int // 变量类型宏定义 #define uchar unsigned char uint temp; // 定义全局变量 uchar bai,shi,ge; uchar code table1[]=0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10;// 带小数点的数字段码表 0.~9. uchar code table2[]=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90;// 数字段码表 0~9 /********************************** 函数名 :delay 功能 : 延时 1ms 左右参数 :z 返回值 : 无 ***********************************/ void delay(uint z) uint i,j; // 定义局部变量 for(i=z;i>0;i--) // 循环 for(j=120;j>0;j--); // 循环 /********************************** 函数名 :display 功能 : 显示电压值参数 :bai,shi,ge 返回值 : 无

78 ***********************************/ 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 void display(uint bai,uint shi,uint ge) P1=0xfb; // 开第一个数码管显示 P0=table1[bai]; // 送第一个数码管显示 delay(2); // 延时 P1=0xfd; // 开第二个数码管显示 P0=table2[shi]; // 送第二个数码管显示 delay(2); // 延时 P1=0xfe; // 开第三个数码管显示 P0=table2[ge]; // 送第三个数码管显示 delay(2); // 延时 /******************************************* 函数名 : main 功能 : 主函数参数 : 无返回值 : 无 /********************************************/ void main() while(1) temp=read_adc0832()*1.96; bai=temp/100; shi=temp%100/10; ge=temp%10; display(bai,shi,ge); // 主循环 // 读取转换后的数字量 // 显示前转换 // 显示电压值 /********************************************************************** * 程序名 ; adc0832_h * 功能 : adc0832 的 c51 编程头文件 * 编程者 : ZPZ * 编程时间 :2008/11/15 **********************************************************************/ #ifndef adc0832_h #define adc0832_h #include <intrins.h> #define uchar unsigned char #define uint unsigned int // 变量类型宏定义 sbit DI= P2^2; // 定义 ADC0832 数据口 sbit CLK= P2^1; // 定义 ADC0832 时钟口 sbit CS= P2^0; // 定义 ADC0832 使能口 /******************************************* 函数名称 : adc0832_init 功能 : adc0832 初始化函数参数 : 无返回值 : 无 /********************************************/ void adc0832_init() ww.zicreate.com

79 第 6 章 AT89S52 单片机扩展功能 C 语言编程 CLK=0; CS=1; _nop_(); CS=0; _nop_(); DI=1; CLK=1; _nop_(); CLK=0; // 芯片复位 // 启动位 DI=1; // 配置位 1 CLK=1; _nop_(); CLK=0; DI=0; // 配置位 2 CLK=1; _nop_(); CLK=0; // 空闲位 _nop_(); CLK=1; DI=1; /******************************************* 函数名称 : adc0832_readbyte() 功能 : 读取 adc0832 转换值函数参数 : 无返回值 : dat /********************************************/ uchar adc0832_readbyte() uchar dat,i; for(i=0;i<=8;i++) // 读出 8 字节数据 return(dat); dat=dat<<1; _nop_(); CLK=1; // 这里要先 1 后 0... 如果是先 0 后 1 则输出结果错误... if(di) dat =0x01; _nop_(); CLK=0; /******************************************* 函数名称 : read_adc0832 // 返回转换值 功能 : 读取 adc0832 转换值函数参数 : 无返回值 : dat /********************************************/ uchar read_adc0832() uchar dat;

80 adc0832_init(); dat=adc0832_readbyte(); CS=1; return(dat); #endif 2. 基于 TLC5615 的 D/A 转换实例 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 // 初始化 adc0832 // 读取转换后的数字量 // 关闭芯片 // 返回数据 图 6-9 TLC5615 应用电路原理图 TLC5615 的 D/A 转换 C 语言程序 : /********************************************************************** * 程序名 ;TLC5615 D/A 转换实例 * 功能 ; 通过改变输入数字量 0~1000, 使得发光二极管由暗逐渐变亮 * 编程者 ;ZPZ * 编程时间 ;2008/11/20 **********************************************************************/ #include<reg52.h> // 包含头文件 #include <intrins.h> #define uint unsigned int // 变量类型宏定义 #define uchar unsigned char sbit CS=P2^0; // 定义片选信号 IO 口 sbit SCLK=P2^1; // 定义时钟信号 IO 口 sbit DIN=P2^2; // 定义数据输入 IO 口 uchar t0_1s=0; // 定义定时器 0 中间变量 uint num=0; // 定义全局变量数字输入量 num /********************************** 函数名 :timer0_init 功能 :T0 初始化函数参数 :f 返回值 : 无 ***********************************/ void timer0_init(bit f) TMOD=0x01; // 定时器 0 工作在方式 1 TH0=0x3c; // 定时器赋初值 50ms TL0=0xb0; ET0=1; // 开 T0 中断 EA=1; // 开总中断 TR0=f; //f 为 1 启动定时器 0, 为 0 禁止定时器 0 /********************************** 函数名 :tlc5615_da ww.zicreate.com

81 第 6 章 AT89S52 单片机扩展功能 C 语言编程 功能 :D/A 转换函数参数 :f 返回值 : 无 ***********************************/ void tlc5615_da(uint dat) uchar i; // 定义局部变量 i dat<<=6; // 将 dat 的数据依次向左移 6 位, 取低 10 位的值 CS=0; // 使能芯片 SCLK=0; // 在以下的 12 个时钟周期, 上升沿时数据锁存行程 DA 输出 for (i=0;i<12;i++) // 前 10 个时钟是 10 位 DA 数据位, 后两个时钟是填充字节 DIN=(bit)(dat&0x8000); SCLK=1; dat<<=1; SCLK=0; CS=1; // CS 的上升沿和下降沿只有在 clk 为低的时候才有效 SCLK=0; for (i=0;i<12;i++); /******************************************* 函数名 : main 功能 : 主函数参数 : 无返回值 : 无 /********************************************/ void main () timer0_init(1); // 定时器 0 初始化 while(1) // 主循环 tlc5615_da(num); //DA 转换 /********************************** 函数名 :timer0 功能 : 定时器 0 中断函数参数 : 无返回值 : 无 ***********************************/ void timer0() interrupt 1 using 0 TH0=0x3c; // 重新赋初值 TL0=0xb0; t0_1s+=1; // 变量 t0_1s 加 1 if(t0_1s==2) // 中断 2 次定时 100ms t0_1s=0; // 变量 t0_1s 清 0 num+=10; // 数字量每次加 10 if(num>=1000) // 如果数字量达到 1000, 则清 0 num=0;

82 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 ww.zicreate.com

83 第 7 章 AT89S52 单片机控制系统应用实例设计 7.1 AT89S52 单片机控制的模拟交通灯系统设计系统实物图 : 系统原理图 : 图 7-1 AT89S52 单片机控制的模拟交通灯系统实物图 图 7-2 AT89S52 单片机控制的模拟交通灯系统原理图

84 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 系统功能描述 : 南北每次通行时间设为 30 秒 东西每次通行间设为 20 秒, 通行时间按 K1 可进行设置修改 按 K1 一次进入调南北通行时间模式, 再按一次 K1 进入调东西通行时间模式, 再按一次 K1 退出设定通行时间模式, 进入设定通行时间模式后按 K2 加 1, 按 K3 减 1 再正常模式下按一下 K2 进入禁止南北通行模式, 再按一下 K2 进入禁止东西通行模式, 再按一下 K2 退出 在正常模式下按一下 K3 进入紧急模式, 再按一下 K3 进入夜间模式, 再按一下 K3 退出 系统的 KEILC51 程序 : /******************************************************************** * 程序名 ; 单片机控制的交通灯 * 功能 : 南北每次通行时间设为 30 秒 东西每次通行间为 20 秒, 时间按 K1 可设置修改 * 按 K1 一次进入调南北通行时间, 再按一次 K1 进入调东西通行时间 再按一次 K1 退出设定 * 通行时间模式, 进入设定通行时间模式后按 K2 加 1, 按 K3 减 1 再正常模式下按 K2 进入禁 * 止南北通行模式, 再按一下 K2 进入禁止东西通行模式, 再按一下 K2 退出 在正常模式下 * 按一下 K3 进入紧急模式, 再按一下 K3 进入夜间模式, 再按一下 K3 退出 * 编程者 : ZPZ * 编程时间 :2009/10/2 *********************************************************************/ #include<at89x52.h> // 将 AT89X52.h 头文件包含到主程序 #define uint unsigned int / 变量类型宏定义 #define uchar unsigned char #define data_bus P0 // 定义数据口 #define shu 5 char sn_num0=30,ew_num0=20; // 定义全局变量 char sn_num,ew_num; uchar a=0,num=0,i=0,j=0,k=0; bit b=0; // 定义位标志 bit c=0; bit v=1; sbit sn_h=p2^7; // 定义数码管的位选口 sbit sn_l=p2^6; sbit ew_h=p2^5; sbit ew_l=p2^4; sbit n_red=p1^2; // 定义 led 灯口 sbit n_yellow=p1^1; sbit n_green=p1^0; sbit s_red=p1^6; sbit s_yellow=p1^7; sbit s_green=p2^0; sbit e_red=p1^3; sbit e_yellow=p1^4; sbit e_green=p1^5; sbit w_red=p2^3; sbit w_yellow=p2^2; sbit w_green=p2^1; sbit k1=p3^2; // 定义键盘口 sbit k2=p3^1; sbit k3=p3^0; uchar code num_table[]= 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f; // 定义显示段码 uchar code num_table1[]= 0x00,0x71; /*********************** 延时子函数 ************************/ void delay(uint t) uint i,j; for(i=t;i>0;i--) for(j=120;j>0;j--);

85 第 7 章 AT89S52 单片机控制系统应用实例设计 /************************** 定时器 1 初始化函数 ***************************/ void timer0_init(bit t) TMOD=0x01; // 定时器 0 工作在方式 1 TH0=0x3c; // 赋初值 TL0=0xb0; EA=1; // 开总中断 ET0=1; // 允许定时器 0 中断 TR0=t; // 为 1 启动定时器 0 /************************** 定时器 1 中断函数 *****************************/ void timer0() interrupt 1 TH0=0x3c; // 重复初值 (50ms) TL0=0xb0; num++; if(num==20) // 定时 1 分钟 (20*50ms) c=~c; //c 取反用于黄灯和数码管闪烁 if(b==0) sn_num--; // 一分钟南北通行时间减 1 if(sn_num<0) b=1;sn_num=sn_num0; else ew_num--; // 一分钟东西通行时间减 1 if(ew_num<0) b=0;ew_num=ew_num0; num=0; /*********************** 显示函数 ************************/ void display(char sn_n,char ew_n) uchar i; for(i=0;i<4;i++) switch(i) case 0: if(a==0)data_bus=num_table[sn_n/10];// 数码管 1 显示南北通行时间的十位 else if(a==1) data_bus=num_table[sn_n/10]; else if(a==2) else data_bus=num_table1[0]; if(c==0) data_bus=num_table1[1]; else data_bus=num_table1[0]; // 数码管 1 不显示 // 数码管 1 显示 F

86 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 ew_h=0; // 关其他的三个数码管 ew_l=0; sn_l=0; sn_h=1; // 开数码管 1 break; case 1: if(a==0)data_bus=num_table[sn_n%10];// 数码管 2 显示南北通行时间的个位 else if(a==1) data_bus=num_table[sn_n%10]; else if(a==2) data_bus=num_table1[0]; else if(c==0) data_bus=num_table1[1]; else data_bus=num_table1[0]; ew_h=0; ew_l=0; sn_h=0; sn_l=1; break; case 2: if(a==0)data_bus=num_table[ew_n/10];// 数码管 3 显示东西通行时间的十位 else if(a==1) data_bus=num_table1[0]; else if(a==2) data_bus=num_table[ew_n/10]; else if(c==0) data_bus=num_table1[1]; else data_bus=num_table1[0]; sn_h=0; sn_l=0; ew_l=0; ew_h=1; break; case 3: if(a==0)data_bus=num_table[ew_n%10];// 数码管 4 显示东西通行时间的个位 else if(a==1) data_bus=num_table1[0]; else if(a==2)

87 第 7 章 AT89S52 单片机控制系统应用实例设计 else delay(3); sn_h=0; sn_l=0; ew_h=0; ew_l=1; break; data_bus=num_table[ew_n%10]; if(c==0) data_bus=num_table1[1]; else data_bus=num_table1[0]; /*********************** 键盘扫描函数 ************************/ void keyscan() if(k1==0) delay(10); if(k1==0) // 键盘消抖 TR0=0; // 关定时器 0 v=0; // 标志位 v 赋 0,v 为 0 时 K2K3 实现时间的加减功能 i++; if(i>2) v=1; // 标志位 v 赋 1,v 为 1 时 K2K3 实现强制南北 强制东西 紧急 夜间功能 TR0=1; // 开定时器 0 i=0; sn_num=sn_num0;// 存储调节好的时间供调节返回后立即从设定好的值执行 ew_num=ew_num0; switch(i) case 0:a=0;break; case 1:a=1;break; case 2:a=2;break; // 选择显示模式 default:break; while(k1==0); delay(10); if(k2==0) delay(10); if(k2==0) if(v==0) if(a==1) // 通行时间加加

88 sn_num0++; if(sn_num0>99) sn_num0=99; if(a==2) ew_num0++; if(ew_num0>99) ew_num0=99; if(v==1) // 进入禁止南北 禁止东西通行模式 j++; if(j==0) a=0; else if(j==1) a=3; else if(j==2) a=4; else a=0; j=0; sn_num=sn_num0; ew_num=ew_num0; while(k2==0); delay(10); 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 if(k3==0) delay(10); if(k3==0) if(v==0) if(a==1) // 通行时间加加 sn_num0--; if(sn_num0<0) sn_num0=0; if(a==2) ew_num0--; if(ew_num0<0) ew_num0=0; if(v==1) // 进入紧急 夜间通行模式 k++; ww.zicreate.com

89 第 7 章 AT89S52 单片机控制系统应用实例设计 if(k==0) a=0; else if(k==1) a=5; else if(k==2) a=6; else a=0; k=0; sn_num=sn_num0; ew_num=ew_num0; while(k3==0); delay(10); /***********************led 控制函数 ************************/ void cotrol_led() if(a==0) if(b==0) s_red=1; n_red=1; e_yellow=1; // 关东西黄灯 w_yellow=1; e_green=1; // 关东西绿灯 w_green=1; n_green=0; // 开南北绿灯 s_green=0; if(sn_num>=shu) s_yellow=1; n_yellow=1; e_red=0; w_red=0; if(sn_num<shu) n_green=1; s_green=1; // 时间大于 shu 时 // 关南北黄灯 // 开东西红灯 // 时间小于 shu 时 // 关南北绿灯 if(c==1) else s_yellow=1; n_yellow=1; // 南北黄灯闪烁

90 s_yellow=0; n_yellow=0; display(sn_num,sn_num); // 显示南北通行时间 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 if(b==1) e_red=1; w_red=1; s_yellow=1; n_yellow=1; n_green=1; s_green=1; e_green=0; w_green=0; if(ew_num>=5) e_yellow=1; w_yellow=1; s_red=0; n_red=0; if(ew_num<5) e_green=1; w_green=1; if(c==1) e_yellow=1; w_yellow=1; else e_yellow=0; w_yellow=0; display(ew_num,ew_num); else if(a==1) n_red=1; n_yellow=1; n_green=1; // 显示东西通行时间 // 设定时间时关闭所有灯 s_red=1; s_yellow=1; s_green=1; e_red=1; e_yellow=1; ww.zicreate.com

91 第 7 章 AT89S52 单片机控制系统应用实例设计 e_green=1; w_red=1; w_yellow=1; w_green=1; display(sn_num0,sn_num0); // 显示设定的南北时间 if(a==2) n_red=1; // 设定时间时关闭所有灯 n_yellow=1; n_green=1; s_red=1; s_yellow=1; s_green=1; e_red=1; e_yellow=1; e_green=1; w_red=1; w_yellow=1; w_green=1; display(ew_num0,ew_num0); // 显示设定的东西时间 if(a==3) // 南北禁止模式下南北红灯亮, 东西绿灯亮 n_red=0; n_yellow=1; n_green=1; s_red=0; s_yellow=1; s_green=1; e_red=1; e_yellow=1; e_green=0; w_red=1; w_yellow=1; w_green=0; display(sn_num,sn_num); // 显示 FF if(a==4) // 东西禁止模式下南北绿灯亮, 东西红灯亮 n_red=1; n_yellow=1; n_green=0; s_red=1; s_yellow=1; s_green=0; e_red=0; e_yellow=1; e_green=1; w_red=0; w_yellow=1; w_green=1; display(ew_num,ew_num); // 显示 FF if(a==5) // 紧急模式下东西南北红灯亮 n_red=0;

92 n_yellow=1; n_green=1; 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 s_red=0; s_yellow=1; s_green=1; e_red=0; e_yellow=1; e_green=1; w_red=0; w_yellow=1; w_green=1; display(ew_num,ew_num); // 显示 FF if(a==6) // 夜间模式下东西南北绿灯亮 n_red=1; n_yellow=1; n_green=0; s_red=1; s_yellow=1; s_green=0; e_red=1; e_yellow=1; e_green=0; w_red=1; w_yellow=1; w_green=0; display(ew_num,ew_num); // 显示 FF /*********************** 主函数 ************************/ void main() sn_num=sn_num0; // 赋设定好的时间 ew_num=ew_num0; timer0_init(1); // 启动定时器 0 while(1) // 主循环 keyscan(); // 键盘扫描 cotrol_led(); //LED 灯控制 7.2 基于 AT89S52 单片机及 DS18B20 温度传感器的测温系统设计 数码管显示系统功能概述 : 实时测量温度, 超过上下限报警, 报警温度可手动调整 K1 是用来进入上下限调节模式的, 当按一下 K1 进入上限调节模式, 再按一下进入下限调节模式 在正常模式下, 按一下 K2 进入查看上限温度模式, 显示 1s 左右自动退出 ; 按一下 K3 进入查看下限温度模式, 显示 1s 左右自动退出 ; 按一下 K4 消除按键音, 再按一下启动按键音 在调节上下限温度模式下,K2 是实现加 1 功能,K3 是实现减 1 功能, K4 是用来设定上下限温度正负的 ww.zicreate.com

93 第 7 章 AT89S52 单片机控制系统应用实例设计 系统原理图 : 图 7-3 基于 AT89S52 单片机的温度测量系统原理图

94 系统实物图 : 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 图 7-4 基于 AT89S52 单片机的温度测量系统实物图 系统的 KEILC51 程序 : /******************************************************************** * 程序名 ; 基于 DS18B20 的测温系统 * 功 能 : 实时测量温度, 超过上下限报警, 报警温度可手动调整 K1 是用来 * 进入上下限调节模式的, 当按一下 K1 进入上限调节模式, 再按一下进入下限 * 调节模式 在正常模式下, 按一下 K2 进入查看上限温度模式, 显示 1s 左右自动 * 退出 ; 按一下 K3 进入查看下限温度模式, 显示 1s 左右自动退出 ; 按一下 K4 消除 * 按键音, 再按一下启动按键音 在调节上下限温度模式下,K2 是实现加 1 功能, * K1 是实现减 1 功能,K3 是用来设定上下限温度正负的 * 编程者 :ZPZ * 编程时间 :2009/10/2 *********************************************************************/ #include<at89x52.h> // 将 AT89X52.h 头文件包含到主程序 #include<intrins.h> // 将 intrins.h 头文件包含到主程序 ( 调用其中的 _nop_() 空操作函数延时 ) #define uint unsigned int // 变量类型宏定义, 用 uint 表示无符号整形 (16 位 ) #define uchar unsigned char // 变量类型宏定义, 用 uchar 表示无符号字符型 (8 位 ) uchar max=0x00,min=0x00; //max 是上限报警温度,min 是下限报警温度 bit s=0; //s 是调整上下限温度时温度闪烁的标志位,s=0 不显示 200ms,s=1 显 示 1s 左右 bit s1=0; //s1 标志位用于上下限查看时的显示 void display1(uint z); // 声明 display1() 函数 #include"ds18b20.h" // 将 ds18b20.h 头文件包含到主程序 #include"keyscan.h" // 将 keyscan.h 头文件包含到主程序 #include"display.h" // 将 display.h 头文件包含到主程序 /*********************** 主函数 ************************/ void main() beer=1; // 关闭蜂鸣器 led=1; // 关闭 LED 灯 timer1_init(0); // 初始化定时器 1( 未启动定时器 1) get_temperature(1); // 首次启动 DS18B20 获取温度 (DS18B20 上点后自动将 EEPROM 中 的上下限温度复制到 TH 和 TL 寄存器 ) ww.zicreate.com

95 第 7 章 AT89S52 单片机控制系统应用实例设计 while(1) // 主循环 keyscan(); // 按键扫面函数 get_temperature(0); // 获取温度函数 keyscan(); // 按键扫面函数 display(temp,temp_d*0.625); // 显示函数 alarm(); // 报警函数 keyscan(); // 按键扫面函数 /******************************************************************** * 程序名 ; ds18b20_h * 功能 : DS18B20 的 c51 编程头文件 * 编程者 :ZPZ * 编程时间 :2009/10/2 * 说明 : 用到的全局变量是 : 无符号字符型变量 temp( 测得的温度整数部分 ),temp_d * ( 测得的温度小数部分 ), 标志位 f( 测量温度的标志位 0 表示 正温度 1 表 * 示 负温度 ), 标志位 f_max( 上限温度的标志位 0 表示 正温度 1 表 * 示 负温度 ), 标志位 f_min( 下限温度的标志位 0 表示 正温度 1 表 * 示 负温度 ), 标志位 w( 报警标志位 1 启动报警 0 关闭报警 ) *********************************************************************/ #ifndef ds18b20_h // 定义头文件 #define ds18b20_h #define uint unsigned int // 变量类型宏定义, 用 uint 表示无符号整形 (16 位 ) #define uchar unsigned char // 变量类型宏定义, 用 uchar 表示无符号字符型 (8 位 ) sbit DQ= P2^3; // 可位寻址变量定义, 用 DQ 表示 P2.3 口 sbit beer=p1^0; // 用 beer 表示 P1.0 sbit led=p1^1; // 用 led 表示 P1.1 uchar temp=0; // 测量温度的整数部分 uchar temp_d=0; // 测量温度的小数部 bit f=0; // 测量温度的标志位,0 表示 正温度 1 表示 负温度 ) bit f_max=0; // 上限温度的标志位 0 表示 正温度 1 表示 负温度 ) bit f_min=0; // 下限温度的标志位 0 表示 正温度 1 表示 负温度 ) bit w=0; // 报警标志位 1 启动报警 0 关闭报警 ) /***************************** 延时子函数 ******************************/ void ds18b20_delayus(uint t) // 延时几 μs while(t--); void ds18b20_delayms(uint t) // 延时 1ms 左右 uint i,j; for(i=t;i>0;i--) for(j=120;j>0;j--); /**************************ds18b20 初始化函数 *************************/ void ds18b20_init() // DS18B20 初始化 DQ=1; // 拉高数据线 DQ=0; // 控制器向 DS18B20 发低电平脉冲 ds18b20_delayus(30); // 延时 480μs 左右 DQ=1; // 控制器拉高总线, while(dq); // 等待 DS18B20 拉低总线 ds18b20_delayus(20); // 延时, 等待上拉电阻拉高总线 DQ=1; // 拉高数据线, 准备数据传输 ; /***************************ds18b20 字节读函数 ************************/ uchar ds18b20_read() //DS18B20 字节读取 uchar i; // 定义一个局部变量 i( 局部变量只在本函数中有效 ) uchar d = 0; // 定义一个局部变量 d DQ = 1; // 准备读 ; for(i=8;i>0;i--) // 一位一位的读, 循环 8 次

96 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 d >>= 1; //d 左移一位, 低位先发 ; DQ = 0; _nop_();_nop_();_nop_(); DQ = 1; // 必须写 1, 否则读出来的将是不预期的数据 ; if(dq) // 在 12us 处读取数据, 送给 d 的最高位 d = 0x80; ds18b20_delayus(10); return d; // 返回读取的值 /*************************ds18b20 字节写函数 **************************/ void ds18b20_write(uchar d) // ds18b20 字节写 uchar i; for(i=8;i>0;i--) // 一位一位的写 DQ=0; _nop_(); _nop_();_nop_(); DQ=d&0x01; // 写数据 ds18b20_delayus(5); DQ=1; d >>= 1; /*************************** 获取温度函数 ****************************/ void get_temperature(bit f) uchar a=0,b=0,c=0,d=0; uint i; ds18b20_init(); //DS18B20 初始化 ds18b20_write(0xcc);// 向 DS18B20 发跳过读 ROM 命令 ds18b20_write(0x44);// 写启动 DS18B20 进行温度转换命令, 转换结果存入内部 RAM if(f==1) // 首次启动 DS18B20 进行温度转换需要 500ms, 若转换时间不够就出错, 读出的是 85 度的错误值 display1(1); // 用开机动画耗时 else ds18b20_delayms(1); ds18b20_init(); //DS18B20 初始化 ds18b20_write(0xcc); // 向 DS18B20 发跳过读 ROM 命令 ds18b20_write(0xbe); // 写读内部 RAM 中 9 字节的内容命令 a=ds18b20_read(); // 读内部 RAM (LSB) b=ds18b20_read(); // 读内部 RAM (MSB) if(f==1) // 局部位变量 f=1 时读上下线报警温度 max=ds18b20_read(); // 读内部 RAM (TH) min=ds18b20_read(); // 读内部 RAM (Tl) if((max&0x80)==0x80) // 若读取的上限温度的最高位 ( 符号位 ) 为 1 表明是负温度 f_max=1;max=(max-0x80); // 将上限温度符号标志位置 1 表示负温度, 将上限温度装换成无符号数 if((min&0x80)==0x80) // 若读取的下限温度的最高位 ( 符号位 ) 为 1 表明是负温度 f_min=1;min=(min-0x80); // 将下限温度符号标志位置 1 表示负温度, 将下限温度装换成无符号数 i=b;i>>=4; if (i==0) f=0; //i 为 0, 表示读取的温度是正温度, 设立正温度标记 temp=((a>>4) (b<<4)); // 整数部分 a=(a&0x0f); temp_d=a; // 小数部分

97 第 7 章 AT89S52 单片机控制系统应用实例设计 else f=1; //i 为 1, 表示读取的温度是负温度, 设立负温度标记 a=~a+1; // 负数的小数部分取反加 1 b=~b; // 负数的整数部分取反 temp=((a>>4) (b<<4)); // 整数部分 a=(a&0x0f); // 小数部分 temp_d=a; /************************* 存储极限温度函数 ***************************/ void store_t() if(f_max==1) / 若上限温度为负, 将上限温度转换成有符号数 ( 最高 1 是负,0 是正 ) max=max+0x80; if(f_min==1) // 若下限温度为负, 将上限温度转换成有符号数 min=min+0x80; ds18b20_init(); //DS18B20 初始化 ds18b20_write(0xcc); // 向 DS18B20 发跳过读 ROM 命令 ds18b20_write(0x4e); // 向 DS18B20 发写字节至暂存器 2 和 3(TH 和 TL) 命令 ds18b20_write(max); // 向暂存器 TH( 上限温度暂存器 ) 写温度 ds18b20_write(min); // 向暂存器 TL( 下限温度暂存器 ) 写温度 ds18b20_write(0xff); // 向配置寄存器写命令, 进行温度值分辨率设置 ds18b20_init(); //DS18B20 初始化 ds18b20_write(0xcc); // 向 DS18B20 发跳过读 ROM 命令 ds18b20_write(0x48); // 向 DS18B20 发将 RAM 中 2 3 字节的内容写入 EEPROM //DS18B20 上电后会自动将 EEPROM 中的上下限温度拷贝到 TH TL 暂存器 /************************** 温度超限报警函数 *************************/ void alarm() // 若上限值是正值 if(f_max==0) if(f_min==0) // 若下限值是正值 if(f==0) // 若测量值是正值 if((temp+temp_d*0.0625)<=min (temp+temp_d*0.0625)>=max) w=1;tr1=1; // 当测量值小于最小值或大于最大值时报警 if((temp+temp_d*0.0625)<max&&(temp+temp_d*0.0625)>min) w=0; // 当测量值大于最小值且小于最大值时不报警 if(f==1)w=1;tr1=1; // 若测量值是负值时报警 if(f_min==1) // 若下限值是负值 if(f==0) // 若测量值是正值 if((temp+temp_d*0.0625)>=max)// 当测量值大于最大值时报警 w=1;tr1=1; if((temp+temp_d*0.0625)<max )// 当测量值小于最大值时不报警 w=0; if(f==1) // 若测量值是负值 if((temp+temp_d*0.0625)>=min)// 当测量值大于最小值时报警 w=1;tr1=1; if((temp+temp_d*0.0625)<min)// 当测量值小于最小值时不报警 w=0;

98 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 if(f_max==1) // 若下限值是负值 if(f_min==1) // 若下限值是负值 if(f==1) // 若测量值是负值 if((temp+temp_d*0.0625)<=max (temp+temp_d*0.0625)>=min) w=1;tr1=1; // 当测量值小于最大值或大于最小值时报警 if((temp+temp_d*0.0625)<min&&(temp+temp_d*0.0625)>max) w=0; // 当测量值小于最小值且大于最大值时不报警 if(f==0)w=1;tr1=1; // 若测量值是正值时报警 #endif /********************************************************************** * 程序名 ; keyscan_h * 功 能 : ds18b20 键盘头文件, 通过键盘设定设定上下限报警温度 * 编程者 :ZPZ * 编程时间 :2009/10/2 **********************************************************************/ #ifndef keyscan_h // 定义头文件 #define keyscan_h sbit key1=p2^2; // 可位寻址变量定义, 用 key1 表示 P2.2 口 sbit key2=p2^1; // 用 key2 表示 P2.1 口 sbit key3=p2^0; // 用 key3 表示 P2.0 口 sbit key4=p3^3; // 用 key4 表示 P3.3 口 uchar i=0; // 定义全局变量 i 用于不同功能模式的选择, 0 正常模式, 1 上限调节模式, 2 下限调节模式 uchar a=0; // 定义全局变量 a 用于不同模式下数码管显示的选择 bit k4=0; //K4 按键双功能选择位,k4=0 时 K4 按键选择消按键音的功能, k4=1 时 K4 按键选择正负温度设定功能 bit v=0; //K2 K3 按键双功能选择位,v=0 时选择上下限查看功能,v=1 时选择上下限温度加减功能 bit v1=0; //v1=1 时定时 1250ms 时间到自动关闭报警上下限查看功能 bit v2=0; // 消按键音功能调整位, 为 0 时开按键音, 为 1 时关按键 音 /*************************** 读键盘延时子函数 **************************/ void keyscan_delay(uint z) // 延时 1ms 左右 uint i,j; for(i=z;i>0;i--) for(j=120;j>0;j--); /**************************** 温度调节函数 ******************************/ int temp_change(int count,bit f) // 上下限温度调整 if(key2==0) // 判断 K2 是否按下 if(v2==0)beer=0; //v2=0 开按键音, 否则消按键音 keyscan_delay(10); // 延时 10ms if(key2==0) // 再次判断 K2 是否按下 ( 实现按按键时消抖 ) beer=1; //K2 按下关按键音 if(f==0) // 若温度为正 count++; // 每按一下 K2 温度上调 1 if(a==1)if(count>125) count=125;// 当温度值大于 125 时不上调 if(a==2)if(count>125) count=125;

99 第 7 章 AT89S52 单片机控制系统应用实例设计 if(f!=0) // 若温度为负 count++; // 每按一下 K2 温度下调 1 if(a==1)if(count>55) count=55;// 当温度值小于 -55 时不再下调 if(a==2)if(count>55) count=55; while(key2==0); keyscan_delay(10); //K2 松开按键时消抖 if(key3==0) if(v2==0)beer=0; keyscan_delay(10); if(key3==0) //K3 按按键时消抖 beer=1; count--; // 每按一下 K3 温度为正时下调 1, 为负时上调 1 if(a==1)if(count<0) count=0;// 当温度值达到 0 时不再调 if(a==2)if(count<0) count=0; while(key3==0); keyscan_delay(10); //K3 松开按键时消抖 return count; /***************************** 读键盘函数 ******************************/ void keyscan() if(key1==0) if(v2==0) beer=0; keyscan_delay(10); if(key1==0) //K1 按按键时消抖 beer=1; TR1=1;// 开定时器 1, 通过 s 标志位的变化, 实现在上下限温度调整时温度显示时闪烁的功 能 k4=1;// 在上下温度调节功能模式下选择 K4 的调整上下限温度正负的功能 v=1; // 在上下温度调节功能模式下选择 K2 K3 的温度加减功能 i++; //K1 按一下 i 加 1,i= 0 进入正常模式,i= 1 进入调上限模式,i= 2 进入调下限模式 if(i>2) //K1 按下三次后退出调节模式 i=0; // 进入正常模式 TR1=0; // 关定时器 1 k4=0; // 在正常模式下选择 K4 的消按键音功能 v=0; // 在正常模式下选择 K2 K3 的查看上下限报警温度功能 store_t(); // 存储调整后的上下限报警温度 switch(i) // 显示选择 case 0:a=0;break; //a=0 选择显示测得的温度 case 1:a=1;break; //a=1 选择显示上限温度 case 2:a=2;break; //a=2 选择显示下限温度 default:break; while(key1==0); //K1 松按键时消抖 keyscan_delay(10); if(a==1&&v==1) //a=1 选择显示上限温度且 v=1 时选择上下限温度加功能 led=0;max=temp_change(max,f_max);// 显示上限温度

100 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 else if(a==2&&v==1) //a=2 选择显示下限温度且 v=1 时选择上下限温度减功能 led=1;min=temp_change(min,f_min); else; if(k4==1) //k4=1 时 K4 按键选择正负温度设定功能 if(key4==0) if(v2==0)beer=0; keyscan_delay(5); if(key4==0) beer=1; if(a==1) if(max>55) f_max=0;else f_max=~f_max;// 当温度大于 55 度时, 只能设定为正温度 if(a==2) if(min>55) f_max=0;else f_min=~f_min;// 当温度大于 55 度时, 只能设定为正温度 while(key4==0); keyscan_delay(10); if(v==0) if(key2==0) if(v2==0)beer=0; if(key2==0) beer=1; a=1; TR1=1; s1=1; ww.zicreate.com //v=0 时选择上下限查看功能 keyscan_delay(10); while(key2==0); keyscan_delay(10); if(key3==0) if(v2==0)beer=0; keyscan_delay(10); if(key3==0) beer=1; a=2; TR1=1; s1=1; while(key3==0); keyscan_delay(10); // 选择上限显示 // 开定时器 1 开始定时一分钟左右 // 上限显示不闪烁, 显示一分钟左右自动退出 // 选择下限显示 // 开定时器 1 开始定时 1s // 下限显示不闪烁, 显示 1s 自动退出 if(v1==1) //v1=1 时定时 1s 时间到自动关闭报警上下限查看功能 a=0;v1=0;tr1=0; //a=0 显示实测温度,v1 清零, 关定时器 1 if(k4==0) //k4=0 时 K4 按键选择消按键音的功能 if(key4==0) if(v2==0)beer=0; keyscan_delay(10); if(key4==0) beer=1; v2=~v2; while(key4==0); // 为 0 时开按键音, 为 1 时关按键音

101 第 7 章 AT89S52 单片机控制系统应用实例设计 keyscan_delay(10); #endif /********************************************************************** * 程序名 ; ds18b20_display_h * 功能 : ds18b20 数码管动态显示头文件, 通过定时器 0 延时实现数码管动态显示 * 编程者 :ZPZ * 编程时间 :2009/10/2 **********************************************************************/ #ifndef ds18b20_display_h // 定义头文件 #define ds18b20_display_h #define uint unsigned int // 变量类型宏定义, 用 uint 表示无符号整形 (16 位 ) #define uchar unsigned char // 变量类型宏定义, 用 uchar 表示无符号字符型 (8 位 ) sbit wei1=p2^4; // 可位寻址变量定义, 用 wei1 表示 P2.4 口 sbit wei2=p2^5; // 用 wei2 表示 P2.5 口 sbit wei3=p2^6; // 用 wei3 表示 P2.6 口 sbit wei4=p2^7; // 用 wei4 表示 P2.7 口 uchar num=0; // 定义 num 为全局无符号字符型变量, 赋初值为 0 uchar code temperature1[]= 0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f; // 定义显示码表 0~9 uchar code temperature2[]= 0xbf,0x86,0xdb,0xcf,0xe6, 0xed,0xfd,0x87,0xff,0xef; // 带小数点的 0.~9. uchar code temperature3[]= 0x00,0x80,0x40,0x76,0x38; // 依次是 不显示. - H L /***************************** 延时子函数 ******************************/ void display_delay(uint t) // 延时 1ms 左右 uint i,j; for(i=t;i>0;i--) for(j=120;j>0;j--); /************************** 定时器 1 初始化函数 ***************************/ void timer1_init(bit t) TMOD=0x10; // 设定定时器 1 工作在方式 1, 最大定时 65.53ms TH0=0x3c; // 定时器赋初值, 定时 50ms TL0=0xb0; EA=1; // 开总中断 ET1=1; // 开定时器 1 中断 TR1=t; // 局部变量 t 为 1 启动定时器 1, 为 0 关闭定时器 1 /************************** 定时器 1 中断函数 *****************************/ void timer1() interrupt 3 TH0=0x3c; // 重新赋初值, 定时 50ms TL0=0xb0; num++; // 每进入一次定时器中断 num 加 1( 每 50ms 加 1 一次 ) if(num<5) s=1;if(w==1)beer=1;led=1;elsebeer=1;led=1; Else // 进入 4 次中断, 定时 200ms 时若报警标志位 w 为 1 则启动报警, 不为 1 不启动 // 实现间歇性报警功能 s=0;if(w==1)beer=0;led=0;elsebeer=1;led=1; if(num>20) // 进入 20 次中断, 定时 1s num=0; //num 归 0, 重新定开始定时 1s s1=0; // 定时 1s 时间到时自动关闭报警上下限显示功能

102 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 v1=1; // 定时 1s 时间到时自动关闭报警上下限查看功能 /********************* 调整报警上下限显示选择函数 **********************/ void selsct_1(uchar f,uchar k) // 消除百位的 0 显示, 及正负温度的显示选择 if(f==0) // 若为正温度, 百位为 0 则不显示百位, 不为 0 则显示 if(k/100==0) P0=temperature3[0]; else P0=temperature1[k/100]; if(f==1) // 若为负温度, 若十位为 0, 百位不显示, 否则百位显示 - if(k%100/10==0) P0=temperature3[0]; else P0=temperature3[2]; void selsct_2(bit f,uchar k) // 消除十位的 0 显示, 及正负温度的显示选择 if(f==0) // 若为正温度, 百位十位均为 0 则不显示十位, 否则显示十位 if((k/100==0)&&(k%100/10==0)) P0=temperature3[0]; else P0=temperature1[k%100/10]; if(f==1) // 若为负温度, 若十位为 0, 十位不显示, 否则十位显示 - if(k%100/10==0) P0=temperature3[2]; else P0=temperature1[k%100/10]; /**************************** 主显示函数 ********************************/ void display(uchar t,uchar t_d) // 用于实测温度 上限温度的显示 uchar i; for(i=0;i<4;i++) // 依次从左至右选通数码管显示, 实现动态显示 switch(i) case 0: // 选通第一个数码管 if(a==0)selsct_1(f,t); // 若 a=0 则在第一个数码管上显示测量温度的百位或 - if(a==1) P0=temperature3[3]; // 若 a=1 则在第一个数码管上显示 H if(a==2) P0=temperature3[4]; // 若 a=2 则在第一个数码管上显示 L wei2=0; // 关第二个数码管 wei3=0; // 关第三个数码管 wei4=0; // 关第四个数码管 wei1=1; // 开第一个数码管 break; case 1: // 选通第二个数码管 if(a==0)selsct_2(f,t); // 若 a=0 则在第二个数码管上显示测量温度的十位或 - if(a==1) // 若 a=1 则在第二个数码管上显示上限报警温度的百位或 - if(s==0) selsct_1(f_max,max);// 若 s=0 则显示第二个数码管, 否则不显示 else P0=temperature3[0]; // 通过 s 标志位的变化实现调节上下限报警温度时数码管 的闪烁 if(s1==1) selsct_1(f_max,max);// 若 s1=1 则显示第二个数码管 (s1 标志位用于上下限查看时 的显示 )

103 第 7 章 AT89S52 单片机控制系统应用实例设计 if(a==2) // 若 a=2 则在第二个数码管上显示下限报警温度的百位或 - if(s==0) selsct_1(f_min,min); else P0=temperature3[0]; if(s1==1) selsct_1(f_min,min); wei1=0; wei3=0; wei4=0; wei2=1; break; case 2: // 选通第三个数码管 if(a==0)p0=temperature2[t%10];// 若 a=0 则在第三个数码管上显示测量温度的个位 if(a==1) // 若 a=1 则在第三个数码管上显示上限报警温度的十位或 - if(s==0) selsct_2(f_max,max);// 若 s=0 则显示第三个数码管, 否则不显示 else P0=temperature3[0]; if(s1==1) selsct_2(f_max,max);// 若 s1=1 则显示第三个数码管 if(a==2) // 若 a=2 则在第三个数码管上显示下限报警温度的十位或 - if(s==0) selsct_2(f_min,min); else P0=temperature3[0]; if(s1==1) selsct_2(f_min,min); wei1=0; wei2=0; wei4=0; wei3=1; break; case 3: // 选通第四个数码管 if(a==0)p0=temperature1[t_d];// 若 a=0 则在第四个数码管上显示测量温度的小数位 if(a==1) // 若 a=1 则在第四个数码管上显示上限报警温度的个位 if(s==0) P0=temperature1[max%10];// 若 s=0 则显示第四个数码管, 否则不显示 else P0=temperature3[0]; if(s1==1) P0=temperature1[max%10];// 若 s1=1 则显示第四个数码管 if(a==2) // 若 a=2 则在第四个数码管上显示下限报警温度的个位 if(s==0) P0=temperature1[min%10]; else P0=temperature3[0]; if(s1==1) P0=temperature1[min%10]; wei1=0; wei2=0; wei3=0; wei4=1; break; display_delay(3); // 每个数码管显示 3ms 左右 /**************************** 开机显示函数 ******************************/ void display1(uint z) // 用于开机动画的显示 uchar i,j; bit f=0; for(i=0;i<z;i++) // z 是显示遍数的设定 for(j=0;j<4;j++) // 依次从左至右显示 - switch(j) case 0:P0=temperature3[2];// 第一个数码管显示 wei2=0; wei3=0; wei4=0; wei1=1; break; case 1:P0=temperature3[2];// 第二个数码管显示 wei1=0; wei3=0; wei4=0; wei2=1; break; case 2:P0=temperature3[2];// 第三个数码管显示

104 #endif wei1=0; wei2=0; wei4=0; wei3=1; break; case 3:P0=temperature3[2];// 第四个数码管显示 wei1=0; wei2=0; wei3=0; wei4=1; break; display_delay(200); // 每个数码管显示 200ms 左右 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 LCD1602 液晶显示 系统功能概述 : 实时测量温度, 超过上下限报警, 报警温度可手动调整 K1 是用来进入上下限调节模式的, 当按一下 K1 进入上限调节模式, 再按一下进入下限调节模式 在正常模式下, 按一下 K2 进入查看上限温度模式, 显示 1s 左右自动退出 ; 按一下 K3 进入查看下限温度模式, 显示 1s 左右自动退出 ; 按一下 K4 消除按键音, 再按一下启动按键音 在调节上下限温度模式下,K2 是实现加 1 功能,K3 是实现减 1 功能, K4 是用来设定上下限温度正负的 系统原理图 : 图 7-5 LCD1602 显示的温度测量系统原理图 ww.zicreate.com

105 第 7 章 AT89S52 单片机控制系统应用实例设计 系统实物图 : 图 7-6 LCD1602 显示的温度测量系统实物图系统的 KEIC51 程序 : /********************************************************************** * 程序名 ; lcd1602_ds18b20 * 功能 : LCD1602 显示温度 * 编程者 : ZPZ * 编程时间 :2009/8/14 **********************************************************************/ #include<at89x52.h> // 包含 AT89X52.h 头文件 #include<intrins.h> // 包含 intrins.h 头文件 #define uchar unsigned char // 变量类型宏定义 #define uint unsigned int uchar display_f=0; // 显示标志位 bit flash_flag=1; // 调节报警温度时温度值闪烁标志位 bit s1=0; sbit key_low=p2^3; #include "lcd_1602.h" // 包含 lcd_1602.h 头文件 #include "ds18b20.h" // 包含 ds18b20.h 头文件 #include "key_scan.h" uchar i=0; // 全局变量, 用于调节定时器 0 时间 bit flag=0; // 标志位 uchar temp_table[7]; // 定义一个数组变量 uchar temp_high_alarm[6]=' ','3','0',0xdf,'C',' '; uchar temp_low_alarm[6]=' ','2','0',0xdf,'C',' '; uchar temp_kong_alarm[6]=' ',' ',' ',0xdf,'C',' '; uchar code table1[]=" Temperature "; uchar code table2[]="high_alarm_set"; uchar code table3[]="low_alarm_set "; uchar code table4[]=" high_alarm "; uchar code table5[]=" low_alarm "; /******************************************* 函数名称 : timer0_init 功能 : 定时器 0 初始化函数

106 参数 : f 位变量, 0 表示关闭定时器 0 1 启动定时器 0 返回值 : 无 /********************************************/ void timer0_init(bit f) TMOD=0x01; // 定时器 0 工作在方式 1 TH0=0x3c; // 赋定时器初值 50ms TL0=0xb0; EA=1; // 开总中断 ET0=1; // 开定时器 0 中断 TR0=f; // 启动定时器 0 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 /******************************************* 函数名称 : temp_transform 功能 : 温度转换函数参数 : 无返回值 : 无 /********************************************/ void temp_transform() if(f==0) temp_table[0]=' '; if(f==1) temp_table[0]='-'; temp_table[1]=temp/10+0x30; // 将温度整数部分的十位转化成 ASCII 码送到 temp_table 数组的第 0 位 temp_table[2]=temp%10+0x30; // 将温度整数部分的个位转化成 ASCII 码送到 temp_table 数组的第 1 位 temp_table[3]='.'; // 将. 的 ASCII 码送到 temp_table 数组的第 2 位 temp_table[4]=(temp_d*0.625)+0x30;// 将温度的小数部分转化成 ASCII 码送到 temp_table 数组的第 1 位 temp_table[5]=0xdf; // 将 " " 的 ASCII 码送到 temp_table 数组的第 4 和 5 位 temp_table[6]='c'; if(f_max==0) temp_high_alarm[0]=' '; if(f_max==1) temp_high_alarm[0]='-'; temp_high_alarm[1]=max/10+0x30; // 将温度整数部分的十位转化成 ASCII 码送到 temp_table 数组的第 0 位 temp_high_alarm[2]=max%10+0x30; // 将温度整数部分的个位转化成 ASCII 码送到 temp_table 数组的第 1 位 if(f_min==0) temp_low_alarm[0]=' '; if(f_min==1) temp_low_alarm[0]='-'; temp_low_alarm[1]=min/10+0x30; // 将温度整数部分的十位转化成 ASCII 码送到 temp_table 数组的第 0 位 temp_low_alarm[2]=min%10+0x30; // 将温度整数部分的个位转化成 ASCII 码送到 temp_table 数组的第 1 位 /******************************************* 函数名称 : display 功能 : 显示函数参数 : 无返回值 : 无 /********************************************/

107 第 7 章 AT89S52 单片机控制系统应用实例设计 void display() if(a==0) get_temperature(0); // 获取温度 temp_transform(); // 温度转换 lcd_1602_gotoxy(1,0x01); // 指定第一行显示的首地址 lcd_1602_printf(table1,14);// 显示 table 数组中的数据 lcd_1602_gotoxy(2,0x44); // 指定第二行显示的首地址 lcd_1602_printf(temp_table,7); // 显示 temp_table 数组中的数据 if(a==1) temp_transform(); // 温度转换 // 指定第一行显示的首地址 lcd_1602_gotoxy(1,0x01); if(v==1) lcd_1602_printf(table2,14);// 显示 table 数组中的数据 if(v==0) lcd_1602_printf(table4,14);// 显示 table 数组中的数据 lcd_1602_gotoxy(2,0x45); // 指定第二行显示的首地址 if(flash_flag==0) lcd_1602_printf(temp_high_alarm,6); // 显示 temp_high_alarm 数组中的数据 else lcd_1602_printf(temp_kong_alarm,6); // 显示 temp_kong_alarm 数组中的数据 if(a==2) temp_transform(); // 温度转换 lcd_1602_gotoxy(1,0x01); // 指定第一行显示的首地址 if(v==1) lcd_1602_printf(table3,14,);// 显示 table 数组中的数据 if(v==0) lcd_1602_printf(table5,14);// 显示 table 数组中的数据 lcd_1602_gotoxy(2,0x45); // 指定第二行显示的首地址 if(flash_flag==0) lcd_1602_printf(temp_low_alarm,6); // 显示 temp_low_alarm 数组中的数据 else lcd_1602_printf(temp_kong_alarm,6); // 显示 temp_kong_alarm 数组中的数据 /******************************************* 函数名称 : main 功能 : 主函数参数 : 无返回值 : 无 /********************************************/ void main() key_low=0; // 利用矩阵键盘的第一列 timer0_init(0); get_temperature(1); // 获取温度 temp_transform(); // 温度转换 lcd_1602_init(); //1602 初始化 while(1) // 主循环 keyscan(); // 键盘扫描 display(); // 显示

108 ds18b20_alarm(); // 温度上下限报警函数 /******************************************* 函数名称 : timer0 功能 : 定时器 0 中断函数参数 : 无返回值 : 无 /********************************************/ void timer0() interrupt 1 TH0=0x3c; // 重赋定时器初值 50ms TL0=0xb0; i++; if(i<8) // 用于蜂鸣器间歇性报警和调节是温度值的闪烁 if(w==1) beep=1; if(s1==0) flash_flag=1;else flash_flag=0; else if(w==1) beep=0; flash_flag=0; if(i>=20) i=0; v1=1; beep=1; /********************************************************************** * 程序名 ; lcd_1602_h * 功能 : LCD1602 的 c51 编程头文件 * 编程者 : ZPZ * 编程时间 :2009/5/2 **********************************************************************/ #ifndef lcd_1602_h #define lcd_1602_h #define uchar unsigned char // 变量类型宏定义 #define uint unsigned int #define data_port P0 // 定义数据口 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 sbit lcde=p1^0; sbit lcdrw=p1^1; sbit lcdrs=p1^2; // 定义使能端口 // 定义读写端口 // 定义数据命令选择端口 /******************************************* 函数名称 : lcd_1602_delay 功能 : 1602 延时子函数参数 : z 返回值 : 无 /********************************************/ void lcd_1602_delay(uint z) uint j,k; // 定义局部变量 for(j=z;j>0;j--) ww.zicreate.com

109 第 7 章 AT89S52 单片机控制系统应用实例设计 for(k=20;k>0;k--); /******************************************* 函数名称 : lcd_1602_write 功能 : 1602 写命令 / 数据函数参数 : f "0" 写命令,"1" 写数据. c 是命令或数据返回值 : 无 /********************************************/ void lcd_1602_write(bit f,uchar c) lcdrw=0; // 写选通 lcdrw 为 "0" 是向 lcd1602 写, 为 "1" 是读 lcdrs=f; // 写数据或命令选通端 "0" 写命令,"1" 写数据 data_port=c; // 把数据或命令送入数据口 lcd_1602_delay(2); // 延时 400μs 左右 lcde=1; //lcde 端给一个脉冲 lcd_1602_delay(5); lcde=0; lcd_1602_delay(2); // 延时 /******************************************* 函数名称 : lcd_1602_read 功能 : 1602 读数据函数参数 : d 返回值 : 无 /********************************************/ /*uchar lcd_1602_read(uchar d) lcdrw=1; // 读选通 lcdrs=1; lcd_1602_delay(2); lcde=1; lcd_1602_delay(2); d=data_port; lcd_1602_delay(2); lcde=0; lcd_1602_delay(2); return d; */ /******************************************* 函数名称 : lcd_1602_init 功能 : 1602 初始化函数参数 : 无返回值 : 无 /********************************************/ void lcd_1602_init() lcde=0; lcd_1602_write(0,0x38); // 设置显示模式,16*2 显示,5*7 点阵,8 位数据接口 lcd_1602_write(0,0x0c); // 写入开显示 不显示光标 光标不闪烁命令 lcd_1602_write(0,0x01); // 写清屏命令 lcd_1602_write(0,0x06); // 写一个字符, 地址指针加一, 光标加一 /******************************************* 函数名称 : lcd_1602_gotoxy 功能 : 1602 显示坐标函数参数 : x"1" 表示第一行 "2" 表示第二行 y 地址 返回值 : 无

110 /********************************************/ void lcd_1602_gotoxy(uchar x, uchar y) if(x==1) lcd_1602_write(0,0x80 y); if(x==2) lcd_1602_write(0,(0x80+0x40) y); /******************************************* 函数名称 : printf 功能 : 1602 写显示函数参数 : f "0" 在第一行显示,"1" 在第二行显示返回值 : 无 /********************************************/ void lcd_1602_printf(uchar *str,uchar num) uchar i; for (i=0;i<num1;i++) lcd_1602_write(1,*str); str++; lcd_1602_delay(5); /******************************************* 函数名称 : lcd_1602_move_left 功能 : 1602 全屏左移函数参数 : 返回值 : 无 /********************************************/ /*void lcd_1602_move_left() uchar num; for(num=0;num<16;num++) lcd_1602_write(0,0x18); lcd_1602_delay(1000); ww.zicreate.com // 在第一行定位显示地址 // 在第二行定位显示地址 // 全屏左移命令 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 */ #endif /******************************************************************** * 程序名 ; ds18b20_h * 功能 : DS18B20 的 c51 编程头文件 * 编程者 : ZPZ * 编程时间 :2009/5/2 * 说明 : 用到的全局变量是 : 无符号字符型变量 temp( 测得的温度整数部分 ),temp_d * ( 测得的温度小数部分 ), 标志位 f( 测量温度的标志位 0 表示 正温度 1 表 * 示 负温度 ), 标志位 f_max( 上限温度的标志位 0 表示 正温度 1 表 * 示 负温度 ), 标志位 f_min( 下限温度的标志位 0 表示 正温度 1 表 * 示 负温度 ), 标志位 w( 报警标志位 1 启动报警 0 关闭报警 ) *********************************************************************/ #ifndef ds18b20_h // 定义头文件 #define ds18b20_h #define uint unsigned int // 变量类型宏定义, 用 uint 表示无符号整形 (16 位 ) #define uchar unsigned char // 变量类型宏定义, 用 uchar 表示无符号字符型 (8 位 ) sbit DQ= P2^0; // 可位寻址变量定义, 用 DQ 表示 P2.3 口 sbit gnd= P2^3; sbit beep=p3^3; // 用 beep 表示 P

111 第 7 章 AT89S52 单片机控制系统应用实例设计 sbit led=p3^0; // 用 led 表示 P3.0 uchar temp=0; // 测量温度的整数部分 uchar temp_d=0; // 测量温度的小数部 uchar max=0; // 测量温度的整数部分 uchar min=0; // 测量温度的小数部 bit f=0; // 测量温度的标志位,0 表示 正温度 1 表示 负温度 ) bit f_max=0; // 上限温度的标志位 0 表示 正温度 1 表示 负温度 ) bit f_min=0; // 下限温度的标志位 0 表示 正温度 1 表示 负温度 ) bit w=0; // 报警标志位 1 启动报警 0 关闭报警 ) /******************************************* 函数名称 : ds18b20_delay 功 能 : ds18b20 延时子函数 参 数 : t 返回值 : 无 /********************************************/ void ds18b20_delayus(uint t) // 延时几 μs while(t--); void ds18b20_delayms(uint t) // 延时 1ms 左右 uint i,j; for(i=t;i>0;i--) for(j=120;j>0;j--); /******************************************* 函数名称 : ds18b20_init 功能 : dds18b20 初始化函数参数 : 无返回值 : 无 /********************************************/ void ds18b20_init() // DS18B20 初始化 DQ=1; // 拉高数据线 DQ=0; // 控制器向 DS18B20 发低电平脉冲 ds18b20_delayus(30); // 延时 480μs 左右 DQ=1; // 控制器拉高总线, while(dq); // 等待 DS18B20 拉低总线 ds18b20_delayus(20); // 延时, 等待上拉电阻拉高总线 DQ=1; // 拉高数据线, 准备数据传输 ; /******************************************* 函数名称 : ds18b20_read 功能 : ds18b20 字节读函数参数 : 无返回值 : 无 /********************************************/ uchar ds18b20_read() //DS18B20 字节读取 uchar i; // 定义一个局部变量 i( 局部变量只在本函数中有效 ) uchar d = 0; // 定义一个局部变量 d DQ = 1; // 准备读 ; for(i=8;i>0;i--) // 一位一位的读, 循环 8 次 d >>= 1; //d 左移一位, 低位先发 ; DQ = 0;

112 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 _nop_(); _nop_(); _nop_(); DQ = 1; // 必须写 1, 否则读出来的将是不预期的数据 ; if(dq) // 在 12us 处读取数据, 送给 d 的最高位 d = 0x80; ds18b20_delayus(10); return d; // 返回读取的值 /******************************************* 函数名称 : ds18b20_write 功能 : ds18b20 字节写函数参数 : d 返回值 : 无 /********************************************/ void ds18b20_write(uchar d) // ds18b20 字节写 uchar i; for(i=8;i>0;i--) // 一位一位的写 DQ=0; _nop_(); _nop_(); _nop_(); DQ=d&0x01; // 写数据 ds18b20_delayus(5); DQ=1; d >>= 1; /******************************************* 函数名称 : get_temperature 功能 : 从 ds18b20 获取温度函数参数 : f 返回值 : 无 /********************************************/ void get_temperature(bit f) uchar a=0,b=0,c=0,d=0; uint i; ds18b20_init(); //DS18B20 初始化 ds18b20_write(0xcc); // 向 DS18B20 发跳过读 ROM 命令 ds18b20_write(0x44); // 写启动 DS18B20 进行温度转换命令, 转换结果存入内部 RAM if(f==1) // 首次启动 DS18B20 进行温度转换需要 500ms, 若转换时间不够就出错, 读出的是 85 度的错误值 // 用开机动画耗时 else ds18b20_delayms(1); ds18b20_init(); ds18b20_write(0xcc); ds18b20_write(0xbe); a=ds18b20_read(); ww.zicreate.com //DS18B20 初始化 // 向 DS18B20 发跳过读 ROM 命令 // 写读内部 RAM 中 9 字节的内容命令 // 读内部 RAM (LSB)

113 第 7 章 AT89S52 单片机控制系统应用实例设计 b=ds18b20_read(); // 读内部 RAM (MSB) if(f==1) // 局部位变量 f=1 时读上下线报警温度 max=ds18b20_read(); // 读内部 RAM (TH) min=ds18b20_read(); // 读内部 RAM (Tl) if((max&0x80)==0x80) f_max=1;max=(max-0x80); 符号数 if((min&0x80)==0x80) f_min=1;min=(min-0x80); 符号数 // 若读取的上限温度的最高位 ( 符号位 ) 为 1 表明是负温度 // 将上限温度符号标志位置 1 表示负温度, 将上限温度装换成无 // 若读取的下限温度的最高位 ( 符号位 ) 为 1 表明是负温度 // 将下限温度符号标志位置 1 表示负温度, 将下限温度装换成无 i=b; i>>=4; if (i==0) f=0; //i 为 0, 表示读取的温度是正温度, 设立正温度标记 temp=((a>>4) (b<<4)); // 整数部分 a=(a&0x0f); temp_d=a; // 小数部分 else f=1; //i 为 1, 表示读取的温度是负温度, 设立负温度标记 a=~a+1; // 负数的小数部分取反加 1 b=~b; // 负数的整数部分取反 temp=((a>>4) (b<<4)); // 整数部分 a=(a&0x0f); temp_d=a; // 小数部分 /******************************************* 函数名称 : ds18b20_store_t 功能 : ds18b20 存储极限温度函数参数 : 无返回值 : 无 /********************************************/ void ds18b20_store_t() if(f_max==1) // 若上限温度为负, 将上限温度转换成有符号数 ( 最高位为 1 是负, 为 0 是正 ) max=max+0x80; if(f_min==1) min=min+0x80; // 若下限温度为负, 将上限温度转换成有符号数 ds18b20_init(); //DS18B20 初始化 ds18b20_write(0xcc); // 向 DS18B20 发跳过读 ROM 命令 ds18b20_write(0x4e); // 向 DS18B20 发写字节至暂存器 2 和 3(TH 和 TL) 命令 ds18b20_write(max); // 向暂存器 TH( 上限温度暂存器 ) 写温度 ds18b20_write(min); // 向暂存器 TL( 下限温度暂存器 ) 写温度 ds18b20_write(0xff); // 向配置寄存器写命令, 进行温度值分辨率设置 ds18b20_init(); //DS18B20 初始化 ds18b20_write(0xcc); // 向 DS18B20 发跳过读 ROM 命令 ds18b20_write(0x48); // 向 DS18B20 发将 RAM 中 2 3 字节的内容写入 EEPROM //DS18B20 上电后会自动将 EEPROM 中的上下限温度拷贝到 TH TL 暂存器

114 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 /******************************************* 函数名称 : ds18b20_alarm 功能 : ds18b20 温度超限报警函数参数 : 无返回值 : 无 /********************************************/ void ds18b20_alarm() // 若上限值是正值 if(f_max==0) if(f_min==0) // 若下限值是正值 if(f==0) // 若测量值是正值 if((temp+temp_d*0.0625)<=min (temp+temp_d*0.0625)>=max) w=1;tr0=1; // 当测量值小于最小值或大于最大值时报警 if((temp+temp_d*0.0625)<max&&(temp+temp_d*0.0625)>min) w=0; // 当测量值大于最小值且小于最大值时不报警 if(f==1)w=1;tr1=1; // 若测量值是负值时报警 if(f_min==1) // 若下限值是负值 if(f==0) // 若测量值是正值 if((temp+temp_d*0.0625)>=max)// 当测量值大于最大值时报警 w=1;tr1=1; if((temp+temp_d*0.0625)<max )// 当测量值小于最大值时不报警 w=0; if(f==1) // 若测量值是负值 if((temp+temp_d*0.0625)>=min)// 当测量值大于最小值时报警 w=1;tr1=1; if((temp+temp_d*0.0625)<min)// 当测量值小于最小值时不报警 w=0; if(f_max==1) // 若下限值是负值 if(f_min==1) // 若下限值是负值 if(f==1) // 若测量值是负值 if((temp+temp_d*0.0625)<=max (temp+temp_d*0.0625)>=min) w=1;tr0=1; // 当测量值小于最大值或大于最小值时报警 if((temp+temp_d*0.0625)<min&&(temp+temp_d*0.0625)>max) w=0; // 当测量值小于最小值且大于最大值时不报警 if(f==0)w=1;tr0=1; // 若测量值是正值时报警 #endif /********************************************************************** * 程序名 ; ds18b20 键盘头文件 * 功能 : 通过键盘设定设定上下限报警温度

115 第 7 章 AT89S52 单片机控制系统应用实例设计 * 编程者 : ZPZ * 编程时间 :2009/8/4 **********************************************************************/ #ifndef keyscan_h // 定义头文件 #define keyscan_h sbit key1=p2^4; // 可位寻址变量定义, 用 key1 表示 P2.2 口 sbit key2=p2^5; // 用 key2 表示 P2.1 口 sbit key3=p2^6; // 用 key3 表示 P2.0 口 sbit key4=p2^7; // 用 key4 表示 P3.3 口 uchar k=0; // 定义全局变量 i 用于不同功能模式的选择, 0 正常模式, 1 上限调节模式, 2 下限调节模式 uchar a=0; // 定义全局变量 a 用于不同模式下数码管显示的选择 bit k4=0; //K4 按键双功能选择位,k4=0 时 K4 按键选择消按键音的功能, k4=1 时 K4 按键选择正负温度设定功能 bit v=0; //K2 K3 按键双功能选择位,v=0 时选择上下限查看功能,v=1 时选择上下限温度加减功能 bit v1=0; //v1=1 时定时 1250ms 时间到自动关闭报警上下限查看功能 bit v2=0; // 消按键音功能调整位, 为 0 时开按键音, 为 1 时关按 键音 /*************************** 读键盘延时子函数 **************************/ void keyscan_delay(uint z) // 延时 1ms 左右 uint i,j; for(i=z;i>0;i--) for(j=120;j>0;j--); /**************************** 温度调节函数 ******************************/ int temp_change(int count,bit f) // 上下限温度调整 if(key2==0) // 判断 K2 是否按下 if(v2==0)beep=0; //v2=0 开按键音, 否则消按键音 keyscan_delay(10); // 延时 10ms if(key2==0) // 再次判断 K2 是否按下 ( 实现按按键时消抖 ) beep=1; //K2 按下关按键音 if(f==0) // 若温度为正 count++; // 每按一下 K2 温度上调 1 if(a==1)if(count>125) count=125;// 当温度值大于 125 时不上调 if(a==2)if(count>125) count=125; if(f!=0) // 若温度为负 count++; // 每按一下 K2 温度下调 1 if(a==1)if(count>55) count=55;// 当温度值小于 -55 时不再下调 if(a==2)if(count>55) count=55; while(key2==0); //K2 松开按键时消抖 keyscan_delay(10); if(key3==0) if(v2==0)beep=0; keyscan_delay(10); if(key3==0) //K3 按按键时消抖

116 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 beep=1; count--; // 每按一下 K3 温度为正时下调 1, 为负时上调 1 if(a==1)if(count<0) count=0;// 当温度值达到 0 时不再调 if(a==2)if(count<0) count=0; while(key3==0); keyscan_delay(10); return count; //K3 松开按键时消抖 /***************************** 读键盘函数 ******************************/ void keyscan() if(key1==0) if(v2==0)beep=0; keyscan_delay(10); if(key1==0) //K1 按按键时消抖 beep=1; TR0=1; // 开定时器 0, 通过 s 标志位的变化, 实现在上下限温度调整时温度显示时闪烁的功能 k4=1; // 在上下温度调节功能模式下选择 K4 的调整上下限温度正负的功能 v=1; // 在上下温度调节功能模式下选择 K2 K3 的温度加减功能 k++; //K1 按一下 i 加 1,i= 0 进入正常模式,i= 1 进入调上限模式,i= 2 进入调下限模式 if(k>2) //K1 按下三次后退出调节模式 k=0; // 进入正常模式 TR0=0; // 关定时器 0 k4=0; // 在正常模式下选择 K4 的消按键音功能 v=0; // 在正常模式下选择 K2 K3 的查看上下限报警温度功能 ds18b20_store_t(); // 存储调整后的上下限报警温度 switch(k) // 显示选择 case 0:a=0;break; //a=0 选择显示测得的温度 case 1:a=1;break; //a=1 选择显示上限温度 case 2:a=2;break; //a=2 选择显示下限温度 default:break; while(key1==0); keyscan_delay(10); //K1 松按键时消抖 if(a==1&&v==1) //a=1 选择显示上限温度且 v=1 时选择上下限温度加功能 led=0;max=temp_change(max,f_max);// 显示上限温度 else if(a==2&&v==1) //a=2 选择显示下限温度且 v=1 时选择上下限温度减功能 led=1;min=temp_change(min,f_min); else; if(k4==1) //k4=1 时 K4 按键选择正负温度设定功能 if(key4==0) ww.zicreate.com

117 第 7 章 AT89S52 单片机控制系统应用实例设计 if(v2==0)beep=0; keyscan_delay(5); if(key4==0) beep=1; if(a==1) if(max>55) f_max=0;else f_max=~f_max;// 当温度大于 55 度时, 只能设定为正温度 if(a==2) if(min>55) f_max=0;else f_min=~f_min;// 当温度大于 55 度时, 只能设定为正温度 while(key4==0); keyscan_delay(10); if(v==0) if(key2==0) if(v2==0)beep=0; keyscan_delay(10); if(key2==0) beep=1; a=1; TR0=1; s1=1; while(key2==0); keyscan_delay(10); if(key3==0) if(v2==0)beep=0; keyscan_delay(10); if(key3==0) beep=1; a=2; TR0=1; s1=1; while(key3==0); keyscan_delay(10); //v=0 时选择上下限查看功能 // 选择上限显示 // 开定时器 1 开始定时一分钟左右 // 上限显示不闪烁, 显示一分钟左右自动退出 // 选择下限显示 // 开定时器 0 开始定时 1s // 下限显示不闪烁, 显示 1s 自动退出 if(v1==1) //v1=1 时定时 1s 时间到自动关闭报警上下限查看功能 a=0;v1=0;tr0=0;s1=0; //a=0 显示实测温度,v1 清零, 关定时器 0 if(k4==0) //k4=0 时 K4 按键选择消按键音的功能 if(key4==0) if(v2==0)beep=0; keyscan_delay(10); if(key4==0)

118 #endif beep=1; v2=~v2; while(key4==0); keyscan_delay(10); 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 // 为 0 时开按键音, 为 1 时关按键音 7.3 基于 AT89S52 单片机及 DS1302 的多功能时钟系统设计系统功能概述 : 本设计是基于 AT89S52 单片机控制, 利用 DS1302 数字时钟芯片精确输出日期和时间 利用 DS18B20 实时获取温度 本系统还设计有闹钟功能, 当时间达到设定的闹钟时间时就会响铃, 一分钟后就自动关闭 系统还有温度报警功能, 当温度值超过设定的报警上下限, 就会报警 闹钟和温度报警都由按键控制启动和关闭的 系统原理图如下所示 : ww.zicreate.com 图 7-7 多功能时钟的电路原理图

119 第 7 章 AT89S52 单片机控制系统应用实例设计 功能介绍 : 在正常模式下, 当 K1 按下时, 进入功能设置选择菜单, 按 K2 或 K3 可以翻页选择菜单, 按 K4 退出菜单选择, 回到正常模式 在正常模式下当按下 K5 未松开时按下 K2 就启动闹钟, 如果只按下 K2 就关闭闹钟 当按下 K5 未松开时按下 K3 就启动温度报警程序, 如果只按下 K2 就关闭温度报警程序 在菜单选择模式下, 当按下 K1 就进入相应的功能设置, 按 K4 就退出设置, 再按 K4 退出菜单选择 在各功能设置模式下,K1 是用来选择要设置的项, 当要设置的项被选中后就会闪烁, 按 K2 或 K3 加减 1, 当按下 K4 就保存设置, 并退出设置, 回到菜单选择模式 在温度设置模式下,K5 是用来设置温度的正负 当启动闹钟时屏幕显示 clock start, 关闭闹钟屏幕显示 clock stop 当启动温度报警程序时屏幕显示 temp alarm start, 关闭温度报警程序时屏幕显示 temp alarm stop 当闹钟响铃时屏幕显示 Clock Alarm 当温度超限时报警时屏幕显示 TemperatureAlarm 系统 C 语言程序如下 : /********************************************************************** * 程序名 ; 1602 液晶显示的日历时钟 * 功能 : 在正常模式下, 当 K1 按下时, 进入功能设置选择菜单, 按 K2 或 K3 可以翻 * 页选择菜单, 按 K4 退出菜单选择, 回到正常模式 在正常模式下当按下 K5 未松开 * 时按下 K2 就启动闹钟, 如果只按下 K2 就关闭闹钟 当按下 K5 未松开时按下 K3 就启 * 动温度报警程序, 如果只按下 K2 就关闭温度报警程序 * 在菜单选择模式下, 当按下 K1 就进入相应的功能设置, 按 K4 就退出设置, 再按 K4 退出菜单选择 * 在各功能设置模式下,K1 是用来选择要设置的项, 当要设置的项被选中后就会闪 * 烁, 按 K2 或 K3 加减 1, 当按下 K4 就保存设置, 并退出设置, 回到菜单选择模式 * 在温度设置模式下,K5 是用来设置温度的正负 * 当启动闹钟时屏幕显示 "clock start", 关闭闹钟屏幕显示 "clock stop" 当启动 * 温度报警程序时屏幕显示 "temp alarm start", 关闭温度报警程序时屏幕显示 * "temp alarm stop" 当闹钟响铃时屏幕显示"Clock Alarm" 当温度超限时报警 * 时屏幕显示 "TemperatureAlarm" * 编程者 :ZPZ * 编程时间 :2009/10/2 **********************************************************************/ #include<at89x52.h> // 包含 AT89X52.h 头文件 #include<intrins.h> // 包含 Aintrins.h 头文件 #define uchar unsigned char // 宏定义用 uchar 表示无符号字符型变量 #define uint unsigned int // 用 uint 表示无符号整形变量 uchar count=0; uchar t=0; // 时间定时全局变量 bit t1=0; // 定时时间小于 160ms 时标志位 uchar t2=0; uchar temp_table[7]; // 定义一个数组变量用于存储温度 uchar idata clock_table[8]; // 定义一个数组变量用于存储闹钟设定的时间 uchar idata temp_high_alarm[5]; // 定义一个数组变量用于存储上限报警温度 uchar idata temp_low_alarm[5]; // 定义一个数组变量用于存储下限报警温度 uchar clock_h=7; uchar clock_m=30; uchar clock_s=0; #include"ds1302.h" #include"lcd_1602.h" #include"ds18b20.h" #include"key_scan.h" // 定义一个全局变量用于存储闹钟的小时数 // 定义一个全局变量用于存储闹钟的小时数 // 定义一个全局变量用于存储闹钟的小时数 // 包含 ds1302.h 头文件 // 包含 lcd_1602.h 头文件 // 包含 ds18b20.h 头文件 // 包含 key_scan.h 头文件 /******************************************* 函数名称 : timer0_init 功能 : 定时器 0 初始化函数参数 : t0_f 位变量, 0 表示关闭定时器 0 1 启动定时器

120 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 返回值 : 无 /********************************************/ void timer0_init(bit t0_f) TMOD=0x01; // 定时器 0 工作在方式 1 TH0=0x3c; // 赋定时器初值 50ms TL0=0xb0; EA=1; // 开总中断 ET0=1; // 开定时器 0 中断 TR0=t0_f; // 启动定时器 0 /******************************************* 函数名称 : ds1302_diplay 功 能 : 在 1602 液晶上显示当前时间 ( 第 1 行格式 : 年 - 月 - 日星期 ; 第 2 行格式 : 时 - 分 - 秒 ) 参 数 : time[]-- 时间数组 返回值 : 无 /********************************************/ void ds1302_diplay() lcd_1602_gotoxy(1,0); // 指定 20 显示的首地址 lcd_1602_printf(" 20",3); // 显示 20 lcd_1602_gotoxy(1,3); // 将显示地址指向第一行第 3 的位置 lcd_1602_printf(all_data.datestring,12); // 显示日期 lcd_1602_gotoxy(1,15); // 将显示地址指向第一行第 15 的位置 lcd_1602_printf(" ",1); // 显示空 lcd_1602_gotoxy(2,0); // 将显示地址指向第二行第 0 的位置 lcd_1602_printf(all_data.timestring,9); // 显示时间 /******************************************* 函数名称 : ds18b20_display 功 能 : 在 1602 液晶的第二行的后 7 位显示 ds18b20 测得的温度 参 数 : 无 返回值 : 无 /********************************************/ void ds18b20_display() lcd_1602_gotoxy(2,9); // 指定显示的首地址第二行第 9 个 lcd_1602_printf(temp_table,7); // 在 1602 上显示温度值 /******************************************* 函数名称 : temp_alarm_display 功 能 : 温度在 1602 液晶的第二行的后 7 位显示 ds18b20 测得的温度 参 数 : 无 返回值 : 无 /********************************************/ void temp_alarm_display() lcd_1602_gotoxy(1,0); // 指定显示的首地址第一行第 0 位 lcd_1602_printf("temperaturealarm",16);// 显示 TemperatureAlarm lcd_1602_gotoxy(2,0); // 指定显示的首地址第二行第 0 位 lcd_1602_printf(" ",4); // 显示 4 个空 lcd_1602_gotoxy(2,4); // 指定显示的首地址第二行第 4 位 lcd_1602_printf(temp_table,7); // 显示测量的温度值 lcd_1602_gotoxy(2,11); // 指定显示的首地址 lcd_1602_printf(" ",5); // 显示 5 个空 ww.zicreate.com

121 第 7 章 AT89S52 单片机控制系统应用实例设计 /******************************************* 函数名称 : alarm_view_display 功能 : 报警值查看函数参数 : 无返回值 : 无 /********************************************/ void alarm_view_display() clock_transform(); // 将设定好的闹钟时间存入 clock_table 数组用于在 lcd1602 上显示 lcd_1602_gotoxy(1,0); // 在第 1 行的第 0 位开始显示 if(clock_start_flag==1) // 如果启动了闹钟在第 1 行的第 0 位显示一个 * lcd_1602_printf("* ",4); if(clock_start_flag==0) // 如果没有启动闹钟在第 1 行的第 0 位不显示 * lcd_1602_printf(" ",4); lcd_1602_gotoxy(1,4); // 在第 1 行的第 4 位开始显示设定好的闹钟时间 lcd_1602_printf(clock_table,8); lcd_1602_gotoxy(1,12); // 在第一行的后 4 位显示空 lcd_1602_printf(" ",4); lcd_1602_gotoxy(2,0); if(temp_start_flag==1) lcd_1602_printf("* H",3); // 如果启动了温度超限报警程序在第 2 行的第 0 位显示一个 * if(temp_start_flag==0) lcd_1602_printf(" H",3); // 如果没有启动温度超限报警程序在第 2 行的第 0 位不显示 * lcd_1602_gotoxy(2,3); // 在第 2 行的第 3 位开始显示设定的上限温度 lcd_1602_printf(temp_high_alarm,5); lcd_1602_gotoxy(2,8); lcd_1602_printf(" L",3); lcd_1602_gotoxy(2,11); // 在第 2 行的第 11 位开始显示设定的下限温度 lcd_1602_printf(temp_low_alarm,5); /******************************************* 函数名称 : clock_start_display 功能 : 启动闹钟, 屏幕显示 Clock Start 参数 : 无返回值 : 无 /********************************************/ void clock_start_display() lcd_1602_gotoxy(1,0); lcd_1602_printf(" Clock Start ",16);// 第一行显示 Clock Start lcd_1602_gotoxy(2,0); lcd_1602_printf(" ",16);// 第二行显示空 /******************************************* 函数名称 : clock_stop_display 功能 : 停止闹钟, 屏幕显示 Clock Stop 函数参数 : 无返回值 : 无 /********************************************/ void clock_stop_display() lcd_1602_gotoxy(1,0); lcd_1602_printf(" Clock Stop lcd_1602_gotoxy(2,0); lcd_1602_printf(" /******************************************* 函数名称 : temp_start_display ",16);// 第一行显示 Clock Stop ",16);// 第二行显示空

122 功能 : 启动温度报警功能屏幕显示 Temp Alarm Start 参数 : 无返回值 : 无 /********************************************/ void temp_start_display() lcd_1602_gotoxy(1,0); lcd_1602_printf("temp Alarm Start",16);// 第一行显示 Temp Alarm Start lcd_1602_gotoxy(2,0); lcd_1602_printf(" ww.zicreate.com ",16);// 第二行显示空 /******************************************* 函数名称 : temp_stop_display 功能 : 停止温度报警功能时屏幕显示 Temp Alarm Stop 参数 : 无返回值 : 无 /********************************************/ void temp_stop_display() lcd_1602_gotoxy(1,0); lcd_1602_printf("temp Alarm Stop ",16); // 第一行显示 Temp Alarm Stop lcd_1602_gotoxy(2,0); lcd_1602_printf(" ",16);// 第二行显示空 /******************************************* 函数名称 : clock_alarm_display 功能 : 闹钟报警时参数 : 无返回值 : 无 /********************************************/ void clock_alarm_display() lcd_1602_gotoxy(1,0); // 指定显示的首地址 lcd_1602_printf(" Clock Alarm ",16);// 第 1 行显示 Clock Alarm lcd_1602_gotoxy(2,0); // 指定显示的首地址 lcd_1602_printf(" ",4); // 显示 4 位空 lcd_1602_gotoxy(2,4); // 指定显示的首地址 lcd_1602_printf(all_data.timestring,8);// 显示时钟时间 lcd_1602_gotoxy(2,12); // 指定显示的首地址 lcd_1602_printf(" ",4); // 显示 4 位空 /******************************************* 函数名称 : ds18b20_alarm 功能 : ds18b20 温度超限报警函数参数 : 无返回值 : 无 /********************************************/ void ds18b20_alarm() // 若上限值是正值 if(f_max==0) if(f_min==0) if(f==0) // 若下限值是正值 // 若测量值是正值 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 if((temp+temp_d*0.0625)<=min (temp+temp_d*0.0625)>=max) w=1;tr0=1;temp_alarm_flag=1;// 当测量值小于最小值或大于最大值时报警 if((temp+temp_d*0.0625)<max&&(temp+temp_d*0.0625)>min)

123 第 7 章 AT89S52 单片机控制系统应用实例设计 w=0;temp_alarm_flag=0; // 当测量值大于最小值且小于最大值时不报警 if(f==1)w=1;tr0=1;temp_alarm_flag=1;// 若测量值是负值时报警 if(f_min==1) // 若下限值是负值 if(f==0) // 若测量值是正值 if((temp+temp_d*0.0625)>=max) // 当测量值大于最大值时报警 w=1;tr0=1;temp_alarm_flag=1; if((temp+temp_d*0.0625)<max ) // 当测量值小于最大值时不报警 w=0;temp_alarm_flag=0; if(f==1) // 若测量值是负值 if((temp+temp_d*0.0625)>=min) // 当测量值大于最小值时报警 w=1;tr0=1;temp_alarm_flag=1; if((temp+temp_d*0.0625)<min) // 当测量值小于最小值时不报警 w=0;temp_alarm_flag=0; if(f_max==1) // 若下限值是负值 if(f_min==1) // 若下限值是负值 if(f==1) // 若测量值是负值 if((temp+temp_d*0.0625)<=max (temp+temp_d*0.0625)>=min) w=1;tr0=1;temp_alarm_flag=1; // 当测量值小于最大值或大于最小值时报警 if((temp+temp_d*0.0625)<min&&(temp+temp_d*0.0625)>max) w=0;temp_alarm_flag=1; // 当测量值小于最小值且大于最大值时不报警 if(f==0)w=1;tr0=1;temp_alarm_flag=1; // 若测量值是正值时报警 /******************************************* 函数名称 : clock_alarm 功能 : 若定时时间到, 闹钟报警函数参数 : 无返回值 : 无 /********************************************/ void clock_alarm() if(clock_h==all_data.hour&&clock_m==all_data.minute&&clock_s==all_data.second) w=1;clock_alarm_flag=1; // 若定时时间到, 闹钟报警 if(clock_h==all_data.hour&&clock_m+1==all_data.minute&&clock_s==all_data.second) w=0;clock_alarm_flag=0; // 若超过定时时间 1 分钟, 闹钟停止报警 /******************************************* 函数名称 : main 功能 : 主函数参数 : 无返回值 : 无 /********************************************/ void main()

124 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 key_gnd=0; timer0_init(1); lcd_1602_init(); // 初始化 1602 液晶 Initial_DS1302(); // 初始化 DS1302 DS1302_SetT(50,59,23,4,2,9,9); // 设定日期与时间 get_temperature(1); // 获取温度 temp_transform(); // 温度转换 while(1) DS1302_GetTime(&all_data);// 获取日期与时间 DateToStr(&all_data); // 存储获取的日期 TimeToStr(&all_data); // 存储获取的时间 if(clock_start_flag==1) // 如果启动了闹钟报警, 就运行闹钟报警函数 clock_alarm(); while(clock_start_dis) clock_start_display(); // 如闹钟启动按键按下, 屏幕显示 Clock Start,2 秒后退出 while(clock_stop_dis) clock_stop_display(); // 如闹钟停止按键按下, 屏幕显示 Clock Stop,2 秒后退出 while(temp_start_dis) temp_start_display();// 如温度报警启动按键按下, 屏幕显示 Temp Alarm Start,2 秒后退出 while(temp_stop_dis) temp_stop_display();// 如温度报警停止按键按下, 屏幕显示 Temp Alarm Stop,2 秒后退出 if(alarm_view_flag==1) // 如果报警值查看按键按下, 进入报警值查看函数 else alarm_view_display(); if(clock_alarm_flag==1) // 如果闹钟报警了, 就进入闹钟报警显示函数 clock_alarm_display(); else if(temp_alarm_flag==1)// 如果温度超限报警了, 就进入温度报警显示函数 temp_alarm_display(); else ds1302_diplay(); // 显示日期时间 ds18b20_display();// 显示温度 keyscan(); get_temperature(0); if(temp_start_flag==1) ds18b20_alarm(); temp_transform(); // 键盘扫描 // 获取温度 // 如果启动了温度超限报警, 就运行温度报警函数 // 温度转换 /******************************************* 函数名称 : timer0 功能 : 定时器 0 中断函数参数 : 无返回值 : 无 /********************************************/ void timer0() interrupt 1 TH0=0x3c; TL0=0xb0; t++; // 重赋定时器初值 50ms //t 加 1, 加够 20 次就定时 1 秒

125 第 7 章 AT89S52 单片机控制系统应用实例设计 if(t<8) t1=1; if(t>7) if(w==1)beep=1; else beep=1; t1=0; if(w==1)beep=0; else beep=1; if(t>=20) // 用于蜂鸣器间歇性报警和调节时被调值的闪烁 //1 秒的前 400 毫秒蜂鸣器不响 //1 秒的后 600 毫秒当 w=1 时蜂鸣器响 // 当定时 1 秒时间到时 t=0; //t 清 0 t2++; if(t2>2) // 定时 2 秒时间到时 t2=0; //t2 清 0 alarm_view_flag=0; // 关闭报警查看显示 clock_start_dis=0; // 关闭启动闹钟显示 clock_stop_dis=0; // 关闭停止闹钟显示 temp_start_dis=0; // 关闭启动温度报警显示 temp_stop_dis=0; // 关闭停止温度报警显示 /********************************************************************** * 程序名 ; ds1302_h * 功能 : 时钟芯片 DS1302 的 c51 编程头文件 * 编程者 : ZPZ * 编程时间 :2009/8/2 **********************************************************************/ #ifndef ds1302_h // 定义头文件 #define ds1302_h #define uchar unsigned char #define uint unsigned int sbit DS1302_CLK = P1^5; sbit DS1302_IO = P1^6; sbit DS1302_RST = P1^7; // 变量宏定义 // 实时时钟时钟线引脚 // 实时时钟数据线引脚 // 实时时钟复位线引脚 typedef struct _SYSTEMTIME_ // 定义结构体类型 uchar Second; // 秒 uchar Minute; // 分 uchar Hour; // 时 uchar Week; // 星期 uchar Day; // 日 uchar Month; // 月 uchar Year; // 年 uchar DateString[12]; // 存储日期的数组 uchar TimeString[9]; // 存储时间的数组 SYSTEMTIME; // 可用于该类型结构体的定义 /******************* 命令 *********************/ #define DS1302_SECOND 0x80 // 秒的地址 #define DS1302_MINUTE 0x82 // 分的地址

126 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 #define DS1302_HOUR 0x84 // 时的地址 #define DS1302_WEEK 0x8A // 周的地址 #define DS1302_DAY 0x86 // 日的地址 #define DS1302_MONTH 0x88 // 月的地址 #define DS1302_YEAR 0x8C // 年的地址 #define WP 0x8e // 控制 ( 写保护 ) #define CHARGE 0x90 // 涓流充电 #define BURST 0xbe // 时钟多字节 /******************* 配置 *********************/ #define CLK_STOP 0x80 // 停止时钟控制位 SECOND bit7 #define CLK_START 0x00 // 启动时钟 #define M12_24 0x80 //12/24 小时值选择位 HOUR bit7 #define PROTECT 0x80 // 寄存器不能写入 CONTROL bit7 #define UPROTECT 0x00 // 寄存器能写入 CONTROL bit7 /************* 涓流充电控制常量 ***************/ #define TC_D1R2 0xA5 //high 1 Diode +2K Resistors #define TC_D2R8 0xAB //low 2 Diodes+8K Resistors #define TC_DISABLED 0x00 //Disabled(TCS<>1010 or DS=00 or RS=00) /******************************************* 函数名称 : DS1302InputByte 功 能 : 向 DS1302 写入一个字节数据 ( 没有 RST 操作 ) 参 数 : d-- 要写入的数据 返回值 : 无 /********************************************/ void DS1302InputByte(uchar d) // 实时时钟写入一字节 ( 内部函数 ) uchar i; uchar shuju=d; // 将要写入的一个字节先送入累加器 ACC for(i=8;i>0;i--) // 循环 8 次 DS1302_IO =(shuju&0x01); // 写入一位 DS1302_CLK = 1; // 给 ds1302 时钟端一个下降沿 DS1302_CLK = 0; shuju=shuju>> 1; //shuju 右移一位 /******************************************* 函数名称 : DS1302OutputByte 功能 : 从 DS1302 读出一个字节数据 ( 没有 RST 操作 ) 参数 : 无返回值 : ACC-- 读出的数据 /********************************************/ uchar DS1302OutputByte() // 实时时钟读取一字节 ( 内部函数 ) uchar i; uchar shuju=0; for(i=8; i>0; i--) // 循环 8 次 shuju=shuju>>1; //shuju 右移一位 if(ds1302_io==1) // 读一位 shuju=(shuju 0x80); DS1302_CLK = 1; // 给 ds1302 时钟端一个下降沿 DS1302_CLK = 0; return(shuju); // 返回读取的值 ww.zicreate.com

127 第 7 章 AT89S52 单片机控制系统应用实例设计 /******************************************* 函数名称 : Write1302 功能 : 向 DS1302 的某个地址写入一个字节数据参数 : addr-- 地址值 ( 寄存器或 RAM) date-- 要写入的地址返回值 : 无 /********************************************/ void Write1302(uchar addr, uchar date)//addr: DS1302 地址, Date: 要写的数据 DS1302_RST = 0; // 复位线拉低 DS1302_CLK = 0; // 时钟线拉低 DS1302_RST = 1; // 复位线拉高 DS1302InputByte(addr); // 地址, 命令 DS1302InputByte(date); // 写 1Byte 数据 DS1302_CLK = 1; // 时钟线拉高 DS1302_RST = 0; // 复位线拉低 /******************************************* 函数名称 : Read1302 功能 : 从 DS1302 的某个地址读出一个字节数据参数 : addr-- 地址值 ( 寄存器或 RAM) 返回值 : date-- 读出的数据 /********************************************/ uchar Read1302(uchar addr) // 读取 DS1302 某地址的数据 uchar date; DS1302_RST = 0; DS1302_CLK = 0; DS1302_RST = 1; DS1302InputByte(addr 0x01); // 地址, 命令 date = DS1302OutputByte(); // 读 1Byte 数据 DS1302_CLK = 1; DS1302_RST = 0; return(date); /******************************************* 函数名称 : DS1302_SetProtect 功能 : 寄存器是否写保护参数 : flag 标志位返回值 : 无 /********************************************/ void DS1302_SetProtect(bit flag) // 是否写保护 if(flag) Write1302(0x8e,0x10); // 当 flag=1 时, 写保护 else Write1302(0x8e,0x00); // 当 flag=0 时, 不写保护 /******************************************* 函数名称 : DS1302_SetTime 功能 : 设置 DS1302 单个时间参数 : Address-- 设置地址 Value-- 设置数值返回值 : 无 /********************************************/ void DS1302_SetTime(uchar Address, uchar Value) // 设置时间函数 DS1302_SetProtect(0); Write1302(Address, ((Value/10)<<4 (Value%10)));

128 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 /******************************************* 函数名称 : DS1302_SetT 功 能 : 设置 DS1302 的所有时间 参 数 : sec min hr wk day mon yer 返回值 : 无 /********************************************/ void DS1302_SetT(uchar sec,uchar min,uchar hr,uchar wk,uchar day,uchar mon,uchar yer) // 设置时间函数 DS1302_SetProtect(0); Write1302(DS1302_SECOND, ((sec/10)<<4 (sec%10))); // 设置秒 Write1302(DS1302_MINUTE, ((min/10)<<4 (min%10))); // 设置分 Write1302(DS1302_HOUR, ((hr/10)<<4 (hr%10))); // 设置时 Write1302(DS1302_WEEK, ((wk/10)<<4 (wk%10)));// 设置星期 Write1302(DS1302_DAY, ((day/10)<<4 (day%10))); // 设置日 Write1302(DS1302_MONTH, ((mon/10)<<4 (mon%10)));// 设置月 Write1302(DS1302_YEAR, ((yer/10)<<4 (yer%10))); // 设置年 /******************************************* 函数名称 : DS1302_Set_date 功 能 : 设置 DS1302 的日期 参 数 : year 返回值 : 无 /********************************************/ void DS1302_Set_date(uchar wk,uchar day,uchar mon,uchar yer) DS1302_SetProtect(0); Write1302(DS1302_WEEK, ((wk/10)<<4 (wk%10))); // 设置星期 Write1302(DS1302_DAY, ((day/10)<<4 (day%10))); // 设置日 Write1302(DS1302_MONTH, ((mon/10)<<4 (mon%10))); // 设置月 Write1302(DS1302_YEAR, ((yer/10)<<4 (yer%10))); // 设置年 /******************************************* 函数名称 : DS1302_Set_time 功能 : 设置 DS1302 的时刻参数 : year 返回值 : 无 /********************************************/ void DS1302_Set_time(uchar sec,uchar min,uchar hr) DS1302_SetProtect(0); Write1302(DS1302_SECOND, ((sec/10)<<4 (sec%10))); // 设置秒 Write1302(DS1302_MINUTE, ((min/10)<<4 (min%10))); // 设置分 Write1302(DS1302_HOUR, ((hr/10)<<4 (hr%10))); // 设置时 /******************************************* 函数名称 : DS1302_GetTime 功能 : 读取 DS1302 的当前时间参数 : *Time-- 读取的时间结构体指针返回值 : 无 /********************************************/ void DS1302_GetTime(SYSTEMTIME *Time) uchar ReadValue; ReadValue = Read1302(DS1302_SECOND); Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); // 读秒 ReadValue = Read1302(DS1302_MINUTE); ww.zicreate.com

129 第 7 章 AT89S52 单片机控制系统应用实例设计 Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); // 读分 ReadValue = Read1302(DS1302_HOUR); Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); // 读时 ReadValue = Read1302(DS1302_DAY); Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); // 读日 ReadValue = Read1302(DS1302_WEEK); Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); // 读周 ReadValue = Read1302(DS1302_MONTH); Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); // 读月 ReadValue = Read1302(DS1302_YEAR); Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); /******************************************* 函数名称 : DateToStr // 读年 功能 : 存储 DS1302 的当前日期参数 : *Time-- 结构体指针返回值 : 无 /********************************************/ void DateToStr(SYSTEMTIME *Time) Time->DateString[0] = Time->Year/10 + '0'; // 将年的十位存入 DateString 所指向的数组 0 位 Time->DateString[1] = Time->Year%10 + '0';// 将年的个位存入 DateString 所指向的数组 1 位 Time->DateString[2] = '-'; Time->DateString[3] = Time->Month/10 + '0'; Time->DateString[4] = Time->Month%10 + '0'; Time->DateString[5] = '-'; Time->DateString[6] = Time->Day/10 + '0'; Time->DateString[7] = Time->Day%10 + '0'; Time->DateString[8] = ' '; switch(time->week%10) case 1: case 2: case 3: case 4: case 5: case 6: case 7: default:break; Time->DateString[9] ='S'; Time->DateString[10] ='U'; Time->DateString[11] ='N';break; Time->DateString[9] ='M'; Time->DateString[10] ='O'; Time->DateString[11] ='N';break; Time->DateString[9] ='T'; Time->DateString[10] ='U'; Time->DateString[11] ='E';break; Time->DateString[9] ='W'; Time->DateString[10] ='E'; Time->DateString[11] ='D';break; Time->DateString[9] ='T'; Time->DateString[10] ='H'; Time->DateString[11] ='U';break; Time->DateString[9] ='F'; Time->DateString[10] ='R'; Time->DateString[11] ='I';break; Time->DateString[9] ='S'; Time->DateString[10] ='A'; Time->DateString[11] ='T';break; // 将 '-' 存入 DateString 所指向的数组 2 位 // 根据周的数字在数组中存入不同的英文简称

130 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 /******************************************* 函数名称 : TimeToStr 功能 : 存储 DS1302 的当前时间参数 : *Time-- 结构体指针返回值 : 无 /********************************************/ void TimeToStr(SYSTEMTIME *Time) Time->TimeString[0] = Time->Hour/10 + '0'; // 将时间存入 TimeString 所指向的数组 Time->TimeString[1] = Time->Hour%10 + '0'; Time->TimeString[2] = ':'; Time->TimeString[3] = Time->Minute/10 + '0'; Time->TimeString[4] = Time->Minute%10 + '0'; Time->TimeString[5] = ':'; Time->TimeString[6] = Time->Second/10 + '0'; Time->TimeString[7] = Time->Second%10 + '0'; Time->TimeString[8] = ' '; /******************************************* 函数名称 : Initial_DS1302 功能 : 初始化 DS1302 参数 : 无返回值 : 无 /********************************************/ void Initial_DS1302() uchar Second=Read1302(DS1302_SECOND); if(second&0x80) DS1302_SetTime(DS1302_SECOND,0); #endif /********************************************************************** * 程序名 ; lcd_1602_h * 功能 : LCD1602 的 c51 编程头文件 * 编程者 : ZPZ * 编程时间 :2009/8/2 **********************************************************************/ #ifndef lcd_1602_h #define lcd_1602_h #define uchar unsigned char // 变量类型宏定义 #define uint unsigned int #define data_port P0 // 定义数据口 sbit lcde=p1^0; // 定义使能端口 sbit lcdrw=p1^1; // 定义读写端口 sbit lcdrs=p1^2; // 定义数据命令选择端口 /******************************************* 函数名称 : lcd_1602_delay 功能 : 1602 延时子函数参数 : z 返回值 : 无 /********************************************/ void lcd_1602_delay(uint z) uint j,k; // 定义局部变量 for(j=z;j>0;j--) for(k=20;k>0;k--); ww.zicreate.com

131 第 7 章 AT89S52 单片机控制系统应用实例设计 /******************************************* 函数名称 : lcd_1602_write 功能 : 1602 写命令 / 数据函数参数 : f "0" 写命令,"1" 写数据. c 是命令或数据返回值 : 无 /********************************************/ void lcd_1602_write(bit w_f,uchar c) lcdrw=0; // 写选通 lcdrw 为 "0" 是向 lcd1602 写, 为 "1" 是读 lcdrs=w_f; // 写数据或命令选通端 "0" 写命令,"1" 写数据 data_port=c; // 把数据或命令送入数据口 lcd_1602_delay(2); // 延时 400μs 左右 lcde=1; lcd_1602_delay(5); lcde=0; lcd_1602_delay(2); //lcde 端给一个脉冲 // 延时 /******************************************* 函数名称 : lcd_1602_read 功能 : 1602 读数据函数参数 : d 返回值 : 无 /********************************************/ /*uchar lcd_1602_read(uchar d) lcdrw=1; lcdrs=1; lcd_1602_delay(2); lcde=1; lcd_1602_delay(2); d=data_port; lcd_1602_delay(2); lcde=0; lcd_1602_delay(2); return d; // 读选通 */ /******************************************* 函数名称 : lcd_1602_init 功能 : 1602 初始化函数参数 : 无返回值 : 无 /********************************************/ void lcd_1602_init() lcde=0; lcd_1602_write(0,0x38); lcd_1602_write(0,0x0c); lcd_1602_write(0,0x01); lcd_1602_write(0,0x06); /******************************************* 函数名称 : lcd_1602_gotoxy 功能 : 1602 显示坐标函数参数 : x"1" 表示第一行 "2" 表示第二行 y 地址 返回值 : 无 /********************************************/ void lcd_1602_gotoxy(uchar x, uchar y) // 设置显示模式,16*2 显示,5*7 点阵,8 位数据接口 // 写入开显示 不显示光标 光标不闪烁命令 // 写清屏命令 // 写一个字符, 地址指针加一, 光标加一

132 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 if(x==1) lcd_1602_write(0,0x80 y); // 在第一行定位显示地址 if(x==2) lcd_1602_write(0,(0x80+0x40) y); // 在第二行定位显示地址 /******************************************* 函数名称 : lcd_1602_printf 功能 : 1602 写显示函数参数 : f "0" 在第一行显示,"1" 在第二行显示返回值 : 无 /********************************************/ void lcd_1602_printf(uchar *str,uchar num) uchar i; for (i=0;i<num;i++) // 循环 num 次 lcd_1602_write(1,*str); // 逐次将 str 所指向的数组数据送 1602 显示 str++; lcd_1602_delay(5); // 延时 /******************************************* 函数名称 : lcd_1602_move_left 功能 : 1602 全屏左移函数参数 : 返回值 : 无 /********************************************/ /*void lcd_1602_move_left() uchar num; for(num=0;num<16;num++) lcd_1602_write(0,0x18); lcd_1602_delay(1000); // 全屏左移命令 */ #endif /******************************************************************** * 程序名 ; ds18b20_h * 功能 : DS18B20 的 c51 编程头文件 * 编程者 : ZPZ * 编程时间 :2009/5/2 * 说明 : 用到的全局变量是 : 无符号字符型变量 temp( 测得的温度整数部分 ),temp_d * ( 测得的温度小数部分 ), 标志位 f( 测量温度的标志位 0 表示 正温度 1 表 * 示 负温度 ), 标志位 f_max( 上限温度的标志位 0 表示 正温度 1 表 * 示 负温度 ), 标志位 f_min( 下限温度的标志位 0 表示 正温度 1 表 * 示 负温度 ), 标志位 w( 报警标志位 1 启动报警 0 关闭报警 ) *********************************************************************/ #ifndef ds18b20_h // 定义头文件 #define ds18b20_h #define uint unsigned int // 变量类型宏定义, 用 uint 表示无符号整形 (16 位 ) #define uchar unsigned char // 变量类型宏定义, 用 uchar 表示无符号字符型 (8 位 ) sbit DQ= P2^0; // 可位寻址变量定义, 用 DQ 表示 P2.3 口 sbit gnd= P2^3; sbit beep=p3^3; // 用 beep 表示 P3.3 sbit led=p3^0; // 用 led 表示 P3.0 uchar temp=0; // 测量温度的整数部分

133 第 7 章 AT89S52 单片机控制系统应用实例设计 uchar temp_d=0; // 测量温度的小数部 uchar max=0; // 测量温度的整数部分 uchar min=0; // 测量温度的小数部 bit f=0; // 测量温度的标志位,0 表示 正温度 1 表示 负温度 ) bit f_max=0; // 上限温度的标志位 0 表示 正温度 1 表示 负温度 ) bit f_min=0; // 下限温度的标志位 0 表示 正温度 1 表示 负温度 ) bit w=0; // 报警标志位 1 启动报警 0 关闭报警 ) /******************************************* 函数名称 : ds18b20_delay 功 能 : ds18b20 延时子函数 参 数 : t 返回值 : 无 /********************************************/ void ds18b20_delayus(uint t) // 延时几 μs while(t--); void ds18b20_delayms(uint t) // 延时 1ms 左右 uint i,j; for(i=t;i>0;i--) for(j=120;j>0;j--); /******************************************* 函数名称 : ds18b20_init 功能 : dds18b20 初始化函数参数 : 无返回值 : 无 /********************************************/ void ds18b20_init() // DS18B20 初始化 DQ=1; // 拉高数据线 DQ=0; // 控制器向 DS18B20 发低电平脉冲 ds18b20_delayus(30); // 延时 480μs 左右 DQ=1; // 控制器拉高总线, while(dq); // 等待 DS18B20 拉低总线 ds18b20_delayus(20); // 延时, 等待上拉电阻拉高总线 DQ=1; // 拉高数据线, 准备数据传输 ; /******************************************* 函数名称 : ds18b20_read 功能 : ds18b20 字节读函数参数 : 无返回值 : 无 /********************************************/ uchar ds18b20_read() //DS18B20 字节读取 uchar i; // 定义一个局部变量 i( 局部变量只在本函数中有效 ) uchar d = 0; // 定义一个局部变量 d DQ = 1; // 准备读 ; for(i=8;i>0;i--) // 一位一位的读, 循环 8 次 d >>= 1; //d 左移一位, 低位先发 ; DQ = 0; _nop_(); _nop_();

134 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 _nop_(); DQ = 1; // 必须写 1, 否则读出来的将是不预期的数据 ; if(dq) // 在 12us 处读取数据, 送给 d 的最高位 d = 0x80; ds18b20_delayus(10); return d; // 返回读取的值 /******************************************* 函数名称 : ds18b20_write 功能 : ds18b20 字节写函数参数 : d 返回值 : 无 /********************************************/ void ds18b20_write(uchar d) // ds18b20 字节写 uchar i; for(i=8;i>0;i--) // 一位一位的写 DQ=0; _nop_(); _nop_(); _nop_(); DQ=d&0x01; // 写数据 ds18b20_delayus(5); DQ=1; d >>= 1; /******************************************* 函数名称 : get_temperature 功能 : 从 ds18b20 获取温度函数参数 : f 返回值 : 无 /********************************************/ void get_temperature(bit f) uchar a=0,b=0,c=0,d=0; uint i; ds18b20_init(); //DS18B20 初始化 ds18b20_write(0xcc); // 向 DS18B20 发跳过读 ROM 命令 ds18b20_write(0x44); // 写启动 DS18B20 进行温度转换命令, 转换结果存入内部 RAM if(f==1) // 首次启动 DS18B20 进行温度转换需要 500ms, 若转换时间不够就出错, 读出的是 85 度的错误值 ds18b20_delayms(500); else ds18b20_delayms(10); ds18b20_init(); //DS18B20 初始化 ds18b20_write(0xcc); // 向 DS18B20 发跳过读 ROM 命令 ds18b20_write(0xbe); // 写读内部 RAM 中 9 字节的内容命令 a=ds18b20_read(); // 读内部 RAM (LSB) b=ds18b20_read(); // 读内部 RAM (MSB) if(f==1) // 局部位变量 f=1 时读上下线报警温度 max=ds18b20_read(); // 读内部 RAM (TH) ww.zicreate.com

135 第 7 章 AT89S52 单片机控制系统应用实例设计 min=ds18b20_read(); if((max&0x80)==0x80) f_max=1;max=(max-0x80); 成无符号数 if((min&0x80)==0x80) f_min=1;min=(min-0x80); 成无符号数 i=b; i>>=4; if (i==0) f=0; temp=((a>>4) (b<<4)); a=(a&0x0f); temp_d=a; // 读内部 RAM (Tl) // 若读取的上限温度的最高位 ( 符号位 ) 为 1 表明是负温度 // 将上限温度符号标志位置 1 表示负温度, 将上限温度装换 // 若读取的下限温度的最高位 ( 符号位 ) 为 1 表明是负温度 // 将下限温度符号标志位置 1 表示负温度, 将下限温度装换 //i 为 0, 表示读取的温度是正温度, 设立正温度标记 // 整数部分 // 小数部分 if(i==1) f=1; //i 为 1, 表示读取的温度是负温度, 设立负温度标记 a=~a+1; // 负数的小数部分取反加 1 b=~b; // 负数的整数部分取反 temp=((a>>4) (b<<4)); // 整数部分 a=(a&0x0f); temp_d=a; // 小数部分 /******************************************* 函数名称 : ds18b20_store_t 功能 : ds18b20 存储极限温度函数参数 : 无返回值 : 无 /********************************************/ void ds18b20_store_t() if(f_max==1) // 若上限温度为负, 将上限温度转换成有符号数 ( 最高位为 1 是负, 为 0 是正 ) max=max+0x80; if(f_min==1) // 若下限温度为负, 将上限温度转换成有符号数 min=min+0x80; ds18b20_init(); //DS18B20 初始化 ds18b20_write(0xcc); // 向 DS18B20 发跳过读 ROM 命令 ds18b20_write(0x4e); // 向 DS18B20 发写字节至暂存器 2 和 3(TH 和 TL) 命令 ds18b20_write(max); // 向暂存器 TH( 上限温度暂存器 ) 写温度 ds18b20_write(min); // 向暂存器 TL( 下限温度暂存器 ) 写温度 ds18b20_write(0xff); // 向配置寄存器写命令, 进行温度值分辨率设置 ds18b20_init(); //DS18B20 初始化 ds18b20_write(0xcc); // 向 DS18B20 发跳过读 ROM 命令 ds18b20_write(0x48); // 向 DS18B20 发将 RAM 中 2 3 字节的内容写入 EEPROM //DS18B20 上电后会自动将 EEPROM 中的上下限温度拷贝到 TH TL 暂存器 /******************************************* 函数名称 : ds18b20_alarm 功能 : ds18b20 温度超限报警函数参数 : 无返回值 : 无 /********************************************/

136 /*void ds18b20_alarm() // 若上限值是正值 if(f_max==0) if(f_min==0) // 若下限值是正值 if(f==0) // 若测量值是正值 if((temp+temp_d*0.0625)<=min (temp+temp_d*0.0625)>=max) 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 w=1;tr0=1; // 当测量值小于最小值或大于最大值时报警 if((temp+temp_d*0.0625)<max&&(temp+temp_d*0.0625)>min) w=0; // 当测量值大于最小值且小于最大值时不报警 if(f==1)w=1;tr0=1; // 若测量值是负值时报警 if(f_min==1) if(f==0) if(f==1) // 若下限值是负值 // 若测量值是正值 if((temp+temp_d*0.0625)>=max)// 当测量值大于最大值时报警 w=1;tr0=1; if((temp+temp_d*0.0625)<max )// 当测量值小于最大值时不报警 w=0; // 若测量值是负值 if((temp+temp_d*0.0625)>=min)// 当测量值大于最小值时报警 w=1;tr0=1; if((temp+temp_d*0.0625)<min)// 当测量值小于最小值时不报警 w=0; if(f_max==1) // 若下限值是负值 if(f_min==1) // 若下限值是负值 if(f==1) // 若测量值是负值 if((temp+temp_d*0.0625)<=max (temp+temp_d*0.0625)>=min) w=1;tr0=1; // 当测量值小于最大值或大于最小值时报警 if((temp+temp_d*0.0625)<min&&(temp+temp_d*0.0625)>max) w=0;tr0=0; // 当测量值小于最小值且大于最大值时不报警 if(f==0)w=1;tr0=1; // 若测量值是正值时报警 */ /******************************************* 函数名称 : temp_transform 功能 : 温度转换函数参数 : 无返回值 : 无 /********************************************/ void temp_transform() if(f==0) ww.zicreate.com

137 第 7 章 AT89S52 单片机控制系统应用实例设计 temp_table[0]=' '; if(f==1) temp_table[0]='-'; temp_table[1]=temp/10+0x30; // 将温度整数部分的十位转化成 ASCII 码送到 temp_table 数组的第 0 位 temp_table[2]=temp%10+0x30; // 将温度整数部分的个位转化成 ASCII 码送到 temp_table 数组的第 1 位 temp_table[3]='.'; // 将. 的 ASCII 码送到 temp_table 数组的第 2 位 temp_table[4]=(temp_d*0.625)+0x30;// 将温度的小数部分转化成 ASCII 码送到 temp_table 数组的第 1 位 temp_table[5]=0xdf; // 将 " " 的 ASCII 码送到 temp_table 数组的第 4 和 5 位 temp_table[6]='c'; if(f_max==0) temp_high_alarm[0]=' '; if(f_max==1) temp_high_alarm[0]='-'; temp_high_alarm[1]=max/10+0x30; // 将温度整数部分的十位转化成 ASCII 码送到 temp_table 数组的第 0 位 temp_high_alarm[2]=max%10+0x30; // 将温度整数部分的个位转化成 ASCII 码送到 temp_table 数组的第 1 位 temp_high_alarm[3]=0xdf; // 将 " " 的 ASCII 码送到 temp_high_alarm 数组的第 4 和 5 temp_high_alarm[4]='c'; if(f_min==0) temp_low_alarm[0]=' '; if(f_min==1) temp_low_alarm[0]='-'; temp_low_alarm[1]=min/10+0x30; // 将温度整数部分的十位转化成 ASCII 码送到 temp_table 数组的第 0 位 temp_low_alarm[2]=min%10+0x30; // 将温度整数部分的个位转化成 ASCII 码送到 temp_table 数组的第 1 位 temp_low_alarm[3]=0xdf; // 将 " " 的 ASCII 码送到 temp_low_alarm 数组的第 4 和 5 temp_low_alarm[4]='c'; #endif /********************************************************************** * 程序名 ; key_scan_h * 功能 : 键盘扫描头文件 * 编程者 : ZPZ * 编程时间 :2009/10/2 **********************************************************************/ #ifndef key_scan_h #define key_scan_h #define uchar unsigned char // 变量类型宏定义 #define uint unsigned int SYSTEMTIME all_data; // 定义一个结构体, 用于存放读取的日期及时间 uchar code not_dis2[]=" "; // 定义显示空的数组 uchar code not_dis3[]=" "; uchar code not_dis4[]=" "; uchar code not_dis5[]=" "; uchar code dis2[]="->"; // 定义显示 -> 的数组 uchar code date_set[]="date Setting "; // 设定日期时要显示的数组 uchar code time_set[]="time Setting "; // 设定时间时要显示的数组 uchar code clock_set[]="clock Setting "; // 设定闹钟时要显示的数组 uchar code temp_set[]="temp Setting "; // 设定报警温度时要显示的数组 uchar code sound_set[]="sound Setting "; // 按键音设置时要显示的数组 uchar code alarm_temp_set[]="alarmtemperature";// 温度超限报警时要显示的数组 sbit key1=p2^4; // 可位寻址变量定义, 用 key1 表示 P2.4 口

138 sbit key2=p2^5; // 用 key2 表示 P2.5 口 sbit key3=p2^6; // 用 key3 表示 P2.6 口 sbit key4=p2^7; // 用 key4 表示 P2.7 口 sbit key5=p3^2; // 用 key5 表示 P3.2 口 sbit key_gnd=p2^2; bit all_setting_flag=0; // 进入设置模式标志位 bit date_setting_flag=0; // 进入日期设置模式标志位 bit time_setting_flag=0; // 进入时间设置模式标志位 bit temp_setting_flag=0; // 进入报警温度设置模式标志位 bit sound_setting_flag=0; // 进入按键音设置模式标志位 bit temp_alarm_start_f=0; // 温度超限报警启动标志位 bit clock_setting_flag=0; // 进入按键音设置模式标志位 bit clock_start_flag=0; // 闹钟启动标志位 bit clock_start_dis=0; // 闹钟启动显示标志位 bit clock_stop_dis=0; // 闹钟停止显示标志位 bit temp_start_flag=0; bit temp_start_dis=0; bit temp_stop_dis=0; bit alarm_view_flag=0; // 报警查询标志位 bit temp_alarm_flag=0; // 温度报警标志位 bit clock_alarm_flag=0; // 温度报警标志位 bit key_sound=0; /******************************************* 函数名称 : keyscan_delay 功能 : 1602 延时子函数参数 : z 返回值 : 无 /********************************************/ void keyscan_delay(uint z) uint j,k; // 定义局部变量 for(j=z;j>0;j--) for(k=120;k>0;k--); /******************************************** 函数名称 : data_setting 功能 : 年份设置调节函数参数 : dat max min 返回值 : tem /********************************************/ uchar data_setting(uchar dat,uchar max,uchar min) char tem=dat; if(key2==0) // 设置选择, 向上翻页 if(key_sound==0) beep=0; // 按键按下启动按键音 keyscan_delay(10); if(key2==0) //K2 按按键时消抖 beep=1; // 按键松开关闭按键音 tem++; // 要设定的数据值加 1 if(tem>max) // 若大于最大值了 tem=min; // 将最小值送给该数据 while(key2==0); //K2 松按键时消抖 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 if(key3==0) ww.zicreate.com // 设置选择, 向下翻页

139 第 7 章 AT89S52 单片机控制系统应用实例设计 if(key_sound==0) beep=0; keyscan_delay(10); if(key3==0) //K3 按按键时消抖 beep=1; tem--; // 要设定的数据值减 1 if(tem<min) // 当小于最小值是 tem=max; while(key3==0); return(tem); /******************************************** 函数名称 : alarm_temp_change 功能 : 上下限报警温度调整参数 : count f 返回值 : count /********************************************/ uchar alarm_temp_change(uchar tem,bit f) char count; count=tem; // 将最大值送该数据 //K3 松按键时消抖 // 返回 tem 值 if(key2==0) // 判断 K2 是否按下 if(key_sound==0) beep=0; keyscan_delay(10); // 延时 10ms if(key2==0) // 再次判断 K2 是否按下 ( 实现按按键时消抖 ) beep=1; if(f==0) // 若温度为正 count++; // 每按一下 K2 温度上调 1 if(count>125) count=125; // 当温度值大于 125 时不上调 else // 若温度为负 count++; // 每按一下 K2 温度下调 1 if(count>55) count=55; // 当温度值小于 -55 时不再下调 while(key2==0); if(key3==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key3==0) //K2 松开按键时消抖 //K3 按按键时消抖 beep=1; count--; // 每按一下 K3 温度为正时下调 1, 为负时上调 1 if(count<0) count=0; while(key3==0); // 当温度值达到 0 时不再调 //K3 松开按键时消抖

140 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 return (count); /******************************************** 函数名称 : date_setting 功能 : 日期设置调节函数参数 : 无返回值 : 无 /********************************************/ void date_setting() char b=0; while(date_setting_flag) // 当日期设置标志位为 1 时进入日期设置循环 if(key1==0) //k1 用于选择要调节的日期 if(key_sound==0) beep=0; keyscan_delay(10); if(key1==0) //K1 按按键时消抖 beep=1; b++; if(b>3) b=0; while(key1==0); //K1 松按键时消抖 keyscan_delay(10); while(key1==0); if(key4==0) //k4 按键扫描函数, 退出设置功能 if(key_sound==0) beep=0; keyscan_delay(10); if(key4==0) //K4 按按键时消抖 beep=1; b=0; date_setting_flag=0; // 将日期设置标志位清 0 DS1302_Set_date(all_data.Week,all_data.Day,all_data.Month,all_data.Year);// 将设置好的日期写入 ds1302 while(key4==0); //K4 松按键时消抖 lcd_1602_gotoxy(1,0); lcd_1602_printf(not_dis2,2); lcd_1602_gotoxy(1,2); lcd_1602_printf(date_set,14); if(t1==1) switch(b) // 用于要设置的数据在设置时不停的闪烁 case(0):lcd_1602_gotoxy(2,1); lcd_1602_printf(not_dis4,4); break; case(1):lcd_1602_gotoxy(2,6); lcd_1602_printf(not_dis2,2); break; case(2):lcd_1602_gotoxy(2,9);

141 第 7 章 AT89S52 单片机控制系统应用实例设计 else lcd_1602_printf(not_dis2,2); break; case(3):lcd_1602_gotoxy(2,12); lcd_1602_printf(not_dis3,3); break; default:break; lcd_1602_gotoxy(2,0); lcd_1602_printf(" 20",3); lcd_1602_gotoxy(2,3); lcd_1602_printf(all_data.datestring,12);// 显示日期 if(b==0) // 设置年 all_data.year=data_setting(all_data.year,99,0); if(b==1) // 设置月 all_data.month=data_setting(all_data.month,12,0); if(b==2) // 设置天 all_data.day=data_setting(all_data.day,31,0); if(b==3) // 设置周 all_data.week=data_setting(all_data.week,7,1); DateToStr(&all_data); /******************************************** 函数名称 : time_setting 功能 : 时间设置函数参数 : 无返回值 : 无 /********************************************/ void time_setting() char c=0; while(time_setting_flag) if(key1==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key1==0) beep=1; c++; if(c>2) c=0; while(key1==0); // 存储设置好的日期 // 当时间设置标志位是 1 时进入时间设置循环 //k1 用于选择要调节的时间 //K1 按按键时消抖 //K1 松按键时消抖

142 if(key4==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key4==0) ww.zicreate.com //k4 按键扫描函数, 退出设置功能 //K4 按按键时消抖 beep=1; c=0; time_setting_flag=0; //k4 按下时时间设置标志位清 0 DS1302_Set_time(all_data.Second,all_data.Minute,all_data.Hour); while(key4==0); //K4 松按键时消抖 lcd_1602_gotoxy(1,0); lcd_1602_printf(not_dis2,2); lcd_1602_gotoxy(1,2); lcd_1602_printf(time_set,14); // 显示 "Time Setting " if(t1==1) else switch(c) case(0):lcd_1602_gotoxy(2,4); lcd_1602_printf(not_dis2,2); break; case(1):lcd_1602_gotoxy(2,7); lcd_1602_printf(not_dis2,2); break; case(2):lcd_1602_gotoxy(2,10); lcd_1602_printf(not_dis2,2); break; default:break; 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 // 用于要设置的数据在设置时不停的闪烁 lcd_1602_gotoxy(2,0); lcd_1602_printf(" ",4); lcd_1602_gotoxy(2,4); lcd_1602_printf(all_data.timestring,8); // 显示时间 lcd_1602_gotoxy(2,12); lcd_1602_printf(" ",4); if(c==0) // 设置时 all_data.hour=data_setting(all_data.hour,23,0); if(c==1) // 设置分 all_data.minute=data_setting(all_data.minute,59,0); if(c==2) // 设置秒 all_data.second=data_setting(all_data.second,59,0); TimeToStr(&all_data); /******************************************** // 存储设置好的时间

143 第 7 章 AT89S52 单片机控制系统应用实例设计 函数名称 : temp_setting 功能 : 报警温度设置函数参数 : 无返回值 : 无 /********************************************/ void temp_setting() char d=0; while(temp_setting_flag) // 当报警温度设置标志位为 1 时进入报警温度设置循环 if(key1==0) //k1 用于选择要调节的温度 if(key_sound==0) beep=0; keyscan_delay(10); if(key1==0) //K1 按按键时消抖 beep=1; d++; if(d>1) d=0; while(key1==0); //K1 松按键时消抖 if(key4==0) //k4 按键扫描函数, 退出设置功能 if(key_sound==0) beep=0; keyscan_delay(10); if(key4==0) beep=1; d=0; //K4 按按键时消抖 temp_setting_flag=0; //k4 按下时报警温度设置标志位清 0 ds18b20_store_t(); //k4 按下时存储设置好的报警温度 while(key4==0); if(key5==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key5==0) //K4 松按键时消抖 // 用于设置温度的正负 //K5 按按键时消抖 beep=1; if(d==0) if(max>55) f_max=0; else f_max=~f_max;// 当温度大于 55 度时, 只能设定为正温度 if(d==1) if(min>55) f_max=0;else f_min=~f_min;// 当温度大于 55 度时, 只能设定为正温度 while(key5==0); //K5 松开按键时消抖 lcd_1602_gotoxy(1,0); lcd_1602_printf(alarm_temp_set,16); // 显示 "AlarmTemperature" if(t1==1) switch(d) case(0):lcd_1602_gotoxy(2,2); lcd_1602_printf(not_dis3,3);

144 else ww.zicreate.com break; case(1):lcd_1602_gotoxy(2,10); lcd_1602_printf(not_dis3,3); break; default:break; lcd_1602_gotoxy(2,0); lcd_1602_printf(" H",2); lcd_1602_gotoxy(2,2); lcd_1602_printf(temp_high_alarm,5); lcd_1602_gotoxy(2,7); lcd_1602_printf(" L",3); lcd_1602_gotoxy(2,10); lcd_1602_printf(temp_low_alarm,5); lcd_1602_gotoxy(2,15); lcd_1602_printf(" ",1); if(d==0) max=alarm_temp_change(max,f_max); if(d==1) min=alarm_temp_change(min,f_min); temp_transform(); /******************************************** 函数名称 : clock_transform 功能 : 闹钟设置好后存储函数参数 : 无返回值 : 无 /********************************************/ void clock_transform() clock_table[0] = clock_h/10 + '0'; clock_table[1] = clock_h%10 + '0'; clock_table[2] = ':'; clock_table[3] = clock_m/10 + '0'; clock_table[4] = clock_m%10 + '0'; clock_table[5] = ':'; clock_table[6] = clock_s/10 + '0'; clock_table[7] = clock_s%10 + '0'; /******************************************** 函数名称 : clock_setting 功能 : 闹钟设置函数参数 : 无返回值 : 无 /********************************************/ void clock_setting() char g=0; while(clock_setting_flag) 第一部分 51 系列 AT89S52 单片机 C 语言程序设计

145 第 7 章 AT89S52 单片机控制系统应用实例设计 if(key1==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key1==0) beep=1; g++; if(g>2) g=0; while(key1==0); if(key4==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key4==0) beep=1; g=0; clock_setting_flag=0; while(key4==0); //K1 按按键时消抖 //K1 松按键时消抖 //k4 按键扫描函数, 退出设置功能 //K4 按按键时消抖 //K4 松按键时消抖 lcd_1602_gotoxy(1,0); lcd_1602_printf(not_dis2,2); lcd_1602_gotoxy(1,2); lcd_1602_printf(time_set,14); if(t1==1) switch(g) case(0):lcd_1602_gotoxy(2,4); lcd_1602_printf(not_dis2,2); break; case(1):lcd_1602_gotoxy(2,7); lcd_1602_printf(not_dis2,2); break; case(2):lcd_1602_gotoxy(2,10); lcd_1602_printf(not_dis2,2); break; default:break; else lcd_1602_gotoxy(2,0); lcd_1602_printf(" ",4); lcd_1602_gotoxy(2,4); lcd_1602_printf(clock_table,8); lcd_1602_gotoxy(2,12); lcd_1602_printf(" ",4); if(g==0) clock_h=data_setting(clock_h,23,0);

146 if(g==1) clock_m=data_setting(clock_m,59,0); if(g==2) clock_s=data_setting(clock_s,59,0); clock_transform(); /******************************************** 函数名称 : sound_setting 功能 : 参数 : 无返回值 : 无 /********************************************/ void sound_setting() char e=0; bit z; while(sound_setting_flag) if(key1==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key1==0) //K1 按按键时消抖 beep=1; e++; if(e>1) e=0; while(key1==0); //K1 松按键时消抖 if(key4==0) //k4 按键扫描函数, 退出设置功能 if(key_sound==0) beep=0; keyscan_delay(10); if(key4==0) //K4 按按键时消抖 beep=1; e=0; sound_setting_flag=0; //K4 按下退出按键音设置功能 key_sound=z; // 保存设置值 while(key4==0); //K4 松按键时消抖 lcd_1602_gotoxy(1,0); lcd_1602_printf(" ",2); lcd_1602_gotoxy(1,2); lcd_1602_printf(sound_set,14); if(t1==1) switch(e) // 按键音设置菜单选择 ww.zicreate.com 第一部分 51 系列 AT89S52 单片机 C 语言程序设计

147 第 7 章 AT89S52 单片机控制系统应用实例设计 else case(0):lcd_1602_gotoxy(2,2); lcd_1602_printf(not_dis4,4); break; case(1):lcd_1602_gotoxy(2,9); lcd_1602_printf(not_dis5,5); break; default:break; lcd_1602_gotoxy(2,0); lcd_1602_printf(" ",2); lcd_1602_gotoxy(2,2); lcd_1602_printf("open",4); lcd_1602_gotoxy(2,6); lcd_1602_printf(" ",3); lcd_1602_gotoxy(2,9); lcd_1602_printf("close",5); lcd_1602_gotoxy(2,14); lcd_1602_printf(" ",2); if(e==0) z=0; if(e==1) z=1; /******************************************** 函数名称 : all_seting 功能 : 设置调节函数参数 : 无返回值 : 无 /********************************************/ void all_setting() char a=0; while(all_setting_flag) if(key2==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key2==0) beep=1; a++; if(a>4) a=0; while(key2==0); // 实现要设置的项的闪烁功能 // 设置选择, 向上翻页 //K2 按按键时消抖 //K2 松按键时消抖 if(key3==0)

148 if(key_sound==0) beep=0; keyscan_delay(10); if(key3==0) beep=1; a--; if(a<0) a=4; while(key3==0); //K3 按按键时消抖 //K3 松按键时消抖 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 if(key4==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key4==0) ww.zicreate.com //k4 按键扫描函数, 退出设置功能 //K4 按按键时消抖 beep=1; a=0; all_setting_flag=0; // 当 K4 按下所有设置标志位清 0 while(key4==0); switch(a) case 0: lcd_1602_gotoxy(1, 2); lcd_1602_printf(date_set,14); lcd_1602_gotoxy(2, 2); lcd_1602_printf(time_set,14); if(key1==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key1==0) beep=1; date_setting_flag=1; while(key1==0); date_setting(); break; case 1: lcd_1602_gotoxy(1, 2); lcd_1602_printf(time_set,14); lcd_1602_gotoxy(2, 2); lcd_1602_printf(clock_set,14); if(key1==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key1==0) beep=1; time_setting_flag=1; while(key1==0); //K4 松按键时消抖 // 日期设置菜单选择 //K1 按按键时消抖 //k1 按下进入日期设置模式 //K1 松按键时消抖 // 时间设置菜单选择 //K1 按按键时消抖 //k1 按下进入时间设置模式 //K1 松按键时消抖

149 第 7 章 AT89S52 单片机控制系统应用实例设计 time_setting(); break; case 2: lcd_1602_gotoxy(1, 2); lcd_1602_printf(clock_set,14); lcd_1602_gotoxy(2, 2); lcd_1602_printf(temp_set,14); if(key1==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key1==0) beep=1; clock_setting_flag=1; while(key1==0); beep=1; clock_setting(); break; case 3: lcd_1602_gotoxy(1, 2); lcd_1602_printf(temp_set,14); lcd_1602_gotoxy(2, 2); lcd_1602_printf(sound_set,14); if(key1==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key1==0) beep=1; temp_setting_flag=1; while(key1==0); beep=1; temp_setting(); break; case 4: lcd_1602_gotoxy(1, 2); lcd_1602_printf(sound_set,14); lcd_1602_gotoxy(2, 2); lcd_1602_printf(date_set,14); if(key1==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key1==0) beep=1; sound_setting_flag=1; while(key1==0); beep=1; sound_setting(); break; default:break; // 闹钟设置菜单选择 //K1 按按键时消抖 //k1 按下进入闹钟设置模式 //K1 松按键时消抖 // 报警温度设置菜单选择 //K1 按按键时消抖 //k1 按下进入报警温度设置模式 //K1 松按键时消抖 // 按键音设置 //K1 按按键时消抖 //k1 按下进入按键音设置模式 //K1 松按键时消抖

150 if(t1==1) else ww.zicreate.com lcd_1602_gotoxy(1, 0); lcd_1602_printf(not_dis2,2); lcd_1602_gotoxy(1, 0); lcd_1602_printf(dis2,2); lcd_1602_gotoxy(2, 0); lcd_1602_printf(not_dis2,2); /******************************************** 函数名称 : keyscan 功能 : 键盘扫描函数参数 : 无返回值 : 无 /********************************************/ void keyscan() if(key1==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key1==0) beep=1; all_setting_flag=1; DS1302_GetTime(&all_data); DateToStr(&all_data); TimeToStr(&all_data); while(key1==0); all_setting(); if(key2==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key2==0) beep=1; clock_start_flag=0; clock_stop_dis=1; w=0; clock_alarm_flag=0; while(key2==0); if(key3==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key3==0) // 用于进入主设置菜单 //K1 按按键时消抖 // 获取日期与时间 // 存储获取的日期 // 存储获取的时间 //K1 松按键时消抖 // 调用所有设置函数 // 用于关闭闹钟 //K2 按按键时消抖 // 关闭闹钟 //K2 松按键时消抖 // 用于关闭温度报警 //K3 按按键时消抖 第一部分 51 系列 AT89S52 单片机 C 语言程序设计 // 菜单选择箭头闪烁功能

151 第 7 章 AT89S52 单片机控制系统应用实例设计 beep=1; temp_start_flag=0; temp_stop_dis=1; w=0; temp_alarm_flag=0; while(key3==0); if(key4==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key4==0) beep=1; TR0=1; alarm_view_flag=1; while(key4==0); if(key5==0) #endif if(key_sound==0) beep=0; keyscan_delay(10); if(key5==0) beep=1; while(key5==0) if(key2==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key2==0) beep=1; clock_start_flag=1; clock_start_dis=1; while(key2==0); if(key3==0) if(key_sound==0) beep=0; keyscan_delay(10); if(key3==0) beep=1; temp_start_flag=1; temp_start_dis=1; while(key3==0); // 关闭温度报警 //K3 松按键时消抖 // 用于查看报警设置值 //K4 按按键时消抖 // 启动报警查看 //K4 松按键时消抖 // 用于启动温度报警和闹钟 //K5 按按键时消抖 // 当 k5 没松开时按 k2 启动闹钟, 按 k3 启动温度报警 //K2 按按键时消抖 // 启动闹钟 //K2 松按键时消抖 //K3 按按键时消抖 // 启动温度报警 //K3 松按键时消抖

152 第二部分 : 单片机常用外围器件 1.1 电阻器 第 1 章常用电子元器件 表 1-1 电阻的分类 分类实物特点 碳膜电阻 金属膜电阻 碳质电阻 绕线电阻 金属玻璃铀电阻 水泥电阻 将结晶碳沉积在陶瓷棒骨架上制成 碳膜电阻器成本低 性能稳定 阻值范围宽 温度系数和电压系数低, 是目前应用最广泛的电阻器 用真空蒸发的方法将合金材料蒸镀于陶瓷棒骨架表面 金属膜电阻比碳膜电阻的精度高, 稳定性好, 噪声, 温度系数小 在仪器仪表及通讯设备中大量采用 用碳质颗粒壮导电物质 填料和粘合剂混合制成一个实体的电阻器 特点 : 价格低廉, 但其阻值误差 噪声电压都大, 稳定性差, 目前较少用 用高阻合金线绕在绝缘骨架上制成, 外面涂有耐热的釉绝缘层或绝缘漆 绕线电阻具有较低的温度系数, 阻值精度高, 稳定性好, 耐热耐腐蚀, 主要做精密大功率电阻使用, 缺点是高频性能差, 时间常数大 将金属粉和玻璃铀粉混合, 采用丝网印刷法印在基板上 耐潮湿, 高温, 温度系数小, 主要应用于厚膜电路 水泥电阻是将电阻线绕在无碱性耐热瓷件上, 外面加上耐热 耐湿及耐腐蚀之材料保护固定并把绕线电阻体放入方形瓷器框内, 用特殊不燃性耐热水泥充填密封而成 水泥电阻 的外侧主要是陶瓷材质 水泥电阻通常用于功率大, 电流大 的场合 贴片电阻 SMT 敏感电阻 熔断电阻 片状电阻是金属玻璃铀电阻的一种形式, 他的电阻体是高可靠的钌系列玻璃铀材料经过高温烧结而成, 电极采用银钯合金浆料 体积小, 精度高, 稳定性好, 由于其为片状元件, 所以高频性能好 敏感电阻是指器件特性对温度, 电压, 湿度, 光照, 气体, 磁场, 压力等作用敏感的电阻器 敏感电阻的符号是在普通电阻的符号中加一斜线, 并在旁标注敏感电阻的类型, 如 : t. v 等 熔断电阻器又名保险丝电阻器, 是一种具有熔断丝 ( 保险丝 ) 及电阻器作用的双功能元器件, 在正常情况下, 具有普通电阻器的电气功能 一旦电路出现故障, 该电阻器会因过负荷而在规定时间内熔断开路, 从而起到保护其他元器件的作用

153 第 1 章常用电子元器件 排阻 排阻就是若干个参数完全相同的电阻, 它们的一个引脚都连到一起, 作为公共引脚 排阻的阻值与小电容是一样的读法, 第一和第二位直读, 第三位是零的个数, 比如 :A 102J,A 103J,A 152J, 分别为 1K,10K 和 1.5K 的排阻 小白点处是公共端 表 1-2 电位器的分类 分类 实物 特点 线绕电位器 用电阻丝在环状骨架上绕制成 它的特点是阻值范围小, 功率较大, 耐高温, 热稳定性好, 且噪声低 阻值变化是线性的, 通常用于大电流电路中 由于电感大, 不易用于高频场合 碳膜电位器 合成碳膜电位 器 它的电阻体是在马蹄形的纸胶板上涂上一层碳膜制成 它的组织变化和中间触头位置的关系有直线式 对数式和指数式三种 碳膜电位器有大型 小型 微型几种, 有的和开关一起组成带开关电位器 合成碳膜电位器的电阻体是由石墨, 炭黑, 有机黏合剂等配成的一种悬浮液, 涂在纤维板或胶纸板上制成的 合成碳膜电位器阻值范围宽, 分辨率高, 寿命长, 价格低, 型号多 实芯电位器 实芯电位器比较常见的的就是有机实芯电位器, 它是用炭 黑 石英粉 粘合剂等材料混合加热压制构成电位体, 然后 再加入塑料基体上经加热聚合而成 双联电位器 单联电位器有自己的转轴, 而双联电位器是两个电位器装在 一个轴上 即同轴双联电位器 高精度单圈电 位器 普通的电位器和一些精密的电位器都是单联电位器 高精度双圈电 位器 多圈电位器的结构大致可分为两种 :1. 电位器的动接点沿着螺旋形的绕组做螺旋运动来调节阻值 2. 通过涡轮 蜗杆来传动, 电位器的接触的接触刷装在轮上并在电阻体上作圆周运动 直划式电位器 采用直滑方式来改变阻值的大小 1. 直插式电阻色环电阻是应用于各种电子设备的最多的电阻类型, 无论怎样安装, 维修者都能方便的读出其阻值,

154 第二部分单片机常用外围器件 便于检测和更换 但在实践中发现, 有些色环电阻的排列顺序不甚分明, 往往容易读错, 在识别时, 可运用如下技巧加以判断 : 技巧 1: 先找标志误差的色环, 从而排定色环顺序 最常用的表示电阻误差的颜色是 : 金 银 棕, 尤其是金环和银环, 一般绝少用做电阻色环的第一环, 所以在电阻上只要有金环和银环, 就可以基本认定这是色环电阻的最末一环 技巧 2: 棕色环是否是误差标志的判别 棕色环既常用做误差环, 又常作为有效数字环, 且常常在第一环和最末一环中同时出现, 使人很难识别谁是第一环 在实践中, 可以按照色环之间的间隔加以判别 : 比如对于一个五道色环的电阻而言, 第五环和第四环之间的间隔比第一环和第二环之间的间隔要宽一些, 据此可判定色环的排列顺序 技巧 3: 在仅靠色环间距还无法判定色环顺序的情况下, 还可以利用电阻的生产序列值来加以判别 比如有一个电阻的色环读序是 : 棕 黑 黑 黄 棕, 其值为 : Ω=1MΩ 误差为 1%, 属于正常的电阻系列值, 若是反顺序读 : 棕 黄 黑 黑 棕, 其值为 Ω=140Ω, 误差为 1% 显然按照后一种排序所读出的电阻值, 在电阻的生产系列中是没有的, 故后一种色环顺序是不对的 色环阻值的标法四色环电阻 : 第一色环是十位数, 第二色环是个位数, 第三色环是应乘颜色次幂颜色次, 第四色环是误差率 例子 : 棕红红金其阻值为 =1.2K 误差为 ±5% 五色环电阻 : 第一色环是百位数, 第二色环是十位数, 第三色环是个位数, 第四色环是应乘颜色次幂颜色次, 第五色环是误差率 例子 : 红红黑棕金五色环电阻最后一环为误差, 前三环数值乘以第四环的 10 颜色次幂颜色次, 其电阻为 =2.2K 误差为 ±5% 表 1-1 阻值色环表 颜色代表数值乘数误差 (%) 温度系数 (PPM/ ) 黑 0 1 宗 1 10 ±1 100 红 ±2 50 橙 黄 绿 ±0.5 蓝 ± 紫 ±0.1 5 灰 ±0.05 白 金 10-1 ±5 银 10-2 ±10 ww.zicreate.com

155 第 1 章常用电子元器件 图 1-1 电阻色环对照图 2. 贴片电阻 我们常说的贴片电阻 (SMD Resistor) 叫 " 片式固定电阻器 "(Chip Fixed Resistor), 又叫 " 矩形片状电阻 "(Rectangular Chip Resistors), 是由 ROHM 公司发明并最早推出市场的 特点是耐潮湿, 耐高温, 可靠度高, 外观尺寸均匀, 精确且温度系数与阻值公差小 按生产工艺分厚膜 (Thick Film Chip Resistors) 薄膜 (Thin Film Chip Resistors ) 两种 厚膜是采用丝网印刷将电阻性材料淀积在绝缘基体 ( 例如玻璃或氧化铝陶瓷 ) 上, 然后烧结形成的 我们通常所见的多为厚膜片式电阻, 精度范围 ±0.5% ~ 10%, 温度系数 :±50PPM/ ~ ±400PPM/ 薄膜是在真空中采用蒸发和溅射等工艺将电阻性材料淀积在绝缘基体工艺 ( 真空镀膜技术 ) 制成, 特点是低温度系数 (±5PPM/ ), 高精度 (±0.01%~±1%) 封装有 :0201,0402,0603,0805,1206,1210,1812,2010,2512 其常规系列的精度为 5%, 1% 阻值范围从 0.1 欧姆到 20M 欧姆 标准阻值有 E24,E96 系列 功率有 1/20W 1/16W 1/8W 1/10W 1/4W 1/2W 1W 贴片电阻常见封装有 9 种, 用两种尺寸代码来表示 一种尺寸代码是由 4 位数字表示的 EIA( 美国电子工业协会 ) 代码, 前两位与后两位分别表示电阻的长与宽, 以英寸为单位 我们常说的 0603 封装就是指英制代码 另一种是米制代码, 也由 4 位数字表示, 其单位为毫米 下表列出贴片电阻封装英制和公制的关系及详细的尺寸 : 英制 (mil) 公制 (mm) 表 1-3 贴片电阻封装英制和公制的关系及详细的尺寸表 长 (L) (mm) 宽 (W) (mm) 高 (H) (mm) 最大工作电压 (V) 额定功率 (W) / / / / / / / / 阻值规格 : 1).E-24 标注方法 E-24 标注法有两位有效数字, 精度在 ±2%(-G), ±5%(-J), ±10%(-K) (1) 常用电阻标注 XXY XX 代表底数,Y 代表指数

156 第二部分单片机常用外围器件 例如 470 = 47Ω 103 = 10kΩ 224 = 220kΩ (2) 小于 10 欧姆的电阻的标注用 R 代表单位为欧姆的电阻小数点, 用 m 代表单位为毫欧姆的电阻小数点例如 1R0 = 1.0Ω R20 = 0.20Ω 5R1 = 5.1Ω R007 = 7.0mΩ 4m7 = 4.7mΩ 2).E-96 标注方法 E-96 标注法有三位有效数字, 精度在 ±1%(-F) (1) 常用电阻标注 XXXY XXX 代表底数,Y 代表指数例如 4700 = 470Ω 1003 = 100kΩ 2203 = 220kΩ (2) 小于 10 欧姆的电阻的标注用 R 代表单位为欧姆的电阻小数点, 用 m 代表单位为毫欧姆的电阻小数点例如 1R00 = 1.00Ω R200 = 0.200Ω 5R10 = 5.10Ω R007 = 7.00mΩ 4m70 = 4.70mΩ (3)E-96 Multiplier Code 标注法 XXY XX 代表底数的代码, 具体数值可从 Multiplier Code 表中查找 Y 代表指数的代码, 具体数值也要从 Multiplier Code 表中查找例如 : 18A = 150Ω 02C = 10.2kΩ 1.2 电容器在一般的电子电路中, 常用电容器来实现旁路 耦合 滤波 振荡 相移以及波形变换等, 这些作用 都是其充电和放电功能的演变 分类实物特性 铝电解电容器 表 1-4 电容器的分类 用浸有糊状电解质的吸水纸夹在两条铝箔中间卷绕而成, 薄的化氧化膜作介质的电容器. 因为氧化膜有单向导电性质, 所以电解电容器具有极性. 容量大, 能耐受大的脉动电流 容量误差大, 泄漏电流大 ; 普通的不适于在高频和低温下应用, 不宜使用在 25kHz 以上频率 钽电解电容器 薄膜电解电容 器 用烧结的钽块作正极, 电解质使用固体二氧化锰 温度特性 频率特性和可靠性均优于普通电解电容器, 特别是漏电流极小, 贮存性良好, 寿命长, 容量误差小, 而且体积小, 单位体积下能得到最大的电容电压乘积 对脉动电流的耐受能力差, 若损坏易呈短路状态 结构与纸质电容器相似, 但用聚脂 聚苯乙烯等低损耗塑材作介质 频率特性好, 介电损耗小 不能做成大的容量, 耐热能力差 滤波器 积分 振荡 定时电路 陶瓷电容器 用高介电常数的电容器陶瓷 钛酸钡一氧化钛 挤压成圆管 圆片或圆盘作为介质, 并用烧渗法将银镀在陶瓷上作为电极制成 它又分高频瓷介和低频瓷介两种 低频瓷介电容器限于在工作频率较低的回路中作旁路或隔直流用, 或对稳定性和损耗要求不高的场合 包括高频在内 这种电容器不宜使用在脉冲电路中, 因为它们易于被脉冲电压击穿 高频瓷介电容器适用于高频电路 ww.zicreate.com

157 第 1 章常用电子元器件 独石电容器 ( 多层陶瓷电容器 ) 云母电容器涤纶电容器 在若干片陶瓷薄膜坯上被覆以电极桨材料, 叠合后一次绕结成一块不可分割的整体, 外面再用树脂包封而成 体积小 容量大 高可靠和耐高温的新型电容器, 高介电常数的低频独石电容器也具有稳定的性能, 体积极小,Q 值高, 容量误差较大 就结构而言, 可分为箔片式及被银式 被银式电极为直接在云母片上用真空蒸发法或烧渗法镀上银层而成, 由于消除了空气间隙, 温度系数大为下降, 电容稳定性也比箔片式高 频率特性好,Q 值高, 温度系数小, 不能做成大的容量, 广泛应用在高频电器中, 并可用作标准电容器 用两片金属箔做电极, 夹在极薄的电容纸中, 卷成圆柱形或者 扁柱形芯子, 介质是涤纶 涤纶薄膜电容, 介电常数较高, 体 积小, 容量大, 稳定性较好, 适宜做旁路电容 微调电容 贴片电容 电容量可在某一小范围内调整, 并可在调整后固定于某个电容值 瓷介微调电容器的 Q 值高, 体积也小, 通常可分为圆管式及圆片式两种 云母和聚苯乙烯介质的通常都采用弹簧式东, 结构简单, 但稳定性较差 线绕瓷介微调电容器是拆铜丝 外电极 来变动电容量的, 故容量只能变小, 不适合在需反复调试的场合使用矩形片状电容的容量标法与片状电阻相同, 其容量范围为 1~4700pf, 耐压由 20~2000V 不等 贴片电容上面没有印字, 贴装无朝向 而贴片电解电容有印字, 标法与片状电阻相同 贴片电解电容有横标方向为正极 1. 标称电容量和允许偏差标称电容量是标志在电容器上的电容量 电容器的基本单位是法拉 (F), 但是, 这个单位太大, 在实地标注中很少采用 其它单位关系如下 : 1F=1000mF 1mF=1000μF 1μF=1000nF 1nF=1000pF 电容器实际电容量与标称电容量的偏差称误差, 在允许的偏差范围称精度 精度等级与允许误差对应关系 :00(01)-±1% 0(02)-±2% Ⅰ-±5% Ⅱ-±10% Ⅲ-±20% Ⅳ -(+20%-10%) Ⅴ-(+50%-20%) Ⅵ-(+50%-30%) 一般电容器常用 Ⅰ Ⅱ Ⅲ 级, 电解电容器用 Ⅳ Ⅴ Ⅵ 级, 根据用途选取 2. 额定电压在最低环境温度和额定环境温度下可连续加在电容器的最高直流电压有效值, 一般直接标注在电容器外壳上, 如果工作电压超过电容器的耐压, 电容器击穿, 造成不可修复的永久损坏 3. 电容器的型号命名方法国产电容器的型号一般由四部分组成 ( 不适用于压敏 可变 真空电容器 ) 依次分别代表名称 材料 分类和序号 第一部分 : 名称, 用字母表示, 电容器用 C 第二部分 : 材料, 用字母表示 第三部分 : 分类, 一般用数字表示, 个别用字母表示 第四部分 : 序号, 用数字表示 用字母表示产品的材料 :A- 钽电解 B- 聚苯乙烯等非极性薄膜 C- 高频陶瓷 D- 铝电解 E- 其它材料电解 G- 合金电解 H- 复合介质 I- 玻璃釉 J- 金属化纸 L- 涤纶等极性有机薄膜 N- 铌电解 O- 玻璃膜 Q- 漆膜 T- 低频陶瓷 V- 云母纸 Y- 云母 Z- 纸介 4. 电容器容量标示

158 第二部分单片机常用外围器件 1) 直标法用数字和单位符号直接标出 如 1uF 表示 1 微法, 有些电容用 R 表示小数点, 如 R56 表示 0.56 微法 2) 文字符号法用数字和文字符号有规律的组合来表示容量 如 p10 表示 0.1pF,1p0 表示 1pF,6P8 表示 6.8pF, 2u2 表示 2.2uF. 3) 色标法用色环或色点表示电容器的主要参数 电容器的色标法与电阻相同 电容器偏差标志符号 :+100%-0--H +100%-10%--R +50%-10%--T +30%-10%--Q +50%-20%--S +80%-20%--Z 4) 数学计数法: 如上图瓷介电容, 标值 272, 容量就是 :27X100pf=2700pf. 如果标值 473, 即为 47X1000pf= 后面的 2 3, 都表示 10 的多少次方 ) 又如:332=33X100pf=3300pf 5. 电容器的分类 1) 按照结构分三大类: 固定电容器 可变电容器和微调电容器 2) 按电解质分类: 有机介质电容器 无机介质电容器 电解电容器和空气介质电容器等 3) 按用途分有: 高频旁路 低频旁路 滤波 调谐 高频耦合 低频耦合 小型电容器 4) 按制造材料的不同可以分为: 瓷介电容 涤纶电容 电解电容 钽电容, 还有先进的聚丙烯电容等等 5) 高频旁路: 陶瓷电容器 云母电容器 玻璃膜电容器 涤纶电容器 玻璃釉电容器 6) 低频旁路: 纸介电容器 陶瓷电容器 铝电解电容器 涤纶电容器 7) 滤波: 铝电解电容器 纸介电容器 复合纸介电容器 液体钽电容器 8) 调谐: 陶瓷电容器 云母电容器 玻璃膜电容器 聚苯乙烯电容器 9) 低耦合: 纸介电容器 陶瓷电容器 铝电解电容器 涤纶电容器 固体钽电容器 10) 小型电容: 金属化纸介电容器 陶瓷电容器 铝电解电容器 聚苯乙烯电容器 固体钽电容器 玻璃釉电容器 金属化涤纶电容器 聚丙烯电容器 云母电容器 6. 固定电容器的检测 A 检测 10pF 以下的小电容因 10pF 以下的固定电容器容量太小, 用万用表进行测量, 只能定性的检查其是否有漏电, 内部短路或击穿现象 测量时, 可选用万用表 R 10k 挡, 用两表笔分别任意接电容的两个引脚, 阻值应为无穷大 若测出阻值 ( 指针向右摆动 ) 为零, 则说明电容漏电损坏或内部击穿 B 检测 10PF~0.01μF 固定电容器是否有充电现象, 进而判断其好坏 万用表选用 R 1k 挡 两只三极管的 β 值均为 100 以上, 且穿透电流要些可选用 3DG6 等型号硅三极管组成复合管 万用表的红和黑表笔分别与复合管的发射极 e 和集电极 c 相接 由于复合三极管的放大作用, 把被测电容的充放电过程予以放大, 使万用表指针摆幅度加大, 从而便于观察 应注意的是 : 在测试操作时, 特别是在测较小容量的电容时, 要反复调换被测电容引脚接触 A B 两点, 才能明显地看到万用表指针的摆动 C 对于 0.01μF 以上的固定电容, 可用万用表的 R 10k 挡直接测试电容器有无充电过程以及有无内部短路或漏电, 并可根据指针向右摆动的幅度大小估计出电容器的容量 7. 电解电容器的检测 A 因为电解电容的容量较一般固定电容大得多, 所以, 测量时, 应针对不同容量选用合适的量程 根据经验, 一般情况下,1~47μF 间的电容, 可用 R 1k 挡测量, 大于 47μF 的电容可用 R 100 挡测量 B 将万用表红表笔接负极, 黑表笔接正极, 在刚接触的瞬间, 万用表指针即向右偏转较大偏度 ( 对于同一电阻挡, 容量越大, 摆幅越大 ), 接着逐渐向左回转, 直到停在某一位置 此时的阻值便是电解电容的正向漏电阻, 此值略大于反向漏电阻 实际使用经验表明, 电解电容的漏电阻一般应在几百 kω 以上, 否则, 将不能正常工作 在测试中, 若正向 反向均无充电的现象, 即表针不动, 则说明容量消失或内部断路 ; 如果所测阻值很小或为零, 说明电容漏电大或已击穿损坏, 不能再使用 ww.zicreate.com

159 第 1 章常用电子元器件 C 对于正 负极标志不明的电解电容器, 可利用上述测量漏电阻的方法加以判别 即先任意测一下漏电阻, 记住其大小, 然后交换表笔再测出一个阻值 两次测量中阻值大的那一次便是正向接法, 即黑表笔接的是正极, 红表笔接的是负极 D 使用万用表电阻挡, 采用给电解电容进行正 反向充电的方法, 根据指针向右摆动幅度的大小, 可估测出电解电容的容量 8. 可变电容器的检测 A 用手轻轻旋动转轴, 应感觉十分平滑, 不应感觉有时松时紧甚至有卡滞现象 将载轴向前 后 上 下 左 右等各个方向推动时, 转轴不应有松动的现象 B 用一只手旋动转轴, 另一只手轻摸动片组的外缘, 不应感觉有任何松脱现象 转轴与动片之间接触不良的可变电容器, 是不能再继续使用的 C 将万用表置于 R 10k 挡, 一只手将两个表笔分别接可变电容器的动片和定片的引出端, 另一只手将转轴缓缓旋动几个来回, 万用表指针都应在无穷大位置不动 在旋动转轴的过程中, 如果指针有时指向零, 说明动片和定片之间存在短路点 ; 如果碰到某一角度, 万用表读数不为无穷大而是出现一定阻值, 说明可变电容器动片与定片之间存在漏电现象 9. 贴片电容的封装贴片电容上面没有印字, 这是和他的制作工艺有关 ( 贴片电容是经过高温烧结面成, 所以没办法在它的表面印字 ), 而贴片电阻是丝印而成 ( 可以印刷标记 ) 贴片电容有中高压贴片电容得普通贴片电容, 系列电压有 6.3V 10V 16V 25V 50V 100V 200V 500V 1000V 2000V 3000V 4000V 贴片电容的尺寸表示法有两种, 一种是英寸为单位来表示, 一种是以毫米为单位来表示, 贴片电容系列的型号有 等 英制 (mil) 表 1-5 贴片电容封装英制和公制的关系及详细的尺寸表 公制 (mm) 长 (L) (mm) 宽 (W) (mm) 贴片电容的材料常规分为三种,NPO,X7R,Y5V NPO 此种材质电性能最稳定, 几乎不随温度, 电压和时间的变化而变化, 适用于低损耗, 稳定性要求要的高频电路 容量精度在 5% 左右, 但选用这种材质只能做容量较小的, 常规 100PF 以下, 100PF-1000PF 也能生产但价格较高 X7R 此种材质比 NPO 稳定性差, 但容量做的比 NPO 的材料要高, 容量精度在 10% 左右 Y5V 此类介质的电容, 其稳定性较差, 容量偏差在 20% 左右, 对温度电压较敏感, 但这种材质能做到很高的容量, 而且价格较低, 适用于温度变化不大的电路中 10. 贴片电解电容的封装 贴片电解电容由于其紧贴电路版, 所以要求温度稳定性要高, 所以贴片电解电容以钽电容为多, 根 据其耐压不同, 贴片电解电容又可分为 A B C D 四个系列, 具体分类如下 : 表 1-6 贴片电解电容封装的详细的尺寸表

160 系列 公制 (mm) 长 (L) (mm) 宽 (W) (mm) 第二部分单片机常用外围器件 耐压 (V) A B C D 二极管半导体二极管又称晶体二极管, 简称二极管 (diode); 它只往一个方向传送电流的电子零件 它是一种具有 1 个零件号接合的 2 个端子的器件, 具有按照外加电压的方向, 使电流流动或不流动的性质 二极管的管压降 : 硅二极管 ( 不发光类型 ) 正向管压降 0.7V, 发光二极管正向管压降为随不同发光颜色而不同 二极管的识别 : 小功率二极管的 N 极 ( 负极 ), 在二极管外表大多采用一种色圈标出来, 有些二极管也用二极管专用符号来表示 P 极 ( 正极 ) 或 N 极 ( 负极 ), 也有采用符号标志为 P N 来确定二极管极性的 发光二极管的正负极可从引脚长短来识别, 长脚为正, 短脚为负 用数字式万用表去测二极管时, 红表笔接二极管的正极, 黑表笔接二极管的负极, 此时测得的阻值才是二极管的正向导通阻值, 这与指针式万用表的表笔接法刚好相反 表 1-7 二极管的分类 分类实物特点 整流二极管 一种将交流电能转变为直流电能的半导体器件 选用整流二极管时, 主要应考虑其反向峰值电压 最大整流电流 最大反向工作电流 截止频率及反向恢复时间等参数 稳压二极管 稳压二极管是一种直到临界反向击穿电压前都具有很高电阻的半导体器件. 在这临界击穿点上, 反向电阻降低到一个很小的数值, 在这个低阻区中电流增加而电压则保持恒定 开关二极管 半导体二极管导通时相当于开关闭合 ( 电路接通 ), 截止时相当于开关打开 ( 电路切断 ), 所以二极管可作开关用 开关二极管是专门用来做开关用的二极管, 它由导通变为截止或由截止变为导通所需的时间比一般二极管短 发光二极管简称为 LED 由镓 (Ga) 与砷 (AS) 磷 (P) 的化合 发光二极管 贴片二极管 物制成的二极管, 当电子与空穴复合时能辐射出可见光, 因而可 以用来制成发光二极管, 在电路及仪器中作为指示灯, 或者组成 文字或数字显示 磷砷化镓二极管发红光, 磷化镓二极管发绿光, 碳化硅二极管发黄光 贴片二极管尺寸比较小, 有稳压贴片二极管 整流贴片二极管 发光贴片二极管等 表 1-8 整流二极管 IN4001~4007 参数表 ww.zicreate.com

161 第 1 章常用电子元器件 表 1-9 整流二极管 IN4001~4007 的电气特性表 图 1-2 整流二极管 IN4001~4007 封装图 表 1-10 稳压二极管 IN4728~4752 参数表

162 第二部分单片机常用外围器件 稳压二极管的封装有 DO-35/DO-41 表 1-11 开关二极管 IN4148 参数表 表 1-12 开关二极管 IN4148 的电气特性表 ww.zicreate.com

163 第 1 章常用电子元器件 图 1-3 开关二极管 IN4148 的封装图 表 1-13 开关二极管 IN4149 参数表 表 1-14 开关二极管 IN4149 的电气特性表 开关二极管 IN4149 的封装同 IN4148 贴片法光二极管背面有一个箭头, 箭头指向的方向是发光二极管的负极, 焊接时应多加注意 1.4 三极管 表 1-15 常用三极管参数 型号极性 PCM (W) ICM (ma) BU(CEO)V ft(mhz) hfe 主要用途 9011 NPN ~198 通用管做功率放大 9012 PNP ~202 低噪声放大管 9013 NPN ~202 低噪声放大管 9014 NPN ~1000 低噪声放大管 9015 PNP ~600 低噪声放大管 9016 NPN ~198 低噪声放大管 9018 NPN ~198 低噪声高频放大管 8050 NPN A ~300 通用功率放大管 8550 PNP A ~300 通用功注 :BUCEO(V)( 集电极 - 发射极击穿电压 ):BUCEO 是指三极管基极开路时, 允许加在集电极与发射极之间的最高电压值 通常情况下 c e 极间电压不能超过 BUCEO, 否则会引起管子击穿损坏 所以加在集电极电压即直流电源电压, 不能高于 BUCEO 一般应取 BUCEO 高于电源电压的一倍 ICM(A)( 集电极最大电流 ): 集电极电流大到三极管所允许的极限值称集电极最大允许电流 使用三极管时, 集电极电流不能超过 ICM 值 PCM( 集电极最大允许耗散功率 ): 三极管工作时, 集电结要承受较大的反向电压和通过较大的电流, 因消耗功率而发热 当集电极所消耗的功率过大时, 就会产生高温而烧坏 因此规定三极管集电极温度升高到不至于将集电结烧坏所消耗的功率为极电结最大消耗功率 三极管在使用时, 不能超过这个极限 hfe( 三极管直流放大倍数 ):hfe 是指静态 ( 无变化信号输入 ) 情况下三极管 Ic 的 Ib 比值, 即 hfe= Ic/Ib ft( 特征频率 ): 三极管工作频率达到一定的程度时, 电流放大倍数 β 要下降,β 下降到 1 时的频率称为特征频率

164 第二部分单片机常用外围器件 1.5 常用开关 图 1-4 三极管的管脚分布及封装图 表 1-16 常用开关的分类 分类实物特点 按钮开关 按钮开关只能短暂的接通电路, 起到触发的作用, 这种按键迎面的两管脚, 如图中 1 和 2 3 和 4 是连通的相当于一个管脚, 所以使用时应注意不要接反 自锁开关拨码开关微动开关拨动开关 在开关按钮第一次按时, 开关接通并保持, 即自锁 ; 在开关按钮第二次按时, 开关断开, 同时开关按钮弹出来 没有按下开关时, 该开关的 1 和 2 5 和 6 脚是连通的, 按下开关后,1 和 2 5 和 6 脚断开,2 和 3 4 和 5 连通 使用时应先进行测量, 找出各个管脚, 找出按下或没按下时各个管脚连通的状况 当将开关上的拨档拨向标有 ON 的一端就接通了相应的两个管脚 开关通断时可自动清洁触点 广泛使用于数据处理 通信 遥控和防盗自动警铃系统等需要手动程式编制的产品上 微动开关是一种施压促动的快速开关, 又叫灵敏开关 外机械力通过传动元件 ( 按销 按钮 杠杆 滚轮等 ) 将力作用于动作簧片上, 并将能量积聚到临界点后, 产生瞬时动作, 使动作簧片末端的动触点与定触点快速接通或断开 拨动开关不止有两位的还有多位的, 当拨档拨到相应的位时就接通了相应位和公共端的连接 拨动开关能很好的不同路得两同 但一次只能连通一路 ww.zicreate.com

165 第 1 章常用电子元器件 摇杆开关 1.6 蜂鸣器 摇杆开关有单向 双向 三 向四向等 当摇杆拨向那个方向就能连通相应的管脚 表 1-17 蜂鸣器的分类 分类实物特点 有源蜂鸣器 无源蜂鸣器 引脚郡朝上放置时, 用黑胶封闭的一种是有源蜂鸣器 有源 蜂鸣器直接接上额定电源 ( 新的蜂鸣器在标签上都有注明 ) 就 可连续发声 引脚郡朝上放置时, 可以看出有绿色电路板的一种是无源蜂 鸣器 无源蜂鸣器则和电磁扬声器一样, 需要接在音频输出 电路中才能发声 迸一步判断有源蜂鸣器和无源蜂鸣器, 还可以用万用表电阻档 Rxl 档测试 : 用黑表笔接蜂鸣器 "+" 引脚, 红表笔在另一引脚上来回碰触, 如果触发出咔 咔声的且电阻只有 8Ω( 或 16Ω) 的是无源蜂鸣器 ; 如果能发出持续声音的, 且电阻在几百欧以上的, 是有源蜂鸣器 1.7 继电器 图 1-5 蜂鸣器常用驱动电路 表 1-18 继电器的分类 分类实物特点 电磁继电器 固态继电器 电磁继电器的工作电路由低压控制电路和高压工作电路两部分构成 只要在线圈两端加上一定的电压, 线圈中就会流过一定的电流, 从而产生电磁效应, 衔铁就会在电磁力吸引的作用下克服返回弹簧的拉力吸向铁芯, 从而带动衔铁的动触点与静触点 ( 常开触点 ) 吸合 当线圈断电后, 电磁的吸力消失, 衔铁就会在弹簧的反作用力返回原来的位置, 使动触点与原来的静触点 ( 常闭触点 ) 吸合 这样吸合 释放, 达到了在电路中的导通 切断的目的 固态继电器与电磁继电器相比, 是一种没有机械运动, 不含运动零件的继电器, 但它具有与电磁继电器本质上相同的功能 SSR 是一种全部由固态电子元件组成的无触点开关元件, 它利用电子元器件的电, 磁和光特性来完成输入与输出的可靠隔离, 利用大功率三极管, 功率场效应管, 单向可控硅和双向可控硅等器件的开关特性, 来达到无触点, 无火花地接通和断

166 开被控电路 第二部分单片机常用外围器件 1. 继电器的选用 : 1) 先了解必要的条件 1 控制电路的电源电压, 能提供的最大电流 ; 2 被控制电路中的电压和电流 ; 3 被控电路需要几组 什么形式的触点 选用继电器时, 一般控制电路的电源电压可作为选用的依据 控制电路应能给继电器提供足够的工作电流, 否则继电器吸合是不稳定的 2) 注意器具的容积 若是用于一般用电器, 除考虑机箱容积外, 小型继电器主要考虑电路板安装布局 对于小型电器, 如玩具 遥控装置则应选用超小型继电器产品 2. 继电器的驱动继电器驱动电流一般需要 20-40mA 或更大, 线圈电阻 欧姆, 因此要加驱动电路 1) 普通三极管驱动继电器电路对于低电压小电流的继电器, 用功率三极管做为开关驱动组件, 其输出电流就是输入电流与三极管增益的乘积 图 1-6 普通三极管驱动继电器电路 2) 达林顿管阵列 ULN2003 驱动继电器电路 ULN2003 是大电流驱动阵列, 多用于单片机 智能仪表 PLC 数字量输出卡等控制电路中 可直接驱动继电器等负载 ULN2000 ULN2800 高压大电流达林顿晶体管阵列系列产品就属于这类可控大功率器件, 由于这类器件功能强 应用范围语广 因此, 许多公司都生产高压大电流达林顿晶体管阵列产品, 从而形成了各种系列产品,ULN2000 ULN2800 系列就是美国 Texas Instruments 公司 美国 Sprague 公司开发的高压大电流达林顿晶体管阵列产品 它们的系列型号分类如表 1-19 所列, 生产 高压大电流达林顿晶体管阵列系列产品的公司与型号对照表如表 1-20 所列 在上述系列产品中,ULN2000 系列能够同时驱动 7 组高压大电流负载,ULN2800 系列则能够同时驱动 8 组高压大电流负载 ULN2003A 由 7 组达林顿晶体管阵列和相应的电阻网络以及钳位二极管网络构成, 具有同时驱动 7 组负载的能力, 为单片双极型大功率高速集成电路 以下介绍 ULN2003A 电路的构成 性能特征 电参数以及典型应用 表 1-19 ULN2000 ULN2800 系列型号分类表 输出电压 50V 50V 95V 50V 50V 95V 输出电流 500mA 600mA 500mA 500mA 600mA 500mA 普通 PMOS CMOS 输入 型号 型号 ULN2001A ULN2011A ULN2021 ULN2801A ULN2811A ULN2821A 14~25C PMOS 输入 ULN2002A ULN2012A ULN2022 ULN2802A ULN2812A ULN2822A 5V TTL CMOS 输入 ULN2003A ULN2013A ULN2023A ULN2803A ULN2813A ULN2823A ww.zicreate.com

167 第 1 章常用电子元器件 6~15V PMOS CMOS 输入 ULN2004A ULN2014A ULN2024A ULN2804A ULN2814A ULN2824A 高输出 TTL 接口 ULN2005A ULN2015A ULN2025A ULN2805A ULN2815A ULN2825A 表 1-20 生产 系列产品的公司与型号对照表 系列 \ 公司 TI Sprague Motorola SGS 三菱东菱三洋 2001 ULN2001A ULN2001A MC1411 L201B M54524P TD62001A LB ULN2002A ULN2002A MC1412 L202B M54525P TD6200A LB ULN2003A ULN2003A MC1413 L203 M54523P TD62003A LB ULN2004A ULN2004A MC1416 L204B N54526P TD62004A LB ULN2005A ULN2005A 2800 ULN2811~ ULN ULN2811~ ULN ULN2821~ ULN2825 ULN2003A 电路的管脚排列如图 1-7 所示 L601B~ L604B TD62081A~ 62084A 图 1-7 ULN2003A 电路的管脚排列及功能图 表 1-21 管脚功能表 引出端序号 符号 功能 引出端序号 符号 功能 1 I1 输入 9 COM 公共端 2 I2 输入 10 O7 输出 3 I3 输入 11 O6 输出 4 I4 输入 12 O5 输出 5 I5 输入 13 O4 输出 6 I6 输入 14 O3 输出 7 I7 输入 15 O2 输出 8 GND(E) 发射极 16 O1 输出 图 1-8 为 ULN2003A 内部原理图, 各引出端的功能符号及说明如表 1-21 所列

168 第二部分单片机常用外围器件 图 1-8 ULN2003A 内部原理图 表 1-22 ULN2003A 的极限参数 项目符号数值单位 最小 最大 最大输入电压 Vi(max) 30 V 集电极 - 发射极电压 Vo(max) 50 V 最大基极输入电流 IB(MAX) 25 ma 输出电流 Io 500 ma 贮存温度 Ts -65~150 结温 Tj 175 引线耐焊接温度 TD 300 集电极 - 发射极电压 Vce V 输入电压 Vi V 集电极电流 Imax 350 ma 工作环境温度 TA 表 1-23 ULN2003A 主要电特性 特性 符号 条件 ( 若无其它规定,TA=-40~ 85 ) 最小 规范值 直流放大倍数 hef VCE=2V,Ic350mA 集电极 - 发射极饱和电压 最大 VCE(sat) IB=500μA,IC=350mA V 箝位二极管正向电压 VF IF=350mA, 输入开路 V 集电极截止电流 ICEX VCE=50V Ii=0mA - 50 μa 单位 Vi=6V μa 箝位二极截止电流 IFEX VF=50V TA=25-50 μa Vi= μa 集电极最大电压 Vamx 空载 50 - V 集电极最大电流 Imax VCE=2V ma 开态延迟时间 ton VCE=5V,16kHz 的方波输入 -1.0 μs 关态延迟时间 toff VCE=5V,16kHz 的方波输入 -1.0 μs ww.zicreate.com

169 第 1 章常用电子元器件 图 1-9 ULN2003A 封装图 图 1-10 ULN2003A 驱动继电器电路图 1.8 接口器件 1.USB 接口 USB, 全称是 Universal Serial Bus,USB 支持热插拔, 即插即用的优点, 所以 USB 接口已经成为 MP3 的最主要的接口方式 USB 有两个规范, 即 USB1.1 和 USB2.0 USB1.1 是目前较为普遍的 USB 规范, 其高速方式的传输速率为 12Mbps, 低速方式的传输速率为 1.5Mbps (b 是 Bit 的意思 ),1MB/s( 兆字节 / 秒 )=8MBbPS( 兆位 / 秒 ),12Mbps=1.5MB/s 目前, 大部分 MP3 为此类接口类型 USB2.0 规范是由 USB1.1 规范演变而来的 它的传输速率达到了 480Mbps, 折算为 MB 为 60MB/s, 足以满足大多数外设的速率要求 USB 2.0 中的 增强主机控制器接口 (EHCI) 定义了一个与 USB 1.1 相兼容的架构 它可以用 USB 2.0 的驱动程序驱动 USB 1.1 设备 也就是说, 所有支持 USB 1.1 的设备 都可以直接在 USB 2.0 的接口上使用而不必担心兼容性问题, 而且像 USB 线 插头等等附件也都可以 直接使用 使用 USB 为打印机应用带来的变化则是速度的大幅度提升,USB 接口提供了 12Mbps 的连接速度, 相比并口速度提高达到 10 倍以上, 在这个速度之下打印文件传输时间大大缩减 USB 2.0 标准进一步将 接口速度提高到 480Mbps, 是普通 USB 速度的 20 倍, 更大幅度降低了打印文件的传输时间 USB 是一种常用的 pc 接口, 他只有 4 根线, 两根电源两根信号, 如下图. 故信号是串行传输的,usb 接口 也称为串行口,usb2.0 的速度可以达到 480Mbps 可以满足各种工业和民用需要.USB 接口的输出电压和 电流是 : +5V 500mA 实际上有误差, 最大不能超过 +/-0.2V 也就是 V usb 接口的 4 根线一般 是下面这样分配的, 需要注意的是千万不要把正负极弄反了, 否则会烧掉 usb 设备或者电脑的南桥芯片 : 黑线 :gnd 红线 :vcc 绿线 :data+ 白线 :data

170 第二部分单片机常用外围器件 图 1-11 usb 接口线定义图 图 1-12 usb 接口实物图 2.9 针串口接口 PC 电脑串行口的典型是 RS-232C 及其兼容接口, 串口引脚有 9 针和 25 针两类 而一般的个人电脑 中使用的都是 9 针的接口,25 针串行口具有 20mA 电流环接口功能, 用 针来实现 我们 只介绍常用 9 针的 rs232c 串口引脚的接口定义 图 真串口公母头实物及管脚排列图 表 针串口引脚定义 25 针串口引脚定义 9 针 RS-232 串口 (DB9). 25 针 RS-232 串口 (DB25) 引脚简写功能说明引脚简写功能说明 ww.zicreate.com

171 第 1 章常用电子元器件 1 CD 载波侦测 (Carrier Detect) 8 CD 载波侦测 (Carrier Detect) 2 RXD 接收数据 (Receive) 3 RXD 接收数据 (Receive) 3 TXD 发送数据 (Transmit) 2 TXD 发送数据 (Transmit) 4 DTR 数据终端准备 (Data Terminal Ready) 20 DTR 数据终端准备 (Data Terminal Ready) 5 GND 地线 (Ground) 7 GND 地线 (Ground) 6 DSR 数据准备好 (Data Set Ready) 6 DSR 数据准备好 (Data Set Ready) 7 RTS 请求发送 (Request To Send) 4 RTS 请求发送 (Request To Send) 8 CTS 清除发送 (Clear To Send) 5 CTS 清除发送 (Clear To Send) 9 RI 振铃指示 (Ring Indicator) 22 RI 振铃指示 (Ring Indicator) 图 1-14 串口通信应用电路 3. 并口接口并行口与串行口的区别是交换信息的方式不同, 并行口能同时通过 8 条数据线传输信息, 一次传输一个字节 ; 而串行口只能用 1 条线传输一位数据, 每次传输一个字节的一位 并行口由于同时传输更多的信息, 速度明显高于串行口, 但串行口可以用于比并行口更远距离的数据传输 图 针并口针脚分布与实物图 25 针并行口插口的针脚功能 : 表 针并口针脚功能表 针脚号 针脚名 功能 针脚号 针脚名 功能 1 STROBE 数据选通脉冲 10 ACKNLG 确认已收到数据

172 第二部分单片机常用外围器件 2 D0 数据线 0 位 11 BUSY 忙信号 3 D1 数据线 1 位 12 PE 缺纸 4 D2 数据线 2 位 13 SLCT 表示设备能工作 5 D3 数据线 3 位 14 AUTOFEDXT 后自动换行 6 D4 数据线 4 位 15 ERROR 出错指示 7 D5 数据线 5 位 16 INIT 初始化设备 8 D6 数据线 6 位 17 SLCTIN 允许设备工作 9 D7 数据线 7 位 18~25 GND 地 4.PS/2 键盘接口 PS/2 设备接口用于许多现代的鼠标和键盘它是由 IBM 开发, 物理上的 PS/2 端口是两类连接器中的一种 5 脚的 DIN 或 6 脚的 mini-din 这两种连接器在电气特性上是十分类似的实际上两者只有一点不同那就是管脚的排列这就意味着这两类连接器可以很容易用一种简单的硬件连线的适配器来转换这种适配器 表 1-26 PS/2 接口针脚定义 图 1-16 PS/2 接口座实物图 PS/2 通讯协议是一种双向同步串行通讯协议 通讯的两端通过 Clock( 时钟脚 ) 同步, 并通过 Data ( 数据脚 ) 交换数据 任何一方如果想抑制另外一方通讯时, 只需要把 Clock( 时钟脚 ) 拉到低电平 如果是 PC 机和 PS/2 键盘间的通讯, 则 PC 机必须做主机, 也就是说,PC 机可以抑制 PS/2 键盘发送数据, 而 PS/2 键盘则不会抑制 PC 机发送数据 一般两设备间传输数据的最大时钟频率是 33kHz, 大多数 PS/2 设备工作在 10~20kHZ 推荐值在 15kHZ 左右, 也就是说,Clock( 时钟脚 ) 高 低电平的持续时间都为 40μs 每一数据帧包含 11~12 个位, 具体含义如表 1-27 所列 表 1-27 数据帧格式说明 ww.zicreate.com

173 第 1 章常用电子元器件 1 个起始位总是逻辑 0 8 个数据位 (LSB) 低位在前 1 个奇偶校验位奇校验 1 个停止位总是逻辑 1 1 个应答位仅用在主机对设备的通讯中 表中, 如果数据位中 1 的个数为偶数, 校验位就为 1; 如果数据位中 1 的个数为奇数, 校验位就为 0; 总之, 数据位中 1 的个数加上校验位中 1 的个数总为奇数, 因此总进行奇校验 图 1-17 PS/2 通讯时序图 1)PS/2 设备和 PC 机的通讯 PS/2 设备的 Clock( 时钟脚 ) 和 Data 数据脚都是集电极开路的, 平时都是高电平 当 PS/2 设备等待发送数据时, 它首先检查 Clock( 时钟脚 ) 以确认其是否为高电平 如果是低电平, 则认为是 PC 机抑制了通讯, 此时它必须缓冲需要发送的数据直到重新获得总线的控制权 ( 一般 PS/2 键盘有 16 个字节的缓冲区, 而 PS/2 鼠标只有一个缓冲区仅存储最后一个要发送的数据 ) 如果 Clock( 时钟脚 ) 为高电平, PS/2 设备便开始将数据发送到 PC 机 一般都是由 PS/2 设备产生时钟信号 发送时一般都是按照数据帧格式顺序发送 其中数据位在 Clock( 时钟脚 ) 为高电平时准备好, 在 Clock( 时钟脚 ) 的下降沿被 PC 机读入 PS/2 设备到 PC 机的通讯时序如图 1-16 所示 当时钟频率为 15kHZ 时, 从 Clock( 时钟脚 ) 的上升沿到数据位转变时间至少要 5μs 数据变化到 Clock( 时钟脚 ) 下降沿的时间至少也有 5μs, 但不能大于 25μs, 这是由 PS/2 通讯协议的时序规定的 如果时钟频率是其它值, 参数的内容应稍作调整 上述讨论中传输的数据是指对特定键盘的编码或者对特定命令的编码 一般采用第二套扫描码集所规定的码值来编码 其中键盘码分为通码 (Make) 和断码 (Break) 通码是按键接通时所发送的编码, 用两位十六进制数来表示, 断码通常是按键断开时所发送的编码, 用四位十六进制数来表示 2)PS/2 接口的嵌入式软件编程方法 PS/2 设备主要用于产生同步时钟信号和读写数据 a)ps/2 向 PC 机发送一个字节从 PS/2 向 PC 机发送一个字节可按照下面的步骤进行 : (1) 检测时钟线电平, 如果时钟线为低, 则延时 50μs; (2) 检测判断时钟信号是否为高, 为高, 则向下执行, 为低, 则转到 (1); (3) 检测数据线是否为高, 如果为高则继续执行, 如果为低, 则放弃发送 ( 此时 PC 机在向 PS/2 设备发送数据, 所以 PS/2 设备要转移到接收程序处接收数据 ); (4) 延时 20μs( 如果此时正在发送起始位, 则应延时 40μs); (5) 输出起始位 (0) 到数据线上 这里要注意的是 : 在送出每一位后都要检测时钟线, 以确保 PC 机没有抑制 PS/2 设备, 如果有则中止发送 ; (6) 输出 8 个数据位到数据线上 ; (7) 输出校验位 ; (8) 输出停止位 (1); (9) 延时 30μs( 如果在发送停止位时释放时钟信号则应延时 50μs); 通过以下步骤可发送单个位 : (1) 准备数据位 ( 将需要发送的数据位放到数据线上 ); (2) 延时 20μs;

174 第二部分单片机常用外围器件 (3) 把时钟线拉低 ; (4) 延时 40μs; (5) 释放时钟线 ; (6) 延时 20μs b)ps/2 设备从 PC 机接收一个字节由于 PS/2 设备能提供串行同步时钟, 因此, 如果 PC 机发送数据, 则 PC 机要先把时钟线和数据线置为请求发送的状态 PC 机通过下拉时钟线大于 100μs 来抑制通讯, 并且通过下拉数据线发出请求发送数据的信号, 然后释放时钟 当 PS/2 设备检测到需要接收的数据时, 它会产生时钟信号并记录下面 8 个数据位和一个停止位 主机此时在时钟线变为低时准备数据到数据线, 并在时钟上升沿锁存数据 而 PS/2 设备则要配合 PC 机才能读到准确的数据 具体连接步骤如下 : (1) 等待时钟线为高电平 (2) 判断数据线是否为低, 为高则错误退出, 否则继续执行 (3) 读地址线上的数据内容, 共 8 个 bit, 每读完一个位, 都应检测时钟线是否被 PC 机拉低, 如果被拉低则要中止接收 (4) 读地址线上的校验位内容,1 个 bit (5) 读停止位 (6) 如果数据线上为 0( 即还是低电平 ),PS/2 设备继续产生时钟, 直到接收到 1 且产生出错信号为止 ( 因为停止位是 1, 如果 PS/2 设备没有读到停止位, 则表明此次传输出错 ) (7) 输出应答位 (8) 检测奇偶校验位, 如果校验失败, 则产生错误信号以表明此次传输出现错误 (9) 延时 45 μs, 以便 PC 机进行下一次传输 读数据线的步骤如下 : (1) 延时 20μs; (2) 把时钟线拉低 (3) 延时 40μs (4) 释放时钟线 (5) 延时 20μs (6) 读数据线 下面的步骤可用于发出应答位 ; (1) 延时 15μs;(2) 把数据线拉低 ;(3) 延时 5μs;(4) 把时钟线拉低 ; (5) 延时 40μs;(6) 释放时钟线 ; (7) 延时 5μs;(8) 释放数据线 图 1-18 PS/2 接口应用电路 1.9 纽扣电池纽扣电池, 也叫扣式电池, 是指外形尺寸象一颗小纽扣的电池, 一般来说直径较大, 厚度较薄 ( 相对于柱状电池如市场上的 5 号 AA 等电池 ); ww.zicreate.com

175 第 1 章常用电子元器件 纽扣电池一般来说常见的有充电的和不充电的两种, 充电的包括 3.6V 可充锂离子扣式电池 (LIR 系列 ), 3V 可充锂离子扣式电池 (ML 或 VL 系列 ); 不充电的包括 3V 锂锰扣式电池 (CR 系列 ) 及 1.5V 碱性锌锰扣式电池 (LR 及 SR 系列 ); 比较常见的纽扣电池有用于电脑主机板上的 CMOS 电池, 型号为 CR2032 用于电子词典里面的 CR20 25, 用于电子表时面的 CR2016 或者 SR44,SR626 等 ; 纽扣电池的型号名称前面的英文字母表示电池的种类, 数字表示尺寸, 前两位数字表示直径, 后两位表示厚度 ; 纽扣电池因体形较小, 直径从 4.8mm 至 30mm, 厚度从 1.0mm 至 7.7mm 不等 ; 一般用于各类电子产品的后备电源, 如电脑主板, 电子表, 电子词典, 电子秤, 记忆卡, 遥控器, 电动玩具等 ; 从电池的背面可以看到相应的标记 LR--- 水银 --1.5V SR--- 水银 V CR--- 锂电 --3V ZA--- 锌空 --1.4V 图 1-19 纽扣电池实物图 表 1-28 AG 系列纽扣电池参数表 规格型号 标称电压 标称容量 负载电阻 尺寸 HK JAPAN (V) (mah) (kω) 直径 (mm) 高度 (mm) AG0 L AG1 L AG2 L AG3 L AG4 L AG5 L AG6 L AG7 L AG8 L AG9 L AG10 L AG11 L AG12 L AG13 L 重量 (g) 表 1-28 AG 系列纽扣电池参数表 电池型号标称电标称容量工作电流 (ma) 最大尺寸 (mm) 重量 (g)

176 第二部分单片机常用外围器件 压 (V) (mah) 标准电流 连续电流 脉冲电流 直径 * 高度 CR3032 3V 550mAh 0.2mA 3.0mA 20mA 30.0mm*3.2mm 6.8g CR2477 3v 950mAh 0.2mA 3.0mA 20mA 24.5mm*7.7mm 9.9g CR2450 3v 550mAh 0.2mA 3.0mA 20mA 24.5mm*5.0mm 5.8g CR2430 3v 270mAh 0.2mA 3.0mA 20mA 24.5mm*3.0mm 4.3g CR2412 3v 90mAh 0.1mA 1.0mA 15mA 24.5mm*1.2mm 2.2g CR2354 3v 530mAh 0.2mA 3.0mA 20mA 23.0mm*5.4mm 6.3g CR2335 3V 300mAh 0.2mA 3.0mA 20mA 23.0mm*3.5mm 4.2g CR2330 3V 260mAh 0.2mA 2.0mA 20mA 23.0mm*3.0mm 3.7g CR2325 3V 190mAh 0.2mA 2.0mA 20mA 23.0mm*2.5mm 3.2g CR2320 3V 130mAh 0.2mA 2.0mA 20mA 23.0mm*2.0mm 2.7g CR2032 3V 220mAh 0.2mA 2.0mA 20mA 20.0mm*3.2mm 3.0g CR2025 3V 150mAh 0.2mA 2.0mA 20mA 20.0mm*2.5mm 2.5g CR2016 3V 75mAh 0.1mA 1.0mA 15mA 20.0mm*1.6mm 1.7g CR1632 3V 120mAh 0.1mA 1.0mA 15mA 16.0mm*3.2mm 1.8g CR V 70mAh 0.1mA 1.0mA 10mA 16.0mm*2.0mm 1.2g CR1616 3V 50mAh 0.1mA 1.0mA 10mA 16.0mm*1.6mm 1.1g CR1225 3V 50mAh 0.1mA 1.0mA 5mA 12.5mm*2.5mm 0.9g CR1216 3V 25mAh 0.1mA 1.0mA 5mA 12.0mm*1.6mm 0.7 CR1025 3V 30mAh 0.1mA 1.0mA 5mA 10.0mm*2.5mm 0.6g CR1220 3V 38mAh 0.1mA 1.0mA 5mA 12.0mm*2.0mm 0.8g ww.zicreate.com

177 第 2 章常用数字逻辑电路 最早的 TTL 门电路是 74 系列 ( 标准型 ), 随后出现了 74H 74L 74S( 肖特基型 ) 74LS( 低功耗肖特基型 ) 74AS 74ALS( 先进低功耗肖特基型 ) 74F( 高速型 ) 系列 74LS 系列速度与 74 系列相当, 但功耗却是 74 系列的 1/5,74LS 系列广泛应用在中 小规模集成电路 74AS 系列与 74S 相比, 功耗相当, 但速度却提高了两倍 74ALS 系列将 74LS 系列的速度功耗又进一步提高 CMOS 逻辑门电路是在 TTL 电路之后出现的一种广泛应用应用的数字集成器件 早期生产的 CMOS 门电路是 4000 系列, 后来发展为 4000B 系列, 其工作速度较慢, 与 TTL 不兼容, 但其具有功耗低 工作范围电压范围宽 抗干扰能力强等特点 随后出现了高速 CMOS 器件 74HC 和 74HCT 系列, 其工作速度快 带负载能力强 新型的 CMOS 器件是 74VHC 和 74VHCT 系列, 其工作速度是 74HC 和 74HCT 系列的两倍 54 系列和 74 系列引脚和逻辑功能基本相同,54 系列是军用产品 表 2-1 常见 CMOS 电路参数 参数 4000B 74HC 74HCT 74LVC 74AUC 电源电压范围 /V 电源最大电压额定值 /V 常用 74HC 系列器件表 表 2-2 常用 74HC 系列器件表 型号逻辑功能工作电压驱动电流传输延迟 74HC00 4 路 2 输入与非门 2.0~6.0 V +/- 5.2 ma 7 ns@5v 74HC02 4 路 2 输入或非门 2.0~6.0 V +/- 5.2 ma 7 ns@5v 74HC04 6 路反相器 2.0~6.0 V +/- 5.2 ma 7 ns@5v 74HC08 4 路 2 输入与门 2.0~6.0 V +/- 5.2 ma 7 ns@5v 74HC11 3 路 3 输入与门 2.0~6.0 V +/- 5.2 ma 10 ns@5v 74HC14 6 路施密特触发反相器 2.0~6.0 V +/- 5.2 ma 12 ns@5v 74HC32 4 路 2 输入或门 2.0~6.0 V +/- 5.2 ma 6 ns@5v 74HC74 具有清零和预设功能的双路 D 型上升沿触发器 2.0~6.0 V +/- 5.2 ma 14 ns@5v 74HC86 4 路 2 输入异或门 2.0~6.0 V +/- 5.2 ma 11 ns@5v 74HC123 带复位功能的双路可再触发单稳多谐振荡器 2.0~6.0 V +/- 5.2 ma 26 ns@5v 74HC 线反相译码器 / 多路分配器 2.0~6.0 V +/- 5.2 ma 12 ns@5v 74HC 线译码器 / 多路分配器 2.0~6.0 V +/- 5.2 ma 11 ns@5v 74HC157 4 路 2 输入多路选择器 2.0~6.0 V +/- 5.2 ma 11 ns@5v 74HC164 8 位串进并出移位寄存器 2.0~6.0 V +/- 5.2 ma 12 ns@5v 74HC165 8 位并进串出移位寄存器 2.0~6.0 V +/- 5.2 ma 16 ns@5v 74HC240 74HC244 具有三态输出的 8 路反相缓冲器 / 线路驱动器 具有三态输出的 8 路正相缓冲器 / 线路驱动器 2.0~6.0 V +/- 7.8 ma 9 ns@5v 2.0~6.0 V +/- 7.8 ma 9 ns@5v 74HC245 具有三态输出的 8 路总线收发器 2.0~6.0 V +/- 7.8 ma 7 ns@5v 74HC273 具有复位功能的 8 路 D 型上升沿触发器 2.0~6.0 V +/- 5.2 ma 15 ns@5v 74HC373 具有三态输出的 8 路 D 型锁存器 2.0~6.0 V +/- 7.8 ma 12 ns@5v 74HC573 具有三态输出的 8 路 D 型锁存器 2.0~6.0 V +/- 7.8 ma 14 ns@5v 74HC595 具有三态输出锁存的 8 位移位寄存器 2.0~6.0 V +/- 7.8 ma 16 ns@5v 74HC 通道模拟多路选择器 / 多路分配器 2.0~10.0 V -- 4 ns@6v

178 第二部分单片机常用外围器件 74HC4052 双路 4 通道模拟多路选择器 / 多路分配器 2.0~10.0 V -- 4 ns@6v 74HC 路 2 通道模拟双掷多路选择器 / 多路分配器 2.0~10.0 V -- 4 ns@6v 74HC 阶脉动进位二进制计数器和振荡器 2.0~6.0 V +/- 5.2 ma 31 ns@5v 74HC4066 低导通阻抗单刀单掷 4 路双向模拟开关 2.0~10.0 V -- 2 ns@6v HC 系列逻辑门电路 图 HC00 的引脚与功能图 4 路 2 输入与非门 图 HC02 的引脚与功能图 4 路 2 输入或非门 图 HC04 的引脚与功能图 6 路反相器 图 HC08 的引脚与功能图 4 路 2 输入与门 图 HC11 的引脚与功能图 3 路 3 输入与门 图 HC14 的引脚与功能图 6 路施密特触发反相器 ww.zicreate.com

179 第 2 章常用数字逻辑电路 图 HC32 的引脚与功能图 4 路 2 输入或门 图 HC86 的引脚与功能图 4 路 2 输入异或门 2.3 双路可再触发单稳多谐振荡器 74HC123 74HC123 是一款高速 CMOS 器件,74HC123 引脚兼容低功耗肖特基 TTL(LSTTL) 系列 74HC123 遵循 JEDEC 标准 no.7a 74HC123 是双路可再触发单稳多谐振荡器, 可通过多达 3 种方式实现输出脉宽控制 74HC123 的 na 和 nb 输入带施密特触发功能, 使得电路对缓慢的输入上升和下降具备更高的容差性 74HC123 单稳触发器作用是不管触发信号持续多长时间, 只固定维持外围阻容给定的一段时间就恢 复触发前状态, 外围电阻电容决定单稳时间, 因为触发是由边缘触发, 上升或下降沿 可再触发单稳不 同之处是前次触发后的单稳没有恢复触发前状态而又有触发信号时, 可再触发单稳将在触发边缘开始继 续维持阻容给定的单稳时间, 而单稳是不理会在翻转后的触发信号的 此芯片也可做多谐振荡器用 74HC123 单稳态触发器 它有两种输入,A 为低电平有效,B 为高电平有效 有两种输出, 正好相 反 用外接的电阻电容作定时元件, 时间自己定 74HC123 为双可重复触发的单稳态, 其输出脉冲的宽 度主要取决于定时电阻 R 与定时电容 C, 脉宽的计算为电容值与电阻值的乘积即 :WP=R Ć, 在实际设 计中 R=5kW,C=80pF, 输出脉宽为 400ns 幅度约 5V 图 HC123 的引脚与功能图

180 第二部分单片机常用外围器件 表 HC123 的引脚说明 引脚号 标号 引脚号 标号 功能 1 1 A 9 2 A 触发输入 ( 时触发 ; 不用时 =H) 2 1B 10 2B 触发输入 ( 时触发 ; 不用时 =L) 3 1 R D 11 2 R D 复位输入 ( 低电平时复位 ; 不用时 =H) 4 1 Q 12 2 Q 触发输出 ( 触发过程中 =L, 其它 =H) 5 2Q 13 1Q 触发输出 ( 触发过程中 =H, 其它 =L) 6 2CEXT 14 1CEXT 接至外部的脉宽控制电容 7 2REXT/CEXT 15 1REXT/CEXT 接至外部的脉宽控制电阻 / 电容器 8 CND 16 VCC 电源正负极 表 HC123 的功能表 注 :H= 高电平 L= 低电平 = 不确定 = 上升沿 = 下降沿 = 高电平脉冲 = 低电平脉冲 图 HC123 的应用电路 2.4 译码器 / 多路分配器 74HC138/74HC139/74HC154 图 HC139 的引脚及功能图 常用的译码器有 2-4 译码器 (74HC139) 2 个输入变量控制 4 个输出端 3-8 译码器 (74HC138) 3 个输入变量控制 8 个输出端 4-16 译码器 (74HC154) 4 个输入变量控制 16 个输出端 线译码器 74LS139 74LS139 的引脚图如图 1-10 所示 : 表 LS139 的功能表 ww.zicreate.com

181 第 2 章常用数字逻辑电路 表 HC139 的引脚说明 引脚号标号引脚号标号功能 1 1 E 15 2 E 输入使能低电平有效 2 1A0 14 2A0 地址输入 3 1A1 13 2A1 4 1 Y Y Y Y Y Y Y Y 3 输出低电平有效 8 GND 16 VCC 电源正负极 线译码器 74HC138 74HC138 译码器可接受 3 位二进制加权地址输入 (A0, A1 和 A3), 并当使能时, 提供 8 个互斥的低有效输出 ( Y 0 至 Y 7) 74HC138 特有 3 个使能输入端 : 两个低有效 ( E 1 和 E 2) 和一个高有效 (E3) 除非 E 1 和 E 2 置低且 E3 置高, 否则 74HC138 将保持所有输出为高 利用这种复合使能特性, 仅需 4 片 74HC138 芯片和 1 个反相器, 即可轻松实现并行扩展, 组合成为一个 1-32(5 线到 32 线 ) 译码器 任选一个低有效使能输入端作为数据输入, 而把其余的使能输入端作为选通端, 则 74HC138 亦可充当一个 8 输出多路分配器, 未使用的使能输入端必须保持绑定在各自合适的高有效或低有效状态 74HC138 与 74HC238 逻辑功能一致, 只不过 74HC138 为反相输出 74HC138 基本参数 : 电压 2.0~6.0V 驱动电流 +/-5.2 ma 传输延迟 11 ns(5v) 图 HC138 引脚及功能图 表 HC138 的引脚说明 引脚号 标号 功能 引脚号 标号 功能 1 A0 9 Y 6 2 A1 地址输入 10 Y 5 3 A2 11 Y

182 第二部分单片机常用外围器件 4 E 1 输入使能低电平有效 12 Y 3 输出低电平有效 5 E 2 13 Y 2 6 E3 输入使能高电平有效 14 Y 1 7 Y 7 输出低电平有效 15 Y 0 8 GND 电源负极 16 VCC 电源正极 表 LS138 的功能表 线译码器 74HC154 74HC154 译码器可接受 4 位高有效二进制地址输入, 并提供 16 个互斥的低有效输出 74HC154 的两个输入使能门电路可用于译码器选通, 以消除输出端上的通常译码 假信号, 也可用于译码器扩展 该使能门电路包含两个 逻辑与 输入, 必须置为低以便使能输出端 任选一个使能输入端作为数据输入, 74HC154 可充当一个 1-16 的多路分配器 当其余的使能输入端置低时, 地址输出将会跟随应用的状态 74HC154 基本参数 : 电压 2.0~6.0V 驱动电流 +/-5.2 ma 传输延迟 11 ns(5v) ww.zicreate.com 图 HC154 的引脚及功能图 表 HC154 的引脚说明 引脚号标号功能引脚号标号功能 1 Y 0 13 Y 11 2 Y 1 14 Y 12 3 Y 2 15 Y 13 4 Y 3 输出低电平有效 16 Y 14 5 Y 4 17 Y 15 输出低电平有效

183 第 2 章常用数字逻辑电路 6 Y 5 18 E 0 输入使能低电平有效 7 Y 6 19 E 1 8 Y 7 输出低电平有效 20 A3 地址输入 9 Y 8 21 A2 10 Y 9 输出低电平有效 22 A1 地址输入 11 Y A0 12 GND 电源负极 24 VCC 电源正极 表 LS154 的功能表 路 2 输入多路选择器 74HC157 74HC157 是四路 2 输入多路选择器, 在公共数据选择输入端 (S) 的控制下, 从两个源中选出 4 位数据信号 被选择的数据通过 74HC157 的 4 个输出端以原码 ( 正相 ) 的形式输出 74HC157 的使能输入端 ( E ) 为低有效, 当 E 置高时, 所有输出 (1Y 至 4Y) 将被强制为低, 无视所有其他输入条件 74HC157 的一般用途是, 把数据从两组寄存器中转移到 4 路通用输出总线上, 而数据从哪个寄存器中读取, 将由公共数据选择输入端 (S) 的状态决定 74HC157 也作为函数信号发生器使用 74HC157 与 74HC158 逻辑功能一致, 但 74HC157 为正相 ( 原码 ) 输出

184 第二部分单片机常用外围器件 图 HC157 的引脚及功能图 表 HC157 功能表 表 HC157 的引脚说明 引脚号 标号 功能 引脚号 标号 功能 1 S 数据选择端 9 3I0 第三路 0 口输入端 2 1I0 第一路 0 口输入端 10 3I1 第三路 1 口输入端 3 1I1 第一路 1 口输入端 11 1Y 第三路输出 4 1Y 第一路输出 12 4I0 第四路 0 口输入端 5 2I0 第二路 0 口输入端 13 4I1 第四路 1 口输入端 6 2I1 第二路 1 口输入端 14 4Y 第四路输出 7 2Y 第二路输出 15 E 使能端 8 GND 电源负极 16 VCC 电源正极 位串进并出移位寄存器 74HC164 74HC164 是带有串行数据输入和并行输出的 8 位边沿触发移位寄存器 数据通过两个输入端 (DSA 和 DSB) 中的任一个串行输入 当其中一端作为数据输入时, 另一端可作为高有效使能端 两输入端必须连接在一起, 或者把未使用的端口绑定为高 在时钟脉冲 (CP) 的每个上升沿, 数据将向右移动一位, 并输入至 Q0,Q0 是两个数据输入端 (DSA 和 DSB) 进行逻辑与运算后的结果, 在时钟脉冲上升沿来临之前存在一段就绪时间 如果 74HC164 的主复位 ( MR ) 输入为低电平, 所有其他输入将被无视, 并且异步清零寄存器, 强制所有输出为低电平 ww.zicreate.com

185 第 2 章常用数字逻辑电路 图 HC164 的引脚及功能图 表 HC164 的引脚说明 引脚号 标号 功能 引脚号 标号 功能 1 DSA 数据输入 8 CP 时钟输入有 0 到 1 边沿触发 2 DSB 9 MR 主复位 3 Q0 10 Q4 4 Q1 数据输出 11 Q5 数据输出 5 Q2 12 Q6 6 Q3 13 Q7 7 GND 电源负极 14 VCC 电源正极 74HC164 是带有串行数据输入和并行输出的 8 位边沿触发移位寄存器, 它还可以扩展成多片级连串入并处 将第一片的 Q7 脚接到下一片的 DSA DSB 输入端, 将 CP 连接到一个时钟端, 这样依次连接就可扩展多片 数码管的静态显示就可利用这种扩张, 如图 1-15 图 2-16 利用 74HC164 扩展的数码管静态显示电路 位并进串出移位寄存器 74HC165 74HC165 是 8 位并行读取或串行输入移位寄存器, 可在末级得到互斥的串行输出 (Q7 和 Q7 ), 当并行读取 ( PL ) 输入为低时, 从 D0 到 D7 口输入的并行数据将被异步地读取进寄存器内 而当 PL 为高时, 数据将从 DS 输入端串行进入寄存器, 在每个时钟脉冲的上升沿向右移动一位 (Q0 Q1 Q2 等等 ) 利用这种特性, 只要把 Q7 输出绑定到下一级的 DS 输入, 即可实现并转串扩展 74HC165 的时钟输入是一个 门控或 结构, 允许其中一个输入端作为低有效时钟使能 ( CE ) 输入 CP 和 CE 的引脚分配是独立的并且在必要时, 为了布线的方便可以互换 只有在 CP 为高时, 才允许 CE 由低转高 在 PL 上升沿来临之前, 不论是 CP 还是 CE, 都应当置高, 以防止数据在 PL 的活动状态发生位移

186 第二部分单片机常用外围器件 图 HC165 引脚及功能图 表 HC165 的引脚说明 引脚号 标号 功能 引脚号 标号 功能 1 PL 非周期并行装载低电平有效 9 Q7 数据串行输出 2 CP 时钟输入由 0 到 1 边沿触发 10 DS 串行数据输入 3 D4 11 D0 4 D5 数据输入 12 D1 数据输入 5 D6 13 D2 6 D7 14 D3 7 Q 7 数据串行反向输出 15 CE 使能端低电平有效 8 GND 电源负极 16 VCC 电源正极 表 HC165 的功能表 2.8 三态输出的 8 路正反相缓冲器 / 线路驱动器 74HC244 74HC240 74HC240 是双线八路反相缓冲器 / 线路驱动器, 具有三态输出 该三态输出由输出使能端 1 OE 和 2 OE 控制 任意 n OE 上的高电平将使输出端呈现高阻态 74HC240 与 74HC244 逻辑功能相似, 只不过 74HC240 带有反相输出 74HC244 是八路正相缓冲器 / 线路驱动器, 具有三态输出 该三态输出由输出使能端 1 OE 和 2 OE 控 制 任意 n OE 上的高电平将使输出端呈现高阻态 1. 双线八路反相缓冲器 / 线路驱动器 74HC240 ww.zicreate.com

187 第 2 章常用数字逻辑电路 图 HC240 引脚及功能图 表 HC240 的引脚说明 引脚号 标号 功能 引脚号 标号 功能 1 1 OE 1 组输出使能端低电平有效 11 2A3 2 组 3 路输入 2 1A0 1 组 0 路输入 12 1Y3 1 组 3 路输出 3 2Y0 2 组 0 路输出 13 2A2 2 组 2 路输入 4 1A1 1 组 1 路输入 14 1Y2 1 组 2 路输出 5 2Y1 2 组 1 路输出 15 2A1 2 组 1 路输入 6 1A2 1 组 2 路输入 16 1Y1 1 组 1 路输出 7 2Y2 2 组 2 路输出 17 2A0 2 组 0 路输入 8 1A3 1 组 3 路输入 18 1Y0 1 组 0 路输出 9 2Y3 2 组 3 路输出 19 2 OE 2 组输出使能端低电平有效 10 GND 电源负极 20 VCC 电源正极 表 HC240 的功能表 2. 双线八路正相缓冲器 / 线路驱动器 74HC244 图 HC244 引脚及功能图 表 HC244 的功能表

188 第二部分单片机常用外围器件 2.9 三态输出的 8 路总线收发器 74HC245 74HC245 八路收发器在发送和接收两个方向上都具有正相三态总线兼容输出 74HC245 的输出使能端 ( OE ) 用于实现轻松级联, 而发送 / 接收端 (DIR) 用于控制方向 OE 控制输出, 使得总线被有效的隔离 74HC245 与 74HC640 逻辑功能相似, 但 74HC245 具有原码 ( 正相 ) 输出 图 HC245 引脚及功能图 表 HC245 的引脚说明 引脚号 标号 功能 引脚号 标号 功能 1 DIR 1 组输出使能端低电平有效 11 B7 2 组 3 路输入 2 A0 1 组 0 路输入 12 B6 1 组 3 路输出 3 A1 2 组 0 路输出 13 B5 2 组 2 路输入 4 A2 1 组 1 路输入 14 B4 1 组 2 路输出 5 A3 2 组 1 路输出 15 B3 2 组 1 路输入 6 A4 1 组 2 路输入 16 B2 1 组 1 路输出 7 A5 2 组 2 路输出 17 B1 2 组 0 路输入 8 A6 1 组 3 路输入 18 B0 1 组 0 路输出 9 A7 2 组 3 路输出 19 OE 2 组输出使能端低电平有效 10 GND 电源负极 20 VCC 电源正极 表 HC245 的功能表 ww.zicreate.com

189 第 2 章常用数字逻辑电路 路 D 型上升沿触发器 74HC273 74HC273 具有八路边沿触发,D 型触发器, 带独立的 D 输入和 Q 输出 74HC273 的公共时钟 (CP) 和主复位 ( MR ) 端可同时读取和复位 ( 清零 ) 所有触发器 每个 D 输入的状态将在时钟脉冲上升沿之前的一段就绪时间内被传输到触发器对应的输出 (Qn) 上 一旦 MR 输入电平为低, 则所有输出将被强制置为低, 而不依赖于时钟或者数据输入 74HC273 适用于要求原码输出或者所有存储元件共用时钟和主复位的应用 74HC273 用于 CMOS 微处理器或存储器的理想缓冲器, 最大频率工作 122MHz 图 HC273 引脚及功能图 表 HC273 的引脚说明 引脚号 标号 功能 引脚号 标号 功能 1 MR 复位端低电平有效 11 CP 时钟输入 2 Q0 0 路输入 12 Q4 4 路输入 3 D0 0 路输出 13 D4 4 路输出 4 Q1 1 路输入 14 Q5 5 路输入 5 D1 1 路输出 15 D5 5 路输出 6 Q2 2 路输入 16 Q6 6 路输入 7 D2 2 路输出 17 D6 6 路输出 8 Q3 3 路输入 18 Q7 7 路输入 9 D3 3 路输出 19 D7 7 路输出 10 GND 电源负极 20 VCC 电源正极 表 HC273 的功能表

190 第二部分单片机常用外围器件 2.11 三态输出的 8 路 D 型锁存器 74HC373/74HC573 74HC373/74HC573 是八路 D 型锁存器, 每个锁存器具有独立的 D 型输入, 以及适用于面向总线的应用的三态输出 所有锁存器共用一个锁存使能 (LE) 端和一个输出使能 ( OE ) 端 74HC373/74HC573 包含八个具有三态输出的 D 型透明锁存器 当 LE 为高时, 数据从 Dn 输入到锁存器, 在此条件下, 锁存器进入透明模式, 也就是说, 锁存器的输出状态将会随着对应的 D 输入每次的变化而改变 当 LE 为低时, 锁存器将存储 D 输入上的信息一段就绪时间, 直到 LE 的下降沿来临 当 OE 为低时,8 个锁存器的内容可被正常输出 ; 当 OE 为高时, 输出进入高阻态 OE 端的操作不会影响锁存器的状态 74HC373 与以下型号逻辑功能相同 : 74HC533, 但输出为反相 74HC563, 但输出为反相且引脚布局不同 74HC573, 但引脚布局不同 1. 八路 D 型锁存器 74HC373 图 HC373 引脚及功能图 表 HC373 的引脚说明 引脚号 标号 功能 引脚号 标号 功能 1 OE 3 态输出使能端低电平有效 11 LE 锁存使能端高电平有效 2 Q0 0 路输入 12 Q4 4 路输入 3 D0 0 路输出 13 D4 4 路输出 4 Q1 1 路输入 14 Q5 5 路输入 5 D1 1 路输出 15 D5 5 路输出 6 Q2 2 路输入 16 Q6 6 路输入 7 D2 2 路输出 17 D6 6 路输出 8 Q3 3 路输入 18 Q7 7 路输入 9 D3 3 路输出 19 D7 7 路输出 10 GND 电源负极 20 VCC 电源正极 表 HC373 的功能表 ww.zicreate.com

191 第 2 章常用数字逻辑电路 2. 八路 D 型锁存器 74HC573 图 HC573 引脚及功能图 表 HC573 的引脚说明 引脚号 标号 功能 引脚号 标号 功能 1 OE 3 态输出使能端低电平有效 11 LE 锁存使能端高电平有效 2 Q0 0 路输入 12 Q4 4 路输入 3 D0 0 路输出 13 D4 4 路输出 4 Q1 1 路输入 14 Q5 5 路输入 5 D1 1 路输出 15 D5 5 路输出 6 Q2 2 路输入 16 Q6 6 路输入 7 D2 2 路输出 17 D6 6 路输出 8 Q3 3 路输入 18 Q7 7 路输入 9 D3 3 路输出 19 D7 7 路输出 10 GND 电源负极 20 VCC 电源正极 表 HC573 的功能表 2.12 三态输出锁存的 8 位移位寄存器 74HC595 74HC595 是 8 阶串行移位寄存器, 带有存储寄存器和三态输出 移位寄存器和存储寄存器分别采用单独的时钟

192 第二部分单片机常用外围器件 在 SH_CP 的上升沿, 数据发生移位, 而在 ST_CP 的上升沿, 数据从每个寄存器中传送到存储寄存器 如果两个时钟信号被绑定到一起, 则移位寄存器将会一直领先存储寄存器一个时钟脉冲 移位寄存器带有一个串行输入 (DS) 端和一个串行标准输出 (Q7') 端, 用于级联 74HC595 还为移位寄存器的 8 个阶提供了异步的复位 ( 低有效 ) 存储寄存器带有 8 个三态总线驱动输出, 当输出使能 (OE) 端为低时, 存储寄存器中的数据可被正常输出 图 HC595 引脚及功能图 表 HC595 的引脚说明 引脚号 标号 功能 引脚号 标号 功能 1 Q1 9 Q7 并行数据输出 2 Q2 10 MR 复位端低电平有效 3 Q3 11 SH_CP 转换寄存器时钟输入 4 Q4 并行数据输出 12 ST_CP 锁存器时钟输入 5 Q5 13 OE 输出使能低电平有效 6 Q6 14 DS 串行数据输入 7 Q7 15 Q0 并行数据输出 8 GND 电源负极 16 VCC 电源正极 表 HC573 的功能表 ww.zicreate.com

193 第 2 章常用数字逻辑电路 图 HC595 的工作时序图

194 3.1 LED 数码管 第 3 章显示器件 LED 显示器是由发光二极管显示字段的显示器件, 也可称为数码管 单片机系统中通常使用 8 段 LED 数码显示器, 其外形及引脚如图 1(a) 所示, 由图可见 8 段 LED 显示器由 8 个发光二极管组成 其中 7 个长条形的发光二极管排列成 日 字形, 另一个圆点形的发光二极管在显示器的右下角作为显示小数点用, 通过不同的组合可用来显示各种数字, 包括 A~F 在内的部分英文字母和小数点. 等字样 LED 显示器有两种不同的形式 : 一种是 8 个发光二极管的阳极都连在一起的, 称为共阳极 LED 显示器 ; 另一种是 8 个发光二极管的阴极都连在一起的, 称为共阴极 LED 显示器 如图 2-1 所示 图 段 LED 数码管显示器 点亮不同的端即可得到要显示的字形 字形码表如表 2-1 所示 表 3-1 LED 数码管字形码表 字型 共阳极代码 共阴极代码 字型 共阳极代码 共阴极代码 0 C0H 3FH 9 90H 6FH 1 F9H 06H A 88H 77H 2 A4H 5BH B 83H 7CH 3 B0H 4FH C C6H 39H 4 99H 66H D A1H 5EH 5 92H 6DH E 86H 79H 6 82H 7DH F 8EH 71H 7 F8H 07H 灭 FFH 00H 8 80H 7FH 1. 一位一体的 LED 数码管 图 3-2 一位一体数码管实物图

195 第 3 章显示器件 由于数码管的型号及尺寸大小种类繁多, 这里只以 0.36 英寸和 0.56 英寸的数码管为例, 使用中应实际测量出管脚分布 文章中标出的仅供参考 图 3-3 一位一体 0.36 英寸的数码管管脚分布图 2. 两位一体的 LED 数码管 图 3-4 一位一体 0.56 英寸的数码管管脚分布图 图 3-5 两位一体数码管实物图

196 第二部分单片机常用外围器件 图 3-6 两位一体 0.36 英寸的数码管管脚分布图 图 3-7 两位一体 0.56 英寸的数码管管脚分布图 ww.zicreate.com

197 第 3 章显示器件 3. 三位一体的 LED 数码管 图 3-8 三位一体数码管实物图 图 3-9 三位一体 0.36 英寸的数码管管脚分布图

198 第二部分单片机常用外围器件 4. 四位一体的 LED 数码管 图 3-10 三位一体 0.56 英寸的数码管管脚分布图 图 3-11 三位一体数码管实物图 ww.zicreate.com

199 第 3 章显示器件 图 3-12 四位一体 0.36 英寸的数码管管脚分布图 图 3-13 四位一体 0.56 英寸的数码管管脚分布图数码管的驱动有三极管驱动 , 锁存器驱动 74HC373/74HC573, 线路驱动器 74HC244 驱动等 1. 三极管驱动 2. 锁存器驱动 图 3-14 三极管驱动数码管常用电路

200 第二部分单片机常用外围器件 3.2 LCD1602 液晶 图 3-15 高速锁存器驱动数码管常用电路 字符型 LCD 简介字符型液晶显示模块是一种专门用于显示字母 数字 符号等点阵式 LCD, 目前常用 16*1,16*2, 20*2 和 40*2 行等的模块 下面以长沙太阳人电子有限公司的 1602 字符型液晶显示器为例, 介绍其用法 一般 1602 字符型液晶显示器实物如图 2-16 所示 图 3-16 LCD1602 字符型液晶显示器实物图 2.LCD1602 的基本参数及引脚功能 1602LCD 分为带背光和不带背光两种, 基控制器大部分为 HD44780, 带背光的比不带背光的厚, 是否带背光在应用中并无差别, 两者尺寸差别如下图 2-17 所示 : 图 LCD 尺寸 ww.zicreate.com

201 第 3 章显示器件 LCD 主要技术参数 : 显示容量 :16 2 个字符 ; 芯片工作电压 : V; 工作电流 :2.0mA(5.0V); 模块最佳工作电压 : 5.0V; 字符尺寸 : (W H)mm 4. 引脚功能说明 1602LCD 采用标准的 14 脚 ( 无背光 ) 或 16 脚 ( 带背光 ) 接口, 各引脚接口说明如表 2-2 所示 : 表 3-2 LCD1602 引脚功能说明 编号符号引脚功能编号符号引脚功能 1 VSS 电源地 9 D2 数据 2 VDD 电源正极 10 D3 数据 3 VL 液晶显示偏压 11 D4 数据 4 RS 数据 / 命令选择 12 D5 数据 5 R/W 读 / 写选择 13 D6 数据 6 E 使能信号 14 D7 数据 7 D0 数据 15 BLA 背光源正极 8 D1 数据 16 BLK 背光源负极 管脚 1 VSS 为地电源 2 VDD 接 5V 正电源 表 3-3 引脚接口说明表 管脚说明 3 VL 为液晶显示器对比度调整端, 接正电源时对比度最弱, 接地时对比度最高, 对比度过高时会产生 鬼影, 使用时可以通过一个 10K 的电位器调整对比度 4 RS 为寄存器选择, 高电平时选择数据寄存器 低电平时选择指令寄存器 5 R/W 为读写信号线, 高电平时进行读操作, 低电平时进行写操作 当 RS 和 R/W 共同为低电平时可以写入指令或者显示地址, 当 RS 为低电平 R/W 为高电平时可以读忙信号, 当 RS 为高电平 R/W 为低电平时可以写入数据 6 E 端为使能端, 当 E 端由高电平跳变成低电平时, 液晶模块执行命令 7~14 D0~D7 为 8 位双向数据线 15 背光源正极 16 背光源负极 5.LCD1602 的指令说明及时序 1602 液晶模块内部的控制器共有 11 条控制指令, 如表 2-4 所示 : 表 3-4 LCD 1602 的控制指令表 序号指令 RS R/W D7 D6 D5 D4 D3 D2 D1 D0 1 清显示 光标返回 * 3 输入模式设置 I/D S 4 显示开 / 关控制设置 D C B 5 光标或字符移位设置 S/C R/L * * 6 功能设置 DL N F * * 7 设置字符发生存贮器地址 字符发生存贮器地址 8 设置数据存贮器地址 显示数据存贮器地址 9 读忙标志或地址 0 1 BF 计数器地址 10 写数据到 CGRAM 或 DDRAM) 1 0 要写的数据内容 11 从 CGRAM 或 DDRAM 读数据 1 1 读出的数据内容 1602 液晶模块的读写操作 屏幕和光标的操作都是通过指令编程来实现的 ( 说明 :1 为高电平

202 为低电平 ) 表 3-5 指令详细说明表 指令号指令码说明 1 0x01 清屏指令, 光标复位到地址 00H 位置 2 0x 02 光标复位, 光标返回到地址 00H x 04 0x 05 0x 06 0x 07 0x 08 0x 09 第二部分单片机常用外围器件 I/D=0: 数据读 / 写后光标左移一位 ;S=0: 数据读 / 写操作整平显示不平移 I/D=0: 数据读 / 写后光标左移一位 ;S=1: 数据读 / 写操作整平显示左移 I/D=1: 数据读 / 写后光标右移一位 ;S=0: 数据读 / 写操作整平显示不平移 I/D=1: 数据读 / 写后光标右移一位 ;S=1: 数据读 / 写操作整平显示左移 D=0: 关显示 C=0: 不显示光标 B=0: 光标不闪烁 D=0: 关显示 C=0: 不显示光标 B=1: 光标闪烁 0x 0a D=0: 关显示 C=1: 显示光标 B=0: 光标不闪烁 0x0b D=0: 关显示 C=1: 显示光标 B=1: 光标闪烁 0x 0c 0x 0d D=1: 开显示 C=0: 不显示光标 B=0: 光标不闪烁 D=1: 开显示 C=0: 不显示光标 B=1: 光标闪烁 0x 0e D=1: 开显示 C=1: 显示光标 B=0: 光标不闪烁 0x 0f D=1: 开显示 C=1: 显示光标 B=1: 光标闪烁 0x 10 0x 14 0x 18 0x 1c 0x 20 0x 24 0x 28 0x2c 0x 30 0x 34 0x 38 0x 3c S/C=0 R/L=0: 光标向左平移一个字符 S/C=0 R/L=1: 光标向右平移一个字符 S/C=1 R/L=0: 整屏向左平移一个字符 S/C=1 R/L=1: 整屏向右平移一个字符 DL=0:4 位数据接口 N=0: 一行显示 F=0:5 7 点阵字符 DL=0:4 位数据接口 N=0: 一行显示 F=1:5 10 点阵字符 DL=0:4 位数据接口 N=1: 两行显示 F=0:5 7 点阵字符 DL=0:4 位数据接口 N=1: 两行显示 F=1:5 10 点阵字符 DL=1:8 位数据接口 N=0: 一行显示 F=0:5 10 点阵字符 DL=1:8 位数据接口 N=0: 一行显示 F=1:5 10 点阵字符 DL=1:8 位数据接口 N=1: 两行显示 F=0:5 7 点阵字符 DL=1:8 位数据接口 N=1: 两行显示 F=1:5 10 点阵字符 7 0x40+D 设置字符发生器 CGRAM 地址 D=0~0x3f 8 9 0x80+D 设置 DDRAM 地址 N=0 时 :D=0~0x4f N=1 时 : 首行 :D=0~0x27 次行 :D=0x40~0x47 6. 与 HD44780 相兼容的芯片时序表如下 : 读忙信号和光标地址 BF: 为忙标志位,BF=1 表示忙, 此时模块不能接收命令或者数据, 如果 BF=0 表示不忙 表 3-6 LCD1602 基本操作时序表 读状态输入 RS=L,R/W=H,E=H 输出 D0 D7= 状态字 写指令输入 RS=L,R/W=L,D0 D7= 指令码,E= 高脉冲输出无 读数据输入 RS=H,R/W=H,E=H 输出 D0 D7= 数据 写数据输入 RS=H,R/W=L,D0 D7= 数据,E= 高脉冲输出无 读写操作时序如图 2-18 和图 2-19 所示 : ww.zicreate.com

203 第 3 章显示器件 图 3-18 读操作时序 图 3-19 写操作时序 表 3-7 时序参数表 7.LCD1602 的 RAM 地址映射及标准字库表液晶显示模块是一个慢显示器件, 所以在执行每条指令之前一定要确认模块的忙标志为低电平, 表示不忙, 否则此指令失效 要显示字符时要先输入显示字符地址, 也就是告诉模块在哪里显示字符, 图 2-20 是 1602 的内部显示地址

204 第二部分单片机常用外围器件 图 3-20 LCD1602 内部显示地址 例如第二行第一个字符的地址是 40H, 那么是否直接写入 40H 就可以将光标定位在第二行第一个字符的位置呢? 这样不行, 因为写入显示地址时要求最高位 D7 恒定为高电平 1 所以实际写入的数据应该是 B(40H) B(80H)= B(C0H) 在对液晶模块的初始化中要先设置其显示模式, 在液晶模块显示字符时光标是自动右移的, 无需人工干预 每次输入指令前都要判断液晶模块是否处于忙的状态 1602 液晶模块内部的字符发生存储器 (CGROM) 已经存储了 160 个不同的点阵字符图形, 如图 所示 比如大写的英文字母 A 的代码是 B(41H), 显示时模块把地址 41H 中的点阵字符图形显示出来, 我们就能看到字母 A 表 3-8 字符代码与图形对应表 ww.zicreate.com

205 第 3 章显示器件 LCD 的软硬件设计实例软硬件设计实例请参看第一部分 51 系列 AT89S52 单片机 C 语言编程的第 6 章 AT89S52 单片机扩展功能 C 语言编程的第 6.2 节 LCD1602 显示 3.3 LCD12864 液晶 1. 概述 ST7920/ST7921 驱动的 LCD12864 模块是一种具有 4 位 /8 位并行 2 线或 3 线串行多种接口方式的液晶显示器件, 内部含有国标一级 二级简体中文字库的点阵图形液晶显示模块 ; 其显示分辨率为 , 内置 8192 个 16*16 点汉字, 和 128 个 16*8 点 ASCII 字符集. 利用该模块灵活的接口方式和简单 方便的操作指令, 可构成全中文人机交互图形界面 可以显示 8 4 行 点阵的汉字. 也可完成图形显示. 低电压低功耗是其又一显著特点 基本特性 : 低电源电压 (VDD: V) 显示分辨率 : 点内置汉字字库, 提供 8192 个 点阵汉字 ( 简繁体可选 ) 内置 128 个 16 8 点阵字符 2MHZ 时钟频率显示方式 :STN 半透 正显驱动方式 :1/32DUTY,1/5BIAS 视角方向 :6 点背光方式 : 侧部高亮白色 LED, 功耗仅为普通 LED 的 1/5 1/10 通讯方式 : 串行 并口可选内置 DC-DC 转换电路, 无需外加负压无需片选信号, 简化软件设计工作温度 : , 存储温度 : 内部方框图 图 3-21 LCD12864 实物图 图 3-22 LCD12864 内部框图

206 第二部分单片机常用外围器件 3. 外形尺寸图 图 3-23 LCD12864 的外形尺寸图 4. 模块接口说明 1) 串行接口 管脚号名称电平功能 表 3-9 串口接口管脚功能表 1 VSS 0V 电源地 2 VDD +5V 电源正 (3~5.5V) 3 VO -- 对比度 ( 亮度 ) 调整 4 CS H/L 模组片选端, 高电平有效 5 SID H/L 串行数据输入端 6 CLK H/L 串行同步时钟, 上升沿时读取 SID 数据 15 PSB L L: 串口方式 ( 见注释 1) 17 RESET H/L 复位端, 低电平有效 ( 见注释 2) 19 A VDD 背光电源正 +5V 20 K VSS 背光电源负 0V * 注释 1: 如在实际应用中仅使用串口通讯模式, 可将 PSB 接固定低电平 * 注释 2: 模块内部接有上电复位电路, 因此在不需要经常复位的场合可将该端悬空 2) 并行接口 管脚号管脚名称电平管脚功能描述 1 VSS 0V 电源地 2 VCC 3.0+5V 电源正 表 3-10 并行接口管脚功能表 3 V0 - 对比度 ( 亮度 ) 调整 4 RS(CS) H/L RS= H, 表示 DB7 DB0 为显示数据 RS= L, 表示 DB7 DB0 为显示指令数据 5 R/W(SID) H/L R/W= H,E= H, 数据被读到 DB7 DB0 R/W= L,E= H L, DB7 DB0 的数据被写到 IR 或 DR 6 E(SCLK) H/L 使能信号 ww.zicreate.com

207 第 3 章显示器件 7 DB0 H/L 三态数据线 8 DB1 H/L 三态数据线 9 DB2 H/L 三态数据线 10 DB3 H/L 三态数据线 11 DB4 H/L 三态数据线 12 DB5 H/L 三态数据线 13 DB6 H/L 三态数据线 14 DB7 H/L 三态数据线 15 PSB H/L H:8 位或 4 位并口方式,L: 串口方式 ( 见注释 1) 16 NC - 空脚 17 RESET H/L 复位端, 低电平有效 ( 见注释 2) 18 VOUT - LCD 驱动电压输出端 19 A VDD 背光源正端 +5V 20 K VSS 背光源负端 0V * 注释 1: 如在实际应用中仅使用并口通讯模式, 可将 PSB 接固定高电平 * 注释 2: 模块内部接有上电复位电路, 因此在不需要经常复位的场合可将该端悬空 5. 模块主要硬件构成说明 1) 控制器接口信号说明 : a) RS,R/W 的配合选择决定控制界面的 4 种模式 : RS R/W 功能说明 表 3-11 控制界面模式设定表 L L MPU 写指令到指令暂存器 (IR) L H 读出忙标志 (BF) 及地址记数器 (AC) 的状态 H L MPU 写入数据到数据暂存器 (DR) H H MPU 从数据暂存器 (DR) 中读出数据 b) E 信号 c) 忙标志 :BF BF 标志提供内部工作情况.BF=1 表示模块在进行内部操作, 此时模块不接受外部指令和数据.BF=0 时, 模块为准备状态, 随时可接受外部指令和数据. 利用 STATUS RD 指令, 可以将 BF 读到 DB7 总线, 从而检验模块之工作状态. d) 字型产生 ROM(CGROM) 字型产生 ROM(CGROM) 提供 8192 个此触发器是用于模块屏幕显示开和关的控制 DFF=1 为开显示 (DISPLAY ON),DDRAM 的内容就显示在屏幕上,DFF=0 为关显示 (DISPLAY OFF) DFF 的状态是指令 DISPLAY ON/OFF 和 RST 信号控制的 e) 显示数据 RAM(DDRAM) 模块内部显示数据 RAM 提供 64 2 个位元组的空间, 最多可控制 4 行 16 字 (64 个字 ) 的中文字型显示, 当写入显示数据 RAM 时, 可分别显示 CGROM 与 CGRAM 的字型 ; 此模块可显示三种字型, 分别是半角英数字型 (16*8) CGRAM 字型及 CGROM 的中文字型, 三种字型的选择, 由在 DDRAM 中 表 3-12 E 端口功能表 E 状态执行动作结果 高 > 低 I/O 缓冲 >DR 配合 /W 进行写数据或指令 高 DR >I/O 缓冲配合 R 进行读数据或指令 低 / 低 > 高 无动作

208 第二部分单片机常用外围器件 写入的编码选择, 在 0000H 0006H 的编码中 ( 其代码分别是 共 4 个 ) 将选择 CGRAM 的自定义字型,02H 7FH 的编码中将选择半角英数字的字型, 至于 A1 以上的编码将自动的结合下一个位元组, 组成两个位元组的编码形成中文字型的编码 BIG5(A140 D75F),GB(A1A0-F7FFH) f) 字型产生 RAM(CGRAM) 字型产生 RAM 提供图象定义 ( 造字 ) 功能, 可以提供四组 点的自定义图象空间, 使用者可以将内部字型没有提供的图象字型自行定义到 CGRAM 中, 便可和 CGROM 中的定义一样地通过 DDRAM 显示在屏幕中 g) 地址计数器 AC 地址计数器是用来贮存 DDRAM/CGRAM 之一的地址, 它可由设定指令暂存器来改变, 之后只要读取或是写入 DDRAM/CGRAM 的值时, 地址计数器的值就会自动加一, 当 RS 为 0 时而 R/W 为 1 时, 地址计数器的值会被读取到 DB6 DB0 中 h) 光标 / 闪烁控制电路此模块提供硬体光标及闪烁控制电路, 由地址计数器的值来指定 DDRAM 中的光标或闪烁位置 6. 指令说明模块控制芯片提供两套控制命令, 基本指令和扩充指令如下 : 指令 清除显示 地址归位 显示状态开 / 关 进入点设定 游标或显示移位控制 功能设定 设定 CGRA M 地址 设定 DDRA M R S R/ W D 7 ww.zicreate.com 表 3-13 指令表 1:( RE=0: 基本指令 ) 指令码 D6 D5 D4 D3 D2 D1 D0 功能 将 DDRAM 填满 "20H", 并且设 定 DDRAM 的地址计数器 (AC) 到 "00H" X 设定 DDRAM 的地址计数器 (AC) 到 "00H", 并且将游标移到开头原点位置 ; 这个指令不改变 DDRAM 的内容 D C B D=1: 整体显示 ON C=1: 游标 ON B=1: 游标位置反白允许 I/D S 指定在数据的读取与写入时, 设 定游标的移动方向及指定显示 的移位 S/C R/L X X 设定游标的移动与显示的移位 控制位 ; 这个指令不改变 DDRAM 的内容 DL X RE X X DL=0/1:4/8 位数据 RE=1: 扩充指令操作 RE=0: 基本指令操作 AC AC 5 AC 4 AC 4 AC 3 AC 3 AC 2 AC 2 AC 1 AC 1 AC 0 AC 0 设定 CGRAM 地址 设定 DDRAM 地址 ( 显示位址 ) 第一行 :80H-87H 第二行 :90H-97H

209 第 3 章显示器件 地址 读取忙标志和地址 0 1 B F AC 6 AC 5 AC 4 AC 3 AC 2 AC 1 AC 0 读取忙标志 (BF) 可以确认内部动作是否完成, 同时可以读出地址计数器 (AC) 的值 写数据到 RAM 1 0 数据 将数据 D7 D0 写入到内部的 RAM (DDRAM/CGRAM/IRAM/GRA M) 读出 RAM 的值 1 1 数据 从内部 RAM 读取数据 D7 D0 (DDRAM/CGRAM/IRAM/GRA M) 表 3-14 指令表 2:( RE=1: 扩充指令 ) 指指令码功能 令 RS R/W D7 D6 D5 D4 D3 D2 D1 D0 待命模式 卷动地址开关开启 反白选择 睡眠模式 扩充功能设定 设定绘图 RAM 地址 进入待命模式, 执行其他指令 都棵终止 待命模式 SR SR=1: 允许输入垂直卷动地址 SR=0: 允许输入 IRAM 和 CGRAM 地址 R1 R0 选择 2 行中的任一行作反白显示, 并可决定反白与否 初始值 R1R0=00, 第一次设定为反白显示, 再次设定变回正常 SL X X SL=0: 进入睡眠模式 SL=1: 脱离睡眠模式 CL X RE G 0 CL=0/1:4/8 位数据 RE=1: 扩充指令操作 RE=0: 基本指令操作 G=1/0: 绘图开关 AC6 0 AC5 0 AC4 AC3 AC3 AC2 AC2 AC1 AC1 AC0 AC0 设定绘图 RAM 先设定垂直 ( 列 ) 地址 AC6AC5 AC0 再设定水平 ( 行 ) 地址 AC3AC2AC1AC0 将以上 16 位地址连续写入即可 备注 : 1 当模块在接受指令前, 微处理顺必须先确认模块内部处于非忙碌状态, 即读取 BF 标志时 BF 需为 0, 方可接受新的指令 ; 如果在送出一个指令前并不检查 BF 标志, 那么在前一个指令和这个指令中间必须延迟一段较长的时间, 即是等待前一个指令确实执行完成, 指令执行的时间请参考指令表中的个别指令说明

210 第二部分单片机常用外围器件 2 RE 为基本指令集与扩充指令集的选择控制位元, 当变更 RE 位元后, 往后的指令集将维持在最后的状态, 除非再次变更 RE 位元, 否则使用相同指令集时, 不需每次重设 RE 位元 7. 具体指令介绍 1) 清除显示 (01H) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L L L L L L L H 功能 : 清除显示屏幕, 把 DDRAM 位址计数器调整为 00H 2) 位址归位(02H) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L L L L L L H X 功能 : 把 DDRAM 位址计数器调整为 00H, 游标回原点, 该功能不影响显示 DDRAM 3) 进入点设定 (04H/05H/06H/07H) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L L L L L H I/D S 功能 : 设定光标移动方向并指定整体显示是否移动 I/D=1 光标右移,I/D=0 光标左移 S=1 且 DDRAM 为写状态 : 整体显示移动, 方向由 I/D 决定 (I/D=1 左移,I/D=0 右移 ) S=0 或 DDRAM 为读状态 : 整体显示不移动 4) 显示状态开 / 关 (08H/0CH/0EH/0FH) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L L L L H D C B 功能 : D=1; 整体显示 ON C=1; 游标 ON B=1; 游标位置 ON 5) 游标或显示移位控制(10H/14H/18H/1CH) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L L L H S/C R/L X X 功能 : 设定游标的移动与显示的移位控制位 : 这个指令并不改变 DDRAM 的内容 6) 功能设定(36H/30H/34H)(0x34 扩充指令集动作,0x30 基本指令集动作 ) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L L H DL X RE X X 功能 :DL=1( 必须设为 1) RE=1; 扩充指令集动作 RE=0: 基本指令集动作 7) 设定 CGRAM 位址 (40H-7FH) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L H AC5 AC4 AC3 AC2 AC1 AC0 功能 : 设定 CGRAM 位址到位址计数器 (AC) 8) 设定 DDRAM 位址 (80H-9FH) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L H AC6 AC5 AC4 AC3 AC2 AC1 AC0 ww.zicreate.com

211 第 3 章显示器件 功能 : 设定 DDRAM 位址到位址计数器 (AC) 9) 读取忙碌状态(BF) 和位址 (BF=1, 状态忙 ) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L H BF AC6 AC5 AC4 AC3 AC2 AC1 AC0 功能 : 读取忙碌状态 (BF) 可以确认内部动作是否完成, 同时可以读出位址计数器 (AC) 的值 10) 写资料到 RAM CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 H L D7 D6 D5 D4 D3 D2 D1 D0 功能 : 写入资料到内部的 RAM(DDRAM/CGRAM/TRAM/GDRAM) 11) 读出 RAM 的值 CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 H H D7 D6 D5 D4 D3 D2 D1 D0 功能 : 从内部 RAM 读取资料 (DDRAM/CGRAM/TRAM/GDRAM) 12) 待命模式(01H) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L L L L L L L H 功能 : 进入待命模式, 执行其他命令都可终止待命模式 13) 卷动位址或 IRAM 位址选择 (02H/03H) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L L L L L L H SR 功能 :SR=1; 允许输入卷动位址 SR=0; 允许输入 IRAM 位址 14) 反白选择(04H\05H) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L L L L L H R1 R0 功能 : 选择 4 行中的任一行作反白显示, 并可决定反白的与否 15) 睡眠模式(08H/0CH) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L L L L H SL X X 功能 :SL=1; 脱离睡眠模式 SL=0; 进入睡眠模式 16) 扩充功能设定(36H/30H/34H) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L L H H X 1 RE G L 功能 :RE=1; 扩充指令集动作 RE=0; 基本指令集动作 G=1; 绘图显示 ON G=0; 绘图显示 OFF 17) 设定 IRAM 位址或卷动位址 (40H-7FH) CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L L H AC5 AC4 AC3 AC2 AC1 AC

212 功能 :SR=1;AC5~AC0 为垂直卷动位址 18) 设定绘图 RAM 位址 (80H-FFH) SR=0;AC3~AC0 写 ICONRAM 位址 CODE: RW RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L L H AC6 AC5 AC4 AC3 AC2 AC1 AC0 功能 : 设定 GDRAM 位址到位址计数器 (AC) 8. 读写时序图 1) 数据传输过程 第二部分单片机常用外围器件 图 位和 4 位数据线的传输过程 图 3-25 串口数据线模式数据传输过程 ww.zicreate.com

213 第 3 章显示器件 2) 并口读写时序 图 3-26 MCU 写资料到 ST7920(8 位数据线模式 ) 3) 串口读写时序 : 图 3-27 MCU 从 ST7920 读资料 (8 位数据线模式 ) 图 3-28 串口方式下 MCU 写数据到 ST

214 第二部分单片机常用外围器件 8. 软件初始化 图 3-29 八位元界面初始化软件流程 ww.zicreate.com

215 第 3 章显示器件 图 3-30 四位元界面初始化软件流程 9. 应用 1) 使用前的准备先给模块加上工作电压, 再按照下图的连接方法调节 LCD 的对比度, 使其显示出黑色的底影 此过程亦可以初步检测 LCD 有无缺段现象 2) 字符显示 LCD12864 每屏可显示 4 行 8 列共 32 个 点阵的汉字, 每个显示 RAM 可显示 1 个中

216 第二部分单片机常用外围器件 图 3-31 背光调节电路连接图文字符或 2 个 16 8 点阵全高 ASCII 码字符, 即每屏最多可实现 32 个中文字符或 64 个 ASCII 码字符的显示 FYD B 内部提供 字节的字符显示 RAM 缓冲区 (DDRAM) 字符显示是通过将字符显示编码写入该字符显示 RAM 实现的 根据写入内容的不同, 可分别在液晶屏上显示 CGROM ( 中文字库 ) HCGROM(ASCII 码字库 ) 及 CGRAM( 自定义字形 ) 的内容 三种不同字符 / 字型的选择编码范围为 :0000~0006H( 其代码分别是 共 4 个 ) 显示自定义字型,02H~ 7FH 显示半宽 ASCII 码字符,A1A0H~F7FFH 显示 8192 种 GB2312 中文字库字形 字符显示 RAM 在液晶模块中的地址 80H~9FH 字符显示的 RAM 的地址与 32 个字符显示区域有着一一对应的关系, 其对应关系如下表所示 表 3-15 字符显示地址分配表 X 坐标 Line1 80H 81H 82H 83H 84H 85H 86H 87H Line2 90H 91H 92H 93H 94H 95H 96H 97H Line3 88H 89H 8AH 8BH 8CH 8DH 8EH 8FH Line4 98H 99H 9AH 9BH 9CH 9DH 9EH 9FH 3) 图形显示水平方向 X 以字节单位, 垂直方向 Y 以位为单位. 先设垂直地址再设水平地址 ( 连续写入两个字节的资料来完成垂直与水平的坐标地址 ) 绘图 RAM 的地址计数器 (AC) 只会对水平地址 (X 轴 ) 自动加一, 当水平地址 =0FH 时会重新设为 00H 但并不会对垂直地址做进位自动加一, 故当连续写入多笔资料时, 程序需自行判断垂直地址是否需重新设定 GDRAM 的坐标地址与资料排列顺序如下图 : 图 3-32 图形显示地址分配表 ww.zicreate.com

217 第 3 章显示器件绘图显示 RAM 提供 个字节的记忆空间, 在更改绘图 RAM 时, 先连续写入水平与垂直的坐标值, 再写入两个字节的数据到绘图 RAM, 而地址计数器 (AC) 会自动加一 ; 在写入绘图 RAM 的期间, 绘图显示必须关闭, 整个写入绘图 RAM 的步骤如下 : (1) 关闭绘图显示功能 (2) 先将水平的位元组坐标(X) 写入绘图 RAM 地址 ; (3) 再将垂直的坐标(Y) 写入绘图 RAM 地址 ; (4) 将 D15 D8 写入到 RAM 中 ; (5) 将 D7 D0 写入到 RAM 中 ; (7) 打开绘图显示功能 绘图显示的缓冲区对应分布请参考图 ) 应用说明应用 LCD12864 显示模块时应注意以下几点 : 1 欲在某一个位置显示中文字符时, 应先设定显示字符位置, 即先设定显示地址, 再写入中文字符编码 2 显示 ASCII 字符过程与显示中文字符过程相同 不过在显示连续字符时, 只须设定一次显示地址, 由模块自动对地址加 1 指向下一个字符位置, 否则, 显示的字符中将会有一个空 ASCII 字符位置 3 当字符编码为 2 字节时, 应先写入高位字节, 再写入低位字节 4 模块在接收指令前, 向处理器必须先确认模块内部处于非忙状态, 即读取 BF 标志时 BF 需为 0, 方可接受新的指令 如果在送出一个指令前不检查 BF 标志, 则在前一个指令和这个指令中间必须延迟一段较长的时间, 即等待前一个指令确定执行完成 指令执行的时间请参考指令表中的指令执行时间说明 5 RE 为基本指令集与扩充指令集的选择控制位 当变更 RE 后, 以后的指令集将维持在最后的状态, 除非再次变更 RE 位, 否则使用相同指令集时, 无需每次均重设 RE 位 5) LCD12864 与单片机 AT89S52 的一种接口电路如下图所示

218 图 3-33 LCD12864 应用电路原理图 第二部分单片机常用外围器件 ww.zicreate.com

219 第 4 章通信相关器件 5.2 RS232 总线接口芯片 MAX233 MAX232(MAX220 MAX249 系列 ) 是专为 RS-232 和 V.28 通信接口设计的收发器, 尤其是 ±12V 供压无法实现的情况 MAX232 器件 (MAX220 MAX249 系列 ) 特别适合电池供电系统, 这是由于其低功耗关断模式可以将功耗减小到 5μW 以内 MAX225 MAXX233 MAX235 以及 MAX245/MAX246/MAX247 不需要外部元件, 推荐用于印刷电路板面积有限的应用 MAX232A 与 MAX232 的外围电路相同, 但主要有以下属性不同 : 表 4-1 MAX232A 与 MAX232 的区别 型号速率外部电容 MAX Kbps 1 uf MAX232A 200Kbps 0.1 uf RS232 采用的不是 TTL 电平的接口标准, 而是负逻辑, 即逻辑 "1" 为 -3 V~-15 V; 逻辑 "0" 为 +3 V~ +15 V; 而 CAN 总线是采用 " 显性 " 和 " 隐性 " 两个互补的逻辑值表示 "0" 和 "1", 其信号是以两线之间的 " 差分 " 电压形式出现的 这样导致两总线之间的信号电压不匹配 无法直接进行正常的通信, 因此, 需要相应的硬件接口电路实现电平标准转换 RS232 通信属于异步串行通信 一般为两点传输, 其每帧的数据格式通常为 : 起始位 + 数据位 + 奇偶校验位 ( 可省略 )+ 停止位 ; 每个数据包的格式通常为 : 数据包头 + 数据字节 + 校验和 ( 溢出不计 ) RS-232 通信端口的各脚定义 RS-232 接口又称之为 RS-232 口 串口 异步口或一个 COM( 通信 ) 口 "RS-232" 是其最明确的名称 在计算机世界中, 大量的接口是串口或异步口, 但并不一定符合 RS-232 标准, 但我们也通常认为它是 RS-232 口 严格地讲 RS-232 接口是 DTE( 数据终端设备 ) 和 DCE( 数据通信设备 ) 之间的一个接口,DTE 包括计算机 终端 串口打印机等设备 DCE 通常只有调制解调器 (MODEM) 和某些交换机 COM 口是 DCE 标准指出 DTE 应该拥有一个插头 ( 针输出 ),DCE 拥有一个插座 ( 孔输出 ) 这经常被制造商忽视 ( 如 :WYSE 终端就是孔输出 DTE 串口 ) 但影响不大, 只要搞清楚 DCE DTE 就行了, 然后按照标准接线图接线就不会错了 (DTE DCE 引脚定义相同 ) 表 4-2 RS-232 接口引脚定义 25 芯 9 芯信号方向来自缩写描述名 2 3 PC TXD 发送数据 3 2 调制解调器 RXD 接受数据 4 7 PC RTS 请求发送 5 8 调制解调器 CTS 允许发送 6 6 调制解调器 DSR 通讯设备准备好 7 5 GND 信号地 8 1 调制解调器 CD 载波检测 20 4 PC DTR 数据终端准备好 22 9 调制解调器 RI 响铃指示器 MAX232 芯片是美信公司专门为电脑的 RS-232 标准串口设计的接口电路, 使用 +5v 单电源供电 内部结构基本可分三个部分 : 第一部分是电荷泵电路 由 脚和 4 只电容构成 功能是产生 +12v 和 -12v 两个电源, 提供给 RS-232 串口电平的需要 第二部分是数据转换通道 由 脚构成两个数据通道 其中 13 脚 (R1IN) 12 脚 (R1OUT) 11 脚 (T1IN) 14 脚 (T1OUT) 为第一数据通道 8 脚 (R2IN) 9 脚 (R2OUT) 10 脚 (T2IN) 7 脚 (T2OUT) 为第二数据通道

220 第二部分单片机常用外围器件 TTL/CMOS 数据从 T1IN T2IN 输入转换成 RS-232 数据从 T1OUT T2OUT 送到电脑 DB9 插头 ; DB9 插头的 RS-232 数据从 R1IN R2IN 输入转换成 TTL/CMOS 数据后从 R1OUT R2OUT 输出 第三部分是供电 15 脚 GND 16 脚 VCC(+5v) 图 4-1 MAX232 引脚分布及功能图表 4-3 MAX232 引脚说明表 管脚号 管脚名 功能 1 C1+ C1 电容正端 2 V+ 经电容接电源正 3 C1- C1 电容负端 4 C2+ C2 电容正端 5 C2- C2 电容负端 6 V- 经电容接电源负 7 T2OUT 转换后 RS232 电平信号输出端 8 R2IN RS232 发送电平信号接收输入端 9 R2OUT 转换后的 TTL 电平接收信号输出端 10 T2IN TTL 电平发送输入端 ( 接单片机的 RXD 发送端 ) 11 T1IN TTL 电平发送输入端 ( 接单片机的 RXD 发送端 ) 12 R1OUT 转换后的 TTL 电平接收信号输出端 13 R1IN RS232 电平信号接收输入端 14 T1OUT 转换后 RS232 电平信号输出端 15 GND 电源地 16 VCC 电源正 ww.zicreate.com

221 第 4 章通信相关器件 图 4-2 MAX232 应用电路原理图 5.2 RS485 总线接口芯片 MAX485 针对 RS-232-C 的不足, 于是就不断出现了一些新的接口标准,RS-485 就是其中之一, 它具有以下特点 : 1. RS-485 的电气特性 : 逻辑 1 以两线间的电压差为 +(2 6) V 表示 ; 逻辑 0 以两线间的电压差为 -(2 6)V 表示 接口信号电平比 RS-232-C 降低了, 就不易损坏接口电路的芯片, 且该电平与 TTL 电平兼容, 可方便与 TTL 电路连接 2. RS-485 的数据最高传输速率为 10Mbps 3. RS-485 接口是采用平衡驱动器和差分接收器的组合, 抗共模干能力增强, 即抗噪声干扰性好 4. RS-485 最大的通信距离约为 1219M, 最大传输速率为 10Mb/S, 传输速率与传输距离成反比, 在 100Kb/S 的传输速率下, 才可以达到最大的通信距离, 如果需传输更长的距离, 需要加 485 中继器 RS-485 总线一般最大支持 32 个节点, 如果使用特制的 485 芯片, 可以达到 128 个或者 256 个节点, 最大的可以支持到 400 个节点 因 RS-485 接口具有良好的抗噪声干扰性, 长的传输距离和多站能力等上述优点就使其成为首选的串行接口 因为 RS485 接口组成的半双工网络, 一般只需二根连线, 所以 RS485 接口均采用屏蔽双绞

222 第二部分单片机常用外围器件 线传输 RS485 接口连接器采用 DB-9 的 9 芯插头座, 与智能终端 RS485 接口采用 DB-9( 孔 ), 与键盘连接的键盘接口 RS485 采用 DB-9( 针 ) 3. 采用 RS485 接口时, 传输电缆的长度如何考虑? 在使用 RS485 接口时, 对于特定的传输线经, 从发生器到负载其数据信号传输所允许的最大电缆长度是数据信号速率的函数, 这个长度数据主要是受信号失真及噪声等影响所限制 下图所示的最大电缆长度与信号速率的关系曲线是使用 24AWG 铜芯双绞电话电缆 ( 线径为 0.51mm), 线间旁路电容为 52.5PF/M, 终端负载电阻为 100 欧时所得出 ( 曲线引自 GB 附录 A) 由图中可知, 当数据信号速率降低到 90Kbit/S 以下时, 假定最大允许的信号损失为 6dBV 时, 则电缆长度被限制在 1200M 实际上, 图中的曲线是很保守的, 在实用时是完全可以取得比它大的电缆长度 当使用不同线径的电缆 则取得的最大电缆长度是不相同的 例如 : 当数据信号速率为 600Kbit/S 时, 采用 24AWG 电缆, 由图可知最大电缆长度是 200m, 若采用 19AWG 电缆 ( 线径为 0 91mm) 则电缆长度将可以大于 200m; 若采用 28AWG 电缆 ( 线径为 0 32mm) 则电缆长度只能小于 200m RS-485 总线, 在要求通信距离为几十米到上千米时, 广泛采用 RS-485 串行总线标准 RS-485 采用平衡发送和差分接收, 因此具有抑制共模干扰的能力 加上总线收发器具有高灵敏度, 能检测低至 200mV 的电压, 故传输信号能在千米以外得到恢复 RS-485 采用半双工工作方式, 任何时候只能有一点处于发送状态, 因此, 发送电路须由使能信号加以控制 RS-485 用于多点互连时非常方便, 可以省掉许多信号线 应用 RS-485 可以联网构成分布式系统, 其允许最多并联 32 台驱动器和 32 台接收器 以往,PC 与智能设备通讯多借助 RS232 RS485 以太网等方式, 主要取决于设备的接口规范 但 RS232 RS485 只能代表通讯的物理介质层和链路层, 如果要实现数据的双向访问, 就必须自己编写通讯应用程序, 但这种程序多数都不能符合 ISO/OSI 的规范, 只能实现较单一的功能, 适用于单一设备类型, 程序不具备通用性 在 RS232 或 RS485 设备联成的设备网中, 如果设备数量超过 2 台, 就必须使用 RS485 做通讯介质,RS485 网的设备间要想互通信息只有通过 主 (Master) 设备中转才能实现, 这个主设备通常是 PC, 而这种设备网中只允许存在一个主设备, 其余全部是从 (Slave) 设备 而现场总线技术是以 ISO/OSI 模型为基础的, 具有完整的软件支持系统, 能够解决总线控制 冲突检测 链路维护等问题在要求通信距离为几十米到上千米时, 广泛采用 RS-485 串行总线标准 RS-485 采用平衡发送和差分接收, 因此具有抑制共模干扰的能力 加上总线收发器具有高灵敏度, 能检测低至 200mV 的电压, 故传输信号能在千米以外得到恢复 RS-485 采用半双工工作方式, 任何时候只能有一点处于发送状态, 因此, 发送电路须由使能信号加以控制 RS-485 用于多点互连时非常方便, 可以省掉许多信号线 应用 RS-485 可以联网构成分布式系统, 其允许最多并联 32 台驱动器和 32 台接收器 图 4-3 MAX485 引脚分布及功能连接图 ww.zicreate.com

223 第 4 章通信相关器件 表 4-4 MAX485 引脚功能说明表 图 4-4 MAX485 应用电路原理图

224 第二部分单片机常用外围器件 5.3 PT2262/PT2272 遥控编解码电路 PT2262/2272 是台湾普城公司生产的一种 CMOS 工艺制造的低功耗低价位通用编解码电路, PT2262/2272 最多可有 12 位 (A0-A11) 三态地址端管脚 ( 悬空, 接高电平, 接低电平 ), 任意组合可提供 地址码,PT2262 最多可有 6 位 (D0-D5) 数据端管脚, 设定的地址码和数据码从 17 脚串行输出, 可用于无线 遥控发射电路 PT2262/2272 特点 :CMOS 工艺制造, 低功耗, 外部元器件少,RC 振荡电阻, 工作电压范围宽 :2.6~ 15v, 数据最多可达 6 位, 地址码最多可达 种 应用范围 : 车辆防盗系统 家庭防盗系统 遥控 玩具 其他电器遥控 图 4-5 PT2262/PT2272 芯片实物图编码芯片 PT2262 发出的编码信号由 : 地址码 数据码 同步码组成一个完整的码字, 解码芯片 PT2272 接收到信号后, 其地址码经过两次比较核对后,VT 脚才输出高电平, 与此同时相应的数据脚也输出高电平, 如果发送端一直按住按键, 编码芯片也会连续发射 当发射机没有按键按下时,PT2262 不接通电源, 其 17 脚为低电平, 所以 315MHz 的高频发射电路不工作, 当有按键按下时,PT2262 得电工作, 其第 17 脚输出经调制的串行数据信号, 当 17 脚为高电平期间 315MHz 的高频发射电路起振并发射等幅高频信号, 当 17 脚为低平期间 315MHz 的高频发射电路停止振荡, 所以高频发射电路完全收控于 PT2262 的 17 脚输出的数字信号, 从而对高频电路完成幅度键控 (ASK 调制 ) 相当于调制度为 100% 的调幅 图 4-6 PT2262/2272 编解码芯片管脚图表 4-5 PT2262 编码芯片管脚功能表 名称 管脚 说明 A0-A 地址管脚, 用于进行地址编码, 可置为 0, 1, f ( 悬空 ), D0-D 数据输入端, 有一个为 1 即有编码发出, 内部下拉 Vcc 18 电源正端 (+) Vss 9 电源负端 (-) TE 14 编码启动端, 用于多数据的编码发射, 低电平有效 ; OSC1 16 振荡电阻输入端, 与 OSC2 所接电阻决定振荡频率 ; OSC2 15 振荡电阻振荡器输出端 ; Dout 17 编码输出端 ( 正常时为低电平 ) ww.zicreate.com

225 第 4 章通信相关器件 名称管脚说明 表 4-6 PT2272 解码码芯片管脚功能表 A0-A 地址管脚, 用于进行地址编码, 可置为 0, 1, f ( 悬空 ), 必须与 2262 一致, 否则不解码 D0-D 地址或数据管脚, 当做为数据管脚时, 只有在地址码与 2262 一致, 数据管脚 才能输出与 2262 数据端对应的高电平, 否则输出为低电平, 锁存型只有在 接收到下一数据才能转换 Vcc 18 电源正端 (+) Vss 9 电源负端 (-) DIN 14 数据信号输入端, 来自接收模块输出端 OSC1 16 振荡电阻输入端, 与 OSC2 所接电阻决定振荡频率 ; OSC2 15 振荡电阻振荡器输出端 ; VT 17 解码有效确认输出端 ( 常低 ) 解码有效变成高电平 ( 瞬态 ) PT2262/PT2272 的地址码和数据码编解码周期如图 4-7 所示 其中 a 为二倍的时钟振荡周期 一个字码由 12 位 AD 码组成, AD 码是由地址码加数据码组成, 比如 8 位地址码加 4 位数据码, 每个 AD 位用两个脉冲来代表 : 两个窄脉冲表示 0 ; 两个宽脉冲表示 1 ; 一个窄脉冲和一个宽脉冲表示 f 也就是地址码的 悬空 图 4-7 编码时序图 PT2262 每次发射时至少发射 4 组字码,PT2272 只有在连续两次检测到相同的地址码加数据码才会把数据码中的 1 驱动相应的数据输出端为高电平和驱动 VT 端同步为高电平 因为无线发射的特点, 第一组字码非常容易受零电平干扰, 往往会产生误码, 所以程序可以丢弃处理 PT2272 解码芯片有不同的后缀, 表示不同的功能, 有 L4/M4/L6/M6 之分, 其中 L 表示锁存输出, 数据只要成功接收就能一直保持对应的电平状态, 直到下次遥控数据发生变化时改变 M 表示非锁存输出, 数据脚输出的电平是瞬时的而且和发射端是否发射相对应, 可以用于类似点动的控制 后缀的 6 和 4 表示有几路并行的控制通道, 当采用 4 路并行数据时为 PT2272-M4, 对应的地址编码应该是 8 位, 如果采用 6 路的并行数据时为 PT2272-M6, 对应的地址编码应该是 6 位 在通常使用中, 一般采用 8 位地址码和 4 位数据码, 这时编码电路 PT2262 和解码 PT2272 的第 1~ 8 脚为地址设定脚, 有三种状态可供选择 : 悬空 接正电源 接地三种状态,3 的 8 次方为 6561, 所以地址编码不重复度为 6561 组, 只有发射端 PT2262 和接收端 PT2272 的地址编码完全相同, 才能配对使用 PT2262 和 PT2272 除地址编码必须完全一致外, 振荡电阻还必须匹配, 否则接收距离会变近甚至无法接收, 随着技术的发展, 市场上出现一批兼容芯片, 在实际使用中只要对振荡电阻稍做改动就能配套使用, 常用的配对电阻如表 4-7 所示 : 芯片 表 4-7 PT2262 和 PT2272 振荡电阻配对表 配对电阻 (Ω) 编码芯片 PT M 1.5M 2.2M 3.3M 4.7M 解码芯片 PT K 270K 390K 680K 820K

226 5.1 A/D 转换器件 1.ADC0832 第 5 章 A/D 和 D/A 转换相关器件 ADC0832 是美国国家半导体公司生产的一种 8 位分辨率 双通道 A/D 转换芯片 由于它体积小, 兼容性, 性价比高而深受单片机爱好者及企业欢迎, 其目前已经有很高的普及率 学习并使用 ADC0832 可是使我们了解 A/D 转换器的原理, 有助于我们单片机技术水平的提高 ADC0832 具有以下特点 : 8 位分辨率 ; 双通道 A/D 转换 ; 输入输出电平与 TTL/CMOS 相兼容 ; 5V 电源供电时输入电压在 0~5V 之间 ; 工作频率为 250KHZ, 转换时间为 32μS; 一般功耗仅为 15mW; 8P 14P DIP( 双列直插 ) PICC 多种封装 ; 商用级芯片温宽为 0 C to +70 C, 工业级芯片温宽为 40 C to +85 C; ADC0832 的管脚图如图 5-1 所示 : 图 5-1 ADC0832 的管脚图分布图 表 5-1 ADC0832 的管脚说明 管脚号 管脚名 功能 管脚号 管脚名 功能 1 CS 片选使能, 低电平芯片使能 5 DI 数据信号输入, 选择通道控制 2 CH0 模拟输入通道 0, 或作为 IN+/- 6 DO 数据信号输出, 转换数据输出 使用 3 CH1 模拟输入通道 1, 或作为 IN+/- 7 CLK 芯片时钟输入 使用 4 GND 芯片参考 0 电位 ( 地 ) 8 VCC/REF 电源输入及参考电压输入 ADC0832 为 8 位分辨率 A/D 转换芯片, 其最高分辨可达 256 级, 可以适应一般的模拟量转换要求 其内部电源输入与参考电压的复用, 使得芯片的模拟电压输入在 0~5V 之间 芯片转换时间仅为 32μS, 据有双数据输出可作为数据校验, 以减少数据误差, 转换速度快且稳定性能强 独立的芯片使能输入, 使多器件挂接和处理器控制变的更加方便 通过 DI 数据输入端, 可以轻易的实现通道功能的选择 单片机对 ADC0832 的控制原理 : 正常情况下 ADC0832 与单片机的接口应为 4 条数据线, 分别是 CS CLK DO DI 但由于 DO 端与 DI 端在通信时并未同时有效并与单片机的接口是双向的, 所以电路设计时可以将 DO 和 DI 并联在一根数据线上使用 当 ADC0832 未工作时其 CS 输入端应为高电平, 此时芯片禁用,CLK 和 DO/DI 的电平可任意 当要进行 A/D 转换时, 须先将 CS 使能端置于低电平并且保持低电平直到转换完全结束 此时芯片开始转换工作, 同时由处理器向芯片时钟输入端 CLK 输入时钟脉冲,DO/DI 端则使用 DI 端输入通道功能选择的数据信号 在第 1 个时钟脉冲的下沉之前 DI 端必须是高电平, 表示启始信号 在第 2 3 个脉冲下沉之前 DI 端应输入 2 位数据用于选择通道功能

227 第 5 章 A/D 和 D/A 转换相关器件 表 5-2 ADC0832 通道选择设置 如表 5-1 所示, 当此 2 位数据为 1 0 时, 只对 CH0 进行单通道转换 当 2 位数据为 1 1 时, 只对 CH1 进行单通道转换 当 2 位数据为 0 0 时, 将 CH0 作为正输入端 IN+,CH1 作为负输入端 IN- 进行输入 当 2 位数据为 0 1 时, 将 CH0 作为负输入端 IN-,CH1 作为正输入端 IN+ 进行输入 如图 5-1 所示 到第 3 个脉冲的下沉之后 DI 端的输入电平就失去输入作用, 此后 DO/DI 端则开始利用数据输出 DO 进行转换数据的读取 从第 4 个脉冲下沉开始由 DO 端输出转换数据最高位 DATA7, 随后每一个脉冲下沉 DO 端输出下一位数据 直到第 11 个脉冲时发出最低位数据 DATA0, 一个字节的数据输出完成 也正是从此位开始输出下一个相反字节的数据, 即从第 11 个字节的下沉输出 DATD0 随后输出 8 位数据, 到第 19 个脉冲时数据输出完成, 也标志着一次 A/D 转换的结束 最后将 CS 置高电平禁用芯片, 直接将转换后的数据进行处理就可以了 作为单通道模拟信号输入时 ADC0832 的输入电压是 0~5V 且 8 位分辨率时的电压精度为 19.53mV 如果作为由 IN+ 与 IN- 输入的输入时, 可是将电压值设定在某一个较大范围之内, 从而提高转换的宽度 但值得注意的是, 在进行 IN+ 与 IN- 的输入时, 如果 IN- 的电压大于 IN+ 的电压则转换后的数据结果始终为 00H 图 5-2 ADC0832 的工作时序图 图 5-3 ADC0832 的应用电路图

228 2.ADC0809 第二部分单片机常用外围器件 ADC0809 是采样频率为 8 位的 以逐次逼近原理进行模 数转换的器件 其内部有一个 8 通道多路开关, 它可以根据地址码锁存译码后的信号, 只选通 8 路模拟输入信号中的一个进行 A/D 转换 主要特性 : 1)8 路 8 位 A/D 转换器, 即分辨率 8 位 2) 具有转换起停控制端 3) 转换时间为 100μs 4) 单个 +5V 电源供电 5) 模拟输入电压范围 0~+5V, 不需零点和满刻度校准 6) 工作温度范围为 -40~+85 摄氏度 7) 低功耗, 约 15mW 图 5-4 ADC0809 管脚分布图 表 5-3 ADC0809 管脚功能表 管脚号管脚名功能管脚号管脚名功能 1 IN3 第 3 路模拟量输入端 位数字量输出端 2 IN4 第 2 路模拟量输入端 16 V REF (-) 基准电压 (-) 3 IN5 第 3 路模拟量输入端 LSB 8 位数字量输出端 ( 最低 位 ) 4 IN6 第 4 路模拟量输入端 位数字量输出端 5 IN7 第 5 路模拟量输入端 位数字量输出端 6 START A/D 转换启动脉冲输入端 位数字量输出端 7 EOC A/D 转换结束输出信号 MSB 8 位数字量输出端 ( 最高 位 ) 位数字量端, 输出 22 ALE 地址锁存允许信号, 输入, 高电平有效 9 OE 数据输出允许信号, 输入 23 ADD C 3 位地址输入线 10 CLOCK 时钟脉冲输入端 24 ADD B 3 位地址输入线 11 VCC 电源 25 ADD A 3 位地址输入线 12 V REF (+) 基准电压 (+) 26 IN0 第 0 路模拟量输入端 13 GND 地 27 IN1 第 1 路模拟量输入端 位数字量输出端 28 IN2 第 2 路模拟量输入端 ADDA ADDB ADDC:3 位地址输入线, 用于选通 8 路模拟输入中的一路 ww.zicreate.com

229 第 5 章 A/D 和 D/A 转换相关器件 ALE: 地址锁存允许信号, 输入, 高电平有效 START: A/D 转换启动脉冲输入端, 输入一个正脉冲 ( 至少 100ns 宽 ) 使其启动 ( 脉冲上升沿使 0809 复位, 下降沿启动 A/D 转换 ) EOC: A/D 转换结束信号, 输出, 当 A/D 转换结束时, 此端输出一个高电平 ( 转换期间一直为低电平 ) OE: 数据输出允许信号, 输入, 高电平有效 当 A/D 转换结束时, 此端输入一个高电平, 才能打开输出三态门, 输出数字量 CLK: 时钟脉冲输入端 要求时钟频率不高于 640KHZ ADC0809 的工作过程是 : 首先输入 3 位地址, 并使 ALE=1, 将地址存入地址锁存器中 此地址经译码选通 8 路模拟输入之一到比较器 START 上升沿将逐次逼近寄存器复位 下降沿启动 A/D 转换, 之后 EOC 输出信号变低, 指示转换正在进行 直到 A/D 转换完成,EOC 变为高电平, 指示 A/D 转换结束, 结果数据已存入锁存器, 这个信号可用作中断申请 当 OE 输入高电平时, 输出三态门打开, 转换结果的数字量输出到数据总线上 表 5-4 模拟转换通到设定

230 第二部分单片机常用外围器件 图 5-3 ADC0809 的工作时序图 图 5-4 ADC0809 的应用电路图 5.2 D/A 转换器件 1.DAC0832 DAC0832 是 8 分辨率的 D/A 转换集成芯片 与微处理器完全兼容 这个 DA 芯片以其价格低廉 接口简单 转换控制容易等优点, 在单片机应用系统中得到广泛的应用 D/A 转换器由 8 位输入锁存器 8 位 DAC 寄存器 8 位 D/A 转换电路及转换控制电路构成 DAC0832 的主要特性参数如下 : * 分辨率为 8 位 ; * 电流稳定时间 1us; * 可单缓冲 双缓冲或直接数字输入 ; * 只需在满量程下调整其线性度 ; * 单一电源供电 (+5V~+15V); * 低功耗,200mW DAC0832 的工作方式 : ww.zicreate.com

231 第 5 章 A/D 和 D/A 转换相关器件根据对 DAC0832 的数据锁存器和 DAC 寄存器的不同的控制方式,DAC0832 有三种工作方式 : 直通方式 单缓冲方式和双缓冲方式 DAC0832 的结构 : 图 5-5 DAC0832 的内部功能及引脚分布图 表 5-5 DAC0832 引脚功能表 引脚号引脚名功能 1 CS 片选信号输入线 ( 选通数据锁存器 ), 低电平有效 2 WR 1 3 AGND 模拟信号地 4~7 D3~D0 8 位数据输入线的低 4 位 数据锁存器写选通输入线, 负脉冲 ( 脉宽应大于 500ns) 有效 8 V REF 基准电压输入线,VREF 的范围为 -10V~+10V 9 R fb 反馈信号输入线, 改变 Rfb 端外接电阻值可调整转换满量程精度 10 DGND 数字信号地 11 I OUT1 电流输出端 1, 其值随 DAC 寄存器的内容线性变化 12 I OUT2 电流输出端 2, 其值与 IOUT1 值之和为一常数 13~16 D7~D4 8 位数据输入线的高 4 位 17 XFER 数据传输控制信号输入线, 低电平有效, 负脉冲 ( 脉宽应大于 500ns) 有效 18 WR 2 DAC 寄存器选通输入线, 负脉冲 ( 脉宽应大于 500ns) 有效 19 ILE 数据锁存允许控制信号输入线, 高电平有效 20 VCC 电源输入端,Vcc 的范围为 +5V~+15V DAC0832 的工作时序 : 图 5-6 DAC0832 的工作时序

232 第二部分单片机常用外围器件 DAC0832 的输出方式 : DAC0832 是电流输出型, 如果要其变成电压输出型, 需要加运算放大器, 下面就是, 加运算放大器后组成的单极性电压输出和双极性电压输出方式 图 5-7 单极性电压输出 图 5-8 具有调增益功能单极性电压输出 ww.zicreate.com

233 第 5 章 A/D 和 D/A 转换相关器件 图 5-9 双极性电压输出 2.TLC5615 TLC5615 为美国德州仪器公司 1999 年推出的产品, 是具有串行接口的数模转换器, 其输出为电压型, 最大输出电压是基准电压值的两倍 带有上电复位功能, 即把 DAC 寄存器复位至全零 TLC5615 性能价格比高, 目前在国内市场很方便购买 a)tlc5615 的特点 (1)10 位 CMOS 电压输出 ; (2)5V 单电源供电 ; (3) 与 CPU 三线串行接口 ; (4) 最大输出电压可达基准电压的二倍 ; (5) 输出电压具有和基准电压相同极性 ; (6) 建立时间 12.5μs; (7) 内部上电复位 ; (8) 低功耗, 最大仅 1.75mW b)tlc5615 引脚说明 图 5-10 TLC5615 引脚分布及功能图 表 5-6 TLC5615 引脚功能表 引脚号 引脚名 功能 引脚号 引脚名 功能 1 DIN 串行数据输入端 5 AGND 模拟地

234 第二部分单片机常用外围器件 2 SCLK 串行时钟输入端 6 REFIN 基准电压输入端 3 CS 芯片选用通端, 低电平有效 7 OUT DAC 模拟电压输出端 4 DOUT 用于级联时串行数据输出端 8 VDD 正电源端 表 5-7 TLC5615 的时序时间表 图 5-11 TLC5615 的时序图 由时序图可以看出, 当片选 CS 为低电平时, 输入数据 DIN 由时钟 SCLK 同步输入或输出, 而且最高有效位在前, 低有效位在后 输入时 SCLK 的上升沿把串行输入数据 DIN 移入内部的 16 位移位寄存 器,SCLK 的下降沿输出串行数据 DOUT, 片选 CS 的上升沿把数据传送至 DAC 寄存器 当片选 CS 为高电平时, 串行输入数据 DIN 不能由时钟同步送入移位寄存器 ; 输出数据 DOUT 保持最近的数值不变而不进入高阻状态 由此要想串行输入数据和输出数据必须满足两个条件 : 第一时钟 SCLK 的有效跳变 ; 第二片选 CS 为低电平 这里, 为了使时钟的内部馈通最小, 当片选 CS 为高电平时, 输入时钟 SCLK 应当为低电平 串行数模转换器 TLC5615 的使用有两种方式, 即级联方式和非级联方式 如不使用级联方式,DIN 只需输入 12 位数据 DIN 输入的 12 位数据中, 前 10 位为 TLC5615 输入的 D/A 转换数据, 且输入时高 位在前, 低位在后, 后两位必须写入数值为零的低于 LSB 的位, 因为 TLC5615 的 DAC 输入锁存器为 12 位宽 如果使用 TL5615 的级联功能, 来自 DOUT 的数据需要输入 16 位时钟下降沿, 因此完成一次 数据输入需要 16 个时钟周期, 输入的数据也应为 16 位 输入的数据中, 前 4 位为高虚拟位, 中间 10 位为 D/A 转换数据, 最后 2 位为低于 LSB 的位即零 ww.zicreate.com

235 第 5 章 A/D 和 D/A 转换相关器件 c) 应用电路实例 图 5-12 TLC5615 应用电路原理图

236 第 6 章电源相关器件 6.1 电源器件的选型 型号 输出电流 (ma) 表 6-1 常用电源芯片选型表 1 输出电压 (V) Min. 输入电压 (V) Max. 输入电压 (V) LM78M NS 三端稳压器 LM78M NS 三端稳压器 LM78L , 7 35 NS 三端稳压器 LM , 1000, ~ NS 三端稳压器 L ~ ST 三端稳压器 L ~ ST 三端稳压器 L ~ ST 三端稳压器 L ~ ST 三端稳压器 L ~ ST 三端稳压器 L ~ ST 三端稳压器 表 6-2 常用电源芯片选型表 2 型号 输出电压 (V) 输出电流 (A) 初始误差 (%) AMS1117 Adj, 1.5, 1.8, 2.5, 2.85, 3.3, 5.0, 1 ± AMS 三端稳压 器 AMS1084 Adj, 1.5, 2.5, 2.85, 3.0, 3.3, 3.5, 5.0 AMS1085 Adj, 1.5, 2.5, 2.85, 3.0, 3.3, 3.5, 5.0 压差 (V) 备注 备注 5 ±1 1.5 AMS 三端稳压 器 3 ±1 1.3 AMS 三端稳压 器 表 6-3 常用电源芯片选型表 3 型号 输入电压 (V) 输出电压 (V) 输出电流 (ma) 频率 (khz) 效率 ( 峰值 ) LM2574 4~40 3.3, 5, 12, Adj , 88, 72 % LM2575 4~40 3.3, 5, 12, 15, Adj , 77, 75 % LM2576 4~40 3.3, 5, 12, 15, Adj , 88, 75 % LM2596 [4.5, 4.75, 7.15]~40 3.3, 5, 12, Adj , 73, 80 % 备注 NS 开关稳压器 NS 开关稳压器 NS 开关稳压器 NS 开关稳压器 6.2 三端稳压器 LM78M05 LM78L05 L7805 LM78LXX 系列三端阳极稳压器可选多种固定输出电压, 使得该类器件适用于一系列广泛的应用 其中,LM78L05 为 LM78LXX 系列的 5V 版 作为齐纳二极管 / 电阻组合的替换方案时,LM78L05 通常可以改善有效输出阻抗达两个数量级, 并降低静态电流 LM78L05 可提供本地卡上稳压, 结合单点调节, 解决分配问题 LM78LXX 系列的电压容许范围允许 LM78L05 使用在逻辑系统, 仪器仪表, 音响和其他固态电子设备 LM78L05 可选塑料 TO-92(Z) 封装, 塑料 SO-8(M) 封装, 以及采用国半微型 SMD 封装技术的芯片级封装 (8 焊球微型 SMD) 由于足够的散热设置,LM78L05 稳压器可提供 100mA 的输出电流,

237 第 6 章电源相关器件 同时还包含限流功能, 以限制峰值输出在安全值的范围内 LM78L05 为输出晶体管提供了安全区域保护, 限制内部功耗 假如内部功耗超出了散热范围, 热关断电路将会启动, 防止芯片过热 LM78L05 可选微型 SMD 封装 ; 全温度范围内输出电压容差 ±5% ; 输出电流 100mA ; 内部热过载保护 ; 输出晶体管安全区保护 ; 内部短路限流 ; 可选塑料 TO-92 和塑料 SO-8 封装 ; 无需外部元件 ; 输出电压 5.0V LM78M05 三端阳极稳压器采用内置限流, 热关断以及安全操作区域保护, 使得该器件几乎不受输出超载的损害 由于充分的散热设置,LM78M05 可提供超过 0.5A 的输出电流 LM78M05 器件的典型应用包括有本地 ( 卡上 ) 稳压器, 结合单点调节, 可有效消除噪声和减缓性能退化 LM78M05 输出电流超过 0.5A ; 不需外部元件 ; 内置过热超载保护 ; 内置短路限流 ; 输出晶体管安全区补偿 ; 可选 TO-220,TO-39 和 TO-252 D-PAK 封装 ; 输出电压 5V 1. LM78M05 图 6-1 LM78M05 实物图 图 6-2 LM78M05 封装图 表 6-4 LM78M05 参数表 2. LM78L

238 第二部分单片机常用外围器件 图 6-3 LM78L05 管脚分布及实物图 表 6-5 LM78L05 参数表 3. L7805 图 6-4 L7805 管脚分布及实物图 ww.zicreate.com

239 第 6 章电源相关器件 表 6-6 L7805 参数表 图 稳压应用电路 6.3 三端稳压器 LM317 LM317 可调节三端阳极稳压器可提供超过 1.5A 的电流,1.2V 至 37V 的输出范围 LM317 器件极易使用, 仅需使用 2 个外部电阻来设置电压输出 此外, 不管是线路调整率还是负载调节, 都优于标准的固定电压稳压器 而且,LM317 集成在标准晶体管封装里, 易于安装和操作 比之固定电压稳压器, 除了性能更佳外,LM317 还提供过载保护 片上包含了限流设置, 热过载保护以及安全区保护 即使调节端口断开, 所有过载保护依然保持完整功能 通常情况下,LM317 不需外接电容即可工作, 除非设备的位置距离输入过滤电容超过 6 英寸, 此时, 需要一个输入旁路, 且可选择添加一个输出电容以增强其瞬时反应性 LM317 的可调节端口可通过旁路连接, 获得非常高的脉动抑制比, 这对于其他的标准三端稳压器来说, 几乎是不可能的任务

240 第二部分单片机常用外围器件 除了作为固定电压稳压器的替代方案,LM317 也适用于其他一系列广泛的应用 由于稳压器是浮动的且只考虑输入 - 输出电压差, 只要该电压差最大值不超过限度, 即使数百伏的供压亦可被调节, 也就是说, 避免了输出短路 此外,LM317 可充当特别简单的可调节开关稳压器, 可编程输出稳压器, 或者通过在可调节端口和输出端口之间连接一个固定阻值的电阻,LM317 可作为精密的电流调整器使用 保证 1% 的输出电压容差 (LM317A); 保证最大 0.01%/V 的线路调整率 (LM317A); 保证 1.5A 输出电流 ; 低至 1.2V 的可调节输出 ; 基于温度的限流常数 ;P+ 增强型产品检验 ;82 db 脉动抑制 ; 输出带有短路保护 图 6-6 LM317 标准应用电路当稳压器离电源滤波器有一定距离时 Cin 是必须的,Co 对稳定性而言是不必要的, 但改进瞬态响应 R 2 输出电压的计算公式为 : VOUT 1.25V(1 ) IAdjR 2, 因为 I Adj 控制在 100μA, 这一项的误差在多数 R 的应用中可也忽略 1 图 6-7 LM317 管脚分布图 ww.zicreate.com

241 第 6 章电源相关器件 表 6-7 LM317 参数表 符号 参数 测试条件 LM117/LM217 LM317 单 位 最小 典 型 Vo 线路调整 Vi-Vo=3 to40v Tj= %/V Vo 负载调节 Vo 5V Io =10mA to IMAX IADJ IADJ VREF Vo / Vo Io(min) Io(max) en SVR 调整引脚电流 调整引脚电流 参考电压 ( 在引脚 3 和引脚 1 ) 输出电压温度稳定性 最小负载电流 最大负载电流 输出噪声电压 电源电压抑制 Vo 5V Io=10mA to IMAX Tj=25 Vi-Vo=2.5 to 40V Io=10mA to IMAX Vi-Vo =2.5 to 40V Io =10mA to IMAX PD PMAX 最大 最小 典型 最大 %/V Tj= mw mw Tj= % % ma ma V 1 1 % Vi-Vo=40V ma Vi-Vo 15v PD<PMAX Vi-Vo =40v PD<PMAX Tj =25 B=10Hz to 10KHz Tj= A A % Tj=25 f=120hz CADJ = db CADJ=10uF db 图 6-8 LM317 应用电路原理图

242 第二部分单片机常用外围器件 图 6-9 LM317 的 5.0V 电子关断稳压器应用电路图 图 6-10 LM317 电流稳压器应用电路图 图 6-11 LM317 可调节电流限流器的应用电路图 图 6-12LM317 软启动应用电路图 6.4 三端稳压器 AMS1117 AMS1117 系列稳压器有可调版与多种固定电压版, 设计用于提供 1A 输出电流且工作压差可低至 1V 在最大输出电流时,AMS1117 器件的压差保证最大不超过 1.3V, 并随负载电流的减小而逐渐降低 AMS1117 的片上微调把基准电压调整到 1.5% 的误差以内, 而且电流限制也得到了调整, 以尽量减少因稳压器和电源电路超载而造成的压力 AMS1117 器件引脚上兼容其他三端 SCSI 稳压器, 提供适用贴片安装的 SOT-223,8 引脚 SOIC, 和 TO-252(DPAK) 塑料封装 AMS1117 特性 : 三端口可调节或固定输出电压 ;1.5V, 1.8V, 2.5V, 2.85V, 3.3V 和 5.0V ; 输出电流 1A ; 工作压差低至 1V; 线荷载调节 :0.2% Max.; 负载调节 :0.4% Max.; 可选 SOT-223,TO-252 和 SO-8 封装 AMS1117 应用 : 高效线性稳压器 ; 后置稳压器, 用于交换式电源 ;5V 至 3.3V 线性稳压器 ; 电池充电器 ; 有源 SCSI 终端 ; 笔记本电源管理 ; 电池供电设备 ww.zicreate.com

243 第 6 章电源相关器件 图 6-13 ASM1117 封装图 表 6-8 ASM1117 选型表 表 6-9 ASM1117 参数表

244 第二部分单片机常用外围器件 图 6-14 ASM1117 典型应用电路 图 6-15 ASM1117 应用电路 ww.zicreate.com

245 7.1 数字温度传感器 DS18B20 温度 第 7 章传感器相关器件 1.DS18B20 温度传感器功能介绍 DS18B20 温度传感器是美国 DALLAS 半导体公司最新推出的一种改进型智能温度传感器, 与传统的热敏电阻等测温元件相比, 它能直接读出被测温度, 并且可根据实际要求通过简单的编程实现 9~12 位的数字值读数方式 DS18B20 的性能特点如下 : 独特的单线接口仅需要一个端口引脚进行通信 ; 多个 DS18B20 可以并联在惟一的三线上, 实现多点组网功能 ; 无须外部器件 ; 可通过数据线供电, 电压范围为 3.0~5.5v; 零待机功耗 ; 温度以 9 或 12 位二进制数字表示 ; 用户可定义报警设置 ; 报警搜索命令识别并标志超过程序限定温度 ( 温度报警条件 ) 的器件 ; 负电压特性, 电源极性接反时, 温度计不会因发热而烧毁, 但不能正常工作 ; DS18B20 采用 3 脚 TO-92 封装或 8 脚 SO 或 µsop 封装, 其其封装形式如图 7-1 所示 图 7-1 DS18B20 的封装形式 DS18B20 的 64 位 ROM 的结构开始 8 位是产品类型的编号, 接着是每个器件的惟一的序号, 共有 48 位, 最后 8 位是前面 56 位的 CRC 检验码, 这也是多个 DS18B20 可以采用一线进行通信的原因 温度报警触发器 TH 和 TL, 可通过软件写入户报警上下限 DS18B20 温度传感器的内部存储器还包括一个高速暂存 RAM 和一个非易失性的可电擦除的 EEPRAM 高速暂存 RAM 的结构为 8 字节的存储器, 结构如图 7-2 所示 图 7-2 DS18B20 的高速暂存 RAM 的结构 头 2 个字节包含测得的温度信息, 第 3 和第 4 字节 TH 和 TL 的拷贝是易失的, 每次上电复位时被刷新 第 5 个字节, 为配置寄存器, 它的内容用于确定温度值的数字转换分辨率,DS18B20 工作时寄存器中的分辨率转换为相应精度的温度数值, 该字节各位的定义如表 7-1 所示

246 表 7-1 配置寄存器 第二部分单片机常用外围器件 D7 D6 D5 D4 D3 D2 D1 D0 TM R1 R 配置寄存器的低 5 位一直为 1,TM 是工作模式位, 用于设置 DS18B20 在工作模式还是在测试模式, DS18B20 出厂时该位被设置为 0, 用户要去改动,R1 和 R0 决定温度转换的精度位数, 来设置分辨率, R1R0 为 00 是 9 位, 01 是 10 位, 10 是 11 位, 11 是 12 位 当 DS18B20 分辨率越高时, 所需要的温度数据转换时间越长 因此, 在实际应用中要将分辨率和转换时间权衡考虑 高速暂存 RAM 的第 字节保留未用, 表现为全逻辑 1 第 9 字节读出前面所有 8 字节的 CRC 码, 可用来检验数据, 从而保证通信数据的正确性 当 DS18B20 接收到温度转换命令后, 开始启动转换 转换完成后的温度值就以 16 位带符号扩展的二进制补码形式存储在高速暂存存储器的第 1 2 字节 单片机可以通过单线接口读出该数据, 读数据时低位在先, 高位在后, 数据格式以 /LSB 形式表示 当符号位 s=0 时, 表示测得的温度值为正值, 可以直接将二进制位转换为十进制 ; 当符号位 s=1 时, 表示测得的温度值为负值, 要先将补码变成原码, 再计算十进制数值 输出的二进制数的高 5 位是符号位, 最后 4 位是温度小数点位, 中间 7 位是温度整数位 表 2-2 是一部分温度值对应的二进制温度数据 表 7-2 DS18B20 输出的温度值 温度值二进制输出十六进制输出 D0h h h A2h h h FFF8h FF5Eh FF6Fh FC90h DS18B20 完成温度转换后, 就把测得的温度值与 RAM 中的 TH TL 字节内容作比较 若 T>TH 或 T<TL, 则将该器件内的报警标志位置位, 并对主机发出的报警搜索命令作出响应 因此, 可用多只 DS18B20 同时测量温度并进行报警搜索 在 64 位 ROM 的最高有效字节中存储有循环冗余检验码 (CRC) 主机 ROM 的前 56 位来计算 CRC 值, 并和存入 DS18B20 的 CRC 值作比较, 以判断主机收到的 ROM 数据是否正确 DS18B20 温度传感器的电源供电方式如图 7-3, 此时 DS18B20 的 1 脚接地,2 脚作为信号线,3 脚接电源 图 7-3 DS18B20 电源供电方式当 DS18B20 处于写存储器操作和温度 A/D 转换操作时, 总线上必须有强的上拉, 上拉开启时间最大为 10us 采用寄生电源供电方式时 VDD 端接地 由于单线制只有一根线, 因此发送接口必须是三态的 ww.zicreate.com

247 第 7 章传感器相关器件 2.DS18B20 温度传感器编程基础 a)ds18b20 传感器操作流程根据 DS18B20 的通讯协议, 主机 ( 单片机 ) 控制 DS18B20 完成温度转换必须经过三个步骤 : 每一次读写之前都要对 DS18B20 进行复位操作 复位成功后发送一条 ROM 指令 最后发送 RAM 指令这样才能对 DS18B20 进行预定的操作 复位要求主 CPU 将数据线下拉 500μs, 然后释放, 当 DS1 8B20 收到信号后等待 16~60μs 左右, 后发出 60~240μs 的存在低脉冲, 主 CPU 收到此信号表示复位成功 DS18B20 的操作流程如图 7-4 所示 图 7-4 DS18B20 的操作流程 b)ds18b20 传感器的指令表 DS18B20 传感器的操作指令如表 7-3 所示 传感器复位后向传感器写相应的命令才能实现相应的功能 表 7-3 DS18B20 的指令表 指令指令代码功能 读 ROM 0x33 读 DS1820 温度传感器 ROM 中的编码 ( 即 64 位地址 ) 符合 ROM 0x55 发出此命令之后, 接着发出 64 位 ROM 编码, 访问单总线上与该编 码相对应的 DS1820 使之作出响应, 为下一步对该 DS1820 的读写 作准备 搜索 ROM 0xF0 用于确定挂接在同一总线上 DS1820 的个数和识别 64 位 ROM 地 址 为操作各器件作好准备 跳过 ROM 0xCC 忽略 64 位 ROM 地址, 直接向 DS1820 发温度变换命令 适用于 单片工作 告警搜索命令 0xEC 执行后只有温度超过设定值上限或下限的片子才做出响应 温度变换 0x44 启动 DS1820 进行温度转换,12 位转换时最长为 750ms(9 位为 93.75ms) 结果存入内部 9 字节 RAM 中 读暂存器 0xBE 读内部 RAM 中 9 字节的内容 写暂存器 0x4E 发出向内部 RAM 的 3 4 字节写上 下限温度数据命令, 紧跟该命令 之后, 是传送两字节的数据 复制暂存器 0x48 将 RAM 中第 3 4 字节的内容复制到 EEPROM 中 重调 EEPROM 0xB8 将 EEPROM 中内容恢复到 RAM 中的第 3 4 字节 读供电方式 0xB4 读 DS1820 的供电模式 寄生供电时 DS1820 发送 0, 外接电源供 电 DS1820 发送

248 第二部分单片机常用外围器件 c) DS18B20 传感器的初始化时序 DS18B20 传感器为单总线结构器件, 在读写操作之前, 传感器芯片应先进性复位操作也就是初始化操作 DS18B20 的初始化时序如图 7-5 所示 首先控制器拉高数据总线, 接着控制器给数据总线一低电平, 延时 480μs, 控制器拉高数据总线, 等待传感器给数据线一个 μs 的低电平, 接着上拉电阻将数据线拉高, 这样才初始化完成 图 7-5 DS18B20 初始化时序 d)ds18b20 传感器的读写时序 (1) 写时序 DS18B20 传感器的读写操作是在传感器初始化后进行的 每次操作只能读写一位 当主机把数据线从高电平拉至低电平, 产生写时序 有两种类型的写时序 : 写 0 时序, 写 1 时序 所有的时序必须有最短 60μs 的持续期, 在各个写周期之间必须有最短 1μs 的恢复期 在数据总线由高电平变为低电平之后,DS18B20 在 15μs 至 60μs 的时间间隙对总线采样, 如果为 1 则向 DS18B20 写 1, 如果为 0 则向 DS18B20 写 0 如图 3-2 的上半部分 对于主机产生写 1 时序时, 数据线必须先被拉至低电平, 然后被释放, 使数据线在写时序开始之后 15μs 内拉至高电平 对于主机产生写 1 时序时, 数据线必须先被拉至低电平, 且至少保持低电平 60μs (2) 读时序在数据总线由高电平变为低电平之后, 数据线至少应保持低电平 1μs, 来自 DS18B20 的输出的数据在下降沿 15μs 后有效, 所以在数据线保持低电平 1μs 之后, 主机将数据线拉高, 等待来自 DS18B2 0 的数据变化, 在下降沿 15μs 之后便可开始读取 DS18B20 的输出数据 整个读时序必须有最短 60μs 的持续期 如图 3-2 的下半部分 读时序结束后数据线由上拉电阻拉至高电平 e)ds18b20 获取温度程序流程图 图 7-6 DS18B20 传感器的读写时序 ww.zicreate.com

249 第 7 章传感器相关器件 DS18B20 的读字节, 写字节, 获取温度的程序流程图如图 7-7 所示 开始开始 开始 DQ=1 d=1 i=8 DQ=0 DQ=1 N i>0 延时 480μs i=8 Y DQ=0 Y DQ=1 DQ=1 N N i>0 Y d >>= 1 延时 2μs DQ=d&0x01 延时 80μs DQ=0 延时 30μs DQ=1 延时 2μs 延时 DQ=1 60μs 结束 DQ=1 d >>= 1 DS18B20 初始化程序流程图 N DQ=1 Y i-- 开始 d = 0x80 DS18B20 初始化 延时 60μs 结束 写 0xcc 跳过读 ROM 写 0x44 启动 DS18B20 i-- DS18B20 写字节程序流程图 延时 500μs return d DS18B20 初始化 写 0xcc 跳过读 ROM 写 0xbe 读 DS18B20 结束 DS18B20 读字节程序流程图 结束 DS18B20 获取温度程序流程图

250 7.2 时钟芯片 DS1302 图 7-7 DS18B20 程序流程图 第二部分单片机常用外围器件 DS1302 是美国 DALLAS 公司推出的一种高性能 低功耗 带 RAM 的实时时钟电路, 它可以对年 月 日 周日 时 分 秒进行计时, 具有闰年补偿功能, 工作电压为 2.5V~5.5V 采用三线接口与 CPU 进行同步通信, 并可采用突发方式一次传送多个字节的时钟信号或 RAM 数据 DS1302 内部有一个 31 8 的用于临时性存放数据的 RAM 寄存器 DS1302 是 DS1202 的升级产品, 与 DS1202 兼容, 但增加了主电源 / 后背电源双电源引脚, 同时提供了对后背电源进行涓细电流充电的能力 1. 引脚功能及结构 DS1302 的引脚排列, 其中 Vcc1 为后备电源,VCC2 为主电源 在主电源关闭的情况下, 也能保持时钟的连续运行 DS1302 由 Vcc1 或 Vcc2 两者中的较大者供电 当 Vcc2 大于 Vcc1+0.2V 时,Vcc2 给 DS1302 供电 当 Vcc2 小于 Vcc1 时,DS1302 由 Vcc1 供电 X1 和 X2 是振荡源, 外接 kHz 晶振 RST 是复位 / 片选线, 通过把 RST 输入驱动置高电平来启动所有的数据传送 RST 输入有两种功能 : 首先,RST 接通控制逻辑, 允许地址 / 命令序列送入移位寄存器 ; 其次,RST 提供终止单字节或多字节数据的传送手段 当 RST 为高电平时, 所有的数据传送被初始化, 允许对 DS1302 进行操作 如果在传送过程中 RST 置为低电平, 则会终止此次数据传送,I/O 引脚变为高阻态 上电运行时, 在 Vcc>2.0V 之前, RST 必须保持低电平 只有在 SCLK 为低电平时, 才能将 RST 置为高电平 I/O 为串行数据输入输出端 ( 双向 ) SCLK 为时钟输入端 下图为 DS1302 的引脚功能图 图 7-8 DS1302 管脚分布及封装形式图 表 7-4 DS1302 管脚功能表 管脚号管脚名功能管脚号管脚名功能 1 V CC2 双电源供电时的主电源 5 RST 复位 / 片选端 2 X1 X1 和 X2 是振荡源, 外接 6 I/O 串行数据输入输出端 3 X kHz 晶振 7 SCLK 时钟输入端 4 GND 电源地 8 V CC1 单电源供电时的主电源, 双电 源时的后备电源 2.DS1302 的控制字节 DS1302 的控制字如表 7-5 所示 控制字节的最高有效位 ( 位 7) 必须是逻辑 1, 如果它为 0, 则不能把数据写入 DS1302 中, 位 6 如果为 0, 则表示存取日历时钟数据, 为 1 表示存取 RAM 数据 ; 位 5 至位 1 指示操作单元的地址 ; 最低有效位 ( 位 0) 如为 0 表示要进行写操作, 为 1 表示进行读操作, 控制字节总是从最低位开始输出 表 7-5 DS1302 的控制字 RAM / CK A4 A3 A2 A1 A0 RD / W 3.DS1302 的寄存器 DS1302 有 12 个寄存器, 其中有 7 个寄存器与日历 时钟相关, 存放的数据位为 BCD 码形式, 其日历 时间寄存器及其控制字见表 7-5 此外,DS1302 还有年份寄存器 控制寄存器 充电寄存器 时钟突发寄存器及与 RAM 相关的寄存器等 时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容 DS1302 与 RAM 相关的寄存器分为两类 : 一类是单个 RAM 单元, 共 31 个, 每个单元组态为一个 8 位的字节, 其命令控制字 ww.zicreate.com

251 第 7 章传感器相关器件 为 C0H~FDH, 其中奇数为读操作, 偶数为写操作 ; 另一类为突发方式下的 RAM 寄存器, 此方式下可一次性读写所有的 RAM 的 31 个字节, 命令控制字为 FEH( 写 ) FFH( 读 ) 寄存器名 表 7-6 DS1302 寄存器分配表 命令字 秒寄存器 80H 81H 分寄存器 82H 83H 时寄存器 84H 85H 日寄存器 86H 87H 月寄存器 88H 89H 周寄存器 8AH 8BH 年寄存器 8CH 8DH 控制寄存器 8E 8FH 充电控制寄存器 90H 91H 批量模式寄存器 BEH BFH 读 表 7-7 DS1302 的日历 时钟寄存器及控制字 寄存器名命令字数值范围各位内容 读写 秒寄存器 80H 81H 0~59 CH 10SEC SEC 分寄存器 82H 83H 0~ MIN MIN 时寄存器 84H 85H 1~12 12/ HR HR 日寄存器 86H 87H 1~ DATE DATE 月寄存器 88H 89H 1~ M MONTH 周寄存器 8AH 8BH 1~ DAY 年寄存器 8CH 8DH 0~99 10YEAR YEAR 充电控制寄存器 90H 91H TCS TCS TCS TCS DS DS RS RS 表 7-8 充电控制寄存器设置功能表 写 DS1302 的充电寄存器可以控制是否充电及充电方式 其中 TCS 是电流充电选择位, 仅在 1010 编码条件下才具备充电能力, 其它禁止充电 DS 位充电式主备电源间的所串的二极管数 RS 用于选择和二极管串联的电阻值的编码 各位的设置如表

252 第二部分单片机常用外围器件 充电电流的计算公式如下 : I MAX = (5.0V diode drop) / R1 (5.0V 0.7V) / 2kΩ 2.2mA 4.DS1302 的工作时序 RST 输入有两种功能 : 首先,RST 接通控制逻辑, 允许地址 / 命令序列送入移位寄存器 ; 其次,RST 提供终止单字节或多字节数据的传送手段 当 RST 为高电平时, 所有的数据传送被初始化, 允许对 DS1302 进行操作 如果在传送过程中 RST 置为低电平, 则会终止此次数据传送,I/O 引脚变为高阻态 上电运行时, 在 Vcc>2.0V 之前,RST 必须保持低电平 只有在 SCLK 为低电平时, 才能将 RST 置为高电平 同样, 在紧跟 8 位的控制指令字后的下一个 SCLK 脉冲的下降沿读出 DS1302 的数据, 读出数据时从低位 0 位到高位 7 图 7-9 单字节读时序 在控制指令字输入后的下一个 SCLK 时钟的上升沿时, 数据被写入 DS1302, 数据输入从低位即位 0 开始 图 7-10 单字节写时序 表 7-9 DS1302 读写时序间隔时间表 ww.zicreate.com

253 第 7 章传感器相关器件 图 7-11 DS1302 读数据时序 5.DS1302 的典型电路接法 图 7-12 DS1302 写数据时序

254 第二部分单片机常用外围器件 图 7-13 DS1302 的典型应用电路 ww.zicreate.com

255 网站 :zicreate.com 邮箱 QQ: 官方微信 :zicreateiot

DPJJX1.DOC

DPJJX1.DOC 8051 111 2K 1 2 3 ' ' 1 CPU RAM ROM / A/D D/A PC CPU 40 68 10 20 8 51 PIII 8051 2 MCS51 8051 8031 89C51 8051 8031 89C51? MCS51 INTEL INTEL 8031 8051 8751 8032 8052 8752 8051 8051 8051 MCS51 8031 8031

More information

W77E58中文手册

W77E58中文手册 W77E58 77E58 8051 8051 8051 77E58 8051 1.5 3 COMS 32K EEPROM 1K SRAM 1 8 2 40M 4 3 8051 4 8051 5 4 8 I/O 6 4 I/O 44 PLCC QFP 7 16 / 8 12 9 10 11 1K 12 13 16 DPTR 14 15 DIP40 W77E58 25/40 PLCC44 W77E58P

More information

6 C51 ANSI C Turbo C C51 Turbo C C51 C51 C51 C51 C51 C51 C51 C51 C C C51 C51 ANSI C MCS-51 C51 ANSI C C C51 bit Byte bit sbit

6 C51 ANSI C Turbo C C51 Turbo C C51 C51 C51 C51 C51 C51 C51 C51 C C C51 C51 ANSI C MCS-51 C51 ANSI C C C51 bit Byte bit sbit 6 C51 ANSI C Turbo C C51 Turbo C C51 C51 C51 C51 C51 C51 C51 C51 C51 6.1 C51 6.1.1 C51 C51 ANSI C MCS-51 C51 ANSI C C51 6.1 6.1 C51 bit Byte bit sbit 1 0 1 unsigned char 8 1 0 255 Signed char 8 11 128

More information

CH559指令周期.doc

CH559指令周期.doc CH55X 汇编指令周期表 CH55X 汇编指令概述 : 型号包含 : a. 指令单周期型号 :CH557 CH558 CH559; b. 指令 4 周期型号 :CH551 CH552 CH553 CH554; c. 非跳转指令的指令周期数与指令字节数相同 ; d. 跳转指令含 MOVC/RET/CALL 通常比字节数多若干个周期 ; e.movc 指令多 4 或 5 个周期 ( 下条指令地址为奇数时多

More information

51 C 51 isp 10 C PCB C C C C KEIL

51 C 51 isp 10   C   PCB C C C C KEIL http://wwwispdowncom 51 C " + + " 51 AT89S51 In-System-Programming ISP 10 io 244 CPLD ATMEL PIC CPLD/FPGA ARM9 ISP http://wwwispdowncom/showoneproductasp?productid=15 51 C C C C C ispdown http://wwwispdowncom

More information

另外,AT89S52 可降至 0Hz 静态逻辑操作, 支持 2 种软件可选择节电模式 空闲模式下,CPU 停止工作, 允许 RAM 定时器/ 计数器 串口 中断继续工作 掉电保护方式下,RAM 内容被保存, 振荡器被冻结, 单片机一切工作停止, 直到下一个中断或硬件复位为止 8 位微控制器 8K 字

另外,AT89S52 可降至 0Hz 静态逻辑操作, 支持 2 种软件可选择节电模式 空闲模式下,CPU 停止工作, 允许 RAM 定时器/ 计数器 串口 中断继续工作 掉电保护方式下,RAM 内容被保存, 振荡器被冻结, 单片机一切工作停止, 直到下一个中断或硬件复位为止 8 位微控制器 8K 字 AT89C52 中文资料 AT89C52 的中文资料 AT89C52 是美国 Atmel 公司生产的低电压 高性能 CMOS 8 位单片机, 片内含 8KB 的可反复檫写的程序存储器和 12B 的随机存取数据存储器 (RAM), 器件采用 Atmel 公司的高密度 非易失性存储技术生产, 兼容标准 MCS- 51 指令系统, 片内配置通用 8 位中央处理器 (CPU) 和 Flash 存储单元, 功能强大的

More information

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File 51 C 51 51 C C C C C C * 2003-3-30 pnzwzw@163.com C C C C KEIL uvision2 MCS51 PLM C VC++ 51 KEIL51 KEIL51 KEIL51 KEIL 2K DEMO C KEIL KEIL51 P 1 1 1 1-1 - 1 Project New Project 1 2 Windows 1 3 N C test

More information

Microsoft Word - 專題封面.doc

Microsoft Word - 專題封面.doc 逢 甲 大 學 資 訊 工 程 學 系 專 題 研 究 報 告 8051 小 遊 戲 -21 點 指 導 教 授 : 陳 德 生 學 生 : 許 博 益 中 華 民 國 九 十 六 年 六 月 I 目 錄 第 一 章 緒 論 1 1-1 研 究 背 景 1 1-2 研 究 動 機 2 1-3 研 究 目 的 3 1-3-1 21 點 源 起 3 1-3-2 21 點 規 則 3 第 二 章 微 電

More information

128K Flash EPROM 的程序?\(Bank=64K\) 切?

128K Flash EPROM 的程序?\(Bank=64K\) 切? 应用说明 华邦 8 位单片机 (8051 内核 ) 应用说明 华邦 8 位单片机 (8051 内核 ) ANSC-UC08-0007 目录 - 1. 应用说明 :...4 1.1...4 1.2 相关寄存器介绍...4 1.2.1 串行口控制寄存器 (SCON)... 4 1.2.2 串行数据缓冲寄存器 (SBUF)... 5 1.2.3 串行口控制 1 (SCON1)... 5 1.2.4 串行数据接收缓冲

More information

目 录

目 录 1 Quick51...1 1.1 SmartSOPC Quick51...1 1.2 Quick51...1 1.3 Quick51...2 2 Keil C51 Quick51...4 2.1 Keil C51...4 2.2 Keil C51...4 2.3 1 Keil C51...4 2.4 Flash Magic...9 2.5 ISP...9 2.6...10 2.7 Keil C51...12

More information

Microsoft Word - 第1章 MCS-51单片机基础.docx

Microsoft Word - 第1章 MCS-51单片机基础.docx 51 单片机应用开发实战手册 作者 : 华清远见 第 1 章 MCS-51 单片机基础 本章目标 单片机作为嵌入式微控制器在工业测控系统 智能仪器和家用电器中得到广泛 应用 虽然单片机的品种很多, 但 MCS-51 系列单片机仍不失为单片机中的主流机 型 本章主要介绍 MCS-51 单片机的基础知识和学习要点, 以目前应用最为广泛的 AT89SXX 系列单片机为例, 介绍单片机的历史发展 应用领域

More information

at89S52.doc

at89S52.doc 主要性能 与 MCS-51 单片机产品兼容 8K 字节在系统可编程 Flash 存储器 1000 次擦写周期 全静态操作 :0Hz~33Hz 三级加密程序存储器 32 个可编程 I/O 口线 三个 16 位定时器 / 计数器 八个中断源 全双工 UART 串行通道 低功耗空闲和掉电模式 掉电后中断可唤醒 看门狗定时器 双数据指针 掉电标识符 8 位微控制器 8K 字节在系统可编程 Flash R 功能特性描述

More information

1-1 SH79F6431 A. 2( ) 9~15V ( 12V) U2 U3 3.3V SH79F B. 1(VCC/GND) SH79F6431 C. VDDIO SH79F6431 P4 P5 P0.6 P0.7 VDDIO VDDIO=5V D. 2 V 1.0

1-1 SH79F6431 A. 2( ) 9~15V ( 12V) U2 U3 3.3V SH79F B. 1(VCC/GND) SH79F6431 C. VDDIO SH79F6431 P4 P5 P0.6 P0.7 VDDIO VDDIO=5V D. 2 V 1.0 SH79F6431 1. SH79F6431 1T 8051 FLASH SH79F JET51 Keil µ vision JTAG 1.1. SH79F6431 LQFP64 1.2. (Target Board) SH79F6431 1 V 1.0 1-1 SH79F6431 A. 2( ) 9~15V ( 12V) U2 U3 3.3V SH79F6431 1 2 1 B. 1(VCC/GND)

More information

2 Keil µ vision 2.1 1) Keil µ vision2 V2.34 µ vision3 2) Sino_Keil.exe Keil c:\keil\ 3) JET51 USB PC C:\Keil\ USB PC 4) S-L

2 Keil µ vision 2.1 1) Keil µ vision2 V2.34 µ vision3 2) Sino_Keil.exe   Keil c:\keil\ 3) JET51 USB PC C:\Keil\ USB PC 4) S-L 1 SH88F516 8051 64K FLASH 1024 EEPROM SH88F516 JET51 S-Lab Keil µ vision ISP51 Keil µ vision ISP51 ISP51 PC RS232 MCU SH88F516 SH88F516 1.1 SH88F516 1.1 SH88F516 SH88Fxx: QFP44, DIP40 RAM Flash E2 ADC

More information

微處理機期末專題

微處理機期末專題 微 處 理 機 期 末 專 題 自 動 鋼 琴 組 員 :b92611004 羅 鈞 瑋 b92611008 吳 妍 儂 b92611038 吳 韋 靜 b92611042 林 佳 穎 一 簡 介 本 組 的 主 題 是 自 動 鋼 琴 在 播 放 音 樂 的 同 時, 鋼 琴 會 自 動 按 下 琴 鍵, 被 按 下 的 琴 鍵 所 對 應 到 的 音 階, 就 是 正 在 撥 放 的 樂 曲 的

More information

µPSD3000 系列

µPSD3000 系列 8032 FLASH MCU µpsd3251f-40t6 µpsd3251 8032 FlashPSD Flash SRAM I/O I 2 C, ADC and PWM 8032, 16 / FlashPSD µpsd32 JTAG ISP 2K SRAM Flash - 64K Flash - 16K Flash - Flash 8032 12 I2C ADC 6 I/O 37 I/O 16

More information

CC213

CC213 : (Ken-Yi Lee), E-mail: feis.tw@gmail.com 49 [P.51] C/C++ [P.52] [P.53] [P.55] (int) [P.57] (float/double) [P.58] printf scanf [P.59] [P.61] ( / ) [P.62] (char) [P.65] : +-*/% [P.67] : = [P.68] : ,

More information

学习MSP430单片机推荐参考书

学习MSP430单片机推荐参考书 MSP430 16 MSP430 C MSP430 C MSP430 FLASH 16 1 CPU 16 ALU 16 PC SP SR R4~R15 2 3 00-FFH 100-1FFH 4 5 1 2 51 24 27 6 1 2 3 4 5 6 4 12 SR SP SR CPU SR CPU C Z N GIE CPUOff CPU OscOff SCG0 SCG1 CPU EXIT SP

More information

<4D F736F F D20B5DAC8FDCBC4D5C2D7F7D2B5B4F0B0B82E646F63>

<4D F736F F D20B5DAC8FDCBC4D5C2D7F7D2B5B4F0B0B82E646F63> 第三章 Q3 1 1. 省略了 I/O 操作的复杂逻辑, 易实现, 耗费低 ; 2. 可以利用丰富的内存寻址模式实现灵活的 I/O 操作 Q3 2 假设存储单元 ds1 处寄存器地址为 0x2000, 代码如下 #define ds1 0x2000 while ( *ds1 == 0 ) ; Q3 3 假设设备 (dev1) 中有两个寄存器 ds1 和 dd1,dev1 的地址为 0x1000,ds1

More information

电子驿站技术文档

电子驿站技术文档 AT89C52 中文资料 电子驿站 http:// www.ourmpu.com E-mail: support@ourmpu.com AT89C52 是美国 ATMEL 公司生产的低电压, 高性能 CMOS 8 位单片机, 片内含 8k bytes 的可反复擦写的只读程序存储器 (PEROM) 和 256 bytes 的随机存取数据存储器 (RAM), 器件采用 ATMEL 公司的高密度 非易失性存储技术生产,

More information

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File 51 C 51 51 C C C C C C * 2003-3-30 pnzwzw@163.com C C C C KEIL uvision2 MCS51 PLM C VC++ 51 KEIL51 KEIL51 KEIL51 KEIL 2K DEMO C KEIL KEIL51 P 1 1 1 1-1 - 1 Project New Project 1 2 Windows 1 3 N C test

More information

*_* IAP In Applications Program, *_* ROM RAM A/D D/A KELL C51 2 0531-86213622 Micro Controller Unit( ) INTEL MCS-48 MCS-51 MCS-96 51 MCS-51 8 MCS-96 16 INTEL / 51 87 LPC W78L DS87 GSM97 ATMEL 89C51

More information

untitled

untitled EDM16080-01 Model No.: Editor: 1. ----------------------------------------------------3 2. ----------------------------------------------------3 3. ----------------------------------------------------3

More information

1

1 W7E65 1. W7E65 ISP Flash EPROM ISP Flash EPROM 52 W7E65 64K Flash EPROM 4K Flash EPROM 4K Flash EPROM loader 64K ROM 1K RAM 4 I/O 4 I/O P4 3 16 / 2 W7E65 Flash EPROM W7E65 2 2 2. CMOS 12 64K ISP Flash

More information

Microsoft Word - P3.doc

Microsoft Word - P3.doc ;P3.3 警报器 ;* ( 程序转载请著明出处, 未声明可适应本站腾龙 /isp 开发套件 / 倚天版开发套件 * ;* E-mail:sxj1974@163.com (51c51 test web) 51 测试网, 自学单片机的网站 * ;* Create by : 石学军 www.51c51.com www.8951.com 更多例程请登陆网站 * org 00h ajmp dlv org 0030h

More information

HD61202 HD HD61203 HD61202, HY HY HD61202 HD61202 HD61203 HD =4096 RAMRAM LCD 2HD HD HD /32--

HD61202 HD HD61203 HD61202, HY HY HD61202 HD61202 HD61203 HD =4096 RAMRAM LCD 2HD HD HD /32-- HD61202 C-7 1 HD61202 HD61202 8 HD61203 HD61202, HY-12864 HY-19264 HD61202 HD61202 HD61203 HD61202 1 6464=4096 RAMRAM LCD 2HD61202 64 3HD61202 68 68 4HD61202 1/32--1/64 HD61202 HD61202 2 CS1,CS2,CS3 CS1

More information

新版 明解C言語入門編

新版 明解C言語入門編 328, 4, 110, 189, 103, 11... 318. 274 6 ; 10 ; 5? 48 & & 228! 61!= 42 ^= 66 _ 82 /= 66 /* 3 / 19 ~ 164 OR 53 OR 164 = 66 ( ) 115 ( ) 31 ^ OR 164 [] 89, 241 [] 324 + + 4, 19, 241 + + 22 ++ 67 ++ 73 += 66

More information

» n ¹ú KS0108 x ÍÍÙ q n KS0108 KS KS0107 KS0108 KS *32 128*64 192*64 KS0108 KS0108 KS0107 KS =4096 RAM RAM LCD 2 KS

» n ¹ú KS0108 x ÍÍÙ q n KS0108 KS KS0107 KS0108 KS *32 128*64 192*64 KS0108 KS0108 KS0107 KS =4096 RAM RAM LCD 2 KS KS0108 KS0108 8 KS0107 KS0108 KS0108 128*32128*64 192*64 KS0108 KS0108 KS0107 KS0108 1 6464=4096 RAMRAM LCD 2KS0108 64 3KS0108 68 68 4KS0108 1/48--1/64 KS0108 CS1,CS2,CS3 CS1 CS2 CS3 E E KS0108 E R/W R/W=1

More information

1 TPIS TPIS 2 2

1 TPIS TPIS 2 2 1 1 TPIS TPIS 2 2 1. 2. 3. 4. 3 3 4 5 4 TPIS TPIS 6 5 350 Mark Coil F3/F6 350 M 150 M 25 M 7.12M 8 M F3 F6 F4 F7 F8 8M AA 7 350 28V 5V IC HCPL2731 0.5mA 6 8 (TPIS) TPIS 9 7 IC AT89C2051 AT89C2051 CMOS8

More information

AT89S51

AT89S51 AT89S51 中文资料 AT89S51 是美国 ATMEL 公司生产的低功耗, 高性能 CMOS8 位单片机, 片内含 4kbytes 的可系统编程的 Flash 只读程序存储器, 器件采用 ATMEL 公司的高密度 非易失性存储技术生产, 兼容标准 8051 指令系统及引脚 它集 Flash 程序存储器既可在线编程 ( ISP) 也可用传统方法进行编程及通用 8 位微处理器于单片芯片中,ATMEL

More information

12232A LED LED LED EL EL CCFL EL CCF

12232A LED LED LED EL EL CCFL EL CCF 12232A 0 50-20 +70-30 +85 LED LED LED EL EL CCFL EL CCF 122 x 32 1/32Duty 1/5Bias 6:00 STN( ), EL LED EL/100VAC 400HZ LED/4.2VDC 1 / VDD-VSS 0 6.5 V Ta=25 LCD VDD-V0 0 12.0 V V1 0 VDD V VDD-VSS - 4.75

More information

STC90C51RC-cn.pdf

STC90C51RC-cn.pdf STC90.STC90C5RC/RD+ STC90C5RC/RD+ 805 5.5V - 3.3V 3.6V - 2.0V V 040MHz080MHz48MHz 4K / 8K / 3K / 6K / 32K / 40K/ 48K/ 56K/ 6K 28052RAM I/O35/39P/P2/P3/P4805I/OP0 I/O ISP/ IAP RxD/P3.0, TxD/P3. EEPROM MAX80

More information

untitled

untitled EDM12832-08 : 25-1 : 116600 : (0411)7612956 7632020 7631122 : (0411)7612958 Model No.: Editor: LCD 1. ----------------------------------------------------3 2. ----------------------------------------------------3

More information

SH79F161B I/O 1. SH79F161B SH79F161B IO 30 I/O I/O 4 I/O SH79F161B 30 I/O Px I/O PxCRy I/O PxPCRy x = 0-3 y = IO PxCRy IO x=0-3 y=0-7

SH79F161B I/O 1. SH79F161B SH79F161B IO 30 I/O I/O 4 I/O SH79F161B 30 I/O Px I/O PxCRy I/O PxPCRy x = 0-3 y = IO PxCRy IO x=0-3 y=0-7 SH79F161B - 10 ADC 8051 V 1.0 SH79F161B I/O 1. SH79F161B 8051 8051 SH79F161B IO 30 I/O I/O 4 I/O SH79F161B 30 I/O Px I/O PxCRy I/O PxPCRy x = 0-3 y = 0-7 2. IO PxCRy IO x=0-3 y=0-7 PxPCRy IO x=0-3 y=0-7

More information

<4D F736F F D20B3E6B4B9A4F930365F32A443AC71C5E3A5DCBEB9B1B1A8EE2E646F63>

<4D F736F F D20B3E6B4B9A4F930365F32A443AC71C5E3A5DCBEB9B1B1A8EE2E646F63> 七段顯示器控制電路四位數 _ 使用解碼器驅動 +5 V 10 uf 8.2 k 12 MHz 20 pf 1 2 3 4 5 6 7 8 9 P1.0 P1.1 P1.2 P1.3 P1.4 P1.5 P1.6 P1.7 RESET 10 P3.0 11 12 13 14 15 16 17 18 19 20 P3.1 P3.2 P3.3 P3.4 P3.5 P3.6 P3.7 XTAL2 XTAL1

More information

AN-8203 FCM8531 用户手册

AN-8203 FCM8531 用户手册 www.fairchildsemi.com AN-8203 FCM8531 用户手册 所有指令兼容二进制代码, 与业界标准的 8051 微控制器执行的功能相同 表 1. 指令集和寻址模式 符号 说明 Rn 当前选择的寄存器区中的寄存器 R0 ~ R7 直接 内部 DATA RAM 位置 (0~127) 或特殊功能寄存器 (SFR) @Ri 间接内部 (0~255) 或外部 RAM 位置由寄存器 R0

More information

新・明解C言語入門編『索引』

新・明解C言語入門編『索引』 !... 75!=... 48 "... 234 " "... 9, 84, 240 #define... 118, 213 #include... 148 %... 23 %... 23, 24 %%... 23 %d... 4 %f... 29 %ld... 177 %lf... 31 %lu... 177 %o... 196 %p... 262 %s... 242, 244 %u... 177

More information

<4D6963726F736F667420576F7264202D20B9F9B0EABBCDBBAFAB48DEB3B4C1A5BDB3F8A7692E646F63>

<4D6963726F736F667420576F7264202D20B9F9B0EABBCDBBAFAB48DEB3B4C1A5BDB3F8A7692E646F63> 臺 北 市 立 松 山 高 級 工 農 職 業 學 校 資 訊 科 專 題 製 作 報 告 題 目 : 反 彈 空 間 指 導 老 師 : 余 耀 銘 學 生 : 廖 國 銓 趙 信 瑋 中 華 民 國 102 年 5 月 摘 要 在 這 高 速 科 技 的 起 飛 下, 科 技 都 建 立 起 於 基 礎, 有 些 人 把 這 基 礎 轉 為 理 論, 教 給 大 眾 學 習 ; 有 些 人 利

More information

CA24064B LED LED LED EL EL CCFL EL CCF /

CA24064B LED LED LED EL EL CCFL EL CCF / CA24064B 0 50-20 +70-30 +85 LED LED LED EL EL CCFL EL CCF 39 2 6 0755-81995643/27890716 0 13713911853 0755-27890716 1 : VDD-VSS 0 6 V LCD VDD-V0 Ta=25 0 28.0 V VI 0 VDD V : VDD-VSS --- 4.75 5.0 5.25 V

More information

專題最終版.doc

專題最終版.doc The Principle and Application of the Electric Combination Lock The Principle and Application of the Electric Combination Lock Abstract Recently, there are more and more burglaries in the society. It's

More information

第5章:汇编语言程序设计

第5章:汇编语言程序设计 第 5 章 : 汇编语言程序设计 程 汇编语言指令格式 系统伪指令 存储器选择方式 常用子程序 1 汇编语言程序设计 PIC 指令系统 语言系统 指 CPU 编 器语言 器语言 器语言 设计 用 语言 设计 语言 汇编语言 2 汇编语言指令格式 汇编语言指令格式 ( 指令 ) label opcode operand comment 指令 用 存 指令 指令语 3 汇编语言指令格式 1 指令 用 指令

More information

Microsoft Word - IRFWX_A051_C_SyncMOS_with_STC_APN_SC_.doc

Microsoft Word - IRFWX_A051_C_SyncMOS_with_STC_APN_SC_.doc EEPROM 应用说明 1 适用产品 :SM59D03G2 SM59D04G2 series 2 应用范围 : 针对需使用 EEPORM 功能替换 STC 89C5X 的应用及汇编语言之范例程序 ( 使用内部扩充内存为暂存区 ) 3 功能说明 : 3.1 本公司上述产品 EEPORM 功能皆可替换 STC89C5X, 仅需对特殊功能缓存器定义 ( 详见表 1) 及 ISP 命令定义 ( 详见表 2)

More information

部分编号派生器件编号 (P89CXX) 操作频率, 最大 (V) 温度范围 (B) 封装 (AA,BB,PN) P89C51 FLASH U=33MHz B=0 70 AA=PLCC P89C52 FLASH F= BB=PQFP P89C54 FLASH PN=PDIP P89C58

部分编号派生器件编号 (P89CXX) 操作频率, 最大 (V) 温度范围 (B) 封装 (AA,BB,PN) P89C51 FLASH U=33MHz B=0 70 AA=PLCC P89C52 FLASH F= BB=PQFP P89C54 FLASH PN=PDIP P89C58 PHILIPS P89C5x 单片机数据手册 1 概述 P89C51/89C52/89C54/89C58 含有非易失 FLASH 并行可编程的程序存储器所有器件都是通过引导装载器串行编程 ISP 见 P89C51RC+/89C51RD+ 数据手册种系列单片机采用先进 CMOS 工艺的单片位微控制器是 80C51 微控制器系列的派生和 80C51 指令相同特点 FLASH 器件选择表 ROM/EPRO

More information

1. 介绍 义隆 8 位单片机指令介绍 Application Notes 义隆 8 位单片机指令介绍 EM78/EM88 系列是基于 RISC 的精简指令微控制器, 每条指令是 13 位 15 位, 除 LCALL LJMP MOV R2,A ADD R2,A 改变 PC 指针的指令是 2 个指令

1. 介绍 义隆 8 位单片机指令介绍 Application Notes 义隆 8 位单片机指令介绍 EM78/EM88 系列是基于 RISC 的精简指令微控制器, 每条指令是 13 位 15 位, 除 LCALL LJMP MOV R2,A ADD R2,A 改变 PC 指针的指令是 2 个指令 1. 介绍 Application Notes EM78/EM88 系列是基于 RISC 的精简指令微控制器, 每条指令是 13 位 15 位, 除 LCALL LJMP MOV R2,A ADD R2,A 改变 PC 指针的指令是 2 个指令 * 周期, 其余为单指令周期 ( 部分第一代芯片 JMP CALL RET RETL RETI JBS JBC JZ JZA DJZ DJZA 指令为 2

More information

<4D6963726F736F667420576F7264202D203130B5A5C6ACBBFACAB5D1E9D6B8B5BCCAE92E646F63>

<4D6963726F736F667420576F7264202D203130B5A5C6ACBBFACAB5D1E9D6B8B5BCCAE92E646F63> 单 片 机 及 接 口 技 术 实 验 指 导 书 张 勇 编 计 算 机 与 通 信 工 程 学 院 信 息 与 通 信 工 程 系 2004.12 1 - 前 言 单 片 机 及 接 口 技 术 是 通 信 工 程 专 业 的 专 业 技 能 课 程, 在 专 业 知 识 结 构 体 系 中 具 有 十 分 重 要 的 地 位, 课 程 的 实 践 性 很 强, 学 习 必 须 理 论 和 实

More information

微處理機

微處理機 3-1 指令格式 標記運算碼運算元註解 標記 1. 標記前不可有空白, 否則會被視為運算碼 2. 標記代表一個 16 位元的記憶體實際位址 3. 標記名稱最多 32 個字元 ( 視組譯器不同而有所不同 ) 4. 標記有大小寫之分 5. 標記可有可無 運算碼 1. 運算碼與標記名稱間, 至少必須空一格, 如果沒有標記名稱, 則運算碼前最少要空一格, 否則會被視為標記 2. 運算碼大小寫相同 3. 可以是

More information

2 12

2 12 SHENZHEN BRILLIANT CRYSTAL TECHNOLOGIC CO.,LTD. The specification for the following models Graphic LCM serial communication control board CB001 PROPOSED BY APPROVED Design Approved TEL:+86-755-29995238

More information

Microsoft PowerPoint - 第一章(07版).PPT

Microsoft PowerPoint - 第一章(07版).PPT 单片机原理及综合设计 嵌入式微控制器的开发入门 微机及单片机原理原理实验室综合楼 419 室 大连理工大学电信学院陈育斌 1 ( 理论课 ) 上课时间表 (10~17 周 ) 周次 星期 一 二 三 四 五 六 日 1 至 6 时间地点 大五节综 309 (18:00) 大连理工大学电信学院陈育斌 2 课程总体安排 总学时 : 理论课 + 实验课 =36 学时 其中 : 理论课 :24: 学时 ;

More information

Microsoft Word - ISSFA-0134_A_AP_User-definedDownload_SC_.doc

Microsoft Word - ISSFA-0134_A_AP_User-definedDownload_SC_.doc 自定义下载应用说明 一 适用产品 :SM59XX 系列 SM59D XX 系列 SM59R XX 系列二 应用方式 : 可以让使用者自定义 command 作为进入 ISP 刻录的通关指令, 透过 UART 连接 ISAP 软件做联机更新三 操作说明 ( 使用 SM59D04G2 为例 ): 1. ISAP 操作方式 : 1.1 先将主程序及 ISP 服务程序烧进 MCU 中 1.2 将 MCU 放至系统版上,

More information

Microsoft PowerPoint - chap5.ppt

Microsoft PowerPoint - chap5.ppt 邏輯運算指令的動作 0 1 0 1 0 0 1 1 OR 1 0 1 1 1 0 0 1 1 1 1 1 1 0 1 1 (a) OR 運算 0 1 0 1 0 0 1 1 XOR 1 0 1 1 1 0 0 1 1 1 1 0 1 0 1 0 (c) XOR 運算 希望設定為 1 的位元 罩網標的位元組 新標的位元組 不改變的位元 希望取補數的位元 罩網標的位元組 新標的位元組 不改變的位元 1

More information

图 内部结构图 8251 的外部引脚如图 所示, 共 28 个引脚, 每个引脚信号的输入输出方式如图中的箭 头方向所示

图 内部结构图 8251 的外部引脚如图 所示, 共 28 个引脚, 每个引脚信号的输入输出方式如图中的箭 头方向所示 实验题目 : 串行接口芯片 8251 实验目的 : 1. 掌握 8251 的工作方式及应用 2. 了解有关串口通讯的知识 串行接口芯片 8251 3. 掌握使用 8251 实现双机通讯的软件编程和电路连接 实验设备 : IA-32 架构的微机系统及应用教学平台两套 实验原理 : 1. 8251 的基本性能 性能 : 8251 是可编程的串行通信接口, 可以管理信号变化范围很大的串行数据通信 有下列基本

More information

C PICC C++ C++ C C #include<pic.h> C static volatile unsigned char 0x01; static volatile unsigned char 0x02; static volatile unsigned cha

C PICC C++ C++ C C #include<pic.h> C static volatile unsigned char 0x01; static volatile unsigned char 0x02; static volatile unsigned cha CYPOK CYPOK 1 UltraEdit Project-->Install Language Tool: Language Suite----->hi-tech picc Tool Name ---->PICC Compiler Executable ---->c:hi-picinpicc.exe ( Command-line Project-->New Project-->File Name--->myc

More information

Microsoft Word - LMB402CBC-AppNote-V0.1.doc

Microsoft Word - LMB402CBC-AppNote-V0.1.doc LMB402CBC 液晶显示模块应用参考 深圳市拓普微科技开发有限公司 版本描述日期编者 0.1 新版本 2006-02-09 杨军 http://www.topwaysz.com 1 / 1 目录 1 概述 3 2 硬件接口 3 3 软件特性 3 3.1 控制器接口信号说明 3 3.2 模块指令系统 4 4 显示数据存储器的地址 4 5 字符发生器 CGRAM 的地址 5 6 应用举例 5 6.1

More information

电子驿站技术文档

电子驿站技术文档 AT89C2051 中文资料 电子驿站 http:// www.ourmpu.com E-mail: support@ourmpu.com AT89C2051 中文资料 AT89C2051 是美国 ATMEL 公司生产的低电压, 高性能 CMOS 8 位单片机, 片内含 2k bytes 的可反复擦写的只读程序存储器 (PEROM) 和 128 bytes 的随机存取数据存储器 (RAM), 器件采用

More information

Microsoft PowerPoint - chap4.ppt

Microsoft PowerPoint - chap4.ppt 定址方式 定址方式 格式 有效位址 立即資料定址 #data8 暫存器定址 Rn (R0 ~ R7) 直接定址 addr8 addr8 絕對定址 addr11 addr11 長程 ( 絕對 ) 定址 addr16 addr16 ( 暫存器 ) 間接定址 @Ri (@R0 @R1) 或 @DPTR R0 R1 或 DPTR ( 暫存器 ) 相對定址 disp8 PC+ 符號擴展之 disp8 ( 基底

More information

新・解きながら学ぶC言語

新・解きながら学ぶC言語 330!... 67!=... 42 "... 215 " "... 6, 77, 222 #define... 114, 194 #include... 145 %... 21 %... 21 %%... 21 %f... 26 %ld... 162 %lf... 26 %lu... 162 %o... 180 %p... 248 %s... 223, 224 %u... 162 %x... 180

More information

逢 甲 大 學

逢    甲    大    學 論 車 Auto Vehicle 立老 磊 年 老 立老 了 見 老 了不 料 利 了 識 更了 力量! i 車. 車 利 89c51 來 流. 令. 車 8051 類 車利 車 ii Abstract The goal of this thesis is to design a small auto vehicle by using IC as its control center. Our auto

More information

FY.DOC

FY.DOC 高 职 高 专 21 世 纪 规 划 教 材 C++ 程 序 设 计 邓 振 杰 主 编 贾 振 华 孟 庆 敏 副 主 编 人 民 邮 电 出 版 社 内 容 提 要 本 书 系 统 地 介 绍 C++ 语 言 的 基 本 概 念 基 本 语 法 和 编 程 方 法, 深 入 浅 出 地 讲 述 C++ 语 言 面 向 对 象 的 重 要 特 征 : 类 和 对 象 抽 象 封 装 继 承 等 主

More information

Microsoft Word - Ö¸Á.doc

Microsoft Word - Ö¸Á.doc 指令集说明 注 由于资源大小问题 其中以下几款 MCU 只有 62 条指令 其余均为 63 条指令 HT48CA0/HT48RA0A 无 RETI 指令 HT48R05A-1 无 TABRDL 指令 指令寻址方式有下面 5 种 立即寻址 此一寻址法是将立即的常数值紧跟在运算码 (opcode) 后 例如 MOV A, 33H ADD A, 33H 直接寻址 直接寻址的情況只允许在存储器之间作数据传送

More information

单片机原理及应用实验指导书.doc

单片机原理及应用实验指导书.doc 1 2 3 4...2...4...9...9 AEDK598 MCS51...9 MCS51...10...10...10...10...10...10...11 P1...12...12...12....12...12...13 P3...14...14...14...14...14...14 I/O...15...15...15...15...15...16...17...17...17...17...17...18...19...19

More information

PowerPoint Presentation

PowerPoint Presentation 7.2 并行接口 二. 可编程并行接口芯片 8255A 的功能及其应用 与 CPU 一侧相连的引脚 D0 PA0 ~ ~ ~ ~ ~ D7 PA7 RESET PC7 WR RD PC4 PC3 PC0 A0 PB0 A1 PB7 CS PA 口 PC 口上半部 PC 口下半部 PB 口 A 组 B 组 与 I/O 设备相连的引脚 7.2 并行接口二. 可编程并行接口芯片 8255A 的功能及其应用

More information

R/W

R/W (HD44780 KS0066 ) 3 3 5 6 10 14 HD44780/KS0066 16 2 LCM 8 1 40 4 LCD HD44780/KS0066 HD44100 IC PCB 0.1 CMOS 1. 2. 3. 4. 5. RH60% 6. 1. 2. 3. PCB 3 4. 5. 6. 1. 280 C 2. 3 4s 3. 4. 5. 3 5 1. 2. IC 3. DC-DC

More information

第十四章 STC单片机比较器原理及实现

第十四章 STC单片机比较器原理及实现 第 14 章 STC 单片机比较器 原理及实现 何宾 2015.02 1 本章主要内容 STC 单片机比较器结构 STC 单片机比较器寄存器组 STC 单片机比较器应用 2 STC 单片机比较器结构 STC15W 系列单片机内置了模拟比较器 对于 STC15W201S STC15W404S, 以及 STC15W1K16S 系 列单片机的比较器内部结构 3 STC 单片机比较器结构 S T C 15W

More information

dfgdafhdafhdafhdafh

dfgdafhdafhdafhdafh 逢 甲 大 學 自 動 控 制 工 程 學 系 專 題 製 作 專 題 論 文 數 位 式 電 子 秤 之 研 製 Design Study of Digital Electronic Weighing Sensor 指 導 教 授 : 賴 啟 智 學 生 : 劉 人 豪 俞 仲 維 中 華 民 國 九 十 八 年 四 月 二 十 二 日 ii . 誌 謝 本 文 承 蒙 賴 啟 智 老 師 指 導,

More information

1.1 ML_ONOFF = 1 Q 3 Q 8 C 0.3V M 2 L 1 ML_ONOFF = 0 Q 3 Q 8 C 1. + R31 VCC R21 10K ML_ONOFF R15 0:off 1:on 1K Green Light VCC=5V L1 Q VDD=12V C

1.1 ML_ONOFF = 1 Q 3 Q 8 C 0.3V M 2 L 1 ML_ONOFF = 0 Q 3 Q 8 C 1. + R31 VCC R21 10K ML_ONOFF R15 0:off 1:on 1K Green Light VCC=5V L1 Q VDD=12V C AUTOMATIC TROLLEY H K Hwang K K Chen J-S Lin S-C Wang M-L Li C-C Lin W-B Lin Dept. Of Electrical Engineering Far East College ABSTRACT This paper proposes an automatic trolley which can move automatically

More information

Microsoft Word - ~ doc

Microsoft Word - ~ doc EEPROM 功能使用方法 1 适用产品 : 1.1 SM39R16A2/ SM39R12A2/ SM39R08A2 1.2 SM39R4051/ SM39R2051 1.3 SM39R04G1/ SM39R02G1 2 EEPROM 功能概述 : 2.1 使用 code flash 仿真为 Internal EEPROM, 在程序执行时, 可将 code flash 作为 data flash 储存数据使用

More information

Microsoft Word - SC16C550应用实例.doc

Microsoft Word - SC16C550应用实例.doc SCC0 应用实例. 概述 SCC0 是 PHILIPS 推出的一款高性能的 UART 芯片, 其具有 字节 FIFO 和 IrDA 编 / 解码模块 本文将结合电路和程序演示如何使用 SCC0 接收和回送 UART 数据 读者可以根据图 制作 SCC0 的 DEMO 版 ; 在 KEIL C 开发环境下, 可利用 PVRD 的 SOFTICE 功能, 方便调试 SCC0 的各种功能. 电路分析 图

More information

JLX

JLX PRODUCT:LCD MODULE. Model No.: JLX177-006 Product Type: 1.77 inch QVGA TFT Modoule. 产品规格书 晶联讯研发研发部 : Written By Checked By Approved By 客户名称 : 结构电子核准 地址 : 深圳市宝安区西乡宝安大道东华工业区 A3 栋 6 楼电话 :0755-29784961 Http://www.jlxlcd.cn

More information

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 月 3 日 1 1 INPUTOUTPUT 1 InputOutput 题目描述 用 cin 输入你的姓名 ( 没有空格 ) 和年龄 ( 整数 ), 并用 cout 输出 输入输出符合以下范例 输入 master 999 输出 I am master, 999 years old. 注意 "," 后面有一个空格,"." 结束,

More information

2005.book

2005.book ...4... 4... 7...10... 10... 10... 10... 10... 11... 11 PCC... 11 TB170... 12 /... 12...13... 13 BP150 / BP151 / BP152 / BP155... 14...15... 15... 15... 15... 15... 15... 15... 16 PS465 / PS477... 17 PS692

More information

<4D F736F F D20B5A5C6ACBBFAD4ADC0EDD3EBD3A6D3C3BCB B3CCD0F2C9E8BCC65FB5DA33B0E65F2DD6D5B8E52D4E65772DBFB1CEF3B1ED2DB3F6B0E6C9E72E646F6378>

<4D F736F F D20B5A5C6ACBBFAD4ADC0EDD3EBD3A6D3C3BCB B3CCD0F2C9E8BCC65FB5DA33B0E65F2DD6D5B8E52D4E65772DBFB1CEF3B1ED2DB3F6B0E6C9E72E646F6378> 单片机原理与应用及 C51 程序设计 ( 第 3 版 )- 终稿 -New 勘误表 1. P18 页 11 行原来 : 汇编语言 机器语言 功能 MOV AL,01H 1011 0000 0000 0011B ; 把 01 送入累加器 A ADD AL,02H 0000 0100 0000 0101B ;02 与 A 中内容相加, 结 果存入 A HLT 11110100B ; 停止操作 汇编语言

More information

第一章

第一章 单片机原理 STC15F2K60S2 微机原理与单片机接口技术复习要点 第一章微型计算机概述 ( 了解概念 ) 1.1.2 微型计算机基本构成 ( 基本结构由哪些部分构成 ) 1.1.3 单片微型计算机简介 ( 什么是单片机, 单片机的结构及各个部分的功能, 常见的单片机有哪些 ) 1>. 微型计算机基本构成 : 微处理器, 存储器 (ROM RAM) 与输入输出接口 (I/O 接口 ) 及外部设备及连接他们的系统总线组成

More information

新版 明解C++入門編

新版 明解C++入門編 511!... 43, 85!=... 42 "... 118 " "... 337 " "... 8, 290 #... 71 #... 413 #define... 128, 236, 413 #endif... 412 #ifndef... 412 #if... 412 #include... 6, 337 #undef... 413 %... 23, 27 %=... 97 &... 243,

More information

Microsoft Word - 新1-3.doc

Microsoft Word - 新1-3.doc 模块三 80C51 的指令系统和程序设计 (1) 了解 80C51 指令系统的构成 (2) 掌握 80C51 单片机的寻址方式 (3) 掌握 80C51 单片机的各种指令及其应用 (4) 掌握汇编语言程序设计方法, 为以后实际控制系统的程序设计奠定基础 3.1 80C51 指令系统概述 对于任何一台计算机, 如果只有硬件 ( 称为裸机 ), 而没有软件 ( 即程序 ) 的支持是不能工作的 单片机也不例外,

More information

Ⅰ Ⅱ 2 Ⅲ 2 Ⅳ 耀

Ⅰ Ⅱ 2 Ⅲ 2 Ⅳ 耀 面 向 2 世 纪 高 等 学 校 计 算 机 类 专 业 十 一 五 规 划 教 材 单 片 机 原 理 及 接 口 技 术 ( 第 二 版 ) 余 锡 存 曹 国 华 编 著 西 安 电 子 科 技 大 学 出 版 社 2 0 0 7 Ⅰ Ⅱ 2 Ⅲ 2 Ⅳ 耀 .,, 0,.., : ()0 :0 2 9; (2), 555.54 5 500 50 5 0.5, 555.5=50 2

More information

PowerPoint 演示文稿

PowerPoint 演示文稿 STC 单片机比较器原理及实现 主讲 : 何宾 Email:hebin@mail.buct.edu.cn 2016.03 STC 单片机比较器结构 STC15W 系列单片机内置了模拟比较器 对于 STC15W201S STC15W404S, 以及 STC15W1K16S 系列单片机的比较器内部结 构 STC 单片机比较器结构 从图中可以看出, 比较器正端输入 CMP+ 的输入电压来自单片机的 P5.5

More information

C语言的应用.PDF

C语言的应用.PDF AVR C 9 1 AVR C IAR C, *.HEX, C,,! C, > 9.1 AVR C MCU,, AVR?! IAR AVR / IAR 32 ALU 1KBytes - 8MBytes (SPM ) 16 MBytes C C *var1, *var2; *var1++ = *--var2; AVR C 9 2 LD R16,-X ST Z+,R16 Auto (local

More information

PowerPoint 簡報

PowerPoint 簡報 微算機原理與實驗 (UEE 2301/1071 ) Chap 5. MCS-51 Addressing Modes 宋開泰 Office:EE709 Phone:5731865( 校內分機 :31865) E-mail:ktsong@mail.nctu.edu.tw URL:http://isci.cn.nctu.edu.tw 1 Addressing Modes Addressing mode is

More information

MPC89LE51_52_53_54_58_515

MPC89LE51_52_53_54_58_515 5 8 bit micro controller 1 特性...2 2 引脚...3 2.1 引脚图...3 2.1 引脚定义...4 3 方框图...6 4 特殊功能寄存器...7 辅助寄存器 AUXR 和 AUXR1...8 5 存储器...9 5.1 RAM...9 MPC89x54/58/515 RAM 空间 (00 7F 可直接或间接寻址 )...9 MPC89x51/5 2/53 RAM

More information

M8Rxxx 指令集说明 Version 年 11 月 上海磐芯电子有限公司 SHANGHAI MASSES ELECTRONIC Co., Ltd. 本公司保留对产品在可靠性, 功能和设计方面的改进作进一步说明的权利 说明文档的更改, 恕不另行通知

M8Rxxx 指令集说明 Version 年 11 月 上海磐芯电子有限公司 SHANGHAI MASSES ELECTRONIC Co., Ltd. 本公司保留对产品在可靠性, 功能和设计方面的改进作进一步说明的权利 说明文档的更改, 恕不另行通知 M8Rxxx 指令集说明 Version 1.04 2014 年 11 月 上海磐芯电子有限公司 SHANGHAI MASSES ELECTRONIC Co., Ltd. 本公司保留对产品在可靠性, 功能和设计方面的改进作进一步说明的权利 说明文档的更改, 恕不另行通知 修正记录 版本 日期 描述 Ver1.02 2014-5-15 补全指令说明 Ver1.03 2014-10-8 勘误 Ver1.04

More information

chap07.key

chap07.key #include void two(); void three(); int main() printf("i'm in main.\n"); two(); return 0; void two() printf("i'm in two.\n"); three(); void three() printf("i'm in three.\n"); void, int 标识符逗号分隔,

More information

单片机学习教程

单片机学习教程 . 89S51 1. 2.p1 3.8 3 4.8 3. 1. 0-F 2. 0000 0255. 1. : BB 2. : ( --- ) : :. 1. 2..232.I 2 C 1. X24C02 MCS-51 2. : 22H 24C02 50H 3. : ; 8 4. :I2C. / 1. 1 2. 2. 1. 1. 2. 2.. 1. 1: 2. 2: 3. 3 1 LED 1 89S51

More information

Microsoft Word - em78 sub program.doc

Microsoft Word - em78 sub program.doc 一 二进制数转换为 ASCⅡ 码 将一个字节的二进制数转换为两位 16 进制数的 ASCⅡ 码 main: mov a,@0x9f ; 二进制数为 0x9f mov 0x30,a ; 二进制数存入 0x30 mov a,@0x02 mov 0x10,a ;0x10 中存放转换次数 mov a,@0x31 mov 0x04,a ;0x04 中为转换后数据存放地址 mov a,0x30 B1: ; 取

More information

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double

More information

C/C++ - 函数

C/C++ - 函数 C/C++ Table of contents 1. 2. 3. & 4. 5. 1 2 3 # include # define SIZE 50 int main ( void ) { float list [ SIZE ]; readlist (list, SIZE ); sort (list, SIZE ); average (list, SIZE ); bargragh

More information

Microsoft PowerPoint - chap3.ppt

Microsoft PowerPoint - chap3.ppt MCS-51 CPU 的規劃模式 位元組位址 1F 18 17 10 0F 08 07 06 05 04 03 02 01 00 通用資料暫存器 暫存器庫 3 暫存器庫 2 暫存器庫 1 R7 R6 R5 R4 R3 R2 R1 R0 內部 RAM 位元組位址 暫存器庫 0 F0 F7 F6 F5 F4 F3 F2 F1 F0 B E0 E7 E6 E5 E4 E3 E2 E1 E0 ACC D0

More information

??????????????????

?????????????????? 2011 3 1 a)8088/8086 b) 1 2 3 -(2) - 48 (48 6) 1 2 http://www.zlgmcu.com/home.asp http://hx51.com/index.asp http://www.daqchina.net/daqchina/chips DAQCHINA HTTP://WWW.QFMCU.COM/ HTTP://MYGO.7I24.COM/ HTTP://WWW.HSEDA.COM/

More information

TSINGTEK DISPLAY CO.,LTD LCD CONTROLLER & DRIVER ST7920 OR EQUIVALENT (f) 639 2A f B1

TSINGTEK DISPLAY CO.,LTD LCD CONTROLLER & DRIVER ST7920 OR EQUIVALENT (f) 639 2A f B1 TSINGTEK DISPLAY CO.,LTD LCD CONTROLLER & DRIVER ST7920 OR EQUIVALENT 588 4 1 0571-85121224 85121742 85121304(f) 639 2A095 0571-88256346 89902095 f B1618 010-62051209 62000662 62568913 82036512 f http://www.tsingtek.com

More information

MSP430ϵÁе¥Æ¬»úµÄÖ¸Áîϵͳ.pps [¼æÈÝģʽ]

MSP430ϵÁе¥Æ¬»úµÄÖ¸Áîϵͳ.pps [¼æÈÝģʽ] 作者 : 利尔达 MSP430 系列单片机的指令系统 1 CPU 内核组成 : 16 位的 (ALU) 算术运算单元 16 个寄存器 (PC SP SR R4~R15) 指令控制单元 2 存储器组织结构 3 外围模块寄存器地址 它们被分配在相应的字模块或字节模块当中 分配在 00-FFH 中为字节, 分配在 100-1FFH 中为字 4 寻址模式 : 5 指令格式 : 1) 书写格式标号指令助记符源操作数,

More information

<4D F736F F D203034CAB5D1E9CBC D20B5C4494F20BDD3BFDACAB5D1E92E646F63>

<4D F736F F D203034CAB5D1E9CBC D20B5C4494F20BDD3BFDACAB5D1E92E646F63> 实验四 ARM 的 I/O 接口实验 一 实验目的 1. 了解 S3C44B0X 的通用 I/O 接口 2. 掌握 I/0 功能的复用并熟练的配置, 进行编程实验二 实验设备 1. EL-ARM-830 教学实验箱,PentiumII 以上的 PC 机, 仿真器电缆 2. PC 操作系统 WIN98 或 WIN2000 或 WINXP,ARM SDT2.5 或 ADS1.2 集成开发环境, 仿真器驱动程序

More information

Microsoft Word - 第1章 MCS-51单片机概述.docx

Microsoft Word - 第1章 MCS-51单片机概述.docx 单片机 C 语言入门 ( 修订版 ) 作者 : 华清远见 第 1 章 MCS-51 单片机概述 本章目标 单片微型计算机简称单片机, 又称为微控制器 (MCU), 是微型计算机的一个重要分支 单片机是 20 世纪 70 年代中期发展起来的一种大规模集成电路芯片, 将 CPU RAM ROM I/O 接口和中断系统等集 成于同一硅片内 20 世纪 80 年代以来单片机发展迅速, 各类新产品不断涌现,

More information

从MCS51向AVR的快速转换.PDF

从MCS51向AVR的快速转换.PDF MCS51 AVR MCS51 AVR ATMEL AVR RISC MCS51 AVR 1 MHZ 1MIPS 8MHZ AVR 224MHZ MCS51 FLASH EEPROM ISP WatchDog AVR MCS51 AT90S1200/2313 AT89C1051/2051 AT90S4414/8515 AT89C51/52 PCB / AVR C ICCAVR60 AVR C IAR

More information

<4D F736F F F696E74202D BDE1B9B9BBAFB3CCD0F2C9E8BCC D20D1ADBBB7>

<4D F736F F F696E74202D BDE1B9B9BBAFB3CCD0F2C9E8BCC D20D1ADBBB7> 能源与动力工程学院 结构化编程 结构化程序设计 循环 循环结构 确定性循环 非确定性循环 I=1 sum=sum+i I = I +1 陈 斌 I>100 Yes No 目录 求和 :1+2+3++100 第四节循环的应用 PROGRAM GAUSS INTEGER I, SUM 计数器 SUM = 0 DO I = 1, 100, 1 SUM = SUM + I print*, I, SUM DO

More information

MPC89LE51_52_53_54_58_515

MPC89LE51_52_53_54_58_515 8051 内核 - 单片机 MPC89LE51_52_53_54_58_515 規格书 北京菱电科技有限公司 TEL:010-82674978 版本 : A1.0 This document contains information on a new product under development by Megawin. Megawin reserves the right to change

More information

93C46串行EEPROM数据读写

93C46串行EEPROM数据读写 一 \ 实验目的 93C46 串行 EEPROM 数据读写 1 学会 93C46 的操作指令, 掌握 93C46 读 / 写程序的编写 2 掌握 93C46 与单片机的接口方式二 实验说明 93C46/56/66 是 1K/2K/4K 位的串行电可擦写的 EPROM 93C46 的 1K 位 EPROM, 可以按 128 字节排列, 也可以 64 字节排列 93C46 芯片有 8 脚, 当 ORG

More information

AT89C2051中文资料.doc

AT89C2051中文资料.doc 图形点阵液晶显示模块使用手册 TG12864C(L) 广州捷胜吉电子科技 地址 : 广州市天河区天河路 561# 新赛格电子城 B2226 电话 :(020)33550997 13829772038 网址 :WWW.GZJSJDZ.COM E-mail:CJKD@21CN.COM 目 录 ( 一 ) 概述 (1) ( 二 ) 外形尺寸图 (1) ( 三 ) 模块主要硬件构成说明 (2) ( 四 )

More information

SST SPAC SST SoftICE SST89C5x/SST89x554RC /564RD /SST89x516/5xRD / SoftICE SoftICE MCU SoftICE SS

SST SPAC SST SoftICE SST89C5x/SST89x554RC /564RD /SST89x516/5xRD / SoftICE SoftICE MCU SoftICE SS SST SoftICE SST89C5x/SST89x554RC /564RD /SST89x516/5xRD2 1...2 1.1...2 1.2...2 1.3 /...2 2 SoftICE...2 3 SoftICE MCU...2 4 SoftICE...3 4.1 SST BootLoader SOFTICE...3 4.2 SoftICE SST MCU...6 5 SoftICE...7

More information

Microsoft Word - DPJBXZXKFJMKSJ01.doc

Microsoft Word - DPJBXZXKFJMKSJ01.doc 第 章 单片机基础知识. 概述.. 单片机发展历程单片机专业名称为 Micro Controller Unit( 微控制器件 ), 是由 Intel 公司发明的, 最早的系列是 MCS-48, 后来有了 MCS-5 常说的 5 系列单片机就是 MCS-5(Micro Controller System), 这是一种 8 位的单片机 后来 Intel 公司把它的核心技术转让给世界上很多小公司, 所以就有许多公司生产

More information

Microsoft PowerPoint - chap2.ppt

Microsoft PowerPoint - chap2.ppt 基本程式設計觀念 人 自然語言 ( 中文 英文...) 高階語言 (C C++ Java) 組合語言 (8051 或是 80x86) 機器語言 (8051 或是 80x86) 機器 林銘波編著 --- 全華科技圖書公司 2.1 計算機的階層式結構 應用程式 ( 或語言 ) 高階語言組合語言硬體 林銘波編著 --- 全華科技圖書公司 2.2 儲存程式計算機 資料輸入 中央處理器讀取 / 寫入控制 CPU

More information

Hz 10MHz 0.5V 5V 0.01% 10s 2 0.5V 5V 1Hz 1kHz 10% 90% 1% 3 1Hz 1MHz 1% EPM7128SLC84-15 LM361 LM361 Zlg

Hz 10MHz 0.5V 5V 0.01% 10s 2 0.5V 5V 1Hz 1kHz 10% 90% 1% 3 1Hz 1MHz 1% EPM7128SLC84-15 LM361 LM361 Zlg 1 1 a. 0.5V 5V 1Hz 1MHz b. 0.1% 2 : a. 0.5V 5V 1Hz 1MHz b. 0.1% (3) a. 0.5V 5V 100 s b. 1% 4 1 10 5 1MHz 6 1 2 1 0.1Hz 10MHz 0.5V 5V 0.01% 10s 2 0.5V 5V 1Hz 1kHz 10% 90% 1% 3 1Hz 1MHz 1% EPM7128SLC84-15

More information