首页资源分类嵌入式开发其它 > 合泰单片机 AD Flash HT66Fxx_应用实例程序

合泰单片机 AD Flash HT66Fxx_应用实例程序

已有 456409个资源

下载专区

上传者其他资源

文档信息举报收藏

标    签: 合泰单片机ADFlashHT66Fxx实例程序

分    享:

文档简介

合泰_单片机_AD_Flash_HT66Fxx_应用实例程序

文档预览

5-1 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5 进阶实验篇 经过基础实验篇的洗礼,相信读者对于HT66F50单片机及其周边单元、程序写 作技巧以及开发环境的使用,都已经有初步的认识!程序其实要多写、多错、多除 错,然后方能由错误中累积经验,增强本身的逻辑观念及程序写作功力。延续上一 5 章的学习成果,本章将继续介绍几个更深入的实验,DC Motor控制、LCD接口、 LCM模块、多颗七段显示器与点矩阵LED扫描、TM接口应用…等等,另外,除了 HT66F50内建E2PROM的读写控制外,有关I2C-Bus及MicroWire-Bus E2PROM的 读写本章也将涉猎。通过这些实验,相信必定能让读者对于HT66Fx0单片机的应用 能有更深一层的了解!本章的实验内容包括: 5-1 直流马达控制实验 5-2 马表-多颗七段显示器控制实验 5-3 静态点矩阵 LED 控制实验 5-4 动态点矩阵 LED 控制实验 5-5 LCD 界面实验 5-6 LCM 字型显示实验 5-7 LCM 自建字型实验 5-8 LCM 与 4×4 键盘控制实验 5-9 LCM 的 DD/CG RAM 读取控制实验 5-10 LCM 的四位控制模式实验 5-11 比大小游戏实验 5-12 STM 单元脉冲测量与 LCM 控制实验 5-13 ETM“单一脉冲输出”模式与脉冲测量实验 5-14 中文显示型 LCM 控制实验 5-15 半矩阵式键盘与 LCM 控制实验 5-16 HT66F40 内建 E2PROM 内存读写实验 5-17 I2C 接口 E2PROM 读写控制实验 5-18 MicroWire-BUS 接口 E2PROM 读写控制实验 5-2 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-1 直流马达控制实验 5-1-1 目 的: 本实验将利用脉冲宽度调制(PWM)的技巧,让直流马达呈现不同的转速; 辅以按键的搭配使用,让使用者控制直流马达加速、减速与转向。 5-1-2 学习重点: 通过本实验,读者应了解如何使用以PWM方法控制直流马达转速的快慢;同 时,对于HT66F50 ETM单元的“PWM Output Mode”及其跨脚位功能(Cross-Pin Function)的使用应更加熟悉。 5-1-3 电路图: 5 PS:若使能PA[2:0]Pull-high功能,则三个10kΩ电阻可省略。 【图5-1-1】直流马达控制电路 “马达(Motor;又称电动机)”被广泛运用于各种电器用品,其可将电能转 换为机械能,以驱动机械作旋转运动、直线运动或振动。作旋转运动的马达,其应 用更遍及各种行业、办公室、家庭等,生活周遭几乎随处可见;作直线运动的马达 称为线型马达(Linear Motor),适用于半导体工业、自动化工业、工具机、产业 机器及仪器工业等。马达构造大致上包含两大单元:一是“转子(Rotor;或电枢 Armature)”为马达旋转的部份,材质为永久磁铁、线圈(外接电源)、导线(无 外接电源)特殊形状的导磁材料;其二为“定子(Stator;场绕组Field)”,定子 则是固定不动的部分,主要是提供周围的磁场,材质为永久磁铁或是线圈。虽然马 达的种类相当多,不过其基本操作原理都相同,基本上都是利用电流流过定子产生 磁场,当转子也通上电流时由于切割定子所产生的磁力线而生成旋转扭矩造成电动 机转子的转动。电动马达是利用电磁感应方式,以同性磁场互斥原理,推动转轴旋 第五章 进阶实验篇 5-3 转,而将电能转换成为机械能。 马达如依其使用的目的来分类,则种类相当繁杂,一般马达因其使用的电源有 交流及直流的差异,而有所谓的交流马达和直流马达,在使用马达前需先了解其使 用的电源是直流电还是交流电,如果是交流电,尚需考虑它是三相还是单相的交流 电,接错电源会导致不必要的损失和危险。 (a) (b) 【图 5-1-2】直流马达工作原理 (c) 【图5-1-2】是直流马达工作示意图:(a)当线圈通电后,转子周围产生磁场, 转子的左侧被推离左侧的磁铁,并被吸引到右侧,从而产生转动;(b)转子依靠 惯性继续转动;(c)当转子运行至水平位置时电流变换器将线圈的电流方向逆转, 线圈所产生的磁场也同时逆转,使这一过程得以重复。如此说来,直流马达的控制 似乎只在于电压(或说是电流)的提供与否,但若单单仅是如此则只能控制其转动 或停止,并无法控制其转速!直流马达转动速度的快慢,是由马达的电动势大小来 5 决定,其转动方向则取决于电压极性。一般转速大小和马达两端电压成线性,其电 压愈大转速愈快,反之则愈小。在电路上以多级的电压来控制马达的转速虽属可行; 但若转速变化是多样、精细的控制时,这样的设计方式似乎有些不切实际! 直流马达一般是以“脉冲宽度调制(Pulse Width Modulation;PWM)”方式 来达成转速的控制,其原理如【图5-1-3】所示,图中TOn(高电平部份)是马达动 作(Active)时间,TOff(低电平部份)则为马达停止(Inactive)时间,两者之和 即为一“PWM周期(PWM Period)”。虽然流经马达的电压不断在ON-OFF之间 切换,但马达线圈为电感元件,流过电感元件的电流为电压的积分,有一个类似“惯 性”的作用,实际流经马达电流变化不大,其正比于【图5-1-3】中脉冲的面积和。 因此当使用者想降低马达转速时,只要减少动作的时间(TOn)、增加停止的时间 (TOff)、并保持周期不变,即可降低平均电流,如【图5-1-3】所示的PWM1波形; 反之,若想加快马达的转速,则需要加长动作的时间、缩短停止的时间、并维持周 期不变,即可升高平均电流,如【图5-1-3】所示的PWM2波形。由于改变转速是 通过改变动作的时间比例,也就是一周期的输出波形中,处于高电平状态的相对时 间宽度(Width),因此这种的控制方式称作“脉冲宽度调制”;而动作时间在PWM 周期所占的比例称为“Duty Cycle(占空比)”,即 。 【图5-1-3】中的脉冲宽度变化需要相当的快,频率经常超过1kHz!因此,若要精 确控制直流马达的驱动信号,最好使用具有内嵌PWM输出功能的微处理器。 5-4 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 【图 5-1-3】改变直流马达转速的 PWM 波形 在了解以PWM方式改变马达转速之后,接下来要探讨的是直流马达的正、反 转控制,【图5-1-2】中若将电压的极性反接就可产生方向相反的磁场变化,进而 使转子改变旋转方向达到反转的目的。【图5-1-4】为直流马达的正、反转控制的 示意图:(a)未供电直流马达,故为停止状态;(b)S1、S4开关On,马达左侧为正、 右侧为负,开始转动;(c)S2、S3开关On,马达右侧为正、左侧为负,转动方向与 (b)相反。 5 (a) (b) 【图 5-1-4】直流马达的正、反转控制 (c) 选用马达时,必须注意其工作电压,一般常见的直流马达电源规格为DC-12V、 DC-24V;另外还要知道“输出转矩(Toque)”的大小(单位:g.cm、k.gm), 以及转速(Rotate Per Minute;RPM),最好能取得代表马达特性的曲线作为选 用时的参考。【图5-1-5】为典型的DC-12V永磁式(PM)马达的特性曲线图,其 横坐标为马达输出转矩,纵坐标则包括转速、电流、输出功率、效率等四条曲线。 观察【图5-1-5】可知这颗马达最大效率约为40%,此时马达输出转矩为100g.cm、 输出功率为2.1瓦特、转速为2000rpm,而所需电流则为440mA。由图中也可看出: 电流供应量越大,输出转矩越大;而转数越高,输出转矩越小,而且大致呈一线性 关系。 第五章 进阶实验篇 5-5 【图 5-1-5】直流马达的特性曲线 马达的规格与外观琳琅满目,在此实在无法一一列出说明,本实验仅就一般常 见的小型5V直流马达为例介绍其控制方式。为了能使单片机直接控制马达的正、 反转,可将【图5-1-4】中S1~S4开关以Q1~Q4取代,并在晶体管的C-E(集极射极)接面并联了一颗二极管(Diode),这主要是因为马达为电感元件,当马达 停止转动的瞬间会产生反向的感应电动势( ),此一电压可能烧毁晶体管 甚至对单片机造成损害,故以二极管提供此反向感应电动势的放电回路,以避免瞬 5 间大电压的产生而损坏电路,以确保电路与芯片的安全;这类用在对电感性负载保 护的二极管一般称为“续流二极管(Free-Wheeling Diode)”。如【图5-1-1】是 常见的直流马达控制电路,请读者观察Q1~Q4晶体管与马达的回路是否很像英文 字母的“H”?因此,此一电路结构被称为“H-Bridge”。在控制过程中,必须注意 不可让Q1与Q3(或Q2与Q4)同时导通,请参考【图5-1-1】,此现象发生在PC0、 PC1输出同时为“1”时,这将导致VCC至地(Ground)之间呈现近乎短路的现象, 造成电流瞬间的暴增,可能造成的结果是晶体管的烧毁,或电源因电流不足造成电 压瞬间下降影响了单片机的正常操作。 HT66F50 ETM单元的PWM输出功能,曾经在【实验4-13】运用来控制LED的 亮度;本实验仍采用ETM单元的PWM输出模式,并配合Cross-Pin Function与四个 3055晶体管组成的H-Bridge结构,控制直流马达的加速、减速与转向。有关ETM 单元的详细说明请参考【2-5-3节】,Cross-Pin Function请参阅【2-5节】;在此 仅将本实验相关控制寄存器简列于【表5-1-1】。 【2-5-3 节】 TM1C0 TM1C1 TM1C2 TM1DL TM1DH TM1AL 【表 5-1-1】本实验相关控制寄存器 T1PAU T1AM1 T1CK2 T1AM0 T1CK1 T1AIO1 T1CK0 T1AIO0 T1ON T1RP2 T1AOC T1APOL T1BM1 T1BM0 T1BIO1 T1BIO0 T1BOC TM1D[7:0] - T1BPOL TM1A[7:0] T1RP1 T1CDN T1PWM1 T1RP0 T1CCLR T1PWM0 TM1D[9:8] 5-6 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 TM1AH TM1BL TM1BH 【2-6-9 节】 TMPC0 Bit T1ACP0 7 T1BCP2 6 - TM1B[7:0] - T1BCP1 T1BCP0 - 5 4 3 5-1-4 程序及流程图: TM1A[9:8] TM1B[9:8] - T0CP1 T0CP0 2 1 0 5 程序5-1 ETM PWM Output Mode直流马达控制实验 1 ;PROGRAM:5-1 PROGRAM (5-1.PJT) 2009.1104 2 ;FUNCTION: ETM PWM DC MOTOR CONTROL PROGRAM By Steven 3 #INCLUDE HT66F50.INC 4 #INCLUDE 5-1.INC 5 ;============================================================================ ============ 6 MY_DATA .SECTION 'DATA' ;==DATA SECTION== 7 DEL1 DB ? ;DELAY LOOP COUNT1 8 DEL2 DB ? ;DELAY LOOP COUNT2 9 DEL3 DB ? ;DELAY LOOP COUNT3 10 INDEX DB ? ;TABLE INDEX 11 ;============================================================================ ============ 12 MY_CODE .SECTION AT 0 'CODE' ;==PROGRAM SECTION== 13 ORG 00H ;HT-66FX0 RESET VECTOR 14 MOV A,00001000B 第五章 进阶实验篇 5-7 15 MOV CP0C,A ;Disable Comparator 0 Function 16 MOV CP1C,A ;Disable Comparator 1 Function 17 CLR ACERL ;Digital I/O Pin is assigned as a I/O line 18 CLR SCOMEN ;Disable LCD Function 19 CLR SEG_PORTC ;CONFIG SEG_PORT AS OUTPUT PWM MODE 20 MOV A,00000111B 21 ORM A,PAC ;CONFIG PA[2:0] AS I/P MODE 22 ORM A,PAPU ;ENABLE PA[2:0] PULL-HIGH 23 MOV A,00010000B ;CONTROL TP1B_0 AS TP1B FUNCTION 24 MOV TMPC0,A 25 CLR TM1C0 ;fINT=fSYS/4 (4MHz/4) 26 MOV A,10101001B ;SET ETPU TP1A AS PWM MODE AND 27 MOV TM1C1,A ;COUNTER IS CLEARDE BY TP1CCRA COMPARE MATCH 28 MOV A,10101000B ;SET ETPU TP1B AS PWM MODE 29 MOV TM1C2,A 30 MOV A,LOW 1024-1 ;SET PWM PERIOD 1023/fINT 31 MOV TM1AL,A 32 MOV A,HIGH 1024-1 33 MOV TM1AH,A 34 MOV A,11111100B ;SET PC0,PC1 TO 0 35 ANDM A,PC 36 ANDM A,PCC ;CONFIG PC0,PC1 O/P MODE 5 37 CLR INDEX ;SET INDEX=0 38 SET T1ON ;START ETPU 39 MAIN: 40 MOV A,INDEX 41 CALL TRANS_SEG ;GET 7 SEG CODE 42 MOV SEG_PORT,A ;DISPLAY 43 MOV A,INDEX 44 ADD A,TAB_PWM 45 MOV TBLP,A 46 TABRDL TM1BL ;GET DUTY CYCLE 47 MOV A,TBLH 48 MOV TM1BH,A ;SET TP1CCRB 49 CALL DELAY ;DELAY 0.25 SEC 50 WAIT_KEY: 51 SNZ SPUP_SW ;SPEED UP SW PRESSED? 52 JMP SPEED_UP ;YES,JUMP TO SPEED_UP 53 SNZ SPDN_SW ;SPEED DOWN PRESSED? 54 JMP SPEED_DN ;YES,JUMP TO SPEED_DOWN 55 SZ DIRE_SW ;SPEED DIRECTION SW PRESSED? 56 JMP WAIT_KEY ;NO,KEEP CURRENT SPEED 57 SNZ T1BCP0 ;WHICH STATE THE DC MOTOR 58 JMP DIRECTION ;NO,JMP TO SPEED_DIRECTION 59 CLR T1BCP0 60 CALL DELAY ;PREVENT Q1-Q3(OR Q2-Q4) TURN AT THE SAME 5-8 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 TIME 61 SET T1BCP1 ;YES,CHANGE DC MOTOR'S STATE 62 JMP MAIN ;JUMP TO MAIN 63 DIRECTION: 64 CLR T1BCP1 ;NO,CHANGE DC MOTOR'S STATE 65 CALL DELAY ;;PREVENT Q1-Q3(OR Q2-Q4) TURN AT THE SAME TIME 66 SET T1BCP0 67 JMP MAIN ;JUMP TO MAIN 68 SPEED_DN: 69 SZA INDEX ;IS INDEX=0? 70 DEC INDEX ;NO,INDEX=INDEX-1 71 JMP MAIN ;JUMP TO MAIN 72 SPEED_UP: 73 INCA INDEX ;ACC=INDEX+1 74 SUB A,10 ;ACC>10? 75 SNZ C ;YES. 76 INC INDEX ;NO,INCREASE INDEX BY 1 77 JMP MAIN ;JUMP TO MAIN 78 ;============================================================================ ============ 5 79 ; RETURN THE TABLE VALUE INDEX BY A 80 ;============================================================================ ============ 81 TRANS_SEG PROC 82 ADDM A,PCL 83 RET A,00111111B ;0 84 RET A,00000110B ;1 85 RET A,01011011B ;2 86 RET A,01001111B ;3 87 RET A,01100110B ;4 88 RET A,01101101B ;5 89 RET A,01111101B ;6 90 RET A,00000111B ;7 91 RET A,01111111B ;8 92 RET A,01100111B ;9 93 TRANS_SEG ENDP 94 ;============================================================================ ============ 95 ; PROC : DELAY 96 ; FUNC : DEALY ABOUT 25*10mS @fSYS=4MHz 97 ; REG : DEL1,DEL2,DEL3 98 ;============================================================================ ============ 99 DELAY PROC 100 MOV A,25 101 MOV DEL1,A ;SET DEL1 COUNTER 第五章 进阶实验篇 5-9 102 DEL_1: MOV A,30 103 MOV DEL2,A ;SET DEL2 COUNTER 104 DEL_2: MOV A,110 105 MOV DEL3,A ;SET DEL3 COUNTER 106 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 107 JMP DEL_3 108 SDZ DEL2 ;DEL2 DOWN COUNT 109 JMP DEL_2 110 SDZ DEL1 ;DEL1 DOWN COUNT 111 JMP DEL_1 112 RET 113 DELAY ENDP 114 ORG LASTPAGE 115 TAB_PWM: ;TM1B TABLE 116 DC 100 ;LOW 117 DC 200 118 DC 300 119 DC 400 120 DC 500 121 DC 600 122 DC 700 123 DC 800 124 DC 900 5 125 DC 1000 ;HIGH 126 END 程程序序解解说说:: 4 载入”5-1.INC”定义档,其内容请参考随书光盘中的档案。 7~10 依序定义变量地址。 13 声明内存地址由 000h 开始(HT66Fx0 复位向量)。 14~18 关闭 CP0、CP1 与 LCD 功能,并设定 ADC 脚位输入为 I/O 功能。 19~22 将 SEG_PORT 定义成输出模式,定义 PA[2:0]为输入模式并使能其 Pull-high 功能。 23~24 定义 TP1B_0、TP1B_1 为 TP1B 功能。 25~29 定义 TM1C0、TM1C1、TM1C2 控制寄存器: T1CK[2:0]:000,设定 fINT=fSYS/4; T1AM[1:0]:10,设定为 PWM 或 Single Pulse 输出模式; T1AIO[1:0]:10,设定 TP1A 为 PWM Output; T1AOC:1,选择 PWM 输出为 Active High; T1CCLR:0,设定当 TM1D=TM1A 时(即比较器 A 比较匹配时)清除计数器; 5-10 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 T1BM[1:0]:10,设定为 PWM 或 Single Pulse 输出模式; T1BIO[1:0]:10,设定 TP1B 为 PWM Output; 30~33 34~36 T1BOC:1,选择 PWM 输出为 Active High。 设定 PWM 周期为 1023×(fINT-1)。 定义 PC0(TP1B_0)、PC1(TP1B_1)为输出模式,并选择 TP1B 为同相输出。 37~38 清除 INDEX 值,并启动 ETM 开始计数。 40~42 显示目前的转速值(“9”:最快~“0”:最慢)。 43~48 依据 INDEX 值进行查表,并将查表结果存入 TM1BL、TM1BH 寄存器;此举即改 变输出波形的 Duty Cycle,进而达到改变马达转速的目的。 49 延迟 250mS。 51~56 检查加速(Speed_UP)、减速(Speed_DN)与方向(Direction)按键,以判断 是否要改变马达的转速、转向。 57~67 此段是使用者按下方向键(Direction)的处理程序,即正转改反转、或反转改正转 5 的程序;57 行先检查 TP1B_0 是否指定为 TP1B 的 PWM 输出脚位,若是则停止 PWM 输出,恢复为 I/O 脚位功能并输出 Low(请注意在 35 行已将 PC.0 设为“0”), 延迟 250ms 后启动 TP1B_1 的 PWM 输出功能,并回到 MAIN 执行程序。如果 TP1B_0 必非指定为 TP1B 的 PWM 输出脚位,则关闭 TP1B_1 的 PWM 输出功能 并输出 Low(请注意在 35 行已将 PC.1 设为“0”),延迟 250ms 后启动 TP1B_0 的 PWM 输出功能,并回到 MAIN 执行程序。 68~71 此段程序是使用者按下减速键(Speed_DN)的处理程序,首先判断 INDEX 是否为 “0”,若是,代表马达转速已经达到最低指数,维持 INDEX 的值;反之,表示马 达尚有减速空间,将 INDEX 减一以降低转速。 72~71 此段是使用者按下加速键(Speed_UP)的处理程序,首先判断 INDEX 是否为“10”, 若是,代表马达转速已经达到最高指数,维持 INDEX 之值;反之,表示马达尚有加 速空间,将 INDEX 加一以提高转速。 81~93 七段显示器显示码查表子程序。 99~113 DELAY 子程序,延迟 250mS;延迟时间的计算请参考【实验 4-1】。 115~125 TON 时间建表区。 第五章 进阶实验篇 5-11 关于直流马达的PWM控制方式,其实与【实验4-13】中控制LED亮度的原理 差不多,只是针对不同的装置特性要稍微有些不同。关于马达的控制,就必须了解 其特性,马达毕竟是个机械装置,无法在瞬间达到其应有的转速!本实验中只是很 简单的利用按键来控制其转速、转向,读者可以发现当按下按键时,需要一段时间 马达方能达到定速,这就如同惯性一般;同理,由转动而静止时,也是需要一段时 间。而马达由静止启动时,也需要耗费较大的电力。一般精确的马达控制,必须要 考虑加速、减速的问题,有兴趣的读者可以多参考这方面的书籍。此外,在进行本 实验时,可将控制芯片电路与马达的电源分开,可避免电源互相干扰。甚至可以用 光隔离(如PC817、PC847)方式使正电源、地线与控制线全部分开,互不相连, 以避免出现不正常动作。 请读者特别留意【程序5-1】中的转向控制程序片段(57~67行),读者应该 不难发现笔者是以TP1B_0与TP1B_1的脚位功能切换来达成改变马达转向的目 的;在第35行将PC[1:0]设为“00”的作用不仅是在选择TP1B的输出同相(参考【实 验4-13】),其另外一个功能是在保证当TP1B_0、TP1B_1由PWM输出功能转换 为I/O时,PC.0、PC.1的输出状态为Low,以确保马达得以顺利完成转向的变换。 此外,在切换的过程加入了250ms的延迟,其主要目的是避免【图5-1-1】中的Q1-Q3 (或Q2-Q4)晶体管瞬间同时导通,使电流激增而造成电路动作不正常。或许读者 会质疑:“程序明明是先、后以TP1B_0、TP1B_1控制Q1-Q3(或Q2-Q4)的关、 5 开,应该不会有同时导通的现象吧?”;由于晶体管由饱和区切换为截止区需要一 定的时间,而单片机执行指令的等级是约数百ns至数µs,所以若不在切换间加上延 迟时间,的确有瞬间同时导通的疑虑存在;电路中瞬间的电流增加,除了易造成噪 声之外,万一电源的电流不足,也会造成电路电压的瞬间下降,这些现象都可能造 成单片机的不正常动作,使用上一定要小心! 5-1-5 动动脑+动动手: 试着改写【程序 5-1】,使马达的转速能有更多种变化。 试着让 Duty Cycle 再降低,观察马达在何种 Duty Cycle 下就无法转动了。 将【程序 5-1】中的 35 行指令删除,重新执行程序后与原来是否不同? 试着修改【程序 5-1】中的 PWM 周期,并更改 115~125 行 TON 时间建表区 的数据,使其与原程序维持一样的 Duty Cycle,感受一下当 PWM 周期改变、 占空比维持不变的情形下,马达的转速、扭力、甚至产生的干扰或杂音有何 差异。 5-12 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-2 马表-多颗七段显示器控制实验 5-2-1 目 的: 本实验利用人类视觉暂留的特性,让依序逐一点亮的七段显示器呈现同时点亮 的错觉,以解决I/O口不足的情况。本实验承接【实验4-3】单颗七段显示器控制实 验 , 但 增 加 为 四 位 数 的 计 数 器 , 配 合 HT66F50 的 STM 单 元 与 外 部 中 断 的 控 制 (INT0),制作一个计时分辨率为0.1秒的马表。 5-2-2 学习重点: 通过本实验,读者能了解如何以扫描的方式来控制多颗七段显示器的显示;同 时对于HT66F50的间接寻址(Indirect Addressing)、外部中断与STM单元的计时 功能,都应有更深一层的认识。 5-2-3 电路图: 5 PS:若使能PA0的Pull-high功能,则R1电阻可省略。 【图 5-2-1】多颗七段显示器控制电路 在一个系统中为了能够达到显示更多信息的目的,通常会有多颗七段显示器并 排使用的情况。若以【实验4-3】的方法来驱动七段显示器,就需要耗费很多个I/O 口。例如,一个显示“时”和“分”的定时器就需要四颗七段显示器,这表示单片 机就需有四组I/O口用在显示器各节段(Segment)的驱动上,这个对I/O资源极为 珍贵的小型控制器而言,无疑是一种浪费!解决之道,就是采用“动态扫描”的驱 动方式以节省I/O引脚。所谓“动态扫描”,乃是利用人类视觉暂留的现象(约 30~45ms)并配合程序的控制,以分时(Time Devision)的方式来依序点亮每一 颗七段显示器,只要轮流显示的速度控制得当,那么虽然是一次只点亮一颗七段显 示器,但是在视觉效果上却是所有显示器都同时亮着,而且也达到了节省I/O引脚 的目的。本实验使用TM单元(STM)中断与外部中断(INT0)配合,设计一个计 时马表的功能,本实验相关控制寄存器仅列于【表5-2-1】,其设定方式请读者参 第五章 进阶实验篇 5-13 考相关章节。 【2-4 节】 【2-5-2 节】 INTEG INTC0 INTC1 MFI0 TM2C0 TM2C1 TM2DL TM2DH TM2AL TM2AH Bit 【表 5-2-1】本实验相关控制寄存器 - - - - INT1S1 - CP0F INT1F INT0F CP0E ADF MF1F MF0F CP1F ADE T2AF T2PF T0AF T0PF T2AE T2PAU T2CK2 T2CK1 T2CK0 T2ON T2M1 T2M0 T2IO1 T2IO0 T2OC TM2D[7:0] TM2D[15:8] TM2A[7:0] TM2A[15:8] 7 6 5 4 3 INT1S0 INT1E MF1E T2PE - T2POL 2 INT0S1 INT0E MF0E T0AE - T2DPX INT0S0 EMI CP1E T0PE - T2CCLR 1 0 5-2-4 程序及流程图: 5 5-14 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 程序5-2 多颗七段显示器控制实验 1 ;PROGRAM : 5-2.ASM (5-2.PJT) 5 2 ;FUNCTION: MULTI 7-SEG LED DEMO PROGRAM 2009.1112 By Steven 3 #INCLUDE HT66F50.INC 4 #INCLUDE 5-2.INC 5 ;======================================================================================== 6 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 7 SCAN DB ? ;SCAN DATA BUFFER 8 DIGIT DB 4 DUP(?) ;BUFFER FOR DIGIT 0~3 9 R_100MS DB ? ;BUFFER FOR 100mSEC 10 STACK_A DB ? ;STACK BUFFER FOR ACC 11 STACK_PSW DB ? ;STACK BUFFER FOR STATUS 12 FG_GO_STOP DBIT ;FLAG FOR GO/STOP 13 FG_100MS DBIT ;FLAG FOR 100mS TIME-OUT 14 ;======================================================================================== 15 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 16 ORG 00H ;HT66FX0 RESET VECTOR 17 JMP MAIN 18 ORG 04H ;HT66FX0 EXTERNAL INTERRUPT 0 VECTOR 19 JMP ISR_EXTINT0 20 ORG 14H ;HT66FX0 STM INTERRUPT VECTOR 21 JMP ISR_STM 22 MAIN: 23 CLR ACERL ;AD DISABLE 24 MOV A,08h 25 MOV CP0C,A ;CP0 DISABLE 26 CLR SCAN_PORT ;CLEAR SCAN_PORT 27 CLR SEG_PORT ;CLEAR SEG_PORT 28 CLR 29 CLR 30 MOV 31 MOV 32 MOV 33 MOV 34 MOV 35 MOV 36 MOV 37 MOV 38 SET 39 SET 40 SET 41 SET 42 MOV 43 MOV 44 SET 45 MOV 46 MOV 47 MOV 48 MOV 49 MOV 50 MOV 51 CLR 52 SET 53 SET 54 CLR 55 RE_START: 56 CLR 57 CLR 58 CLR 59 CLR 60 WAIT_100MS: 61 SNZ 62 JMP 63 CLR 64 INC 65 MOV 66 SUB 67 SNZ 68 JMP 69 CLR 70 INC 71 MOV 72 SUB 73 SNZ 74 JMP SCAN_PORTC SEG_PORTC A,00000000B TM2C0,A A,11000001B TM2C1,A A,LOW 5000 TM2AL,A A,HIGH 5000 TM2AH,A MF0E T2AE PAPU.3 PAC.3 A,00000010B INTEG,A INT0E A,10000000B SCAN,A A,OFFSET DIGIT MP0,A A,20 R_100MS,A FG_100MS EMI T2ON FG_GO_STOP DIGIT[0] DIGIT[1] DIGIT[2] DIGIT[3] FG_100MS WAIT_100MS FG_100MS DIGIT[0] A,DIGIT[0] A,10 Z WAIT_100MS DIGIT[0] DIGIT[1] A,DIGIT[1] A,10 Z WAIT_100MS 第五章 进阶实验篇 5-15 ;CONFIG SCAN_PORT AS OUTPUT MODE ;CONFIG SEG_PORT AS OUTPUT MODE ;CLOCK SOURCE=fSYS/4 ;TIMER/COUNTER MODE, ;CLEAR BY CCRA COMPARE MATCH ;SET CCRA=5000 FOR 5mS TIME-OUT PERIOD ;ENABLE MF0 INTERRUPT ;ENABLE TM2 CCRA MATCH INTERRUPT ;ENABLE PA3 PULL-UP;;;;;;;; ;CONFIG PA.3(INT0B) AS INPUT ;SELECT INT0 FALLING EDGE TRIGGER ;ENABLE EXTERNAL INTERRUPT 0 ;GET START ADDRESS OF DIG BUFFER ;RE-LOAD INITIAL VALUE 5 ;ENABLE GLOBAL INTERRUPT ;START TIMER ;CLEAR GO_STOP_FLAG ;INITIAL DIG3~DIG0 ;100 mS TIME-OUT ;NO. ;100 mS TIME-OUT ;INCREASE DIGIT[0] ;DIGIT[0] = 10? ;NO. ;YES, RESET DIGIT[0] ;INCREASE DIGIT[1] BY 1 ;DIGIT[1] = 10? ;NO. 5-16 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 75 CLR DIGIT[1] ;YES, RESET DIGIT[1] 76 INC DIGIT[2] ;INCREASE DIG2 BY 1 77 MOV A,DIGIT[2] 78 SUB A,6 79 SNZ Z ;DIGIT[2] = 6? 80 JMP WAIT_100MS ;NO. 81 CLR DIGIT[2] ;YES, RESET DIGIT[2] 82 INC DIGIT[3] ;INCREASE DIGIT[3] BY 1 83 MOV A,DIGIT[3] 84 SUB A,10 85 SNZ Z ;DIGIT[3] = 10? 86 JMP WAIT_100MS ;NO. 87 JMP RE_START ;YES. 88 ;======================================================================================== 89 ; STM INTERRUPT SERVICE ROUTINE 90 ;======================================================================================== 91 ISR_STM: 92 MOV STACK_A,A ;PUSH A 93 MOV A,STATUS 94 MOV STACK_PSW,A ;PUSH STATUS 95 CLR SEG_PORT 5 96 RLA SCAN 97 SNZ ACC.4 ;GHOST EFFECT ;ALL DIGIT HAVE BEEN SCANNED? 98 JMP $+4 ;NO. 99 MOV A,OFFSET DIGIT ;ET START ADDRESS OF DIG BUFFER 100 MOV MP0,A 101 MOV A,00000001B ;YSE. RE-LOAD INITIAL DATA 102 MOV SCAN,A ;UPDATE SCAN BUFFER 103 MOV SCAN_PORT,A ;SACN DATA OUT 104 MOV A,IAR0 ;INDIRECT ADDRESSING 105 CALL TRANS ;GET DISPLAY CODE 106 SZ SCAN.1 ;IS DIG1 LIGHT? 107 SET ACC.7 ;YES. SET DOT 108 MOV SEG_PORT,A ;SEND DISPLAY CODE 109 INC MP0 ;NEXT DIGIT 110 SNZ FG_GO_STOP ;FLAG = STOP ? 111 JMP $+6 ;YES. 112 SDZ R_100MS ;CHECK 100mS TIME-OUT 113 JMP $+4 ;NO. 114 SET FG_100MS ;YES. SET 100mS FLAG 115 MOV A,20 ;RE-LOAD INITIAL VALUE 116 MOV R_100MS,A 117 CLR T2AF ;CLEAR TM2 COMPARE MATCH FLAG 118 MOV A,STACK_PSW 119 MOV STATUS,A ;POP STATUS 120 MOV A,STACK_A ;POP A 121 RETI 第五章 进阶实验篇 5-17 122 ;======================================================================================== 123 ; EXTERNAL INTERRUPT SERVICE ROUTINE 124 ;======================================================================================== 125 ISR_EXTINT0: 126 SZ FG_GO_STOP ;FLAG=0 ? 127 JMP $+3 ;NO. 128 SET FG_GO_STOP ;YES. SET FLAG=1 129 JMP $+2 130 CLR FG_GO_STOP ;SET FLAG=0 131 CLR INT0F ;CLEAR FLAG 132 RETI 133 ;======================================================================================== 134 ; RETURN THE TABLE VALUE INDEX BY A 135 ;======================================================================================== 136 TRANS PROC 137 ADDM A,PCL ;COMMON CATHOD 7-SEG LED CODE 138 RET A,3FH ;'0' 139 RET A,06H ;'1' 140 RET A,5BH ;'2' 141 RET A,4FH ;'3' 142 RET A,66H ;'4' 143 RET A,6DH ;'5' 144 RET A,7DH ;'6' 5 145 RET A,07H ;'7' 146 RET A,7FH ;'8' 147 RET A,67H ;'9' 148 TRANS ENDP 149 END 程程序序解解说说:: 4 载入”5-2.INC”定义档,其内容请参考随书光盘中的档案。 7~13 依序定义变量地址。 16 18 20 23~25 26~29 30~33 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 声明内存地址由 04h 开始(HT66Fx0 外部中断 0 向量地址)。 声明内存地址由 14h 开始(HT66Fx0 STM 中断向量地址)。 关闭 CP0 功能,并设定 ADC 脚位输入为 I/O 功能。 将 SCAN_PORT、SEG_PORT 定义成输出模式,并将其状态设为 Low。 定义 TM2C0、TM2C1 控制寄存器: T2CK[2:0]:000,设定 fINT=fSYS/4; 5-18 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 T2M[1:0]:11,设定为 Timer/Counter 模式; T2CCLR:0,设定当 TM2D=TM2A 时(即比较器 A 比较匹配时)清除计数器。 34~37 38~39 设定 TM2A=5000;故 STM 计时中断时间为 5000× fSYS/4(5ms @ fSYS=4MHz)。 使能 MF0 与 STM 中断。 40~44 定义 INT0(PA.3)为输入模式,并使能其 Pull-high 功能。 设定 INT0 的为下降沿 触发形式,且使能其中断功能。 45~48 设定扫描寄存器(SCAN)初值,并将 MP0 指向 DIGIT 存储器的地址。 49~51 设定 100ms 计数器初值为 20,并清除代表已计时 100ms 的 FG_100MS 标志。 52~54 使能中断总开关(EMI),HT66F50 可开始接受外部中断;启动 STM 计时功能并 清除 FG_GO_STOP 标志(此标志在 STM 中断服务子程序中,是用来判断是否计 时的依据)。 56~59 清除存储器 DIGIT[0]~DIGIT[3],这四个存储器在程序中分别储存 1/10 秒、秒的个 位数、秒的十位数及分钟的计数值。 5 61~62 等待 100ms 的计数时间。 63~87 此段程序为计时达 100ms 的处理程序,首先清除 FG_100MS 标志;接着按计时的 规则逐一更新 DIGIT[0]~DIGIT[3]存储器的数值;若计时已到达“9:59.9”则重新 将 DIGIT[0]~DIGIT[3]清除后继续执行(JMP RE_START)。 91~121 STM 中断服务子程序,其主要功能是每隔 5ms 更新扫描的显示器与显示值,每中 断 20 次后需设定 FG_100MS 标志,以提供主程序做为是否已计时 100ms 的判断 依据;但若 FG_GO_STOP 标志为“0”代表暂停计数,此时扫描动作继续运行, 但会停止 FG_100MS 标志的设定。95~109 行的程序是逐一点亮(扫描)DIGIT[0]~ DIGIT[3];其中是以间接寻址法(MP0 配合 IAR0),循序将 DIGIT[0]~DIGIT[3] 的数值经由 TRANS 子程序转换为七段显示码后输出至 SEG_PORT,并配合 SCAN_PORT 的左移动作点亮对应的显示器。同时,每个显示器被点亮的时间由 STM 的中断时间所控制(为 7ms)。 125~132 外部中断服务子程序,此段程序的目的是将控制是否计时的 FG_GO_STOP 标志加 以反向。 136~148 七段显示器查表子程序。 本实验的重点就在于扫描时间的掌握,如果每一颗七段显示器点亮的时间不够 第五章 进阶实验篇 5-19 长(扫描时间过短),显示的数字就不清楚(因为LED通电之后要达到相对的亮度 需要一定的时间);反之,若每个位数停留的时间太久(扫描时间过长),就会看 到数字闪烁,甚至看到数字是逐一点亮的情形。由于视觉暂留的时间约30~45ms, 而【程序5-2】以STM的Timer/Counter模式控制,让每一个数字点亮约5ms(4×5 =20ms),不致超过视觉暂留时间,所以可以清楚看见七段显示器上的数字。而 以5ms为计时时间的另一个目的是在中断20次后即为100ms的时间,刚好可以进行 显示数值的更新程序。在【程序5-2】执行时,使用者可以通过“GO/STOP”按键 来控制定时器开始或暂停计数,若想让时间归零的话,可以按下RESET按键达成 此一目的;当然啰,要使用硬件复位功能的话,“配置选项”的设定与PB0/RESB 脚位的连接要重新考虑,请参考【实验4-16】! 另外,在INT0_ISR的中断服务子程序中,因为只是单纯进行标志清除、设定, 没有涉及存储器值的运算,所以Acc、STATUS寄存器就不需像STM_ISR中还要先 做内存值保存的动作。 5-2-5 动动脑+动动手: 试着将 STM 计时的时间延长,观察七段显示器的显示情形。 试着将 STM 计时的时间缩短,观察七段显示器的显示情形。 5 修改【程序 5-2】将其成为 00:00~23:59 的 24 小时定时器;以 SEG3、 SEG2 显示小时,SEG1、SEG0 显示分钟,秒针的跳动就以 SEG0 的“h” 字节闪、灭来表示。 5-20 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-3 静态点矩阵LED控制实验 5-3-1 目 的: 本实验利用视觉暂留的特性,通过HT66F50的“时基计数器”(Time Base Counter;TB)单元控制扫描时间,在8×8点矩阵LED上显示字型。 5-3-2 学习重点: 通过本实验,读者能了解如何以扫描的方式来控制8×8点矩阵LED的显示;并 应熟悉HT66F50 Time Base Counter的控制与其中断操作特性。 5-3-3 电路图: 5 【图 5-3-1】8×8 点矩阵 LED 控制电路 “点矩阵(Dot-Matrix)LED”在各式广告牌上都看的到,其控制方式其实与 【实验5-2】多颗七段显示器的扫描控制差不多,也是利用人类视觉暂留的特性, 让依序一排一排点亮点矩阵的LED,呈现同时发亮的错觉,只要适当的控制各排所 需点亮的字型码(Pattern)与点亮的时间,就可以看到各种的字型。 第五章 进阶实验篇 5-21 【图 5-3-2】8×8 点矩阵 LED 内部结构 【图5-3-2】为8×8点矩阵LED的内部电路,一般应用上是将其分成行(Column; C0~C7)、列(Row;R0~R7)加以控制。例如本实验的电路中(【图5-3-1】), 是将HT66F50的Port D作为列扫描的控制;而Port E则作为字型输出的行控制。举 例来说,如果要显示如【图5-3-3】的“↑”符号,则就需依【图5-3-4】的顺序逐 一送出字型码并配合Port E的扫描序列,并给予每列适当的停留时间;如果分为八 5 列扫描,且取16ms的视觉暂留时间,则每列仅能停留大约2ms的时间。 【图 5-3-3】“↑”字型 5-22 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 (a) (b) (c) (d) (e) (f) (g) (h) 【图 5-3-4】欲显示“↑”字型所需依序送出的字型码 本范例程序利用HT66F50的“时基计数器(Time Base Counter;TB)”产生 所需的控制信号,大约每2.048ms中断一次,在其中断服务程序中切换扫描列并送 出对应的图样,完成显示的动作。HT66F50的Time Base Counter界面架构如【图 5-3-5】所示,其内含两组定时器: TB0与 TB1。其主要功能是根据计数频率源 (fTB)提供一个规律性的内部中断(Regular Internal Interrupt),两者的操作方 5 式完全相同,只是TB0计数周期的时间比TB1多了四种不同的选择。TB0计时溢位 所产生的中断周期时间范围为28/fTB~215/fTB,可由TB0[2:0]三个位加以选定;当计 数时间结束时,TB会设定TB0F标志,若此时TB0E=“1”且EMI=“1”,则CPU 将至24h执行ISR。TB1计时溢位所产生的中断周期时间范围为212/fTB~215/fTB,可 由TB1[1:0]两位选定;当计数时间结束时,TBC会设定TB1F标志,若此时TB1E= “1”且EMI=“1”,则CPU将至28h执行ISR。以下将本实验相关控制寄存器简 列于【表5-3-1】,详细说明请读者参考各相关章节。 【图 5-3-5】HT66F50 的 TBC 内部结构 【2-4 节】 【2-13 节】 【表 5-3-1】本实验相关控制寄存器 INTC0 - CP0F INT1F INT0F CP0E INT1E INTC2 MF3F TB1F TB0F MF2F MF3E TB1E TBC TBON TBCK TB11 TB10 LXTLP TB02 Bit 7 6 5 4 3 2 INT0E TB0E TB01 1 EMI MF2E TB00 0 5-3-4 程序及流程图: 第五章 进阶实验篇 5-23 5 程序5-3 TBC静态点矩阵LED扫描控制 1 ;PROGRAM: 5-3.ASM (5-3.PJT) 2009.1112 2 ;FUNCTION: STATIC 8*8 DOT-MATRIX LED DEMO PROGRAM By Steven 3 ;NOTE: CONFIG. OPTION : TB CLOCK SOURCE fTb: fSYS/4 4 #INCLUDE HT66F50.INC 5 #INCLUDE 5-3.INC 6 ;======================================================================================== 7 MY_DATA .SECTION 'DATA' ;==DATA SECTION== 8 DEL1 DB ? ;DELAY LOOP COUNT 1 5-24 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 9 DEL2 DB ? ;DELAY LOOP COUNT 2 10 DEL3 DB ? ;DELAY LOOP COUNT 3 11 COUNT DB ? ;TABLE INDEX 12 COUNT1 DB ? 13 COUNT2 DB ? 14 BUFFER DB 8 DUP (?) 15 SCAN DB ? 16 STACK_A DB ? ;STACK BUFFER FOR ACC 17 STACK_PSW DB ? ;STACK BUFFER FOR STATUS 18 ;======================================================================================== 19 MY_CODE .SECTION AT 0 'CODE' ;==PROGRAM SECTION== 20 ORG 00H ;HT-66FX0 RESET VECTOR 21 JMP INIT 22 ORG 24H ;HT-66F50 TB0 INTERRUPT VECTOR 23 JMP ISR_TB0 24 INIT: CLR SCAN_PORT ;TURN OFF ALL SCAN LINE 25 CLR DOT_PORT ;CLEAR DISPLAY DATA 26 CLR SCAN_PORTC ;CONFIG SCAN_PORT AS OUTPUT MODE 27 CLR DOT_PORTC ;CONFIG DOT_PORT AS OUTPUT MODE 28 MOV A,01000011B ;TB0 TIME-OUT PERIOD IS 2048/fTB 29 MOV TBC,A 5 30 SET TB0E 31 SET EMI ;fTB=fSYS/4, TBON=1 ;ENABLE TB0 INTERRUPT ;ENABLE GLOBAL INTERRUPT 32 MAIN: MOV A,2 ;COUNT1 FOR PATTERN NUMBER 33 MOV COUNT1,A 34 MOV A,TAB_MATRIX ;SET TABLE POINTER 35 MOV TBLP,A 36 MAIN_1: CALL COPY ;COPY ROM DATA TO RAM 37 MOV A,OFFSET BUFFER 38 MOV MP0,A ;INITIAL MEMORY POINTER 0 39 MOV A,00000001B 40 MOV SCAN,A 41 SET TBON 42 MOV A,200 43 CALL DELAY 44 CLR TBON 45 SDZ COUNT1 46 JMP MAIN_1 ;NEXT PATTERN 47 JMP MAIN ;YES.RE-START 48 ;======================================================================================== 49 ; PROC : COPY 50 ; FUNC : COPY DISPLAY CODE(POINTER BY TBLP) TO DISPLAY BUFFER[7:0] 51 ; PARA : TBLP :POINT TO TABLE START ADDRESS 52 ; REG : ACC,MP0,IAR0,COUNT 53 ;======================================================================================== 54 COPY PROC 55 MOV A,OFFSET BUFFER 第五章 进阶实验篇 5-25 56 MOV MP0,A ;INITIAL MEMORY POINTER 0 57 MOV A,8 58 MOV COUNT,A ;SET BYTE COUNTER 59 COPY_1: TABRDL IAR0 ;READ TABLE DATA AND COPY TO BUFFER 60 INC TBLP ;INCREASE TABLE POINTER 61 INC MP0 ;POINT TO NEXT BUFFER ADDRESS 62 SDZ COUNT ;COUNT-1 = 0? 63 JMP COPY_1 ;NO, COPY NEXT BYTE 64 RET ;YES, RETURN 65 COPY ENDP 66 ;======================================================================================== 67 ; TB0 INTERRUPT SERVICE ROUTINE 68 ;======================================================================================== 69 ISR_TB0: 70 MOV STACK_A,A ;PUSH A 71 MOV A,STATUS 72 MOV STACK_PSW,A ;PUSH STATUS 73 CLR DOT_PORT ;GHOST EFFECT 74 MOV A,SCAN ;UPDATE SCAN BUFFER 75 MOV SCAN_PORT,A ;SACN DATA OUT 76 MOV A,IAR0 77 MOV DOT_PORT,A 78 INC MP0 ;POINT TO NEXT BUFFER ADDRESS 5 79 RL SCAN 80 SNZ SCAN.0 ;ALL DIGIT HAVE BEEN SCANNED? 81 JMP $+3 ;NO. 82 MOV A,OFFSET BUFFER ;YES.GET START ADDRESS OF DIG BUFFER 83 MOV MP0,A 84 MOV A,STACK_PSW 85 MOV STATUS,A ;POP STATUS 86 MOV A,STACK_A ;POP A 87 RETI ;YES, RETURN 88 ;======================================================================================== 89 ; PROC : DELAY 90 ; FUNC : DEALY ABOUT ACC*10mS @fSYS=4MHz 91 ; PARA : ACC : DELAY FACTOR 92 ; REG : DEL1,DEL2,DEL3 93 ;======================================================================================== 94 DELAY PROC 95 MOV DEL1,A ;SET DEL1 COUNTER 96 DEL_1: MOV A,30 97 MOV DEL2,A ;SET DEL2 COUNTER 98 DEL_2: MOV A,110 99 MOV DEL3,A ;SET DEL3 COUNTER 100 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 101 JMP DEL_3 102 SDZ DEL2 ;DEL2 DOWN COUNT 5-26 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 103 JMP DEL_2 104 SDZ DEL1 105 JMP DEL_1 106 RET 107 DELAY ENDP 108 ORG LASTPAGE 109 TAB_MATRIX: 110 DC 00011000B 111 DC 00011000B 112 DC 00111100B 113 DC 01111110B 114 DC 11111111B 115 DC 00011000B 116 DC 00011000B 117 DC 00011000B 118 119 DC 00010000B 120 DC 00011000B 121 DC 00011100B 122 DC 11111111B 123 DC 11111111B 5 124 DC 00011100B 125 DC 00011000B 126 DC 00010000B 127 END ;DEL1 DOWN COUNT 程程序序解解说说:: 5 载入”5-3.INC”定义档,其内容请参考随书光盘中的档案。 8~17 依序定义变量地址。 20 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 22 声明内存地址由 24h 开始(HT66F50 TB0 中断向量地址)。 24~27 将 SCAN_PORT、DOT_PORT 定义成输出模式,并熄灭所有灯号。 28~29 定义 TBC 控制寄存器: 30~31 TBCK:1,选择计数频率来源为 fSYS/4; TB0[2:0]:011,设定 Time Base Interrupt 周期时间为 2048×(fSYS/4)≒2.048ms @fSYS=4MHz。 使能中断总开关(EMI)与 TB0(TB0E),HT66F50 可开始接受 TB0 中断。 32~33 设定 COUNT1 为 2,代表有两组点矩阵图案要显示。 34~35 将 TBLP 指向第一组要显示的点矩阵图案的起始地址。 第五章 进阶实验篇 5-27 36 调用 COPY 子程序,将一组点矩阵图案复制到 BUFFER[]数组,以便进入 TB0_ISR 后送出显示数据。 37~40 将 MP0 指向 BUFFER[]数组的起始地址,并设定 SCAN 扫描存储器为 00000001B。 41 设定 TBON 为“1”,TBC 开始计数。 42~43 调用 DELAY 子程序,延迟两秒钟;延迟时间的计算请参考【实验 4-1】。 44~47 设定 TBON 为“0”,停止 TBC 计数;判断 COUNT 减一是否为 0,成立则重新执 行程序(JMP MAIN);反之,则显示下一个点矩阵图案(JMP MAIN_1)。 54~65 COPY 子程序,根据 TBLP 指定的位置,将连续八个地址所存放的点阵数据由程序 存储器复制到 BUFFER[]数组。 69~87 TB0 中断服务子程序,根据 SCAN 存储器之值送出扫描列的信号,并依 MP0 指定 的地址送出对应的位图案。将 SCAN 存储器左移之后判断是否已完成八列的扫描, 若是则重新将 MP0 指向 BUFFER[]数组的起始地址;否则继续下一列扫描。 94~107 DELAY 子程序,延迟时间的计算请参考【实验 4-1】。 109~126 两组点矩阵图案数据建表区。 5 【程序5-3】是以Port E负责字型码的输出,而以Port D做为列扫描的控制。TB 模块的中断功能则用来掌控每列点亮的时间,而每个图案呈现的时间长短,则由 DELAY子程序的延迟时间决定。有时为了获得更高分辨率的字型、或同时显示多 个字型,就必须增加LED的列数及行数,此时每列扫描时停留的时间势必将缩短! 过短的停留时间会使LED无法进入完全导通的状态,致使其亮度大打折扣!解决的 方式是:增加通过LED的电流,使LED能在导通的瞬间达到应有的亮度。不过此时 要特别注意,因为这时候的大电流是针对瞬间导通时所设计的,切记勿让此电流长 时间流经LED,否则将会造成电路的损害;尤其在以ICE测试时,务必避免单步执 行或断点停留在某列LED点亮的指令上! 另外,【程序5-3】的设计方式是先将程序存储器中的点矩阵图案先复制到 BUFFER[]数组后再交予TB0_ISR程序进行扫描;读者当然也可以省略此步骤而直 接以程序存储器的点阵数据进行显示,笔者的目的无非是让读者多熟悉间接寻址方 式的使用,以便在【实验5-4】能更灵活的运用。 5-3-5 动动脑+动动手: 若修改 5-3.INC 定义档的设定,使 SCAN_PORT、DOT_PORT 的定义调换; 请问执行结果有何不同? 5-28 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 若修改【程序 5-3】中 TB0_ISR 程序的扫描顺序,使 SCAN 存储器是由左 移改为右移;请问执行结果有何不同? 若将【程序 5-3】第 43 行指令(CALL DELAY)删除,是否仍可看到两组 图案的交替显示?为什么? 试想若将【程序 5-3】的列扫描时间控制由 TB0 更替为 TB1,是否可行?有 何限制呢? 5 5-29 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-4 动态点矩阵LED控制实验 5-4-1 目 的: 承续【实验5-3】静态点矩阵LED图案显示,本实验在8×8点矩阵LED上显示动 态的移动字型。 5-4-2 学习重点: 通过本实验,读者能运用程序的技巧,在8×8点矩阵LED上做动态显示,并应 更熟悉HT66F50“间接寻址法(Indirect Addressing Mode)”的运用。 5-4-3 电路图: 5 【图 5-4-1】8×8 点矩阵 LED 控制电路 【实验5-3】中在点矩阵LED上显示静态的字型,相信读者已经十分清楚该如 何控制。若果真如此,那么只需要再使用一点程序上的技巧,就可以让字型达到移 动的效果。参考【图5-4-2】,如果在程序存储器(ROM)中建立图中所需的十六 种图案的字型码,然后再让每个字型重复显示几次,也就是说依序由(1)到(16) 让字型在点矩阵上停留80ms(5次×8列×2ms/列),应该就可以看到“↑”符号移 出点矩阵后再移回原位置的效果!至于移动速度的快慢,则是取决于每个图案重复 5-30 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 显示的次数(在程序中,笔者是以DELAY子程序的延迟时间决定图案跑动的速度)。 (1) (2) (3) (4) (5) (6) (7) (8) 5 (9) (10) (11) (12) (13) (14) (15) (16) 【图 5-4-2】产生字型移动效果所需依序送出的字型 问题是这种作法,一个字型码需要约八个Bytes的程序存储空间,光是一个字 型的移动效果就必须耗费掉128 Bytes(8×16),万一要多几个字型的移动特效, 耗费掉大半的程序内存不说,光是建表的工程就可能浪费掉许多宝贵的时光!所以, 上述控制字型移动的观念虽然正确,但是否有其它的替代方案可行,以避免耗费内 存并节省建表工程所需时间呢?答案当然是肯定的!读者可以再仔细观察【图 5-4-2】,如果我们将原来的字型先搬到数据存储器(RAM)中,然后再将数据存 储器中的字型依序移位、显示,是不是就达到一样的效果了呢?简而言之,就是以 程序技巧来换取程序所需的空间。 第五章 进阶实验篇 5-31 (1) (2) (3) (4) 5 (5) (6) (7) (8) (9) (10) (11) (12) 5-32 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 (13) (14) (15) (16) 【图 5-4-3】以 BUFFER 产生字型移动效果 首先,在数据存储器中保留16 Bytes做为字型移动缓冲区(BUFFER[0]~ BUFFER[15]);要显示字型时,将八个Bytes的字型码由程序存储器先复制到 BUFFER[0]~BUFFER[7]的数据存储器中,并将BUFFER[8]~BUFFER[15]清除为0 (如【图5-4-3】中(1))。紧接着把BUFFER[0]~BUFFER[7]循序送出显示后,再 将BUFFER[0]~ BUFFER[15]中的数据“循环移位(Circular Shift)”一次(如【图 5 5-4-3】中(2)),然后再一次将BUFFER[0]~BUFFER[7]循序送出显示;如此重复 循环移位与显示的动作,就可获得字型移动的效果了。本实验相关控制寄存器,请 参阅【表5-4-1】。 【2-4 节】 【2-13 节】 【表 5-4-1】本实验相关控制寄存器 INTC0 - CP0F INT1F INT0F CP0E INT1E INTC2 MF3F TB1F TB0F MF2F MF3E TB1E TBC TBON TBCK TB11 TB10 LXTLP TB02 Bit 7 6 5 4 3 2 INT0E TB0E TB01 1 EMI MF2E TB00 0 5-4-4 程序及流程图: 第五章 进阶实验篇 5-33 COPY子程序 SHIFT子程序 TBLP指向ROM的数据起始地址 TEMP=BUFFER[0] MP0指向BUFFE[0]的地址 MP1指向BUFFE[8]的地址 Set COUNT=15 i=1 5 Set COUNT=8 依TBLP读取数据 并存在MP0所指的地址 清除MP1所指的地址內容 TBLP=TBLP+1 MP0=MP0+1 MP1=MP1+1 NO COUNT-1=0 ? YES RETUTN BUFFER[i]=BUFFER[i+1] i=i+1 NO COUNT-1=0 ? YES BUFFER[15]=TEMP RETUTN 5-34 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 ISR_TB0子程序 Push Acc、PSW YES SCAN.0= 1 ? NO MP0指向DIGIT[0] 设定SCAN=00000001b SCAN_PORT=SCAN 依IAR0查表 并将送到DOT_PORT SCAN左移一位 MP0=MP0+1 SCAN.0= 1 NO ? YES MP0重新指向 BUFFER[0] POP Acc、PSW RETUTN 程序5-4 动态点矩阵LED 1 ;PROGRAM : 5-4.ASM (5-4.PJT) 2009.1110 2 ;FUNCTION: DYNAMIC 8X8 DOT-MATRIX LED DEMO PROGRAM By Steven 3 ;NOTE: CONFIG. OPTION : TB CLOCK SOURCE fTb: fSYS/4 5 4 #INCLUDE HT66F50.INC 5 #INCLUDE 5-4.INC 6 ;======================================================================================== 7 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 8 DEL1 DB ? ;DELAY LOOP COUNT 1 9 DEL2 DB ? ;DELAY LOOP COUNT 2 10 DEL3 DB ? ;DELAY LOOP COUNT 3 11 COUNT DB ? ;UNIVERSAL COUNTER 12 SCAN DB ? ;BUFFER FOR SCAN DATA 13 BUFFER DB 16 DUP(?) ;BUFFER FOR DISPLAY DATA 14 STACK_A DB ? ;STACK BUFFER FOR A 15 STACK_PSW DB ? ;STACK BUFFER FOR PSW 16 ;======================================================================================== 17 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 18 ORG 00H ;HT66FX0 RESET VECTOR 19 JMP MAIN 20 ORG 024H ;HT66FX0 TB0 INTERRUPT VECTOR 21 JMP ISR_TB0 22 MAIN: CLR SCAN_PORT ;TURN OFF ALL SCAN LINE 23 CLR DOT_PORT ;CLEAR DISPLAY DATA 24 CLR SCAN_PORTC ;CONFIG SCAN_PORT AS OUTPUT MODE 25 CLR DOT_PORTC ;CONFIG DOT_PORT AS OUTPUT MODE 26 MOV A,01000011B ;TB0 TIME-OUT PERIOD IS 2048/fTB 27 MOV TBC,A ;fTB=fSYS/4, TBON=1 28 SET TB0E ;ENABLE TB0 INTERRUPT 29 SET EMI ;ENABLE GLOBAL INTERRUPT 第五章 进阶实验篇 5-35 30 CALL COPY ;COPY PATTERN TO BUFFER[] 31 MAIN_1: 32 MOV A,OFFSET BUFFER ;GET DISPLAY START ADDRESS 33 MOV MP0,A 34 MOV A,00000001B ;INITIAL SCAN DATA 35 MOV SCAN,A 36 SET TBON ;START SCANNING 37 MOV A,10 ;DELAY 100ms 38 CALL DELAY 39 CLR TBON ;STOP SCANNING 40 CALL SHIFT ;SHIFT BUFFER 1 BYTE 41 JMP MAIN_1 ;RE DO 42 ;======================================================================================== 43 ; TB0 INTERRUPT SERVICE ROUTINE 44 ;======================================================================================== 45 ISR_TB0: 46 MOV STACK_A,A ;PUSH A 47 MOV A,STATUS 48 MOV STACK_PSW,A ;PUSH STATUS 49 CLR DOT_PORT ;GHOST EFFECT 50 MOV A,SCAN ;UPDATE SCAN BUFFER 51 MOV SCAN_PORT,A ;SACN DATA OUT 52 MOV A,IAR0 5 53 MOV DOT_PORT,A 54 INC MP0 ;POINT TO NEXT BUFFER ADDRESS 55 RL SCAN 56 SNZ SCAN.0 ;ALL DIGIT HAVE BEEN SCANNED? 57 JMP $+3 ;NO. 58 MOV A,OFFSET BUFFER ;YES.GET START ADDRESS OF DIG BUFFER 59 MOV MP0,A 60 MOV A,STACK_PSW 61 MOV STATUS,A ;POP STATUS 62 MOV A,STACK_A ;POP A 63 RETI 64 ;======================================================================================== 65 ; PROC : SHIFT 66 ; FUNC : SHIFT DISPLAY BUFFER BY 1 LOCATION 67 ; REG : ACC,MP0,IAR0,MP1,IAR1,TEMP,COUNT 68 ;======================================================================================== 69 SHIFT PROC ;CIRCULAR SHIFT DATA IN BUFFER BY ONE 70 MOV A, OFFSET BUFFER ;TOTAL 16 BYTES 71 MOV MP0,A ;INITIAL MEMORY POINTER 0 72 MOV MP1,A ;INITIAL MEMORY POINTER 1 73 MOV A,IAR0 74 MOV SCAN,A ;SAVE FIRST DATA 75 INC MP0 ;INCREASE MP0 BY 1 76 MOV A,16-1 5-36 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 77 MOV COUNT,A ;SET COUNT 78 SHIFT_1: 79 MOV A,IAR0 ;GET BUFFER+1 DATA 80 MOV IAR1,A ;COPY TO BUFFER 81 INC MP0 ;INCREASE MP0 BY 1 82 INC MP1 ;INCREASE MP1 BY 1 83 SDZ COUNT ;COUNT-1 = 0? 84 JMP SHIFT_1 ;NO, NEXT BYTE 85 MOV A,SCAN ;YES. 86 MOV IAR1,A ;RE-LOAD FIRST DATA TO BUFFER END 87 RET 88 SHIFT ENDP 89 ;======================================================================================== 90 ; PROC : COPY 91 ; FUNC : COPY DISPLAY CODE TO DISPLAY BUFFER[7:0] AND CLEAR BUFFER[15:8] 92 ; REG : ACC,MP0,IAR0,MP1,IAR1,TBLP,COUNT 93 ;======================================================================================== 94 COPY PROC 95 MOV A,OFFSET BUFFER 96 MOV MP0,A ;INITIAL MEMORY POINTER 0 97 MOV A,OFFSET BUFFER+8 5 98 MOV MP1,A ;INITIAL MEMORY POINTER 1 99 MOV A,8 100 MOV COUNT,A ;SET BYTE COUNTER 101 MOV A,OFFSET TABLE ;INITIAL TABLE POINTER 102 MOV TBLP,A 103 COPY_1: CLR IAR1 ;CLEAR BUFFER 104 TABRDL IAR0 ;READ TABLE DATA AND COPY TO BUFFER 105 INC TBLP ;INCREASE TABLE POINTER 106 INC MP0 ;POINT TO NEXT BUFFER ADDRESS 107 INC MP1 ;POINT TO NEXT BUFFER ADDRESS 108 SDZ COUNT ;COUNT-1 = 0? 109 JMP COPY_1 ;NO, COPY NEXT BYTE 110 RET ;YES, RETURN 111 COPY ENDP 112 ;======================================================================================== 113 ; PROC : DELAY 114 ; FUNC : DEALY ABOUT ACC*10mS @fSYS=4MHz 115 ; PARA : ACC : DELAY FACTOR 116 ; REG : DEL1,DEL2,DEL3 117 ;======================================================================================== 118 DELAY PROC 119 MOV DEL1,A ;SET DEL1 COUNTER 120 DEL_1: MOV A,30 121 MOV DEL2,A ;SET DEL2 COUNTER 122 DEL_2: MOV A,110 123 MOV DEL3,A ;SET DEL3 COUNTER 第五章 进阶实验篇 5-37 124 DEL_3: SDZ 125 JMP 126 SDZ 127 JMP 128 SDZ 129 JMP 130 RET 131 DELAY ENDP 132 ORG 133 TABLE: DC 134 DC 135 DC 136 DC 137 DC 138 DC 139 DC 140 DC 141 END DEL3 DEL_3 DEL2 DEL_2 DEL1 DEL_1 LASTPAGE 00011000B 00111100B 01111110B 11111111B 00011000B 00011000B 00011000B 00011000B ;DEL3 DOWN COUNT ;DEL2 DOWN COUNT ;DEL1 DOWN COUNT 程程序序解解说说:: 5 载入”5-4.INC”定义档,其内容请参考随书光盘中的档案。 5 8~15 依序定义变量地址。 18 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 20 声明内存地址由 24h 开始(HT66F50 TB0 中断向量地址)。 22~25 将 SCAN_PORT、DOT_PORT 定义成输出模式,并熄灭所有灯号。 26~27 定义 TBC 控制寄存器: 28~29 TBCK:1,选择计数频率来源为 fSYS/4; TB0[2:0]:011,设定 Time Base Interrupt 周期时间为 2048×(fSYS/4)≒2.048ms @fSYS=4MHz。 使能中断总开关(EMI)与 TB0(TB0E),HT66F50 可开始接受 TB0 中断。 30 调用 COPY 子程序,将点矩阵图案复制到 BUFFER[0]~BUFFER[7],以便进入 ISR_TB0 后送出显示数据;COPY 子程序会同时将 BUFFER[8]~BUFFER[15]的内 容清除。 32~35 将 MP0 指向 BUFFER[]数组的起始地址,并设定 SCAN 扫描存储器为 00000001B。 36 设定 TBON 为“1”,TBC 开始计数。 37~38 调用 DELAY 子程序,延迟 100ms;延迟时间的计算请参考【实验 4-1】。 5-38 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 39 40~41 45~63 69~88 设定 TBON 为“0”,停止 TBC 计数。 调用 SHIFT 子程序,将 BUFFER[0]~BUFFER[15]的数据循环移位一次;并重新显 示点矩阵图案(JMP MAIN_1)。 TB0 中断服务子程序,根据 SCAN 存储器之值送出扫描列的信号,并依 MP0 指定 的地址送出对应的位图案。将 SCAN 存储器左移之后判断是否已完成八列的扫描, 若是则重新将 MP0 指向 BUFFER[]数组的起始地址;否则继续下一列扫描。 SHIFT 子程序,运用间接寻址法将存储器 BUFFER[0]~BUFFER[15]内的数据循环 移位一次,如下图: 94~111 COPY 子程序,根据 TBLP 指定的位置,将连续八个地址所存放的点阵数据由程序 存储器复制到 BUFFER[0]~BUFFER[7]数组;并将 BUFFER[8]~BUFFER[15]清除 为零。 5 118~131 DELAY 子程序,延迟时间的计算请参考【实验 4-1】。 133~140 两组点矩阵图案数据建表区。 COPY子程序的功能,是运用间接寻址法将8 Bytes的字型码由程序存储器复制 到数据存储器BUFFER[0]~BUFFER[7],且同时将BUFFER[8]~BUFFER[15]的内 容清除为零。SHIFT子程序则担负起将BUFFER中的数据循环移位一次的工作,以 制造字型移动的显示效果。程序中每次都将BUFFER[0]~BUFFER[7]的字型码重复 显示100ms,所以字型是以每列100ms的速度向上移动,读者可以试着调整DELAY 时间来改变字型移动的快慢。 5-4-5 动动脑+动动手: 试着改写【程序 5-4】,使图案的移动由向上移变成往下移。 是否可以试着写出向左、向右移动的控制程序呢? 若修改 5-3.INC 定义档的设定,使 SCAN_PORT、DOT_PORT 的定义调换; 请问执行结果有何不同?请读者先由分析中预测其结果再与实际的执行结 果比对。 试着增加另一组图案并改写【程序 5-4】,使两个图案交替移动。 第五章 进阶实验篇 5-39 5-5 LCD界面实验 5-5-1 目 的: 本实验介绍液晶显示器(LCD)的基本构造与驱动原理,并利用HT66F50的 LCD输出接口与I/O脚位控制,配合STM Timer/Counter模式的运作,达到在LCD 上显示计时的功能。 5-5-2 学习重点: 通过本实验,读者应了解LCD的驱动原理,并学习如何以HT66F50 COM0~ COM3配合I/O脚位,进行LCD所提供的各项图案与数值显示;另外,对于STM的 计时功能运用应更加熟练。 5-5-3 电路图: 5 【图 5-5-1】LCD 控制电路 在单片机的应用中,人机界面占据相当重要的地位;其主要包括事件输入以及 结果指示,结果指示通常包括LED/LCD显示、通信接口、外围设备操控等等。而 在这些人机界面当中,LCD 显示技术由于其具有显示多样化、成本较低、省电等 特点而得以广泛使用于各式应用场合。 5-40 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 讲解LCD驱动之前,先就其显示原理做一简单的介绍。“LCD(Liquid Crystal Display)”是利用液晶分子的物理结构与光学特性进行显示的一种技术。液晶分 子是介于固体和液体之间的一种棒状结构的大分子物质。在自然状态下,其具有光 学各向异性的特点;而在电(磁)场作用下,则呈现各向同性的特性,以下以TN (Twisted Nematic1)LCD面板的基本结构说明其基本显示原理。 (a)玻璃基板间未加电压 偏光板 玻璃基板 液晶分子涂层 玻璃基板 偏光板 5 螺旋结构 AC (b)玻璃基板间加上电压 【图 5-5-2】LCD 控制电路 如【图5-5-2】所示,LCD面板由上、下玻璃基板与偏光板组成,在两玻璃基 板之间,按照螺旋结构将液晶分子有规律的进行涂层。液晶面板的电极是通过一种 ITO(Indium Tin Oxide)的金属化合物蚀刻在两层玻璃基板上。液晶分子的排列 为螺旋结构,对光线具有“旋光性 (Rotation of Polarization)”,上、下偏光板的 偏振角度相互垂直。当上下基板间未加电压时,自然光通过偏光板后,只有与偏光 板方向相同的光线得以进入液晶分子的螺旋结构涂层中,由于螺旋结构的旋光性, 将入射光线方向旋转九十度后照射到另一端的偏光板上。由于上、下偏光板的偏振 角度相互垂直,入射光线通过另一端的偏光板完全反射,光线完全进入观察者的眼 中,看到的效果就为白色(亮的状态)。若在上、下基板间施加电压时,液晶分子 的螺旋结构在电(磁)场的作用下,变成了同向排列的结构,对入射光线方向未产 生任何旋转作用。然而,由于上、下偏光板的偏振角度相互垂直,入射光线无法经 由另一端的偏光板反射,导致光线无法进入观察者的眼中,此时看到的效果就为黑 色(暗的状态)。如此通过在上、下玻璃基板电极间施加不同的电压,即可实现液 晶显示的两种基本状态:亮(未加偏压)和暗(施加偏压)。在实际的LCD驱动电 压中,有几个参数相当重要: 交流电压,液晶分子是需要交流信号来驱动的,直 1 向列型液晶:液晶分子大致以长轴方向平行配置,因此具有一度空间的规则性排列。此类型液晶的黏度小、反应速 度快,是最早被应用的液晶;普遍使用于液晶电视、膝上型计算机以及各类型显示装置上。 第五章 进阶实验篇 5-41 流电压长时间的加在液晶分子两端,将会影响液晶分子的电气与化学特性,引起显 示模糊以及寿命的减短,其破坏性为不可恢复; 扫描频率,驱动液晶分子的交流 电压频率一般在60~100Hz之间,具体的频率是依LCD面板的面积与设计而定。频 率过高,会增加驱动所需的功耗;频率太低,将导致显示闪烁的情形。 液晶分子是一种电压积分型材料,它的扭曲程度(透光性)仅仅和极板间电压 的有效值2有关,和充电波形无关。LCD显示亮、暗的分界电压称为Vth,当电压有 效值超过Vth,螺旋结构的旋光角度加大;透光率急剧变化、透明度急剧上升。反 之,则透明度急剧下降。光线的透射率与交流电压的有效值关系如【图5-5-3】: 【图 5-5-3】光线的透射率与交流电压的有效值的关系图 5 (a)外观 (b)背板-COM 端布线 (c)SEG 端布线 【图 5-5-4】简易型 LCD 面板布线范例 市面上有许多LCD专用的驱动IC(LCD Driver)或内建LCD驱动接口的单片机, 正是经由系统的控制,依照使用者定义的显示图案,产生点亮LCD所需的驱动波形, 点亮对应的图样(Pattern)而达到显示的效果。然而这类芯片能驱动的点数一般 比较多,在需要少量点数显示的应用场合就显得浪费。单片机的I/O通过适当的程 控与硬件分压的设计,也可以达到驱动LCD的效果;这在一般少点数的LCD应用上 是十分普遍的应用。如【图5-5-4】是一个3 COMs×6 SEGs的简单型LCD面板范 例,厂商除了提供布线图之外,通常也会一并提供如【表5-5-1】的LCD区段码对 应表。读者可将SEG与COM视为【图5-5-2】的上、下玻璃基板电极,所以只要于 两端提供适当的偏压,即可控制各个节段的亮和暗。注意,如前所述,为了避免液 晶分子的寿命减短,此一偏压必须是交流电压!此类LCD是以区段(Segment)方 2 此有效值是指电压的均方根值(Root-Mean-Square;RMS)。 5-42 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 式控制显现图案的,故一般称为“Segment Type”LCD Pannel。 【表 5-5-1】COMs×6 SEGs LCD 对应表 SEG0 SEG1 SEG2 SEG3 SEG4 SEG5 COM0 1e 1d 1c 2e 2d 2c COM1 1b 1a - 2b 3a - COM2 1g 1f - 2g 4f - 【图 5-5-5】以单片机 I/O 引脚驱动 LCD 范例 【图5-5-5】是直接以HT46R22单片机的I/O引脚驱动LCD的范例,请注意在 5 PB[7:6]与PB3引脚上连接了39KΩ的电阻至地,由于HT46R22 I/O引脚的内部上拉 电阻约在30KΩ~50KΩ之间(工作于5V时),通过输出电位的改变与输入/输出模 式的切换,即可提供LCD COM端三组不同的电压: 当PB为输出模式且输出High, COM端电压为VDD; 当PB为输出模式且输出Low,COM端电压为0V(即VSS); 当PB为输入模式时,COM端电压为 。只要能配合程序的控制,在适当时机送 出SEG端与COM端的信号,即可达到LCD显示的效果。【图5-5-6】是COM端电压、 SEG端电压与LCD亮点的关系,请读者参考图中的相关说明;请注意,图中COM 端与SEG端电位差的平均值恒为零,这就达到了“液晶分子需以交流信号驱动”的 基本原则! 第五章 进阶实验篇 5-43 5 【图 5-5-6】LCD 面板的驱动信号 送至SEG端的电压有两种:VA(即VDD)或VSS(即0V);当COM端输出电压 是在VB(即VDD/2)时,由于上、下玻璃基板电极间的偏压仅可能为VDD/2或-VDD/2, 其有效值小于LCD的临界电压Vth,所以此时LCD呈现亮的状态。然而,当COM电 压为VA或VSS时,玻璃基板电极两端的偏压可能为VDD、-VDD或0V。毫无疑问的, 当偏压为0V时,LCD为亮的状态;而若两端电压为VDD或-VDD时,其有效值大于Vth, 故LCD呈现暗的状态。通过如【图5-5-6】的信号机制,在1、2、3三个不同时间区 段分别让COM0~COM2逐一到达VA、VSS的值,再通过SEG电压的配合,可以让 对应的节段在适当时机呈现亮、暗的状态,进而显示出对应的图案或字型。另外, 在1、2、3三个时间区段点亮各节段时,是在COM与SEG端先提供VDD的电压后再 转为-VDD,此方式将可延长LCD的使用寿命。不过,请读者注意,在此所指的“暗” 状态,是指可以看到图样的情况。请参考【图5-5-7】的显示范例;图中所显现的 区段是在电极偏压有效值大于Vth时,各区段呈现暗的状态。 【图 5-5-7】Segment Type LCD 面板应用范例 5-44 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 【图5-5-6】中,在1、2、3三个不同时间区段分别让COM0~COM2逐一输出 VA、VSS的值,让LCD面板呈现一次图案的显现称之为“帧(Frame)”。帧扫描 频率一般在60~100Hz之间,实际的频率是依LCD面板的面积与设计而定。频率过 高,会增加驱动所需的功耗;频率太低,将导致显示图案产生闪烁的情形。LCD的 “占空比(Duty)”是指每个COM的有效选通时间(如【图5-5-6】中COM电压维 持在VA以及VSS的区间)与整个扫描周期的比值;由于 STN/TN的LCD一般是采用 分时动态扫描的驱动模式,其Duty是固定为 。例如【图5-5-4】的简易型LCD 面板,其占空比为 。LCD的偏压是指SEG/COM的电位差,而“偏压比(Bias)” 通常是以最低与最高电位差的比值来表示,如【图5-5-6】所示的驱动波形,其偏 压比为 。一般而言,Bias和Duty之间是有一定关系的;COM数越多,则每根COM 对应的扫描时间变短,若要达到同样的显示亮度和显示对比度,VA电压就要提高, 亮与暗的电位差亦需加大! 5 【图 5-5-8】HT66F50 LCD 驱动接口架构 【图5-5-8】是HT66F50内建的LCD界面,由架构上不难看出它是将一般以单 片机I/O产生LCD驱动信号所需外加的偏压电阻纳入MCU内部,其可提供 、四 个COM(Common)端,至于SEG(Segment)端的段数就取决于使用者对于整 体I/O脚位的定义。通过SCOMC控制寄存器的设定,尚可调整LCD的驱动电流,详 细的说明请读者参阅【2-10节】。 【2-10 节】 【2-4 节】 【2-5-2 节】 SCOMC INTC0 INTC1 MFI0 TM2C0 TM2C1 TM2DL TM2DH TM2AL TM2AH Bit 【表 5-5-2】本实验相关控制寄存器 D7 - ADF T2AF T2PAU T2M1 7 ISEL1 CP0F MF1F T2PF T2CK2 T2M0 6 ISEL0 INT1F MF0F T0AF T2CK1 T2IO1 5 SCOMEN COM3EN COM2EN COM1EN COM0EN INT0F CP0E INT1E INT0E EMI CP1F ADE MF1E MF0E CP1E T0PF T2AE T2PE T0AE T0PE T2CK0 T2ON - - - T2IO0 T2OC T2POL T2DPX T2CCLR TM2D[7:0] TM2D[15:8] TM2A[7:0] TM2A[15:8] 4 3 2 1 0 第五章 进阶实验篇 5-45 本实验的电路如【图5-5-1】所示,LCD的外观与COM/SEG结构请参考【图 5-5-9】与【表5-5-3】。根据【图5-5-5】范例电路的说明,欲产生如【表5-5-3】 规格的LCD驱动信号,需四个不同时间区段(以下简称“Phase”)分别将VDD、 0V的电压送至COM0~COM3以完成一次帧扫描,至于扫描过程中对应的字节 (Segment)是亮或暗,就取决于在SEG0~SEG8所给予的信号电平而定了。 COM0 COM1 COM2 COM3 【表 5-5-3】4 COMs×9 SEGs LCD 对应表 SEG0 SEG1 SEG2 SEG3 SEG4 SEG5 SEG6 SEG7 1a 1b 2a 2b 3a 3b 4a 4b 1f 1c 2f 2c 3f 3c 4f 4c 1g 1d 2g 2d 3g 3d 4g 4d 1e COL 2e ℃ 3e AM 4e PM SEG8 P1 P2 P3 P4 【图 5-5-9】本实验采用的 LCD 字节对应 5 【表 5-5-4】本实验 LCD 驱动信号定义 Phase0 Phase1 Phase2 Phase3 PhaseCount COM0 COM1 COM2 COM3 0 0 V DD 2 V DD 2 V DD 2 1 VDD V DD 2 V DD 2 V DD 2 2 V DD 2 0 V DD 2 V DD 2 3 V DD 2 VDD V DD 2 V DD 2 4 V DD 2 V DD 2 0 V DD 2 5 V DD 2 V DD 2 VDD V DD 2 6 V DD 2 V DD 2 V DD 2 0 7 V DD 2 V DD 2 V DD 2 VDD 送至 Segment 信号电平 Segment 不显现 0 VDD 0 VDD 0 VDD 0 VDD Segment 显现 VDD 0 VDD 0 VDD 0 VDD 0 5-46 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-5-4 程序及流程图: 5 第五章 进阶实验篇 5-47 程序5-5 LCD控制实验 1 ;PROGRAM: 5-5.ASM (5-5.PJT) 2009.1117 2 ;FUNCTION: LCD DEMO PROGRAM By Steven 3 ;NOTE: USING STM AS A 16-BIT TIMER 4 #INCLUDE HT66F50.INC 5 ;======================================================================================== 6 MY_DATA .SECTION 'DATA' ;==DATA SECTION== 7 DEL1 DB ? ;DELAY LOOP COUNT 1 8 DEL2 DB ? ;DELAY LOOP COUNT 2 9 DEL3 DB ? ;DELAY LOOP COUNT 3 10 COUNT DB ? ;COUNTER 11 SECOND DB ? ;SECOND BUFFER 12 MINUTE DB ? ;MINUTE BUFFER 13 DISPBUF DB 5 DUP (?) ;LCD DISPLAY BUFFER 14 DIGIT DB 4 DUP (?) ;DISPLAY DATA 1 15 PhaseCount DB ? ;LCD PHASE COUNT 16 SecCounter DB ? ;COUNTER FOR 0.5 SECOND 17 FG_HalfSEC DBIT ;FLAG FOR 0.5 SECOND 18 STACK_A DB ? ;STACK BUFFER FOR ACC 19 STACK_STATUS DB ? ;STACK BUFFER FOR PSW 20 ;======================================================================================== 21 #INCLUDE 5-5.INC 22 ;======================================================================================== 5 23 MY_CODE .SECTION AT 0 'CODE' ;==PROGRAM SECTION== 24 ORG 00H ;HT-66FX0 RESET VECTOR 25 JMP INIT 26 ORG 14H ;HT-66F50 TB0 INTERRUPT VECTOR 27 JMP ISR_STM 28 INIT: CLR ACERL ;Digital I/O Pin is assigned as a I/O line 29 MOV A,00001000B 30 MOV CP0C,A ;Disable Comparator 0 Function 31 MOV CP1C,A ;Disable Comparator 1 Function 32 CLR SEGBYTEC ;CONFIG SEGBYTE PORT AS OUTPUT MODE 33 CLR SEG9C ;CONFIG SEG9 PORT AS OUTPUT MODE 34 CLR COM0C ;CONFIG COM0 PORT AS OUTPUT MODE 35 CLR COM1C ;CONFIG COM1 PORT AS OUTPUT MODE 36 CLR COM2C ;CONFIG COM2 PORT AS OUTPUT MODE 37 CLR COM3C ;CONFIG COM3 PORT AS OUTPUT MODE 38 MOV A,01111111B ;ENABLE LCD FUNCTION AND, 39 MOV SCOMC,A ;SET COM0~COM3 1/2 BIAS OUTPUT 40 SET MF0E ;ENABLE STM INTERRUPT 41 SET T2AE ;ENABLE T2CCRA COMPARE INTERRUPT 42 CLR TM2C0 ;fINT=fSYS/4=1MHz 43 MOV A,11000001B ;STM IS IN THE TIMER/COUNTER MODE, 44 MOV TM2C1,A ;AND TM2D IS CLEARED BY CCRA COMPARE MATCH 45 MOV A,LOW 4000 ;SET 4ms STM TIMER INTERRUPT 46 MOV TM2AL,A 5-48 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 47 MOV A,HIGH 4000 48 MOV TM2AH,A 49 CLR T2AF ;CLEAR T2AF 50 CLR MF0F ;CLEAR MF0F 51 SET EMI ;ENABLE GLOBAL INTERRUPT 52 CLR PhaseCount ;INITIAL PHASE COUNTER 53 CLR FG_HalfSEC ;CLEAR FLAG 54 MOV A,125 ;INITIAL COUNTER FOR 1 SECOND COUNTING 55 MOV SecCounter,A 56 CLR DISPBUF[0] ;CLEAR ALL DISPLAY BUFFER 57 CLR DISPBUF[1] 58 CLR DISPBUF[2] 59 CLR DISPBUF[3] 60 CLR DISPBUF[4] 61 CLR SECOND ;INITIAL TIMER BUFFER 62 CLR MINUTE 63 CLR DIGIT[0] ;INITIAL DIGIT BUFFER 64 CLR DIGIT[1] 65 CLR DIGIT[2] 66 CLR DIGIT[3] 67 SET COL 5 68 SET AM 69 SET T2ON ;DISPLAY ":" ;DISPLAY "AM" ;START STM 70 MAIN: MOV A,2 ;SET COUNT=2 71 MOV COUNT,A ;2*0.5SEC = 1SEC 72 LOOP: SNZ FG_HalfSEC 73 JMP $-1 ;WAIT FOR 0.5 SECOND 74 CLR FG_HalfSEC ;RESET 0.5 SECOND FLAG 75 SZ PhaseCount ;PHASE COUNT=0 ? 76 JMP $-1 ;NO. WAIT 77 MOV A,10000000B ;TOGGLE LCD "COL(:)" SEGMENT 78 XORM A,DISPBUF[0] 79 SDZ COUNT ;REACH 1 SEC ? 80 JMP LOOP ;NO 81 MOV A,1 ;UPDATE SECOND BUFFER 82 ADD A,SECOND 83 DAA SECOND ;BCD ADJUST 84 MOV A,60H 85 XOR A,SECOND ;1 MINUTE? 86 SNZ Z 87 JMP UPDATE ;NO. 88 CLR SECOND ;YES,RESET SECOND BUFFER 89 MOV A,1 ;UPDATE MINUTE BUFFER 90 ADD A,MINUTE 91 DAA MINUTE ;BCD ADJUST 92 MOV A,60H 93 XOR A,MINUTE ;1 HOUR? 第五章 进阶实验篇 5-49 94 SNZ Z 95 JMP UPDATE ;NO. 96 CLR MINUTE ;YES.RESET MINUTE BUFFER 97 MOV A,10000000B 98 XORM A,DISPBUF[2] ;TOGGLE LCD "AM" SEGMENT 99 XORM A,DISPBUF[3] ;TOGGLE LCD "PM" SEGMENT 100 UPDATE:SWAPA MINUTE ;UPDATE HIGH NIBBLE 101 AND A,0FH 102 MOV DIGIT[0],A 103 MOV A,MINUTE ;UPDATE LOW NIBBLE 104 AND A,0FH 105 MOV DIGIT[1],A 106 SWAPA SECOND ;UPDATE HIGH NIBBLE 107 AND A,0FH 108 MOV DIGIT[2],A 109 MOV A,SECOND ;UPDATE LOW NIBBLE 110 AND A,0FH 111 MOV DIGIT[3],A 112 JMP MAIN ;RE-DO 113 ORG LASTPAGE-100H 114 ;======================================================================================== 115 ; STM INTERRUPT SERVICE ROUTINE 116 ; 4 COMs x 13 SEGMENTs LCD SCANNING PROCEDURE 5 117 ;======================================================================================== 118 ISR_STM:MOV STACK_A,A ;PUSH A 119 MOV A,STATUS 120 MOV STACK_STATUS,A ;PUSH STATUS 121 CLR T2AF 122 MOV A,PhaseCount 123 XOR A,0 124 SNZ Z ;CHECK IF PhaseCount=0 125 JMP $+3 ;NO 126 CALL UPDATE_DISPALY ;YES. 127 JMP ISR_STM_1 128 SZ PhaseCount.0 ;NO.CHECK IF PhaseCount=2,4,6 ? 129 JMP $+6 ;NO. 130 RR DISPBUF[0] ;YES,ROTATE LEFT DISPBUF[] 131 RR DISPBUF[1] 132 RR DISPBUF[2] 133 RR DISPBUF[3] 134 RR DISPBUF[4] 135 CPL DISPBUF[0] ;COMPLEMENT DISPBUF[] 136 CPL DISPBUF[1] 137 CPL DISPBUF[2] 138 CPL DISPBUF[3] 139 CPL DISPBUF[4] 140 ISR_STM_1: 5-50 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 141 CALL SEGMENTOUT ;SET SEGMENT 1~9 STATE 142 MOV A,PhaseCount 143 ADDM A,PCL ;COMPUTATIONAL JUMP 144 JMP COM0_0 ;JUMP COM0 LOW PROCESS 145 JMP COM0_1 ;JUMP COM0 HIGH PROCESS 146 JMP COM1_0 ;JUMP COM1 LOW PROCESS 147 JMP COM1_1 ;JUMP COM1 HIGH PROCESS 148 JMP COM2_0 ;JUMP COM2 LOW PROCESS 149 JMP COM2_1 ;JUMP COM2 HIGH PROCESS 150 JMP COM3_0 ;JUMP COM3 LOW PROCESS 151 JMP COM3_1 ;JUMP COM3 HIGH PROCESS 152 COM0_0: CLR COM0EN ;DISABLE COM0 PORT 1/2 BIAS OUTPUT 153 CLR COM0 ;SET COM0 PORT LOW 154 JMP COM3_0+2 155 COM0_1: CLR COM0EN ;DISABLE COM0 PORT 1/2 BIAS OUTPUT 156 SET COM0 ;SET COM0 PORT HIGH 157 JMP COM3_0+2 158 COM1_0: CLR COM1EN ;DISABLE COM1 PORT 1/2 BIAS OUTPUT 159 CLR COM1 ;SET COM1 PORT LOW 160 JMP COM3_0+2 161 COM1_1: CLR COM1EN 5 162 SET COM1 163 JMP COM3_0+2 ;DISABLE COM1 PORT 1/2 BIAS OUTPUT ;SET COM1 PORT HIGH 164 COM2_0: CLR COM2EN ;DISABLE COM2 PORT 1/2 BIAS OUTPUT 165 CLR COM2 ;SET COM2 PORT LOW 166 JMP COM3_0+2 167 COM2_1: CLR COM2EN ;DISABLE COM2 PORT 1/2 BIAS OUTPUT 168 SET COM2 ;SET COM2 PORT HIGH 169 JMP COM3_0+2 170 COM3_0: CLR COM3EN ;DISABLE COM3 PORT 1/2 BIAS OUTPUT 171 CLR COM3 ;SET COM3 PORT LOW 172 INC PhaseCount 173 JMP $+19 174 COM3_1: CLR COM3EN ;DISABLE COM3 PORT 1/2 BIAS OUTPUT 175 SET COM3 ;SET COM3 PORT HIGH 176 CLR PhaseCount ;RESET PHASE COUNTER TO RE-START 177 RR DISPBUF[0] ;RESTORE DISPLAY BUFFER 178 SWAP DISPBUF[0] 179 CPL DISPBUF[0] 180 RR DISPBUF[1] 181 SWAP DISPBUF[1] 182 CPL DISPBUF[1] 183 RR DISPBUF[2] 184 SWAP DISPBUF[2] 185 CPL DISPBUF[2] 186 RR DISPBUF[3] 187 SWAP DISPBUF[3] 第五章 进阶实验篇 5-51 188 CPL DISPBUF[3] 189 RR DISPBUF[4] 190 SWAP DISPBUF[4] 191 CPL DISPBUF[4] 192 SDZ SecCounter ;CHECK IF 0.5 SECOND 193 JMP $+4 194 MOV A,125 ;RELOAD COUNTER 195 MOV SecCounter,A 196 SET FG_HalfSEC ;SET FLAG 197 MOV A,STACK_STATUS 198 MOV STATUS,A ;POP STATUS 199 MOV A,STACK_A ;POP A 200 RETI 201 ;======================================================================================== 202 ; PROC : SEGMENTOUT 203 ; FUNC : OUTPUT SEGMENT STATE IN DISPBUF[0]~DISPBUF[4] 204 ;======================================================================================== 205 SEGMENTOUT PROC 206 MOV A,00001111B ;SET COM0~COM3=VDD/2 207 ORM A,SCOMC 208 CLR SEGBYTE ;SET SEG1~SEG8 TO LOW 209 CLR SEG9 ;SET SEG9 TO LOW 210 SZ DISPBUF[0].0 ;DISPBUF[0].0=0 ? 5 211 SET SEG1 ;NO,SET SEG1 PROT HIGH 212 SZ DISPBUF[0].4 ;DISPBUF[0].4=0 ? 213 SET SEG2 ;NO,SET SEG2 PROT HIGH 214 SZ DISPBUF[1].0 ;DISPBUF[1].0=0 ? 215 SET SEG3 ;NO,SET SEG3 PROT HIGH 216 SZ DISPBUF[1].4 ;DISPBUF[1].4=0 ? 217 SET SEG4 ;NO,SET SEG4 PROT HIGH 218 SZ DISPBUF[2].0 ;DISPBUF[2].0=0 ? 219 SET SEG5 ;NO,SET SEG5 PROT HIGH 220 SZ DISPBUF[2].4 ;DISPBUF[2].4=0 ? 221 SET SEG6 ;NO,SET SEG6 PROT HIGH 222 SZ DISPBUF[3].0 ;DISPBUF[3].0=0 ? 223 SET SEG7 ;NO,SET SEG7 PROT HIGH 224 SZ DISPBUF[3].4 ;DISPBUF[3].4=0 ? 225 SET SEG8 ;NO,SET SEG8 PROT HIGH 226 SZ DISPBUF[4].0 ;DISPBUF[4].0=0 ? 227 SET SEG9 ;NO,SET SEG9 PROT HIGH 228 RET ;YES,RETURN 229 SEGMENTOUT ENDP 230 ;======================================================================================== 231 ; PROC : UPDATE_DISPALY 232 ; FUNC : UPDATE DISPBUF[0]~DISPBUF[3] BY DIGIT[0] TO DIGIT[3] 233 ; PARA : ACC : DELAY FACTOR 234 ; CALL : TRANS_SEGMENT 5-52 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 235 ;======================================================================================== 236 UPDATE_DISPALY PROC 237 MOV A,10000000B ;CLEAR DISPBUF[] BUT RESERVED MSB STATE 238 ANDM A,DISPBUF[0] 239 ANDM A,DISPBUF[1] 240 ANDM A,DISPBUF[2] 241 ANDM A,DISPBUF[3] 242 MOV A,DIGIT[0] ;UPDATE DISPBUF[0] BY DIGIT[0] 243 CALL TRANS_SEGMENT 244 ORM A,DISPBUF[0] 245 MOV A,DIGIT[1] ;UPDATE DISPBUF[1] BY DIGIT[1] 246 CALL TRANS_SEGMENT 247 ORM A,DISPBUF[1] 248 MOV A,DIGIT[2] ;UPDATE DISPBUF[2] BY DIGIT[2] 249 CALL TRANS_SEGMENT 250 ORM A,DISPBUF[2] 251 MOV A,DIGIT[3] ;UPDATE DISPBUF[3] BY DIGIT[3] 252 CALL TRANS_SEGMENT 253 ORM A,DISPBUF[3] 254 RET 255 UPDATE_DISPALY ENDP 5 256 ;======================================================================================== 257 ; PROC : TRANS_SEGMENT 258 ; FUNC : TRANSLATE 0~9 DIGIT TO SEGMENT CODE 259 ;======================================================================================== 260 TRANS_SEGMENT: ;Pdcbegfa ;SEGMENT ORDER 261 ADDM A,PCL 262 RET A,01111011B ;'0' 263 RET A,00110000B ;'1' 264 RET A,01011101B ;'2' 265 RET A,01110101B ;'3' 266 RET A,00110110B ;'4' 267 RET A,01100111B ;'5' 268 RET A,01101111B ;'6' 269 RET A,00110001B ;'7' 270 RET A,01111111B ;'8' 271 RET A,01110111B ;'9' 272 END 程程序序解解说说:: 7~19 依序定义变量地址。 21 载入”5-5.INC”定义档,其内容请参考随书光盘中的档案。 24 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 26 声明内存地址由 14h 开始(HT66Fx0 STM 中断向量地址)。 第五章 进阶实验篇 5-53 28~31 关闭 CP0、CP1 功能,并设定 ADC 脚位输入为 I/O 功能。 32~37 将 SEG_BYTE、SEG9 以及 COM0~COM3 成输出模式。 38~39 使能 SCOM 接口功能,并设定偏压电流为 200µA。 40~41 使能 MF0E 与 STM 中断(T2AE)。 42~42 定义 TM2C0、TM2C1 控制寄存器: T2CK[2:0]:000,设定 fINT=fSYS/4; T2M[1:0]:11,设定为 Timer/Counter 模式; T2CCLR:0,当 TM2D=TM2A 时(即比较器 A 比较匹配时)清除计数器。 45~48 设定 TM2A=4000;因此 STM 比较匹配时间为 4000×1µs=4ms(@ fSYS=4MHz)。 49~51 清除 T2AF、MF0F 中断标志,并使能中断总开关(EMI),HT66F50 可开始接受 T2AE 中断。 52 清除 PhaseCount 存储器,此存储器用以判断目前是 LCD 扫描的第几个相次;请参 考【表 5-5-4】。 53 清除 FG_HalfSEC 标志,此标志当计时达 0.5 秒时会由 STM_ISR 中断服务子程序 设定为“1”,做为程序后续处理的判断依据。 5 54~55 设定 SecCounter 为 125,此存储器会由 ISR_STM 中断服务子程序递减,125×4ms =0.5 秒。 54~62 清除 SECOND、MINUTE、DISPBUF []与 DIGIT[]数组;DISPBUF []存放节段的显 示数据,DIGIT[]则存放计时时间,SECOND、MINUTE 分别为秒、分的计时存储器。 67~68 设定显示 COL(:)与 AM 节段。 69 启动 STM 开始计数。 70~71 设定 COUNT 为二,用以判定是否已计时一秒钟。 72~74 等待 0.5 秒的计时时间,若时间已到则清除 FG_HalfSEC 标志。 75~76 等待 PhaseCount 为零。 77~78 将 COL(:)节段反向,用以产生每 0.5 秒闪、灭的效果。 79~80 判断是否已计时一秒钟,若时间已到则更新 DIGIT[]数组的计时时间;否则跳至 LOOP 继续等待。 81~112 此 段 程 序 为 计 时 达 一 秒 钟 时 的 处 理 程 序 , 其 按 照 计 时 的 进 位 规 则 逐 一 递 增 SECOND、MINUTE 存储器之值,并依 SECOND、MINUTE 更新 DIGIT[0]~DIGIT[3] 5-54 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 存储器的数值;若计时已到达“59:59”则先将 AM、PM 节段的状态切换,并继 续执行(JMP MAIN)。 113 由于 ISR_STM 中断服务子程序中有许多计算式的跳转与查表运算,为避免发生跨 页而导致程序执行不正常,故索性将整段程序置于倒数第二页的程序存储器空间。 118~200 ISR_STM 中断服务子程序,这段程序主要掌控 LCD COM0~COM3 的扫描时序, 每 4ms 中断一次,送出 COM0~COM3 的电平与节段亮、灭的电平。同时每 0.5 秒就设定 FG_HalfSEC 标志,做为主程序后续处理的判断依据。 122~126 判断 PhaseCount 是 否为 零,若是则调 用 UPDATE_DISPLAY 子程序 ;依据 DIGIT[0]~DIGIT[3]的内容更新 DISPBUF[0]~DISPBUF[3]的值,并跳至显示程序 (JMP ISR_STM_1)。 128~139 判断 PhaseCount 是否为偶数,若成立则将 DISPBUF[0]~DISPBUF[3]的内容右移 一位;若为奇数,则将 DISPBUF[0]~DISPBUF[3]的内容取反向。请读者参考【表 5-5-4】,当 PhaseCount 为偶数时,正值扫描的 COM 端电位为 0,所以欲显现的 节段应送高电平(即 VDD);而当 PhaseCount 为奇数时,正值扫描的 COM 端电 5 位为 VDD,欲显现的节段应送低电平,因此必须将显示的节段状态反向。而送出的 节段数据是每两次更新(右移)一次。 141 调用 SEGMENTOUT 子程序;依据 DISPBUF[0]~DISPBUF[3]的值设定各节段的 状态,VDD 或 0V。 134~191 依据 PhaseCount 之值,设定 COM0~COM3 的输出电平为 0、VDD 或 VDD/2;请读 者参考【表 5-5-4】。若 PhaseCount 为 7 时表示已完成一个帧扫描,除将 PhaseCount 重新设为零之外,并将历经三次移位、七次取反向的 DISPBUF[0]~DISPBUF[3]存 储器数据还原,以保留最高位的节段状态。 192~196 判断 SecCounter 减一是否为零,若是代表 0.5 秒的计时时间已到,设定 FG_HalfSEC 标志,并重新设定 SecCounter 为 125。 205~229 SEGMENTOUT 子程序,依据 DISPBUF[0]~DISPBUF[3]的值设定各节段的状态 (VDD 或 0);DISPBUF[0]~DISPBUF[3]存储器与各节段的对应关系请参考【表 5-5-5】。除了 DISPBUF[4]之外,其它每个存储器有两个位对应到的节段是由同一 个 COM 端所控制,所以本段程序就以每个存储器的两个位(Bit-4 与 Bit-0)做为节 段状态设定的依据,每做完一个 COM 端的扫描就将 DISPBUF[0]~DISPBUF[3]右 移一位(130~134 行),作为下一个 COM 端的节段状态判定。 第五章 进阶实验篇 5-55 【表 5-5-5】DISPBUF[0]~DISPBUF[3]与节段的关系 Bit 7 6 5 4 3 2 1 DISPBUF[0] COL 1d 1c 1b 1e 1g 1f DISPBUF[1] ℃ 2d 2c 2b 2e 2g 2f DISPBUF[2] AM 3d 3c 3b 3e 3g 3f DISPBUF[3] PM 4d 4c 4b 4e 4g 4f DISPBUF[4] - - - - P4 P3 P2 COM COM0 COM1 COM2 COM3 COM0 COM1 COM2 0 1a 2a 3a 4a P1 COM3 236~255 UPDATE_DISPLAY 子程序,依据 DIGIT[0]~DIGIT[3]的内容更新 DISPBUF[0]~ DISPBUF[3]的值;请注意,为了保留 DISPBUF[0]~DISPBUF[3]最高位所代表的节 段状态,并不是直接将数据搬入存储器,而是先将 DISPBUF[0]~DISPBUF[3]与 1000000b AND 之后再与根据 DIGIT[0]~DIGIT[3]所查回的建表数据做 OR 运算。 260~271 LCD 字形建表区。 有了【实验5-3】与【实验5-4】的点矩阵显示控制经验之后,对于LCD的扫描 控制应该也不致过于陌生。要注意的是每一个节段的亮灭控制要比点矩阵来的复 杂,并非单纯的“高电位-亮”、“低电位-灭”的控制逻辑,而必须考虑COM 端的电平状态,当COM端为VDD/2时,节段恒为熄灭状态;而当COM端为VDD时, 5 则节段为“低电位-亮”、“高电位-灭”。反之,若COM端为零时,节段为“高 电位-亮”、“低电位-灭”。 【程序5-5】的说明中已详述的各片段程序的功能,读者若能配合有关LCD的 原理说明并参考【表5-5-5】,应该可以洞悉其中的精髓。根据【表5-5-5】,笔者 将COM0~COM3扫描的四个时相(Phase),以PhaseCount区分为八个相次。此 举是为了延长LCD的使用寿命,必须尽量让加诸于LCD的偏压平均值为零,因此将 每个COM端的扫描分为0V与VDD两个相次。而253~264行的LCD字形建表数据是依 据COM端为0V的相次时,节段(Segment)的亮灭状态所设定。所以在相次为奇 数时(即COM0~COM3电平设定分别为VDD),必须将节段数据反向方能显现正 确的图案,而程序中是除了PhaseCount为零之外,每次都对DISPBUF[]数组取反 向的动作,每取两次就恢复原来非反向之值,而PhaseCount此时恰为偶数(即 COM0~COM3电平设定分别为0V时)! 5-5-5 动动脑+动动手: 请将【程序 5-5】第 75~76 行等待 PhaseCount 为零的指令删除,观察 LCD 的显示有何变化(请特别注意“:”节段的闪烁速率),为什么? 试更改【程序 5-5】中的扫描速率(即更改 TM2A 的设定值),观察 LCD 的 5-56 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 显示有何变化。 试更改【程序 5-5】中的 LCD 偏压电流的设定(即更改 ISEL[1:0]的设定值), 观察 LCD 的显示有何变化。 试更改【程序 5-5】使其计数时间为 24 小时时钟(“00:00”~“23:59”)。 承上题,但将显示时间改为“00:00”~“12:00”,并辅以 AM、PM 表 示。 试将【程序 5-5】与【程序 4-11】结合,将 A/D 转换器的转换结果以十六进 制显示于 LCD 上。 承上题,但将显示值改为十进制。 5 5-57 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-6 LCM字型显示实验 “液晶显示器(Liquid Crystal Display;LCD)”的显示原理与驱动方式,在 【5-5节】已有详细的介绍,相信读者也已领略到要驱动多点数的LCD面板并非一 件容易的事!而本节所介绍的“LCM(Liquid Crystal Display Module)”,是指 内含驱动芯片的LCD模块(以下简称LCM),其架构如【图5-6-1】所示;使用者 只要了解驱动芯片控制的方式就可以了,复杂的LCD驱动信号就交给驱动芯片自行 产生吧! 【图 5-6-1】 5 LCM一般可分为“文字(Text)型”以及“绘图(Graphic)型”两大类,本 实验将以介绍文字型液晶显示模块为主,由于其显示方式是电压驱动,因此电路本 身所需的工作电流非常低,再加上又有许多的内建字型,所以被广泛的应用于讲求 人机界面的各种场合,例如传真机、复印机、计算器及各式数字仪器上。 目前市面上常见的文字型LCM模块,不管是可以显示几列、几个字,通常内部 的控制器(LCD Controller;【图5-6-1】中的LCD控制器)都是使用由日本HITACHI 公司制造的-HD44780A或与其兼容的驱动芯片(如KS0066U)来控制。所以, 即使购买的LCM是不同厂牌或型号的文字型LCD模块,其控制方法都大同小异。再 进行实验之前,先对此驱动芯片的特性做一番介绍。HD44780A内部共有80个字节, 可供储存单片机送过来的显示数据。本章节将针对其控制方式及特性加以详细说 明。 5-58 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 LCM模块引脚说明: 脚位 1 2 3 4 5 6 符号 Vss VDD VC RS RW E 7~14 DB0~DB7 15~16 VA、VK 方向 - - - I I I I/O - 【表 5-6-1】LCM 模块引脚说明 名 称 及 功 能 电源接地端(Ground)。 电源正端:接+5V。 亮度调整电压输入端(Contrast Adjustment Voltage),输入 0V 时字符最清晰。 寄存器选择:“Low”:指令寄存器(IR) “High”:数据寄存器(DR) 读/写控制:“Low”:写入数据或命令至 LCM “High”:读取 LCM 数据 使能信号:“Low”:LCM 使能 “High”:LCM 除能 数据总线:以 8 位控制方式时, DB0 ~ DB7 皆有效。 若以 4 位控制方式,则仅 DB4~ DB7 有效,DB0~DB3 不必连接。 LCD 须在有光源的地方方能看到显示的字形,部份 LCM 模块在背板上附加了 LED 以提供光源。此时 15 脚为背板 LED 阳极(Anode)输入、16 脚则为阴极(Cathode)。 市售LCM模块一般皆为十四或十六个引脚,且功能及引脚位置大致相同,但实 际应用时仍需先确定其引脚规格与电气特性。另外,具背光功能的LCM模块会有额 外的两个引脚,做为背光装置的电源输入之用;各引脚的功能说明,请参考【表 5-6-1】。 如何让 LCM 显示数据: 5 HD44780内部储存显示数据的内存(共80 Bytes),称为“Display Data RAM (DD RAM)”。以20(字)×2(列)LCM为例,其DD RAM的地址分配,第一 列从00h到13h;第二列由40h到53h。只要事先定义好LCM的功能,再将欲显示数 据的“字符码(Character Code;恰好为ASCII Code)”写到LCM内部的DD RAM, LCM就会将这个字在其对应的位置上显示出来;例如:要在LCM的第一列显示一 个“A”,那么只要先设定显示地址为00h,再将41h(“A”的ASCII码)写入到 DD RAM即可。若欲显示在第二列时,则需设定显示地址为40h,至于显示地址与DD RAM的对应关系请参考【表5-6-2】。 第五章 进阶实验篇 5-59 【表 5-6-2】显示地址与 DD RAM 的对应关系 012 … 14 15 显示位置 00h 01h 02h … 0Eh 0Fh DD RAM地址 (a)16×1 LCM 第一列 第二列 012 … 18 19 00h 01h 02h … 12h 13h 40h 41h 42h … 52h 53h (b)20×2 LCM 显示位置 DD RAM地址 DD RAM地址 012 … 18 19 显示位置 第一列 00h 01h 02h … 12h 13h DD RAM地址 第二列 40h 41h 42h … 52h 53h DD RAM地址 第三列 14h 15h 16h 26h 27h DD RAM地址 第四列 54h 55h 56h 66h 67h DD RAM地址 (c)20×4 LCM 5 HD44780的结构与功能: HD44780的主要特性如下: 80 Bytes 的DD RAM(Display Data Memory); 有一内建192个5×7字型的CG ROM(Character Generator ROM); 64 Bytes的CG RAM(Character Generator RAM),可提供使用者自建 八个字型(每个字型由8 Bytes组成); 内部有两个寄存器:指令寄存器(Instruction Register;IR)与数据寄存 器(Data Register;DR)。 IR寄存器(Instruction Register)仅可写入,其功能是接收命令以定义LCM, 例如清除显示、LCM功能设定、DD RAM或CG RAM地址设定、...等命令,稍后将 会针对LCM的指令加以详细的说明。 DR寄存器(Data Register)则有以下功能: 做为外部写数据到LCM DD RAM或CG RAM时的数据缓冲区; 做为外部读取LCM DD RAM或CG RAM数据时的数据缓冲区。在读出数 据后,DD RAM或CG RAM下一个地址的内容会被自动放入DR寄存器, 以备外界的读取。 5-60 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 LCM内部的标志与存储器: 忙碌标志(Busy Flag,BF):因为LCM在处理内部工作时,通常要花 上40µS ~ 1.64mS的时间,但外部控制的芯片(如HT66Fx0)执行一个 指令,通常只要几个µS,如果单片机将命令或数据持续不断的送给LCM 的话,LCM会因为反应不及而导致大部分数据都无法正常写入!所以, 单片机在存取LCM数据之前,一定要先检查BF标志。若BF=“1”,表 示LCM正在处理内部的工作,此时外部用来控制LCM的芯片无法对LCM 做任何写入的动作;反之,当BF=“0”时,则表示外部控制芯片可以存 取LCM的数据。 数据显示存储器(Display Data RAM,DD RAM):DD RAM共80 Bytes, 用以存放欲显示数据的字符码。一个DD RAM地址对应一个显示位置, 只要写入不同的字符码即可显示不同的字型,未对应到显示的DD RAM, 则可供使用者自由使用。至于显示地址与DD RAM的对应关系,请参考 【表5-6-2】。 字符产生器存储器(Character Generator ROM,CG ROM):LCM内 5 部有存放内建字型的ROM,称为CG ROM,内建192个5×7的点矩阵字型, 如【表5-6-3】所示。当外部控制芯片将这些字型的字符码写入DD RAM 时,CG ROM就会自动将相对应的字型显示出来。而字型栏中的CG RAM(1)、CG RAM(2)、… ,是表示当欲显示数据的字符码为0H~07H 时,是叫出CG RAM里由使用者自建的造型码加以显示,而不是CG ROM 内建的字型。 自建字符产生器存储器(Character Generator RAM,CG RAM):CG RAM提供使用者存放八个自己所设计的5×7点矩阵造型数据码(若不需 要显示光标时,则可设计5×8点矩阵造型数据码),以便显示所需的特殊 字符造型。字符码与CG RAM地址的对应关系,请参考【表5-6-4】。当 显示数据的字符码为00h~07h,即可叫出相对存放于CG RAM位置内的 字型并加以显示。 地址计数器(Address Counter,AC):AC是用来指示写数据到DD RAM 或CG RAM的地址。使用地址设定命令将地址写入IR寄存器后,地址信 号就会由IR寄存器传到AC,当数据写入或读出后,AC的内容值会自动加 一或减一(由进入模式命令中的I/D值决定的)。 第五章 进阶实验篇 5-61 【表 5-6-3】HD44780A 字符码与字型对应表 5 【表 5-6-4】字符码与 CG RAM 地址及自造字型对应表 5-62 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 指令 清除显示器 光标归位 进入模式 显示器 ON/OFF 控制 【表 5-6-5】HT44780A LCM 模块指令表 指 令 码 RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 指 令 说 明 执行 时间 0 0 0 0 0 0 0 0 0 1 DD RAM 里的所有地址填入空白码 20H,AC 设定 为“00”h,I/D 设定为“1” 1.64ms 0 0 0 0 0 0 0 0 1 X DD RAM 的 AC 设为 0H,光标回到左上角第一行的 第一个位置,DD RAM 内容不变。 1.64ms I/D=0 CPU 写数据到 DD RAM 或读取数据之后 AC 减 1,光标会向左移动 0 0 0 0 0 0 0 1 I/D S I/D=1 CPU 写数据到 DD RAM 或读取数据之后 AC 加 1,光标会向右移动 S=0 显示器画面不因读写数据而移动。 40µs CPU 写数据到 DD RAM 后,整个显示器会 S=1 向左移(若 I/D=0)或向右移(若 I/D=1),但从 DD RAM 读取数据时则显示器不会移动 显示器控制: D=0:所有数据不显示 D=1:显示所有数据 0 0 0 0 0 0 1 DC B 光标控制: C=0:不显示光标 C=1:显示光标 40µs 光标闪数控制: B=0:不闪烁 B=1:闪烁 S/C=0,R/L=0:光标位置向左移( AC 值减 1 ) 5 光标或显 示器移动 0 0 0 0 0 1 S/C R/L X X S/C=0, R/L=1:光标位置向右移( AC 值加 1 ) S/C=1, R/L=0:显示器与光标一起向左移 S/C=1, R/L=1:显示器与光标一起向右移 40µs 设定数据位长度: DL=0:使用四位(DB7~DB4)控制模式 DL=1:使用八位(DB7~DB0)控制模式 功能设定 0 0 0 0 1 DL N F X X 设定显示器的行数: 40µs N=0:单列显示 N=1:双列显示两行 设定字型: F=0:5 X 7 点阵字型 F=1:5 X 10 点阵字型 CG RAM 地址设定 0 0 01 CG RAM Address 将 CG RAM 的地址( DB5~DB0 )写入 AC 40µs DDRA 地址设定 001 DD RAM Address 将 DD RAM 的地址( DB6~DB0 )写入 AC 40µs 读取忙碌标志 和地址 0 1 BF Address Counter BF=1,表示目前 LCM 正忙着内部的工作,因此无 法接受外部的命令,必须等到 BF=0 之后,才可以 0 接受外部的命令。在(DB6~DB0)可读出 AC 值 写资料到 CG RAM 或 1 0 Write Data 将数据写入 DD RAM 或 CG RAM 40µs DD RAM 从 CG RAM 或 DD RAM 1 1 读取数据 Read Data 读取 CG RAM 或 DD RAM 数据 40µs LCM 模块指令说明: 【表5-6-5】为LCM模块的控制指令,LCM执行这些命令要花40µs~1.64ms的 时间,使用者只要将这些命令写入IR寄存器,即可对LCM进行定义及控制。 (1)- 清除显示器(Clear Display) RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 指令码 0 0 0 0 0 0 0 0 0 1 第五章 进阶实验篇 5-63 指令会将DD RAM里的所有地址填入空白码(20h),且将DD RAM的地址计 数器(即AC)设定为00h,并将I/D设定为1(亦即当写数据到DD RAM或读取数据 之后AC会加一,光标会向右移动)。 (2)- 光标归位(Cursor Home) RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 指令码 0 0 0 0 0 0 0 0 1 X X:Don’t Care 此指令会将DD RAM的“地址计数器(AC)”设为00h,但不会改变DD RAM 内部的值;它与第一个指令的差异就是不会清除DD RAM内原有的数据,只是单纯 的将光标归位。 (3)- 进入模式(Entry Mode) RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 指令码 0 0 0 0 0 0 0 1 I/D S 此指令会设定光标移动的方向,以及显示器是否要移动,其中: I/D=0:当外部写数据到DD RAM或从DD RAM读取数据之后,地址计数器(AC) 将会被减1,因此光标会向左移动。 I/D=1:当外部写数据到DD RAM或从DD RAM读取数据之后,地址计数器(AC) 5 将会被加1,因此光标会向右移动。 S=1: 当外部写数据到DD RAM后,整个显示器会向左移(若I/D=0)或向右移(若 I/D=1),但从DD RAM读取数据时则显示器不会移动。 S=0: 显示器画面不会因为外部读写数据而移动。 (4)- 显示器ON/OFF控制(Display ON/OFF) RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 指令码 0 0 0 0 0 0 1 D C B 此指令控制了整个显示器和光标的显示(ON)或不显示(OFF),以及光标 闪烁与否。 D=0:所有数据都不显示; D=1:显示所有数据; C=0:不显示光标; C=1:显示光标; B=0:光标不闪烁; B=1:光标闪烁; (5)- 光标或显示器移动(Cursor or Display Shift) RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 指令码 0 0 0 0 0 1 S/C R/L X X 此指令可以在不改变显示数据的情况下,移动光标位置或是控制显示器向左或 向右移动。 S/C R/L 动 作 0 0 光标位置向左移( AC值减1 ) 5-64 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 0 1 光标位置向右移( AC值加1 ) 1 0 显示的数据连同光标一起向左移 1 1 显示的数据连同光标一起向右移 注:如果只移动显示数据,则AC的内容不会改变。 以20×2的LCM为例,虽然可以看见的DD RAM为40个,但是LCM屏幕上却不 一定是只有对应到00h~13h与40h~53h的地址,使用者可以控制LCM屏幕左、右移 动以观看不同的地址数据,其关系如【图5-6-2】所示: 26h 27h 00h 01h 02h … 11h 12h 13h 14h 15h … 66h 67h 40h 41h 42h … 51h 52h 53h 54h 55h … 屏幕不移动时,LCM显示与DD RAM的地址关系 26h 27h 00h 01h 02h … 11h 12h 13h 14h 15h … 66h 67h 40h 41h 42h … 51h 52h 53h 54h 55h … 屏幕左移一次时,LCM显示与DD RAM的地址关系 26h 27h 00h 01h 02h … 11h 12h 13h 14h 15h … 66h 67h 40h 41h 42h … 51h 52h 53h 54h 55h … 屏幕右移一次时,LCM显示与DD RAM的地址关系 【图 5-6-2】LCM 显示与 DD RAM 的地址关系 5 (6)- 功能设定(FunctionSet) RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 指令码 0 0 0 0 1 DL N F X X 在定义LCM时,功能设定(FunctionSet)指令必须最先执行!其指令功能说 明如下: A. 设定数据位长度 DL=0:使用四位(DB7~DB4)控制模式,数据的读或写必须分成两次完成 (先读写高四位,其次再读写低四位)。 DL=1:使用八位(DB7~DB0)控制模式。 B. 设定显示器的列数 N=0:单列显示。 N=1:双列显示。 C. 设定字型 F=0:5 × 7点矩阵字型。 F=1:5 ×10点矩阵字型。注意:设定为5 ×10点矩阵字型时,LCM将只显示 单一列。 【图5-6-3】与【图5-6-4】分别是LCM与外部单片机以四位及八位总线连接方 式的接口。如【图 5-6-3】所示,使用四位总线模式时,必须接到LCM的DB7~DB4 这四条总线上,如此LCM方能正常工作,此时必须将一个Byte的数据分成两次读写, 第五章 进阶实验篇 5-65 并且是高四位先读写之后才是低四位的读写,如此才算真正完成一个Byte数据的存 取动作!而以八位总线连接方式时,则只需读写一次即完成存取一个Byte数据的动 作,这是四位与八位总线连接接口最大的不同。虽然四位控制模式较为繁琐,但在 I/O资源有限的情况之下,有时又不得不采用。 7 DB0 DB2 DB1 10 DB3 11 DB4 12 DB5 13 DB6 14 DB7 9 8 【图 5-6-3】LCM 四位总线连接接口 5 【图 5-6-4】LCM 八位总线连接接口 (7)- CG RAM地址设定(Set CG RAM Address) RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 指令码 0 0 0 1 A A A A A A 此指令是将CG RAM的地址(DB5~DB0)写入地址计数器(AC)。使用者在建 立自己的字型时,必须先利用此一指令设定所欲输入字型的地址。 (8)- DD RAM地址设定(Set DD RAM Address) RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 指令码 0 0 1 A A A A A A A 此指令是将DD RAM的地址(DB6~DB0)写入“地址计数器(AC)”内。使用 者可以利用此一指令,改变字型在LCM上的显示位置。 5-66 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 (9)- 读取忙碌标志(BF)和地址(AC)(Read Busy Flag and Address) RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 指令码 0 1 BF A A A A A A A 当BF=“1”,表示目前HD44780正忙着内部的工作,因此LCM无法再接受 外部输入的命令或数据,必须等到BF=“0”之后,才可继续接受命令或数据。在 读取BF的同时,也会读到地址计数器的值(DB6~DB0),读出的地址可能是CG RAM或是DD RAM的地址,须视先前的地址指令是针对CG RAM或DD RAM的地址 而定。 (10)- 写数据到CG RAM或DD RAM(Write Data to CG or DD RAM) RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 指令码 1 0 D D D D D D D D 此指令功能为,依前一次地址指令所设定的RAM的地址(CG RAM或DD RAM),将数据(DB7 ~DB0)写入到DD RAM或CG RAM中。 5 (11)- 自CG RAM或DD RAM读取数据(Read Data from CG or DD RAM) RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 指令码 1 1 D D D D D D D D 此指令功能为读取CG RAM或DD RAM的数据。至于究竟是读CG RAM或是 DD RAM,则需依前一次地址设定指令所设定的RAM(CG RAM或DD RAM)为主。 第五章 进阶实验篇 5-67 LCM模块读取/写入时序与常用子程序(WLCMD and WLCMC): Symbol Item Min. Max. Unit tCYCE Enable Cycle Time 1000 - nS PWEN Enable Pulse Width 450 - nS tEr、tEf Enable Rise and Fall Time - 25 nS 5 tAS Setup Time 140 - ns tAH Address Hold Time 10 - nS tDDR Data Delay Time - 320 nS tDHR Data Hold Time 20 - nS 【图 5-6-5】LCM 的读取时序 【图5-6-5】是从LCM读取一个Byte的时序图。首先,需设定“RS”(RS= “0”选到命令寄存器IR,RS=“1”选到数据寄存器DR),用以选择要读出LCM 中的哪一个寄存器(IR或DR),同时将“RW”脚设为“High”(表示要做读取的 动作),延迟tAS时间(最少需140nS)后,再将“E”升为“High”,延迟TDDR时 间(最大320nS)后,此时单片机便可以读取DB7~DB0上的数据,单片机在读取数 据之后,必须将“E”的信号设定为“Low”,如此便完成了一个Byte的读取动作。 5-68 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 Symbol Item Min. Max. Unit tCYCE Enable Cycle Time 1000 - nS PWEN Enable Pulse Width 450 - nS tEr、tEf Enable Rise and Fall Time - 25 nS 5 tAS Setup Time 140 - ns tAH Address Hold Time 10 - nS tDSW Data Setup Time 195 - nS tDHR Data Hold Time 10 - nS 【图 5-6-6】LCM 的写入时序 观察【图5-6-6】写入时序。要将一个 Byte数据写入LCM时,首先需设定“RS” (RS=“0”选到命令寄存器IR,RS=“1”选到数据寄存器DR ),以选择要将 数据写入LCM中的哪一个寄存器(IR或DR),同时将“RW”脚设为“Low”(表 示要做写的动作),延迟tAS时间(最少需140nS)之后再将“E”脚设定为 “High” (使能写入动作),其次将所想要写入LCM的数据放到DB7~DB0。最少延迟tDSW的 时间之后,才可以将“E”设定为“Low”,而完成数据写入动作。“E”由“Low” 转态到“High”再转态为“Low”的时间,称为PWEN,至少必须维持450nS。 在了解LCM的读、写时序关系之后,要来控制LCM就不是难事了。以【图5-6-4】 八位总线连接接口为例,只要写程序让HT66F50单片机的I/O引脚按照时序图上的 要求,“依时依序”的变化就大功告成了!现在,就介绍一个往后实验中经常会使 用到的子程序-“WLCMD”及“WLCMC”,分别负责将数据写到LCM的DR及IR 寄存器。虽然是两个子程序,但是从【图5-6-5】、【图5-6-6】可以看出,其实写 入DR或IR寄存器只有“一线之隔”,即“RS”=“1”或“0”的差异而已!所以, 可将这两个子程序加以集成,以达到节省程序存储器的目的。当然啰,如前面的说 明“必须确定LCM有空的时候(BF=0),才能再次的写数据或命令送给LCM”, 所以在子程序中也包含了检查LCM是否忙碌的部份!请参考以下的程序及流程图: 第五章 进阶实验篇 5-69 WLCMD子程序 Set FLAG=1 WLCMC子程序 Set FLAG=0 Confing LCD_DATA Port as Input Mode Set RW=1 & RS=0 Set EN=1 Confing LCD_DATA Port asOutput Mode Set RW=1 & RS=FLAG Read LCD_DATA Port Set EN=1 LCD_DATA Port=Acc YES LCD Busy ? NO Set EN=0 Set EN=0 RETUTN 5 1 ;======================================================================================== 2; 8-BIT MODE LCD DATA/COMMAND WRITE PROCEDURE 3 ;======================================================================================== 4 WLCMD PROC 5 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 6 JMP $+2 7 WLCMC: CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 8 SET LCD_DATAC ;CONFIG LCD_DATA AS INPUT MODE 9 CLR LCD_CONTR ;CLEAR ALL LCD CONTROL SIGNAL 10 SET LCD_RW ;SET RW SIGNAL (READ) 11 NOP ;FOR TAS 12 SET LCD_EN ;SET EN HIGH 13 NOP ;FOR TDDR 14 WF: SZ LCD_READY ;IS LCD BUSY? 15 JMP WF ;YES, JUMP TO WAIT 16 CLR LCD_DATAC ;NO, CONFIG LCD_DATA AS OUTPUT MODE 17 MOV LCD_DATA,A ;LATCH DATA/COMMAND ON LCD DATA PORT 18 CLR LCD_CONTR ;CLEAR ALL LCD CONTROL SIGNAL 19 SZ DC_FLAG ;IS COMMAND WRITE? 20 SET LCD_RS ;NO, SET RS HIGH 21 SET LCD_EN ;SET EN HIGH 22 NOP 23 CLR LCD_EN ;SET EN LOW 24 RET 5-70 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 25 WLCMD ENDP 读者只要先把HT66F50用来控制“E”、“RS”与“R/W”的Port定义为输出 模式,然后将要写入LCM的数据(LCM的指令或字型码)放在“Acc”寄存器,再 调用此子程序就可以了。程序中在设定“RS”与“R/W”后,于设定“E”之前塞 入了一个“NOP”指令,这是为了要再次提醒读者TAS时间(最少需140nS)的重 要性!以HT66F50工作在4MHz频率的情形下,此行指令并不需要;但若使用较快 速的芯片(或提高工作频率)来控制LCM时,就必须对LCM时序上的时间仔细考 虑!否则,就算是程控信号变化的程序没有错误,LCM也不一定会正常动作。 5 第五章 进阶实验篇 5-71 5-6-1 目 的: 通过LCM命令的应用,对LCM进行初始化设定并在LCM上显示两行字型。 5-6-2 学习重点: 通过本实验,读者能熟悉LCM的基本控制方式,举凡硬件上的相关电路及程序 的控制上都能得心应手、操控自如。 5-6-3 电路图: 5 【图 5-6-7】LCM(8-Bit)控制电路 本实验采用八位的LCM控制方式,关于LCM的相关命令以及特性请读者先参 阅在本实验之前的相关说明。 5-72 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-6-4 程序及流程图: 5 程序5-6 LCM字型显示实验 1 ;PROGRAM : 5-6.ASM (5-6.PJT) 2009.1104 2 ;FUNCTION: 16X2 LCD DEMO PROGRAM By Steven 3 #INCLUDE HT66F50.INC 4 #INCLUDE 5-6.INC 5 ;======================================================================================== 6 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 7 DEL1 DB ? ;DELAY LOOP COUNT 1 8 DEL2 DB ? ;DELAY LOOP COUNT 2 9 DEL3 DB ? ;DELAY LOOP COUNT 3 10 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 11 LINE_COUNT DB ? ;DISPLAY LINE COUNT 12 ;======================================================================================== 13 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 14 ORG 0H ;HT66FX0 RESET VECTOR 15 CALL INIT_LCM 16 MAIN: 17 MOV A,01H ;CLEAR DISPLAY 18 CALL WLCMC 19 MOV A,80H ;SET LINE ONE, POSITION 0 20 CALL WLCMC 21 MOV A,10H 22 MOV LINE_COUNT,A ;SET LINE COUNTER 23 MAIN_1: 24 MOV A,31H ;WRITE '1' 25 CALL WLCMD 26 CALL DELAY ;DELAY 100mS 27 SDZ LINE_COUNT ;LINE_COUNT-1 = 0? 28 JMP MAIN_1 ;NO, NEXT POSITION 29 MOV A,0C0H ;SET LINE TWO, POSITION 0 30 CALL WLCMC 第五章 进阶实验篇 5-73 31 MOV A,16 32 MOV LINE_COUNT,A ;SET LINE COUNTER 33 MAIN_2: 34 MOV A,32H ;WRITE '2' 35 CALL WLCMD 36 CALL DELAY ;DELAU 100mS 37 SDZ LINE_COUNT ;LINE_COUNT-1 = 0? 38 JMP MAIN_2 ;NO, NEXT POSITION 39 JMP MAIN ;RE-START 40 ;======================================================================================== 41 ; PROC : INIT_LCM 42 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 43 ; REG : ACC 44 ;======================================================================================== 45 INIT_LCM PROC 46 CLR LCM_EN ;SET EN=0 47 CLR LCM_RW ;SET RW=0 48 CLR LCM_RS ;SET RS=0 49 CLR LCM_ENC ;CONFIG EN AS O/P MODE 50 CLR LCM_RWC ;CONFIG RW AS O/P MODE 51 CLR LCM_RSC ;CONFIG RS AS O/P MODE 52 CALL DELAY 53 MOV A,38H ;FUNCTION SET: 8-BIT,2-LINE,5X7 DOTS 54 CALL WLCMC 55 MOV A,0FH ;ON/OFF CONTR: DISPLAY ON,CURSOR BLINKING ON 56 CALL WLCMC 57 MOV A,06H ;ENTRY MODE : INCREMENT,DISPLAY NOT SHIFT 58 CALL WLCMC 5 59 MOV A,01H ;CLEAR DISPLAY 60 CALL WLCMC 61 RET 62 INIT_LCM ENDP 63 ;======================================================================================== 64 ; PROC : WLCMD/WLCMC 65 ; FUNC : WRITE DATA/COMMAND TO LCM 66 ; PARA : ACC : COMMAND/DATA 67 ; REG : ACC,DC_FLAG 68 ;======================================================================================== 69 WLCMD PROC 70 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 71 JMP $+2 72 WLCMC: CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 73 SET LCM_DATAPORTC ;CONFIG LCM_DATAPORT AS I/P MODE 74 CLR LCM_RS ;SET RS=0 (IR) 75 SET LCM_RW ;SET RW=1 (READ) 76 NOP ;FOR TAS 77 SET LCM_EN ;SET EN=1 78 NOP ;FOR TDDR 79 WF: SZ LCM_DATAPORT.7 ;IS LCM BUSY? 80 JMP WF ;YES, JUMP TO WAIT 81 CLR LCM_EN ;SET EN=0 82 CLR LCM_DATAPORTC ;NO, CONFIG LCM_DATAPORT AS O/P MODE 83 MOV LCM_DATAPORT,A ;LATCH DATA/COMMAND ON LCM_DATAPORT 84 CLR LCM_RW ;SET RW=0 (WRITE) 85 CLR LCM_RS ;SET RS=0 (IR) 86 SZ DC_FLAG ;IS COMMAND WRITE? 87 SET LCM_RS ;NO, SET RS=1 (DR) 88 SET LCM_EN ;SET EN=1 5-74 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 89 NOP ;FOR PWEN 90 CLR LCM_EN ;SET EN=0 91 RET 92 WLCMD ENDP 93 ;======================================================================================== 94 ; PROC : DELAY 95 ; FUNC : DEALY ABOUT 10*10mS @fSYS=4MHz 96 ; REG : DEL1,DEL2,DEL3 97 ;======================================================================================== 98 DELAY PROC 99 MOV A,10 100 MOV DEL1,A ;SET DEL1 COUNTER 101 DEL_1: MOV A,30 102 MOV DEL2,A ;SET DEL2 COUNTER 103 DEL_2: MOV A,110 104 MOV DEL3,A ;SET DEL3 COUNTER 105 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 106 JMP DEL_3 107 SDZ DEL2 ;DEL2 DOWN COUNT 108 JMP DEL_2 109 SDZ DEL1 ;DEL1 DOWN COUNT 110 JMP DEL_1 111 RET 112 DELAY ENDP 113 END 5 程程序序解解说说:: 4 载入“5-6.INC”定义档,其内容请参考随书光盘中的档案。 7~11 依序定义变量地址。 13 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 15 INIT_LCM 子程序,对 LCM 进行定义。 17~18 将 LCM 整个显示器清空。 19~20 将光标移至第一列的第一个位置。 21~22 在此 LCM 一列共有 16 个位置,因此 LINE_COUNT 设为 10H。 24~26 LCM 的字型表与 ASCII 的对应关系,请参阅【表 5-6-3】LCD 字符码与字型对应表, ASCII 中 31H 为“1”。在此即是将“1”写入 LCD,加入延迟子程序目的是为了能 看到 LCM 上显示“1”,不会因为速度过快而无法看见逐字显示的效果。 27~28 判断光标是否已到达 LCM 第一列尾端,不成立则继续显示“1”。 29~32 光标已到达 LCM 第一列尾端,所以将光标由第一列移至第二列的第一个位置,并将 LINE_COUNT 重置为 16。 34~36 如同 24~26 行的动作,差别在于显示的字型为“2”(32H)。 第五章 进阶实验篇 5-75 37~39 判断光标是否已到达 LCM 第二列尾端,不成立则继续显示“2”,反之则重新开始。 45~62 INIT_LCM 子程序,其功能是对 LCM 进行定义。 56~52 LCM_EN、LCM_RW 与 LCM_RS 定义为输出模式,并设定状态为“0”;并调用 DELAY 子程序延迟 0.1 秒。 53~54 将 LCM 设定为双行显示(N = 1)、使用八位(DB7 ~ DB0)控制模式(DL = 1)、 5×7 点矩阵字型(F = 0)。 55~56 将 LCM 设定为显示所有数据(D = 1)、显示光标(C = 1)、光标所在位置的字会 闪烁(B = 1)。 57~58 将 LCM 的地址计数器(AC)设为递加(I/D = 1)、显示器画面不因读写数据而移 动(S = 0)。 59~60 将 LCM 整个显示器清空。 69~71 WLCMD 子程序进入点,将 DC_FLAG 设定为“1”,代表欲写入的内容为数据。 72 WLCMC 子程序进入点,将 DC_FLAG 设定为“0”,代表欲写入的内容为命令。 (PS. DC_FLAG:Data/Command Flag;“1”=Data、“0”=Command) 73 定义 LCD_DATA PORT 为输入模式,接收 LCM 忙碌标志(BF)的内容。 5 74~78 设定 RS 为“0”、RW 为“1”(Read)并使能 LCM(Enable),用来检查 LCM 是否处于忙碌状态,“NOP”指令是让 LCM 有足够的缓冲时间接受命令并完成工 作,即考虑【图 5-6-3】中的 TAS、TDDR 的时序。 79~80 检查 LCD_DATA PORT 的 BIT 7(即 Busy Flag)是否处于忙碌状态(BF=“1”), 直到 BF=“0”才继续执行程序。 81 设定 EN 为“0”。 82 定义 LCD_DATA Port 为输出模式,用来输出命令或数据至 LCM。 83 将欲输出至 LCM 上的命令或数据移至 LCD_DATAPORT。 74~87 设定 RS 为“0”、RW 为“0”(Read),并判断 DC_FLAG 标志是否为“0”, 成立表示 LCM 欲写入的内容为“命令”;反之,则表示欲写入的内容为“数据”, 故将 RS 重新设为“1”。 88 设定 LCM 控制信号 EN=“1”。 89~91 让 LCM 有足够的缓冲时间接受命令或数据并完成工作,完成后将 LCM 除能回到主 程序继续下面的动作。“NOP”指令是让 LCM 有足够的缓冲时间接受命令并完成 工作,即考虑【图 5-6-4】中的 TEr、PWEN 的时序。 5-76 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 98~112 DELAY 子程序,延迟 0.1 秒;延迟时间的计算请参考【实验 4-1】。 本程序主要在16×2 LCM的第一列及第二列上分别显示“1”、“2”的字型。 程序一开始先对LCM进行初始化的设定,如设定LCM为八位控制模式、两列显示、 5×7的点矩阵字型、显示光标、AC值加一、清除…等等。除了RS、RW、E与DB7~ DB0有一定的时序关系之外,LCM的设定也有依定的顺序;【图5-6-8】是HD44780 数据手册中所描述的初始程序,程序中有关LCM定义步骤就是依此要求逐步完成 的。初始程序完成之后,接下来就是分别把AC设为DD RAM的第一列(00h)与第 二列并显示“1”、“2”的字型。所有的命令与字型码的写入,都是通过WLCMC 与WLCMD两个子程序来达成,对于这些子程序上不明了的读者,烦请再次参阅之 前的说明。 5 【图 5-6-8】HT44780 初始化程序(8-Bit 控制模式) 本实验中所使用的WLCMD、WLCMC子程序在读取忙碌标志时有点投机取巧, 请读者查阅【表5-6-6】LCM模块指令表,读取忙碌标志时不是应该与AC(地址计 数器)同时读取吗?没错,不过若是只要检查LCM忙碌与否,其实是可以将其忽略 的,如WLCMD、WLCMC子程序就是省略了AC读取的程序。但为因应不时之需, 还是将比较正统、合理的读取方式明列于后以方便读者使用,为了与原来子程序有 所区分,给予不同的程序名称:WLCMDM、WLCMCM;它较WLCMD、WLCMC 子程序多用了两个存储器:LCM_TEMP用来存放调用时置于ACC的命令或数据; LCM_AC则用于存放忙碌标志与地址计数器之值。 WLCMDM/WLCMCM子程序: 1 ;======================================================================================== 2 ; PROC : WLCMDM/WLCMCM 3 ; FUNC : WRITE DATA/COMMAND TO LCM AND RETURN AC ADDRESS 4 ; PARA : ACC : COMMAND/DATA 5 ; REG : ACC,DC_FLAG,LCM_TEMP 第五章 进阶实验篇 5-77 6 ; RETN : LCM_AC : 1 BUSY BIT + 7-BIT AC 7 ;======================================================================================== 8 WLCMDM PROC 9 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 10 JMP $+2 11 WLCMCM: CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 12 MOV LCM_TEMP,A 13 SET LCM_DATAPORTC ;CONFIG LCM_DATAPORT AS I/P MODE 14 CLR LCM_RS ;SET RS=0 (IR) 15 SET LCM_RW ;SET RW=1 (READ) 16 NOP ;FOR TAS 17 WF: SET LCM_EN ;SET EN=1 18 NOP ;FOR TDDR 19 MOV A,LCM_DATAPORT 20 MOV LCM_AC,A 21 CLR LCM_EN ;SET EN=0 22 SZ LCM_AC.7 ;IS LCM BUSY? 23 JMP WF ;YES, JUMP TO WAIT 24 CLR LCM_DATAPORTC ;NO, CONFIG LCM_DATAPORT AS O/P MODE 25 MOV A,LCM_TEMP 26 MOV LCM_DATAPORT,A ;LATCH DATA/COMMAND ON LCM_DATAPORT 27 CLR LCM_RW ;SET RW=0 (WRITE) 28 CLR LCM_RS ;SET RS=0 (IR) 5 29 SZ DC_FLAG ;IS COMMAND WRITE? 30 SET LCM_RS ;NO, SET RS=1 (DR) 31 SET LCM_EN ;SET EN=1 32 NOP ;FOR PWEN 33 CLR LCM_EN ;SET EN=0 34 RET 35 WLCMDM ENDP 5-6-5 动动脑+动动手: 试着改写程序,让“1”、“2”由原来第一列显示完后再换第二列显示的做法, 改成是上下交替显示的方式。 原范例程序是以 LINE_COUNT 存储器来控制换行的动作;试将 LCM 显示 的子程序改为 WLCMDM 与 WLCMCM,并以返回值-LCM_AC 存储器来控 制换行的动作。 5-78 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-7 LCM自建字型实验 5-7-1 目 的: 在LCM上自建字型,并利用程序的技巧让显示的图案产生动态的效果。 5-7-2 学习重点: 通过本实验,读者能熟悉如何在LCM的CG RAM(Character Generator RAM) 中建立自己的字型。 5-7-3 电路图: 5 【图5-7-1】LCM(8-Bit)控制电路 观察【表5-6-4】,除了CGROM的对应地址之外,还有一个区域是用来存放自 订字形,称为“CG RAM(Character Generator RAM)”,可让使用者设计八个 字形。每个字形都是以5×8的点阵字形呈现(【图5-7-2(a)】);建造字型的过程 其实就是决定点阵中各点的亮、灭,亮点为“1”、其余为“0”(【图5-7-2 (b)】), 最后再将这些组合依序填入CG RAM即可。不过,因为这些自建字型是存放在RAM 架构的内存中,一旦关闭电源数据就会消失,请读者特别注意。 (a) 5×8 的点阵 (b) 字形范例 【图 5-7-2】LCM 自订字形 看来,建立字形似乎是个乏味、无趣的过程!为了避免读者有此印象,本实验 第五章 进阶实验篇 5-79 试着让读者在繁复的建表过程后,能有个有趣的结果呈现;【图5-7-3】是笔者想 建立的两组人形图案,由于5×8点阵实在太过粗糙,无法显示细腻的图案,因此以 四个5×8点阵组成一个人形,图形所对应的数据请读者参考【程序5-7】中CG RAM 数组的定义;程序将试着以这两个图案组成步行的效果。每个人形图案需使用四个 CG RAM地址存放,【图5-7-3】中的数字代表该字形在CG RAM的存放地址。 (a) (b) 【图 5-7-3】步行图案 5-7-4 程序及流程图: 5 程序5-7 LCM自建字型实验 1 ;PROGRAM : 5-7.ASM (5-7.PRJ) BY STEVEN 2 ;FUNCTION: 16X2 LCD CG-RAM DEMO PROGRAM 2009/02/21 3 #INCLUDE HT66F50.INC 4 #INCLUDE 5-7.INC 5 ;-------------------------------------------------------------------- 6 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 7 DEL1 DB ? ;DELAY LOOP COUNT 1 8 DEL2 DB ? ;DELAY LOOP COUNT 2 9 DEL3 DB ? ;DELAY LOOP COUNT 3 10 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 11 COUNT DB ? ;DISPLAY COUNT 12 INDEX DB ? ;CG RAM DATA INDEX 13 ;-------------------------------------------------------------------- 14 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 5-80 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 15 ORG 00H ;HT66FXX RESET VECTOR 16 CALL INIT_LCM 17 MOV A,01000000B ;SET CG RAM START ADDRESS 18 CALL WLCMC 19 MOV A,8*8/2 20 MOV COUNT,A ;SET CG RAM WRITE COUNTER 21 MOV A,OFFSET TAB_CG RAM ;GET TABLE START ADDRESS 22 MOV TBLP,A 23 NEXT: TABRDL ACC ;READ DATA 24 CALL WLCMD ;WRITE TO CG_RAM 25 MOV A,TBLH 26 CALL WLCMD ;WRITE TO CG_RAM 27 INC TBLP ;INCREASE POINTER BY 1 28 SDZ COUNT ;COUNT-1 = 0? 29 JMP NEXT ;NO, NEXT DATA 30 MAIN: 31 MOV A,86H ;SET LINE 1 POSITION 6 32 CALL WLCMC 33 CLR ACC ;WRITE CG RAM DATA 0 34 CALL WLCMD 35 MOV A,01H 5 36 CALL WLCMD 37 MOV A,0C6H ;WRITE CG RAM DATA 1 ;SET LINE 1 POSITION 6 38 CALL WLCMC 39 MOV A,02H ;WRITE CG RAM DATA 2 40 CALL WLCMD 41 MOV A,03H ;WRITE CG RAM DATA 3 42 CALL WLCMD 43 CALL DELAY ;DELAY 200ms 44 45 MOV A,86H ;SET LINE 1 POSITION 6 46 CALL WLCMC 47 MOV A,04H ;WRITE CG RAM DATA 4 48 CALL WLCMD 49 MOV A,05H ;WRITE CG RAM DATA 5 50 CALL WLCMD 51 MOV A,0C6H ;SET LINE 1 POSITION 6 52 CALL WLCMC 53 MOV A,06H ;WRITE CG RAM DATA 6 54 CALL WLCMD 55 MOV A,07H ;WRITE CG RAM DATA 7 56 CALL WLCMD 57 CALL DELAY ;DELAY 200ms 58 JMP MAIN ;JUMP TO MAIN 59 ;======================================================================================== 60 ; PROC : INIT_LCM 61 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 第五章 进阶实验篇 5-81 62 ; REG : ACC 63 ;======================================================================================== 64 INIT_LCM PROC 65 CLR LCM_EN ;SET EN=0 66 CLR LCM_RW ;SET RW=0 67 CLR LCM_RS ;SET RS=0 68 CLR LCM_ENC ;CONFIG EN AS O/P MODE 69 CLR LCM_RWC ;CONFIG RW AS O/P MODE 70 CLR LCM_RSC ;CONFIG RS AS O/P MODE 71 72 MOV A,38H ;FUNCTION SET: 8-BIT,2-LINE,5X7 DOTS 73 CALL WLCMC 74 MOV A,0CH ;ON/OFF CONTR: DISPLAY ON,CURSOR BLINKING OFF 75 CALL WLCMC 76 MOV A,06H ;ENTRY MODE : INCREMENT,DISPLAY NOT SHIFT 77 CALL WLCMC 78 MOV A,01H ;CLEAR DISPLAY 79 CALL WLCMC 80 RET 81 INIT_LCM ENDP 82 ;======================================================================================== 83 ; PROC : WLCMD/WLCMC 84 ; FUNC : WRITE DATA/COMMAND TO LCM 5 85 ; PARA : ACC : COMMAND/DATA 86 ; REG : ACC,DC_FLAG 87 ;======================================================================================== 88 WLCMD PROC 89 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 90 JMP $+2 91 WLCMC: CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 92 SET LCM_DATAPORTC ;CONFIG LCM_DATAPORT AS I/P MODE 93 CLR LCM_RS ;SET RS=0 (IR) 94 SET LCM_RW ;SET RW=1 (READ) 95 NOP ;FOR TAS 96 SET LCM_EN ;SET EN=1 97 NOP ;FOR TDDR 98 WF: SZ LCM_DATAPORT.7 ;IS LCM BUSY? 99 JMP WF ;YES, JUMP TO WAIT 100 CLR LCM_EN ;SET EN=0 101 CLR LCM_DATAPORTC ;NO, CONFIG LCM_DATAPORT AS O/P MODE 102 MOV LCM_DATAPORT,A ;LATCH DATA/COMMAND ON LCM_DATAPORT 103 CLR LCM_RW ;SET RW=0 (WRITE) 104 CLR LCM_RS ;SET RS=0 (IR) 105 SZ DC_FLAG ;IS COMMAND WRITE? 106 SET LCM_RS ;NO, SET RS=1 (DR) 107 SET LCM_EN ;SET EN=1 108 NOP ;FOR PWEN 5-82 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 109 CLR LCM_EN ;SET EN=0 110 RET 111 WLCMD ENDP 112 ;======================================================================================== 113 ; PROC : DELAY 114 ; FUNC : DEALY ABOUT 20*10mS @fSYS=4MHz 115 ; REG : DEL1,DEL2,DEL3 116 ;======================================================================================== 117 DELAY PROC 118 MOV A,20 119 MOV DEL1,A ;SET DEL1 COUNTER 120 DEL_1: MOV A,30 121 MOV DEL2,A ;SET DEL2 COUNTER 122 DEL_2: MOV A,110 123 MOV DEL3,A ;SET DEL3 COUNTER 124 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 125 JMP DEL_3 126 SDZ DEL2 ;DEL2 DOWN COUNT 127 JMP DEL_2 128 SDZ DEL1 ;DEL1 DOWN COUNT 129 JMP DEL_1 5 130 RET 131 DELAY ENDP 132 ORG LASTPAGE 133 TAB_CG RAM: ;TAKE CARE THE ORDER OF BYTE 134 DC 0C00H,0C1EH,0706H,0B07H ;WORKING-MAN FOR FIG.5-7-3(a) 135 DC 0000H,0000H,1800H,0204H 136 DC 0111H,0101H,1A02H,000CH 137 DC 1010H,0608H,0103H,0001H 138 DC 0C00H,0C1EH,0706H,0306H ;WORKING-MAN FOR FIG.5-7-3(b) 139 DC 0000H,0000H,0000H,0810H 140 DC 0505H,0403H,0304H,000FH 141 DC 1008H,1010H,0608H,000CH 142 END 程程序序解解说说:: 4 载入”5-7.INC”定义档,其内容请参考随书光盘中的档案。 7~12 依序定义变量地址。 15 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 16 INIT_LCM 子程序,对 LCM 进行定义。 17~18 设定 CG RAM 起始地址。 19~29 将程序存储器中的两组人形图案数据填入 LCM 的 CG RAM 中。 第五章 进阶实验篇 5-83 31~32 设定 DD RAM 地址为第一列第六个位置。 33~36 将编号 0 与 1 的图案送至 LCM 显示。 37~38 设定 DD RAM 地址为第二列第六个位置。 39~42 将编号 2 与 3 的图案送至 LCM 显示。 43 调用 DELAY 子程序,延迟 0.2 秒。 45~46 设定 DD RAM 地址为第一列第六个位置。 47~50 将编号 4 与 5 的图案送至 LCM 显示。 51~52 设定 DD RAM 地址为第二列第六个位置。 53~56 将编号 2 与 3 的图案送至 LCM 显示。 57 调用 DELAY 子程序,延迟 0.2 秒。 58 跳至 MAIN 重复图案的显示动作。 64~81 INIT_LCM 子程序,其功能是对 LCM 进行定义。 65~70 LCM_EN、LCM_RW 与 LCM_RS 定义为输出模式,并设定状态为“0”。 72~73 将 LCM 设定为双行显示(N = 1)、使用八位(DB7 ~ DB0)控制模式(DL = 1)、 5×7 点矩阵字型(F = 0)。 5 74~75 将 LCM 设定为显示所有数据(D = 1)、显示光标(C = 1)、光标所在位置的字会 闪烁(B = 1)。 76~77 将 LCM 的地址计数器(AC)设为递加(I/D = 1)、显示器画面不因读写数据而移 动(S = 0)。 78~79 将 LCM 整个显示器清空。 88~111 WLCMD 子程序与 WLCMC 子程序。 117~131 DELAY 子程序,延迟 0.2 秒;延迟时间的计算请参考【实验 4-1】。 133~141 CG RAM 自建字型数据定义区。 程序一开始先对LCM做初始化的设定,接下来就是连续填入【表5-7-3】的人 形图案。然后设定DD RAM地址,让两个图案显示在第一列、第二列的中央的位置, 并交替显示,形成行人原地踏步的效果。 5-7-5 动动脑+动动手: 试着在 CG RAM 中建立一些简单的中文字型,如“甲”、“上”、“下”、…. 5-84 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 等等。 改变 DELAY 子程序的延迟时间,观察图形的变化。 5 5-85 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-8 LCM与4×4键盘控制实验 5-8-1 目 的: 在LCM上显示使用者在4×4 Keypad上所按下的按键值(“0”~“F”)。 5-8-2 学习重点: 通过本实验,了解数值于LCM显示时的字形码转换,对于LCM内部AC存储器 的读取与应用亦应有更进一步的认识。 5-8-3 电路图: 5 PS:若使能PA[7:4]Pull-high功能,则10kΩ电阻可省略。 【图 5-8-1】LCM 与 4×4 键盘控制电路 如【图5-8-1】所示,LCM与4×4键盘是经常搭配在各样产品应用的,如密码锁、 计算器…等等。本实验是以连接于PA的4×4键盘做为输入装置,使用者按下的按键 (0~F)经转换后显示在连接于PD的LCM;虽然本例是将LCM的Data Bus与 Keypad分别连接在不同的I/O Port,但由于LCM所有数据与命令的读、写动作,都 必须配合“E”(Enable)信号加以控制,若有需要时是可将其Data Bus与Keypad (或其它装置)共享,只要确定在执行按键扫描时避免对LCM进行任何的读写,就 不致影响LCM的正常操作。有关4×4键盘与LCM的相关数据,请参考【实验4-7】 与【实验5-6】中的说明。 5-86 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-8-4 程序及流程图: 程序5-8 LCM与4×4键盘控制实验 5 1 ;PROGRAM : 5-8.ASM (5-8.PJT) 2009.1105 2 ;FUNCTION: 16X2 LCD vs. 4x4 KEYPAD DEMO PROGRAM By Steven 3 #INCLUDE HT66F50.INC 4 #INCLUDE 5-8.INC 5 ;======================================================================================== 6 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 7 DEL1 DB ? ;DELAY LOOP COUNT 1 8 DEL2 DB ? ;DELAY LOOP COUNT 2 9 DEL3 DB ? ;DELAY LOOP COUNT 3 10 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 11 LCM_AC DB ? ;BUFFER FOR LCM READ 12 LCM_TEMP DB ? ;BUFFER FOR LCM CONTROL 13 COUNT DB ? ;UNIVERSAL COUNTER 14 KEY_COUNT DB ? ;ROW COUNTER USED IN READ_KEY 15 KEY DB ? ;KEY CODE REGISTER 16 KEY_PS DB ? ;KEY CODE REGISTER 17 ;======================================================================================== 18 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 19 ORG 00H ;HT66FX0 RESET VECTOR 20 CLR ACERL ;AD DISABLE 21 MOV A,08h 22 MOV CP0C,A ;CP0 DISABLE 23 MOV CP1C,A ;CP1 DISABLE 24 CALL INIT_LCM ;INITIAL LCM 25 MAIN: 26 CALL READ_KEY ;READ KEYPAD 第五章 进阶实验篇 5-87 27 MOV A,16 28 XOR A,KEY 29 SZ Z ;KEY PRESSED ? 30 JMP MAIN ;NO, RE-READ KEYPAD 31 MOV A,KEY 32 MOV KEY_PS,A ;RESERVE KEY CODE 33 WAIT: 34 CALL READ_KEY ;CHECK KEYPAD RELEASED 35 MOV A,16 36 XOR A,KEY 37 SNZ Z ;IS KEY RELEASED? 38 JMP WAIT ;NO,WAIT KEY RELEASE 39 CALL DELAY ;FOR DE-BOUNCING WHEN KEY RELEASE 40 MOV A,KEY_PS 41 SUB A,10 ;CONVERT TO ASCII CODE 42 SZ C 43 ADD A,40H-30H-9 44 ADD A,30H+10 45 CALL WLCMDM ;DISPLAY KEY IN DATA 46 MOV A,LCM_AC ;CHECK IF LINE FULL ? 47 SUB A,16 48 SNZ Z 49 JMP MAIN ;NO.READ NEXT KEY 5 50 MOV A,01H ;YES. CLEAR LCM 51 CALL WLCMCM 52 JMP MAIN 53 ;======================================================================================== 54 ; PROC : WLCMDM/WLCMCM 55 ; FUNC : WRITE DATA/COMMAND TO LCM AND RETURN AC ADDRESS 56 ; PARA : ACC : COMMAND/DATA 57 ; REG : ACC,DC_FLAG,LCM_TEMP 58 ; RETN : LCM_AC : 1 BUSY BIT + 7-BIT AC 59 ;======================================================================================== 60 WLCMDM PROC 61 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 62 JMP $+2 63 WLCMCM: 64 CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 65 MOV LCM_TEMP,A 66 SET LCM_DATAPORTC ;CONFIG LCM_DATAPORT AS I/P MODE 67 CLR LCM_RS ;SET RS=0 (IR) 68 SET LCM_RW ;SET RW=1 (READ) 69 NOP ;FOR TAS 70 WF: SET LCM_EN ;SET EN=1 71 NOP ;FOR TDDR 72 MOV A,LCM_DATAPORT 73 MOV LCM_AC,A 5-88 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 74 CLR LCM_EN ;SET EN=0 75 SZ LCM_AC.7 ;IS LCM BUSY? 76 JMP WF ;YES, JUMP TO WAIT 77 CLR LCM_DATAPORTC ;NO, CONFIG LCM_DATAPORT AS O/P MODE 78 MOV A,LCM_TEMP 79 MOV LCM_DATAPORT,A ;LATCH DATA/COMMAND ON LCM_DATAPORT 80 CLR LCM_RW ;SET RW=0 (WRITE) 81 CLR LCM_RS ;SET RS=0 (IR) 82 SZ DC_FLAG ;IS COMMAND WRITE? 83 SET LCM_RS ;NO, SET RS=1 (DR) 84 SET LCM_EN ;SET EN=1 85 NOP ;FOR PWEN 86 CLR LCM_EN ;SET EN=0 87 RET 88 WLCMDM ENDP 89 ;======================================================================================== 90 ; PROC : INIT_LCM 91 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 92 ; REG : ACC 93 ;======================================================================================== 94 INIT_LCM PROC 5 95 CLR LCM_EN 96 CLR LCM_RW ;SET EN=0 ;SET RW=0 97 CLR LCM_RS ;SET RS=0 98 CLR LCM_ENC ;CONFIG EN AS O/P MODE 99 CLR LCM_RWC ;CONFIG RW AS O/P MODE 100 CLR LCM_RSC ;CONFIG RS AS O/P MODE 101 102 MOV A,38H ;FUNCTION SET: 8-BIT,2-LINE,5X7 DOTS 103 CALL WLCMCM 104 MOV A,0CH ;ON/OFF CONTR: DISPLAY ON,CURSOR BLINKING OFF 105 CALL WLCMCM 106 MOV A,06H ;ENTRY MODE : INCREMENT,DISPLAY NOT SHIFT 107 CALL WLCMCM 108 MOV A,01H ;CLEAR DISPLAY 109 CALL WLCMCM 110 RET 111 INIT_LCM ENDP 112 ;======================================================================================== 113 ; SCAN 4x4 MATRIX ON KEY PORT AND RETURN THE CODE IN KEY REGISTER 114 ; IF NO KEY BEEN PRESSED, KEY=16. 115 ;======================================================================================== 116 READ_KEY PROC 117 MOV A,11110000B 118 MOV KEY_PORTC,A ;CONFIG PORT 119 MOV KEY_PORTPU,A 120 SET KEY_PORT ;INITIAL PORT 第五章 进阶实验篇 5-89 121 CLR KEY ;INITIAL KEY REGISTER 122 MOV A,04 123 MOV COUNT,A ;SET ROW COUNTER 124 CLR C ;CLEAR CARRY FLAG 125 SCAN_KEY: 126 RLC KEY_PORT ;ROTATE SCANNING BIT 127 SET C ;MAKE SURE C=1 128 SNZ KEY_PORT.4 ;COLUMN 0 PRESSED? 129 JMP END_KEY ;YES. 130 INC KEY ;NO, INCREASE KEY CODE. 131 SNZ KEY_PORT.5 ;COLUMN 1 PRESSED? 132 JMP END_KEY ;YES. 133 INC KEY ;NO, INCREASE KEY CODE. 134 SNZ KEY_PORT.6 ;COLUMN 2 PRESSED? 135 JMP END_KEY ;YES. 136 INC KEY ;NO, INCREASE KEY CODE. 137 SNZ KEY_PORT.7 ;COLUMN 3 PRESSED? 138 JMP END_KEY ;YES. 139 INC KEY ;NO, INCREASE KEY CODE. 140 SDZ COUNT ;HAVE ALL ROWs BEEN CHECKED? 141 JMP SCAN_KEY ;NO, NEXT ROW. 142 END_KEY: 143 RET 5 144 READ_KEY ENDP 145 ;======================================================================================== 146 ; PROC : DELAY 147 ; FUNC : DEALY ABOUT 10*10mS @fSYS=4MHz 148 ; REG : DEL1,DEL2,DEL3 149 ;======================================================================================== 150 DELAY PROC 151 MOV A,10 152 MOV DEL1,A ;SET DEL1 COUNTER 153 DEL_1: MOV A,30 154 MOV DEL2,A ;SET DEL2 COUNTER 155 DEL_2: MOV A,110 156 MOV DEL3,A ;SET DEL3 COUNTER 157 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 158 JMP DEL_3 159 SDZ DEL2 ;DEL2 DOWN COUNT 160 JMP DEL_2 161 SDZ DEL1 ;DEL1 DOWN COUNT 162 JMP DEL_1 163 RET 164 DELAY ENDP 165 END 5-90 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 程程序序解解说说:: 4 载入”5-8.INC”定义档,其内容请参考随书光盘中的档案。 7~16 依序定义变量地址。 19 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 20~23 关闭 CP0、CP1 功能,并设定 ADC 脚位输入为 I/O 功能。 24 调用 INIT_LCM 子程序,对 LCM 进行定义。 26~30 调用 READ_KEY 扫描键盘子程序,完成后判断 KEY 值是否为“16”,若成立,表 示键盘尚未被按下,重新扫描键盘(JMP MAIN);反之,则代表键盘已有输入, 则程序继续执行。 31~32 将由键盘扫描所得到的结果储存至 KEY_PS 存储器。 34~38 如同 26~30 行叙述,只是判断式由“SZ”改成“SNZ”,检查按键是否已经放开, 否则一直等到按键放开才跳离循环,继续往下执行。万一 LCD_DATAPORT 与 KEY_PORT 共用同一个 I/O Port 的话,如果按键尚未放开就贸然执行 LCM 的控制 程序,那么从 LCD_DATAPORT 送出的 LCM 控制命令或数据,必然受到使用者按 5 按键的干扰,造成数据或命令的传送错误!因此必须确定按键已经放开后,才能执 行控制 LCM 显示的动作。当然,本例非属共用一个 I/O Port 的状况,理应不需理会 此现象,不过笔者还是在此提出说明与写法,以因应读者的不时之需。 39 调用 DELAY 子程序,延迟 100mS。 40~44 此段程序的目的是将 KEY_PS 存储器的内容转为 ASCII 码。首先是 KEY_PS 之值 是否大于等于 10,若不是,直接将 KEY_PS 加上 30h 即获得其 ASCII 码;若是大 于等于 10,则要获得“A”~“F”的 ASCII 码,必须再加上 7。请读者参考【表 5-5-3】 LCM 字符码与字型码对照表,相信必能推敲出其中的端倪。(注:字型“0”~“9” 的 ASCII 码是 30H ~ 39H,而字型“A”~“F”的 ASCII 码是 41H ~ 46H。这点是 必需注意的地方,详细内容请参照 LCM 相关章节。) 45 调用 WLCMD 子程序显示按键值。 46~52 通过调用 WLCMD 子程序所回传的 LCM_AC 值,判断 LCM 是否已显示至第一列的 第 16 行地址,若不是则重新读取按键(JMP MAIN);否则清空 LCM 显示器后再 重新读取按键。 60~87 WLCMDM 子程序与 WLCMCM 子程序,请参考【实验 5-6】的说明。 93~110 INIT_LCM 子程序,其功能是对 LCM 进行定义: 第五章 进阶实验篇 5-91 LCM_EN、LCM_RW 与 LCM_RS 定义为输出模式,并设定状态为“0”;并调用 DELAY 子程序延迟 0.1 秒; 将 LCM 设定为双列显示(N = 1)、使用八位(DB7 ~ DB0)控制模式(DL = 1)、 5×7 点矩阵字型(F = 0); 将 LCM 设定为显示所有数据(D = 1)、显示光标(C = 1)、光标所在位置的字会 闪烁(B = 1); 将 LCM 的地址计数器(AC)设为递加(I/D = 1)、显示器画面不因读写数据而移 动(S = 0); 将 LCM 整个显示器清空。 115~143 READ_KEY 子程序,请参考【实验 4-7】。 149~163 DELAY 子程序,至于延迟时间的计算请参考【实验 4-1】。 程序一开始首先对LCM做初始化的设定,紧接着就是调用READ_KEY子程序 读取4×4键盘上的按键值;之后再次调用READ_KEY子程序的目的是要确定按键已 经确实放开,然后再调用WLCMDM子程序显示按键值!在显示之前先将按键值减 去10的目的,是要判断按键值是否大于9,如果不是,就将按键值直接加上30h转 5 换为字型码,以便LCM可以显示正确的字型;否则表示按键值>9,必须将按键值 再加上37h以转换成“A”~“F”的字型码。 请 读 者 注 意 , 本 范 例 用 来 传 送 LCM 命 令 与 数 据 的 子 程 序 (WLCMCM 、 WLCMDM)与前几节所使用的略有不同,在WLCMC、WLCMD子程序中,只是单 纯以LCM_READY(即LCM_AC.7)判断LCM是否尚处于忙碌状态,事实上当以时 序配合由LCM读出忙碌标志的同时,LCM内部地址计数器(Address Counter;AC) 的值亦会同时呈现在LCD_DATAPORT[6:0]上,而本范例即是利用WLCMCM、 WLCMDM子程序所读回的AC值判断光标的所在地址,以决定是否清除LCM屏幕, 重新开始显示。 5-8-5 动动脑+动动手: 本范例程序所显示的键值为 0~9 与大写英文字母 A~F,试修改程序使英文 字母改为小写 a~f。 本范例程序当输入 16 个按键值后,会清除显示屏并重新将输入键值显示于 第一列上。请改写程序,当按键值填满第一列即将之后的按键值显示于第二 列,待填满第二列后才清除 LCM 并重新显示。 5-92 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 修改程序,让第一个按键值显示在第一列,让第二个按键值显示在第二列。 写一程序,当按键值为奇数时,则在第一列显示按键值;反之,若按键值为 偶数,则将按键值显示在第二列。 5 5-93 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-9 LCM的DD/CG RAM读取控制实验 5-9-1 目 的: 运用HT66F50 CTM单元的Timer/Counter模式产生一个“0”~“F”的随机数 并显示在LCM第一列,在LCM的第二列则以跑马灯的方式配合按键的控制,判断 使用者按下按键时,光标位置上的数值与所产生的随机数值是否相同。 5-9-2 学习重点: 通过本实验,了解如何由LCM的DD RAM或CG RAM读回数据。此外,也应对 利用Timer/Counter产生随机数的方式有所认识。 5-9-3 电路图: 5 PS:若使能PA[2:0]Pull-high功能,则三颗10kΩ电阻可省略。 【图 5-9-1】LCM 与按键控制电路 本实验希望呈现如下的执行结果:首先,在LCM第一列显示由Timer/ Counter 产生的随机数(“0”~“F”)。其次,在第二列显示“0”~“F”的字型,并制 造光标在字型上移动的效果,如下图(此图例中产生的随机数值为“8”): 当使用者按下按键之后,再由程序判断此时光标停留位置上的数值与随机数是 否相同,分别显示出以下的画面: 5-94 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 (按下按键时光标停留于”5”的位置) (按下按键时光标停留于”8”的位置) 随机数的产生有许多的方法,由于本实验使用到按键有无被按下的判断,使用 者很难(几乎不可能)控制每一次按下按键的时间都相同,因此利用Timer/Counter 来产生随机数应是最容易、最方便的选择。 在【实验5-6】中,已经介绍了如何依照LCM读、写时序的要求,而写出相关 的子程序(WLCMC、WLCMD),如果要由LCM的DD RAM或CG RAM读回数据, 其实也只是“依样画葫芦”-“根据LCM DD/CG RAM的读写命令及时序,依序 设定控制脚位的电位变化”就可以了。请读者参考【图5-6-3】、【图5-6-4】及【表 5-6-5 】 , 并 对 照 RLCM 子 程 序 及 其 流 程 图 。 另 外 , 本 实 验 以 CTM 单 元 的 5 Timer/Counter模式来产生随机数,【表5-9-1】为相关控制寄存器的内容,详细说 明请参考【2-5-1节】与【实验4-9】。 【2-5-1 节】 【表 5-9-1】本实验相关控制寄存器 TM0C0 TM0C1 TM0AL TM0AH T0PAU T0M1 - T0CK2 T0M0 - T0CK1 T0IO1 - T0CK0 T0ON T0IO0 T0OC TM0A[7:0] - - T0RP2 T0POL - TM0DL TM0D[7:0] TM0DH - - - - - - Bit7 6 5 4 3 2 T0RP1 T0RP0 T0DPX T0CCLR TM0A[9:8] TM0D[9:8] 1 Bit0 5-9-4 程序及流程图: 第五章 进阶实验篇 5-95 5 PRINT子程序 SET TBLP=Acc Read Data from Table TBLP=TBLP+1 Data=NULL ? YES RETURN NO Call WLCMD Display Data 程序5-9 LCM DD/CG RAM读取控制实验 1 ;PROGRAM : 5-9.ASM (5-9.PJT) 2 ;FUNCTION: 16X2 LCM DD RAM READ DEMO PROGRAM 3 #INCLUDE HT66F50.INC 4 #INCLUDE 5-9.INC 2009.1105 By Steven 5-96 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5 ;======================================================================================== 6 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 7 DEL1 DB ? ;DELAY LOOP COUNT 1 8 DEL2 DB ? ;DELAY LOOP COUNT 2 9 DEL3 DB ? ;DELAY LOOP COUNT 3 10 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 11 LCM_AC DB ? ;BUFFER FOR LCM READ 12 LCM_TEMP DB ? ;BUFFER FOR LCM CONTROL 13 COUNT DB ? ;UNIVERSAL COUNTER 14 INDEX DB ? ;ROW COUNTER USED IN READ_KEY 15 TEMP DB ? 16 FACTOR DB ? 17 RANDOM DB ? 18 ;======================================================================================== 19 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 20 ORG 00H ;HT66FX0 RESET VECTOR 21 CLR ACERL ;AD DISABLE 22 MOV A,08h 23 MOV CP0C,A ;CP0 DISABLE 24 MOV A,00000111B 25 ORM A,PAC 5 26 ORM A,PAPU 27 MOV A,11000000B ;CONFIG PA[2:0] I/P MODE ;ENABLE PA[2:0] PULL-HIGH ;CONFIG CTM IN TIMER/COUNTER MODE 28 MOV TM0C1,A ;TM0D IS CLEARED BY TMRP MATCH 29 MOV A,00011000B ;START CTM, T0CK[2:0]=001 30 MOV TM0C0,A ;fINT=fSYS (4MHz) 31 CALL INIT_LCM ;INITIAL LCM 32 MOV A,8 33 MOV FACTOR,A 34 MAIN: 35 MOV A,01H ;CLEAR LCM 36 CALL WLCMCM 37 MOV A,0C0H ;SET LIN 2, POSITION 0 38 CALL WLCMCM 39 MOV A,OFFSET STR02F 40 CALL PRINT 41 MOV A,TM0DH 42 XOR A,TM0DL 43 AND A,0FH ;GET LOW BYTE NUMBER (0~F) 44 ADD A,STR02F 45 MOV TBLP,A 46 TABRDL RANDOM 47 MOV A,80H+7 ;SET LINE 1,POSITION 7 48 CALL WLCMCM 49 MOV A,RANDOM ;DISPLAY RANDOM NUMBER 50 CALL WLCMDM 51 MAIN_1: 52 MOV 53 MOV 54 MOV 55 MOV 56 MAIN_2: 57 MOV 58 CALL 59 CALL 60 MOV 61 MOV 62 CALL 63 MOV 64 CALL 65 MOV 66 CALL 67 MOV 68 CALL 69 MOV 70 CALL 71 SNZ 72 JMP 73 SZ 74 JMP 75 SLOWER:INCA 76 JMP 77 FASTER: DECA 78 SZ 79 JMP 80 MOV 81 JMP 82 MAIN_3: 83 SNZ 84 JMP 85 INC 86 SDZ 87 JMP 88 JMP 89 MAIN_4: 90 MOV 91 XOR 92 SZ 93 JMP 94 MISS: 95 MOV 96 CALL 97 MOV 98 CALL A,0C0H INDEX,A A,16 COUNT,A A,INDEX WLCMCM RLCM TEMP,A A,INDEX WLCMCM A,0FFH WLCMDM A,FACTOR DELAY A,INDEX WLCMCM A,TEMP WLCMDM SW_FASTER FASTER SW_SLOWER MAIN_3 FACTOR FASTER+1 FACTOR Z MAIN_3 FACTOR,A MAIN_3 SW_HIT MAIN_4 INDEX COUNT MAIN_2 MAIN_1 A,RANDOM A,TEMP Z BINGO A,80H WLCMCM A,OFFSET STR1 PRINT 第五章 进阶实验篇 5-97 ;SET LINE 2, POSITION 0 ;RESERVED CURSOR POSITION CODE ;SET POSITION COUNT ;RE-LOAD CURSOR POSITION CODE ;READ DD RAM DATA ;RESERVED DATA ;RESTORE CURSOR POSITION ;MASK WITH "█" ;DELAY FACTOR*10ms ;NO,RESTORE CURSOR POSITION ;RESTORE DD RAM DATA 5 ;IS KEY PRESSED? ;YES, JUMP TO MAIN_3 ;IS TEMP = RANDOM? ;YES,JUMP TO BINGO ;NO, DISPLAY "MISS!" MESSAGE ;SET LINE 1 POSITION 0 ;LOAD STRING START ADDRESS ;PRINT ON LCD 5-98 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 99 MOV A,100 ;DELAY 1 SEC. 100 CALL DELAY 101 JMP MAIN 102 BINGO: 103 MOV A,80H+10 ;DISPLAY "BINGO!" 104 CALL WLCMCM ;SET LINE 1 POSITION 10 105 MOV A,OFFSET STR2 ;LOAD STRING START ADDRESS 106 CALL PRINT ;PRINT ON LCD 107 MOV A,250 ;DELAY 2.5 SEC. 108 CALL DELAY 109 JMP MAIN 110 ;======================================================================================== 111 ; PROC : RLCM 112 ; FUNC : READ DD RAM/CG RAM FORM LCM 113 ; REG : ACC 114 ; RETN : DD RAM/CG RAM DATA IN ACC 115 ;======================================================================================== 116 RLCM PROC 117 SET LCM_DATAPORTC ;CONFIG LCD_DATA AS INPUT MODE 118 CLR LCM_RS ;SET RW=0 119 SET LCM_RW 5 120 NOP 121 SET LCM_EN ;SET RW=1 ;FOR TAS ;SET EN=1 122 NOP ;FOR TDDR 123 RWF: SZ LCM_DATAPORT.7 ;IS LCD BUSY? 124 JMP RWF ;YES,WAIT 125 CLR LCM_EN ;SET EN=0 126 SET LCM_RW ;SET LCD_RW 127 SET LCM_RS ;SET RS=1 (DATA READ) 128 NOP 129 SET LCM_EN ;SET EN 130 NOP 131 MOV A,LCM_DATAPORT ;READ LCD DATA 132 CLR LCM_EN ;CLEAR EN 133 RET 134 RLCM ENDP 135 ;======================================================================================== 136 ; PROC : PRINT 137 ; FUNC : DISPLAY STRING ON LCM, STRING END WITH NULL AND POINT BY ACC(LAST PAGE) 138 ; REG : ACC 139 ; RETN : DD RAM/CG RAM DATA IN ACC 140 ;======================================================================================== 141 PRINT PROC 142 MOV 143 PRINT_1: 144 TABRDL TBLP,A ACC ;LOAD TABLE POINTER ;READ STRING 第五章 进阶实验篇 5-99 145 XOR A,NULL 146 SZ Z ;END OF STRING CHARACTER? 147 RET ;YES, STOP PRINT 148 TABRDL ACC ;NO, RE-READ 149 CALL WLCMDM ;SEND TO LCD 150 INC TBLP ;INCREASE DATA POINTER 151 JMP PRINT_1 ;NEXT CHARACTER 152 RET ;YES, RETURN 153 PRINT ENDP 154 ;======================================================================================== 155 ; PROC : WLCMDM/WLCMCM 156 ; FUNC : WRITE DATA/COMMAND TO LCM AND RETURN AC ADDRESS 157 ; PARA : ACC : COMMAND/DATA 158 ; REG : ACC,DC_FLAG,LCM_TEMP 159 ; RETN : LCM_AC : 1 BUSY BIT + 7-BIT AC 160 ;======================================================================================== 161 WLCMDM PROC 162 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 163 JMP $+2 164 WLCMCM:CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 165 MOV LCM_TEMP,A 166 SET LCM_DATAPORTC ;CONFIG LCM_DATAPORT AS I/P MODE 167 CLR LCM_RS ;SET RS=0 (IR) 5 168 SET LCM_RW ;SET RW=1 (READ) 169 NOP ;FOR TAS 170 WF: SET LCM_EN ;SET EN=1 171 NOP ;FOR TDDR 172 MOV A,LCM_DATAPORT 173 MOV LCM_AC,A 174 CLR LCM_EN ;SET EN=0 175 SZ LCM_AC.7 ;IS LCM BUSY? 176 JMP WF ;YES, JUMP TO WAIT 177 CLR LCM_DATAPORTC ;NO, CONFIG LCM_DATAPORT AS O/P MODE 178 MOV A,LCM_TEMP 179 MOV LCM_DATAPORT,A ;LATCH DATA/COMMAND ON LCM_DATAPORT 180 CLR LCM_RW ;SET RW=0 (WRITE) 181 CLR LCM_RS ;SET RS=0 (IR) 182 SZ DC_FLAG ;IS COMMAND WRITE? 183 SET LCM_RS ;NO, SET RS=1 (DR) 184 SET LCM_EN ;SET EN=1 185 NOP ;FOR PWEN 186 CLR LCM_EN ;SET EN=0 187 RET 188 WLCMDM ENDP 189 ;======================================================================================== 190 ; PROC : INIT_LCM 191 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 5-100 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 192 ; REG : ACC 193 ;======================================================================================== 194 INIT_LCM PROC 195 CLR LCM_EN ;SET EN=0 196 CLR LCM_RW ;SET RW=0 197 CLR LCM_RS ;SET RS=0 198 CLR LCM_ENC ;CONFIG EN AS O/P MODE 199 CLR LCM_RWC ;CONFIG RW AS O/P MODE 200 CLR LCM_RSC ;CONFIG RS AS O/P MODE 201 202 MOV A,38H ;FUNCTION SET: 8-BIT,2-LINE,5X7 DOTS 203 CALL WLCMCM 204 MOV A,0CH ;ON/OFF CONTR: DISPLAY ON,CURSOR BLINKING OFF 205 CALL WLCMCM 206 MOV A,06H ;ENTRY MODE : INCREMENT,DISPLAY NOT SHIFT 207 CALL WLCMCM 208 MOV A,01H ;CLEAR DISPLAY 209 CALL WLCMCM 210 RET 211 INIT_LCM ENDP 212 ;======================================================================================== 5 213 ; PROC : DELAY 214 ; FUNC : DEALY ABOUT ACC*10mS @fSYS=4MHz 215 ; REG : DEL1,DEL2,DEL3 216 ;======================================================================================== 217 DELAY PROC 218 MOV DEL1,A ;SET DEL1 COUNTER 219 DEL_1: MOV A,30 220 MOV DEL2,A ;SET DEL2 COUNTER 221 DEL_2: MOV A,110 222 MOV DEL3,A ;SET DEL3 COUNTER 223 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 224 JMP DEL_3 225 SDZ DEL2 ;DEL2 DOWN COUNT 226 JMP DEL_2 227 SDZ DEL1 ;DEL1 DOWN COUNT 228 JMP DEL_1 229 RET 230 DELAY ENDP 231 ORG LASTPAGE 232 STR02F: DC '0123456789ABCDEF',NULL 233 STR1: DC 'MISS!',NULL ;DEFINE STRING DATA 1 234 STR2: DC 'BINGO!',NULL ;DEFINE STRING DATA 2 235 END 第五章 进阶实验篇 5-101 程程序序解解说说:: 4 载入”5-9.INC”定义档,其内容请参考随书光盘中的档案。 7~17 依序定义变量地址。 20 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 21~23 关闭 CP0 功能,并设定 ADC 脚位输入为 I/O 功能。 24~26 将 PA[3:0]定义成输入模式,并使能其上拉电阻功能。 27~30 定义 TM0C0、TM0C1 控制寄存器: T0CK[2:0]:001,设定 fINT=fSYS; T0M[1:0]:11,设定为 Timer/Counter 模式; T0CCLR:0,设定当 TM0D[9:7]=T0RP[2:0]时清除计数器; T0ON:1,CTM 开始计数。 31 调用 INIT_LCM 子程序,对 LCM 进行定义。 32~33 设定 FACTOR 存储器值为 8;此存储器决定光标移动的速度。 35~36 将 LCM 整个显示器清空。 37~38 设定 DD RAM 地址为第二列的首行。 5 39~40 调用 PRINT 子程序,将“0”~“F”依序显示在 LCM。 41~43 将 TM0DL 与 TM0DH 寄存器执行 XOR 的动作,然后与常数 0Fh 做 AND,主要目 的是取得一个小于或等于“F”的随机数。 44~46 将随机数转换为对应的 ASCII 码,并存放于 RANDOM 存储器。 47~48 设定 DD RAM 的地址到 LCM 第一列的正中央。 49~50 调用 WLCMDM 子程序,将随机数显示在 LCM 上。 52~55 设定索引值 INDEX 内容为“C0h”(INDEX 是用来控制移动中的光标地址),并 设定计数器 COUNT 内容为 16(在此 LCM 可见范围为 16×2 个 Byte,由于游戏数 字的范围为“0”~“F”,因此只需扫描 16 次,以下将有详细的解说)。 57~58 将 DD RAM 的地址设定在与索引值 INDEX 所对应的地址(以程序第一次执行至此, 索引值 INDEX 为 C0H 其所对应的地址即为显示器第二列的第一个位置)。 59~64 调用 RLCM 子程序读取 LCD_DATA 的内容值存入 TEMP 存储器中,并执行 61~62 行的动作。完成后写入“▉”于目前 INDEX 与 LCM 所对应的地址,表示游戏中的 光标正停留在此位置。 5-102 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 65~66 调用 DELAY 子程序,延迟 FACTOR×10mS。此延迟时间的长短决定了光标移动 的速度,读者可通过 Faster、Slower 按键改变延迟的时间,试试自己反应的快慢。 67~70 将刚刚设为“▉”的地址回复成正常的数字(以第一次程序执行至此,即将“▉” 改为“0”),原本地址所存放的内容在 TEMP 存储器。 71~88 判断是否有按键输入,若按下 Slower 按键,则在 FACTOR 不为 255 的前提下,将 FACTOR 值加一,并继续扫描下一个 LCM 地址。当按下 Faster 按键,则在 FACTOR 不为零的前提下,将 FACTOR 值减一,并继续扫描下一个 LCM 地址。其间会判断 COUNT 减一是否为 0,若成立,则表示游戏的光标已将“0”至“F”扫描一次, 依然无任何按键输入,重新由“0”开始扫描;反之,则进行下个地址的扫描工作。 (注:设定 LCM 时已将 LCM 的光标显示关闭,在此自行设定了一个光标,利用 LCM 字型码中的“▉”覆盖原来索引值 INDEX 对应的地址内容,来表示光标正停留在此 位置。)但若按下 Hit 按键,则跳至 MAIN_4 执行程序。 90~93 将答案(RANDOM)与结果(TEMP)互相比对,若结果等于 0(Z = 1)即表示答 对;反之则答错了。 5 95~101 调用 PRINT 子程序,于 LCM 左上角显示“MISS!”并延迟 100mS,完成后程序 重新开始。 103~109 调用 PRINT 子程序,于 LCM 右上角显示“BINGO!”并延迟 250mS,完成后程 序重新开始。 116~134 RLCM 子程序,负责读取 LCM DD RAM 的内容,请参考实验中有关 LCM 读取子程 序的说明。 117 定义 LCM_DATAPORT 为输入模式,接收 LCM 忙碌标志(BF)的内容。 118 将 LCM 的 RS 控制信号设定为“0”。 119~122 将设定 RW 为“1”(Read)并使能 LCM(Enable),用来检查 LCM 是否处于忙 碌状态,“NOP”指令是让 LCM 有足够的缓冲时间接受命令并完成工作,即考虑 【图 5-6-3】中的 TAS、TDDR 的时序。 123~124 检查 LCM_DATA PORTC 的 BIT 7(即 Busy Flag)是否处于忙碌状态(BF=“1”), 直到 BF=“0”才继续执行程序。 154 清除 LCD_CONTR Port(目的是将 LCM 的控制信号 E、RS、RW 设定为“0”, 结束此次的读取动作)。 125~128 设定 RW=“1”、RS=“1”;表示准备进行 LCM DR(Data Register)的读取动 作。 第五章 进阶实验篇 5-103 129 设定 LCM 控制信号 E=“1” 131 读取 LCM 的数据。 132 将 LCM 的控制信号 E 设定为“0”,结束此次的读取动作。 141~153 PRINT 子程序,此子程序负责将定义好的字符串依序显示于 LCM 上。在调用此子 程序之前,除了必须先设定好 LCM 的位置之外,尚需先在 Acc 寄存器中指定字符 串的起始地址(字符串必须存放在最末程序页-Last Page),并请在字符串的最后 一个字符塞入 NULL,代表字符串结束。 161~188 WLCMDM 与 WLCMCM 子程序,请参考【实验 5-6】中的说明。 217~230 DELAY 子程序,延迟时间的计算请参考【实验 4-1】中的说明。 232~234 字符串定义区,请注意每一个字符串必须以 NULL 做为结束。 随机数的产生方式其实有各种不同的做法,而本实验因为使用到按键检测,所 以程序一开始就先启动HT66F50的CTM的Timer/Counter功能,由于每次按按键的 时间皆不相同,所以采用Timer/ Counter来产生随机数是既方便又简单的方法。 DELAY子程序延迟时间的长短决定了光标移动的速度,读者可以通过Fsater、 Slower两个按键调整延迟时间试试自己反应的快慢。另外要注意的是,当读取TM 5 单元的寄存器时,必须先读取High Byte再读取Low Byte方能正确读出其值! 5-9-5 动动脑+动动手: 本实验的范例程序执行时,并未限定使用者输入的时间。请读者修改程序, 若光标已经重复扫描每个数值十次,然而使用者却未按下任何按键,则立即 显示“MISS!”的错误画面。 修改程序,一开始提供使用者 50 分的分数,答对一次加五分、答错一次扣 五分,并将分数显示在 LCM 上。 改写程序,使得所产生的随机数重复率再降低。例如,在十次之内所产生的 随机数均不得重复(有点类似 CD Player 的随机播放模式,在整张 CD 播放 完毕之前,随机播放的曲目不得重复,在此假设 CD 的曲目为十首)。 5-104 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-10 LCM的四位控制模式实验 5-10-1 目 的: 采用LCM的四位控制模式,于LCM的CG RAM建立“大”、“小”两个字型, 并分别显示在LCM的第一、二排。 5-10-2 学习重点: 通过本实验,了解LCM的四位控制模式;并学习在与其它装置共用Port的情况 下,如何在不影响其它装置的状态将四位数据或命令送达LCM的技巧。 5-10-3 电路图: 5 【图 5-10-1】四位总线连接接口 【图 5-10-2】四位总线控制时序范例 LCM的八位及四位控制模式,唯一的差别就是将要写入或读出的数据分成两次 来处理,而且是先存取高四位(DB7~DB4)后再存取低四位(DB3~DB0)。【图 5-10-2】的时序图是将指令写到LCM、由LCM读回忙碌标志(BF)以及读回数据 第五章 进阶实验篇 5-105 寄存器(DR)的范例。根据此时序范例,理论上只要将【实验5-6】的WLCMC与 WLCMD程序稍加修改即可! 但是要特别考虑的是:PD[3:0]可能用来控制其它的外围元件,虽然LCM的数 据或命令是经PD[7:4]传输,但是在HT66F50指令运用上仍是得以“MOV PD,A” 来达成,也就是说,如果不妥善处理的话,此一动作可能也会一并改变连接于PD[3:0] 的装置状态!所以该如何保证PD[3:0]、PDC[3:0]不受“MOV PD,A”指令影响而 仍 维 持 原 来 状 态 呢 ? 请 参 考 以 下 的WLCMD_4 与 WLCMC_4 子 程 序 , 其 中 以 LCM_DATAPORT表示PD,LCDM_DATAPORTC则为PDC。第9~10行利用OR 的方式,将连接至LCM DB7~DB3的PD[7:4]定义为输入模式,此举将不致影响 PD[3:0]原来的状态与输入/输出设定。同理,在19~21行的程序先是以00001111B 与 PD 执 行 AND 运 算 , 其 目 的 是 将 PD[7:4] 的 状 态 先 清 为 零 , 接 着 以 相 同 方 式 将 PD[7:4]定义成输出模式;以上的做法也依旧维持PD[3:0]原来的状态与输入/输出设 置。22~24行、33~37行则以OR的方式配合SWAP指令将命令或数据分两次由 PD[7:4]送至LCM DB7~DB3的PD[7:4]。 WLCMD_4/ WLCMC_4子程序: 1 ;===================================================================================== === 2 ; 4-BIT MODE LCD DATA/COMMAND WRITE PROCEDURE 3 ;===================================================================================== 5 === 4 WLCMD_4 PROC 5 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 6 JMP $+2 7 WLCMC_4: CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 8 MOV LCM_TEMP,A ;SAVED COMAND/DATA IN LCD_TEMP 9 MOV A,11110000B 10 ORM A,LCM_DATAPORTC ;CONFIG LCM_DATAPORT[7:4] AS I/P MODE 11 SET LCM_RW ;SET RW=1 (READ) 12 CLR LCM_RS ;SET RS=0 (IR) 13 NOP ;FOR TAS 14 SET LCM_EN ;SET EN=1 15 NOP ;FOR TDDR 16 WF_4: SZ LCM_DATAPORT.7 ;IS LCD BUSY? 17 JMP WF_4 ;YES, JUMP TO WAIT 18 CLR LCM_EN ;SET EN=0 19 MOV A,00001111B 20 ANDM A,LCM_DATAPORT ;SET LCM_DATAPORT[7:4]=0000 21 ANDM A,LCM_DATAPORTC ;CONFIG LCM_DATAPORT[7:4] AS O/P MODE 22 MOV A,LCM_TEMP 23 AND A,11110000B ;GET HIGH NIBBLE DATA/COMMAND 24 ORM A,LCM_DATAPORT ;LATCH DATA/COMMAND ON LCM_DATAPORT[7:4] 25 CLR LCM_RW ;SET RW=0 (WRITE) 26 CLR LCM_RS ;SET RS=0 (IR) 5-106 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 27 SZ DC_FLAG ;IS COMMAND WRITE? 28 SET LCM_RS ;NO, SET RS=1 (DR) 29 NOP ;FOR TAS 30 SET LCM_EN ;SET EN=1 31 NOP ;FOR PWEN 32 CLR LCM_EN ;SET EN=0 33 MOV A,00001111B 34 ANDM A,LCM_DATAPORT ;SET LCM_DATAPORT[7:4]=0000 35 SWAPA LCM_TEMP 36 AND A,11110000B ;GET LOW NIBBLE DATA/COMMAND 37 ORM A,LCM_DATAPORT ;LATCH DATA/COMMAND ON LCM_DATAPORT[7:4] 38 SET LCM_EN ;SET EN=1 39 NOP ;FOR PWEN 40 CLR LCM_EN ;SET EN=0 41 RET 42 WLCMD_4 ENDP 如【实验5-6】,WLCMD_4、WLCMC_4子程序仅是读取LCM的忙碌状态做 判断,并非中规中矩的依指令表将AC一并读回;为方便读者,笔者还是依【实验 5-8】范例将完整的AC读取子程序列出,也期望读者能不厌其烦的比较其间的差异: 5 WLCMD_4M/ WLCMC_4M子程序: 1 ;===================================================================================== === 2 ; PROC : WLCMD_4M/WLCMC_4M 3 ; FUNC : WRITE DATA/COMMAND TO LCM UNDER 4-BIT MODE (HIGH NIBBLE CONNECT) AND RETURN AC 4 ; PARA : ACC : COMMAND/DATA 5 ; REG : ACC,DC_FLAG,LCM_TEMP 6 ; RETN : LCM_AC : 1 BUSY BIT + 7 AC BIT 7 ;===================================================================================== === 8 WLCMD_4M PROC 9 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 10 JMP $+2 11 WLCMC_4M: CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 12 MOV LCM_TEMP,A ;SAVED COMAND/DATA IN LCD_TEMP 13 MOV A,11110000B 14 ORM A,LCM_DATAPORTC ;CONFIG LCM_DATAPORT[7:4] AS I/P MODE 15 SET LCM_RW ;SET RW=1 (READ) 16 CLR LCM_RS ;SET RS=0 (IR) 17 NOP ;FOR TAS 18 WF_4: SET LCM_EN ;SET EN=1 19 NOP ;FOR TDDR 20 MOV A,LCM_DATAPORT ;READ HIGH NIBBLE RETURN DATA 21 CLR LCM_EN ;SET EN=0 22 AND A,11110000B ;MASK LOW NIBBLE 第五章 进阶实验篇 5-107 23 SET LCM_EN ;SET EN=1 24 MOV LCM_AC,A ;SAVE IN LCM_AC 25 MOV A,LCM_DATAPORT ;READ LOW NIBBLE RETURN DATA 26 CLR LCM_EN ;SET EN=0 27 AND A,11110000B ;MASK LOW NIBBLE 28 SWAPA ACC ;SWAP RETURN DATA TO LOW NIBBLE 29 ORM A,LCM_AC ;COMBINE WITH HIGH NIBBLE 30 SZ LCM_AC.7 ;IS LCD BUSY? 31 JMP WF_4 ;YES, JUMP TO WAIT 32 CLR LCM_EN ;SET EN=0 33 MOV A,00001111B 34 ANDM A,LCM_DATAPORTC ;CONFIG LCM_DATAPORT[7:4] AS O/P MODE 35 ANDM A,LCM_DATAPORT ;SET LCM_DATAPORT[7:4]=0000 36 MOV A,LCM_TEMP 37 AND A,11110000B ;GET HIGH NIBBLE DATA/COMMAND 38 ORM A,LCM_DATAPORT ;LATCH DATA/COMMAND ON LCM_DATAPORT[7:4] 39 CLR LCM_RW ;SET RW=0 (WRITE) 40 CLR LCM_RS ;SET RS=0 (IR) 41 SZ DC_FLAG ;IS COMMAND WRITE? 42 SET LCM_RS ;NO, SET RS=1 (DR) 43 NOP ;FOR TAS 44 SET LCM_EN ;SET EN=1 45 NOP ;FOR PWEN 5 46 CLR LCM_EN ;SET EN=0 47 MOV A,00001111B 48 ANDM A,LCM_DATAPORT ;SET LCM_DATAPORT[7:4]=0000 49 SWAPA LCM_TEMP 50 AND A,11110000B ;GET LOW NIBBLE DATA/COMMAND 51 ORM A,LCM_DATAPORT ;LATCH DATA/COMMAND ON LCM_DATAPORT[7:4] 52 SET LCM_EN ;SET EN=1 53 NOP ;FOR PWEN 54 CLR LCM_EN ;SET EN=0 55 RET 56 WLCMD_4 ENDP 57 END 5-108 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-10-4 程序及流程图: 5 第五章 进阶实验篇 5-109 程序5-10 LCM四位控制模式 1 ;PROGRAM : 5-10.ASM (5-10.PJT) 2009.1105 2 ;FUNCTION: 16X2 LCM 4-BIT MODE CONTROL PROGRAM By Steven 3 #INCLUDE HT66F50.INC 4 #INCLUDE "5-10.INC" 5 ;======================================================================================== 6 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 7 DEL1 DB ? ;DELAY LOOP COUNT 1 8 DEL2 DB ? ;DELAY LOOP COUNT 2 9 DEL3 DB ? ;DELAY LOOP COUNT 3 10 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 11 LCM_TEMP DB ? ;BUFFER FOR LCM PROCEDURE 12 LINE_COUNT DB ? ;DISPLAY COUNT 13 ;======================================================================================== 14 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 15 ORG 00H ;HT-66FX0 RESET VECTOR 16 CALL INIT_LCM 17 MOV A,01000000B ;SET CG RAM START ADDRESS 18 CALL WLCMC_4 19 MOV A,2*8 20 MOV LINE_COUNT,A ;SET CG RAM WRITE COUNTER 21 MOV A,OFFSET TAB_CG RAM ;GET TABLE START ADDRESS 22 MOV TBLP,A 5 23 NEXT: 24 TABRDL ACC ;READ DATA 25 CALL WLCMD_4 ;WRITE TO CG_RAM 26 INC TBLP ;INCREASE POINTER BY 1 27 SDZ LINE_COUNT ;COUNT-1 = 0? 28 JMP NEXT ;NO, NEXT DATA 29 MAIN: 30 MOV A,01 ;CLEAR DISPLAY 31 CALL WLCMC_4 32 MOV A,80H ;SET LINE ONE 33 CALL WLCMC_4 34 MOV A,16 35 MOV LINE_COUNT,A 36 MAIN_1: 37 MOV A,0 ;WRITE '小' 38 CALL WLCMD_4 39 CALL DELAY ;JUST FOR SEEING THE DISPLAY 40 SDZ LINE_COUNT 41 JMP MAIN_1 42 MOV A,0C0H ;SET LINE TWO 43 CALL WLCMC_4 44 MOV A,16 45 MOV LINE_COUNT,A 46 MAIN_2: 5-110 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 47 MOV A,1 ;WRITE '大' 48 CALL WLCMD_4 49 CALL DELAY ;JUST FOR SEEING THE DISPLAY 50 SDZ LINE_COUNT 51 JMP MAIN_2 52 JMP MAIN 53 ;======================================================================================== 54 ; PROC : INIT_LCM 55 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 56 ; REG : ACC 57 ;======================================================================================== 58 INIT_LCM PROC 59 CLR LCM_EN ;SET EN=0 60 CLR LCM_RW ;SET RW=0 61 CLR LCM_RS ;SET RS=0 62 CLR LCM_ENC ;CONFIG EN AS O/P MODE 63 CLR LCM_RWC ;CONFIG RW AS O/P MODE 64 CLR LCM_RSC ;CONFIG RS AS O/P MODE 65 66 MOV A,28H ;FUNCTION SET: 4-BIT,2-LINE,5X10 DOTS 67 CALL WLCMC_4 5 68 MOV A,0CH 69 CALL WLCMC_4 ;ON/OFF CON.: DISPLAY ON, BLINKING OFF 70 MOV A,06H ;ENTRY MODE : INCREMENT, SHIFT 71 CALL WLCMC_4 72 MOV A,01H ;CLEAR DISPLAY 73 CALL WLCMC_4 74 RET 75 INIT_LCM ENDP 76 ;======================================================================================== 77 ; PROC : WLCMD_4/WLCMC_4 78 ; FUNC : WRITE COMMAND OR DATA TO LCM UNDER 4-BIT MODE (HIGH NIBBLE CONNECT) 79 ; PARA : ACC : COMMAND/DATA 80 ; REG : ACC,DC_FLAG,LCM_TEMP 81 ;======================================================================================== 82 WLCMD_4 PROC 83 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 84 JMP WLCM_4 85 WLCMC_4: 86 CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 87 WLCM_4:MOV LCM_TEMP,A ;SAVED COMAND/DATA IN LCD_TEMP 88 MOV A,11110000B 89 ORM A,LCM_DATAPORTC ;CONFIG LCM_DATAPORT[7:4] AS I/P MODE 90 SET LCM_RW ;SET RW=1 (READ) 91 CLR LCM_RS ;SET RS=0 (IR) 92 NOP ;FOR TAS 93 SET LCM_EN ;SET EN=1 第五章 进阶实验篇 5-111 94 NOP ;FOR TDDR 95 WF_4: SZ LCM_DATAPORT.7 ;IS LCD BUSY? 96 JMP WF_4 ;YES, JUMP TO WAIT 97 CLR LCM_EN ;SET EN=0 98 MOV A,00001111B 99 ANDM A,LCM_DATAPORTC ;CONFIG LCM_DATAPORT[7:4] AS O/P MODE 100 ANDM A,LCM_DATAPORT ;SET LCM_DATAPORT[7:4]=0000 101 MOV A,LCM_TEMP 102 AND A,11110000B ;GET HIGH NIBBLE DATA/COMMAND 103 ORM A,LCM_DATAPORT ;LATCH DATA ON LCM_DATAPORT[7:4] 104 CLR LCM_RW ;SET RW=0 (WRITE) 105 CLR LCM_RS ;SET RS=0 (IR) 106 SZ DC_FLAG ;IS COMMAND WRITE? 107 SET LCM_RS ;NO, SET RS=1 (DR) 108 NOP ;FOR TAS 109 SET LCM_EN ;SET EN=1 110 NOP ;FOR PWEN 111 CLR LCM_EN ;SET EN=0 112 MOV A,00001111B 113 ANDM A,LCM_DATAPORT ;SET LCM_DATAPORT[7:4]=0000 114 SWAPA LCM_TEMP 115 AND A,11110000B ;GET LOW NIBBLE DATA/COMMAND 116 ORM A,LCM_DATAPORT ;LATCH DATA/COMMAND ON LCM_DATAPORT[7:4] 5 117 SET LCM_EN ;SET EN=1 118 NOP ;FOR PWEN 119 CLR LCM_EN ;SET EN=0 120 RET 121 WLCMD_4 ENDP 122 ;======================================================================================== 123 ; PROC : DELAY 124 ; FUNC : DEALY ABOUT 10*10mS @fSYS=4MHz 125 ; REG : DEL1,DEL2,DEL3 126 ;======================================================================================== 127 DELAY PROC 128 MOV A,10 129 MOV DEL1,A ;SET DEL1 COUNTER 130 DEL_1: MOV A,30 131 MOV DEL2,A ;SET DEL2 COUNTER 132 DEL_2: MOV A,110 133 MOV DEL3,A ;SET DEL3 COUNTER 134 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 135 JMP DEL_3 136 SDZ DEL2 ;DEL2 DOWN COUNT 137 JMP DEL_2 138 SDZ DEL1 ;DEL1 DOWN COUNT 139 JMP DEL_1 140 RET 5-112 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 141 DELAY ENDP 142 ORG LASTPAGE 143 TAB_CG RAM: 144 DC 00000000B 145 DC 00000100B 146 DC 00000100B 147 DC 00010101B 148 DC 00010101B 149 DC 00000100B 150 DC 00001100B 151 DC 00000000B 152 153 DC 00000000B 154 DC 00000100B 155 DC 00000100B 156 DC 00011111B 157 DC 00000100B 158 DC 00001010B 159 DC 00010001B 160 DC 00000000B 161 END 5 程程序序解解说说:: ;CHARACTER '小' ;CHARACTER '大' 4 6~12 15 16 17~18 19~22 24~25 26 27~28 载入”5-10.INC”定义档,其内容请参考随书光盘中的档案。 依序定义变量地址。 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 调用 INIT_LCM 子程序,对 LCM 进行定义。 设定 CG RAM 的地址为 00H,准备写入自建字型。 设定计数器 LINE_COUNT 为 16 并将 TBLP 指向自建字型数据的起始地址。 经由查表将自建字型的数据取出写入 CG RAM 中。 将 TBLP 加一。 判断 COUNT 减一是否为 0。成立,表示所有自建字型已输入完毕;反之,则表示 自建字型尚未建立完成,继续填入字型码。 30~31 32~33 34~35 37~38 将 LCM 整个显示器清空。 将光标移至第一列的第零个位置。 设定计数器 LINE_COUNT 为 16。 将自建字型“小”显示于 LCM 上。 第五章 进阶实验篇 5-113 39 调用 DELAY 子程序,延迟 100ms。 40~41 判断 LCM 光标是否已至第一列最后一个位置,成立则换到第二列;反之则继续显示。 42~43 将光标移至第二列的第零个位置。 44~45 设定计数器 LINE_COUNT 为 16。 47~48 将自建字型“大”显示于 LCM 上。 49 调用 DELAY 子程序,延迟 100ms。 50~52 判断 LCM 光标是否已至第二列最后一个位置,成立则重新从第一列显示,反之则继 续显示。 58~75 INIT_LCM 子程序,其功能是对 LCM 进行定义。 59~64 LCM_EN、LCM_RW 与 LCM_RS 定义为输出模式,并设定状态为“0”。 66~67 将 LCM 设定为双行显示(N = 1)、使用四位(DB7 ~ DB4)控制模式(DL = 0)、 5×7 点矩阵字型(F = 0)。 68~69 将 LCM 设定为显示所有数据(D = 1)、显示光标(C = 1)、光标所在位置的字会 闪烁(B = 1)。 70~71 将 LCM 的地址计数器(AC)设为递加(I/D = 1)、显示器画面不因读写数据而移 5 动(S = 0)。 72~73 将 LCM 整个显示器清空。 82~84 WLCMD_4 子程序进入点,将 DC_FLAG 设定为“1”,代表欲写入的内容为数据。 85~86 WLCMC_4 子程序进入点,将 DC_FLAG 设定为“0”,代表欲写入的内容为命令。 (PS. DC_FLAG:Data/Command Flag;“1”=Data、“0”=Command) 88~89 定义 LCM_DATAPORT[7:4]为输入模式,接收 LCM 忙碌标志(BF)的内容。 90~94 95~96 将 LCM 的 RS 控制信号设定为“0”,并设定 RW 为“1”(Read)且使能 LCM (Enable),用来检查 LCM 是否处于忙碌状态,“NOP”指令是让 LCM 有足够的 缓冲时间接受命令并完成工作,即考虑【图 5-6-3】中的 TAS、TDDR 的时序。 检查 LCM_DATA PPORT 的 BIT 7(即 Busy Flag)是否处于忙碌状态(BF=1), 直到 BF=0 才继续执行程序。 97 将 LCM 的 EN 控制信号设定为“0” 98~100 定义 LCM_DATAPORT[7:4]为输出模式,用来输出命令或数据至 LCM。 101~103 将要输出到 LCM 上的命令或数据移到 LCM_DATAPORT[7:4],此阶段乃是处理高 四位(High Nibble)部分。 5-114 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 104~108 设定 RS、RW 为“0”后,判断 DC_FLAG 标志是否为“0”,成立表示 LCM 欲写 入的内容为“命令”;反之,则表示欲写入的内容为“数据”。 109 设定 LCM 控制信号 E=“1”。 110~111 让 LCM 有足够的缓冲时间接受命令或数据并完成工作,完成后将 LCM 除能回到主 程序继续下面的动作。“NOP”指令是让 LCM 有足够的缓冲时间接受命令并完成 工作,即考虑【图 5-6-4】中的 TEr、PWEN 的时序。 112~116 将 Acc 的高、低四个位数据互换;并将低四位(Low Nibble)的命令或数据移到 LCM_DATAPORT[7:4]。 117 设定 LCM 控制信号 E=“1”。 119 将 LCM 除能回到主程序继续下面的动作。 127~141 DELAY 子程序,延迟 0.1 秒:关于延迟时间的计算请读者参考【实验 4-1】。 144~160 自建字型数据定义区。 5 除了RS、RW、E与DB7~DB4有一定的时序关系之外,LCM的设定也有一定 的顺序;【图5-10-3】是HD44780数据手册中所描述的四位控制模式初始程序,程 序中有关LCM定义步骤就是依此要求逐步完成的。程序一开始先对LCM做初始化 的设定,紧接着在设定CG RAM的地址之后开始建立“小”及“大”两个字型,最 后就是重复的在第一及第二行显示这两个自建的字型。除了LCM的控制子程序 (WLCMC_4与WLCMD_4)改以四位处理之外,与前两个实验实际上并没有什么 差异。要提醒读者的是在【图5-10-2】四位的控制时序范例中,在读取忙碌标志(BF) 时,理应将(BF)与光标地址(AC6~AC0)分两次读取,可是因为本范例并不需 要光标位置的信息,所以在控制子程序中,只把包含忙碌标志的高四位读回做判断 而已! 第五章 进阶实验篇 5-115 【图 5-10-3】HT44780 初始化程序(4-Bit 控制模式) 5-10-5 动动手+动动脑: 改写程序,让“大”、“小”两个字型变为上下交替显示。 【程序 5-10】中自建字形的建表,是以每笔 8-Bit 就占据一个程序空间,显 5 得相当浪费;请仿照【程序 5-7】的做法,将每两笔数据集成在一个程序空 间中。 5-116 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-11 比大小游戏实验 5-11-1 目 的: 利用HT66F50的STM Timer/Counter模式产生两个随机数,让使用者猜猜两个 数字的大小关系,由程序判断其正确性后再分别显示出“MISS!”或“BINGO!” 的字符串,分别代表使用者猜的正确与否;本实验采用LCM的四位控制模式。 5-11-2 学习重点: 通过本实验,读者除了应更熟悉LCM的四位控制模式之外,也应了解十六进制 与BCD码的转换关系。 5-11-3 电路图 : 5 PS:若使能PA[2:0]Pull-high功能,则10kΩ电阻可省略。 【图 5-11-1】比大小游戏实验电路 十六进制与BCD的转换,在许多单片机的应用场合都会使用到。基本的原理很 简单,假设DIG0代表要转换的8-Bit数值,DIG2、DIG1及DIG0分别代表转换为十 进制之后的百位数、十位数及个位数,请参考HEX2BCD(Hex To BCD)子程序 的流程图。因为本实验是将STM单元Timer/Counter所产生的8-Bit随机数显示在 LCM上,所以光是转成BCD码是不够的,必须再将其进一步转换成LCM的字符码 (Chararcter Code),请参考流程图中的虚线路径,只要将转换好的BCD(“0” ~“9”)再加上30h就可以了!此程序称之为HEX2ASCII(Hex To ASCII)子程序。 本实验想在LCM上呈现如下的画面: 首先将 Timer/ Counter 产生的 8-Bit 随机数显示在 LCM 上,同时在第一、二 列上分别显示“大”、“小”。接着使用者可通过“Greater”、“Less”按钮选 第五章 进阶实验篇 5-117 择第二个随机数是大于或小于随机数 1。在使用者按下“Enter”按键之后,再由 程序判断此时使用者所选择的随机数大小关系是否正确,分别显示出以下的画面: 有关本实验所使用的STM单元相关控制寄存器简列于【表5-11-1】,详细内容 请读者参阅【2-5-2节】。 【表 5-11-1】本实验相关控制寄存器 TM2C0 T2PAU T2CK2 T2CK1 T2CK0 T2ON - - - 【2-5-2 节】 TM2C1 TM2RP TM2AL T2M1 T2M0 T2IO1 T2IO0 T2OC TM2RP[7:0] TM2A[7:0] T2POL T2DPX T2CCLR TM2AH TM2A[15:8] TM2DL TM2D[7:0] TM2DH TM2D[15:8] Bit7 6 5 4 3 2 1 Bit0 5 5-11-4 程序及流程图: 5-118 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 程序5-11 比大小游戏实验 1 ;PROGRAM : 5-11.ASM (5-11.PRJ) 2009.1105 5 2 ;FUNCTION: GREAT OR LESS LCM GAME DEMO PROGRAM By Steven 3 #INCLUDE HT66F50.INC 4 #INCLUDE 5-11.INC 5 ;======================================================================================== 6 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 7 DEL1 DB ? ;DELAY LOOP COUNT 1 8 DEL2 DB ? ;DELAY LOOP COUNT 2 9 DEL3 DB ? ;DELAY LOOP COUNT 3 10 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 11 LCM_TEMP DB ? ;BUFFER FOR LCM PROCEDURE 12 LINE_COUNT DB ? ;DISPLAY COUNT 13 DIG0 DB ? ;ASCII BUFFER FOR DIGIT 0 14 DIG1 DB ? ;ASCII BUFFER FOR DIGIT 1 15 DIG2 DB ? ;ASCII BUFFER FOR DIGIT 2 16 TEMP DB ? ;TEMPORY BUFFER 17 COUNT DB ? ;UNIVERSAL COUNTER 18 RANDOM DB ? ;RANDOM BUFFER 19 INDEX DB ? ;INDEX REGISTER 20 CLICK DB ? 21 ;======================================================================================== 22 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 23 ORG 00H ;HT-66FX0 RESET VECTOR 24 CLR ACERL ;AD DISABLE 25 MOV A,08H 26 MOV CP0C,A ;DISABLE CPO 27 MOV A,00000111B 第五章 进阶实验篇 5-119 28 ORM A,SW_PORTC ;CONFIG SW_PORT[2:0] AS I/P MODE 29 ORM A,SW_PORTPU ;ENABLE SW_PORT[2:0] PULL-UP 30 CLR TM2RP ;SET TM2RP=0 31 MOV A,11000000B ;TIMER/COUNTER MODE 32 MOV TM2C1,A ;,CLEAR BY CCRP COMPARE MATCH 33 MOV A,00011000B ;fINT=fSYS,T0ON 34 MOV TM2C0,A 35 CALL INIT_LCM 36 MOV A,01000000B ;SET CG RAM START ADDRESS 37 CALL WLCMC_4 38 MOV A,2*8/2 39 MOV LINE_COUNT,A ;SET CG RAM WRITE COUNTER 40 MOV A,OFFSET TAB_CG RAM ;GET TABLE START ADDRESS 41 MOV TBLP,A 42 NEXT: 43 TABRDL ACC ;READ DATA 44 CALL WLCMD_4 ;WRITE TO CG_RAM 45 MOV A,TBLH ;GET DATA 46 CALL WLCMD_4 ;WRITE TO CG_RAM 47 INC TBLP ;INCREASE POINTER BY 1 48 SDZ LINE_COUNT ;COUNT-1 = 0? 49 JMP NEXT ;NO, NEXT DATA 50 MAIN: 5 51 MOV A,01 ;CLEAR DISPLAY 52 CALL WLCMC_4 53 MOV A,TM2DH ;GET TM2DH 54 XOR A,TM2DL ;XOR WITH TM2DL AS RANDOM NUMBER 1 55 MOV RANDOM,A ;RESERVED RANDOM NUMBER 1 56 CALL HEX2ASCII ;CONVERT RANDOM 1 TO ASCII CODE 57 MOV A,82H ;SET LINE 1 POSITION 2 58 CALL WLCMC_4 59 CALL WRITE_DIG ;DISPLAY RANDOM 1 ON LCD 60 MOV A,86H ;SET LINE 1 POSITION 6 61 CALL WLCMC_4 62 MOV A,00 ;DISPLAY "小" 63 CALL WLCMD_4 64 MOV A,0C6H ;SET LINE 2 POSITION 6 65 CALL WLCMC_4 66 MOV A,01 ;DISPLAY "大" 67 CALL WLCMD_4 68 MOV A,87H ;SET LINE 1 POSITION 7 CODE ON CLICK 69 MOV CLICK,A 70 LOOP_1: 71 MOV A,CLICK 72 CALL WLCMC_4 ;SET POSITION AS CODE IN CLICK 73 WAIT: 74 SNZ SW_GREAT ;SW_GREAT SWITCH PRESSED? 5-120 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 75 SET CLICK.6 76 SNZ SW_LESS 77 CLR CLICK.6 78 SNZ SW_ENTER ;ENTER SWITCH PRESSED? 79 JMP LOOP_3 ;YES. JUMP TO LOOP_3 80 MOV A,15 ;NO. DELAY 0.15 SEC 81 CALL DELAY 82 JMP LOOP_1 83 LOOP_3: 84 MOV A,TM2DH ;GET TM2DH 85 XOR A,TM2DL ;XOR WITH TM2DL AS RANDOM NUMBER 2 86 MOV TEMP,A ;RESERVED RANDOM NUMBER 2 87 CALL HEX2ASCII ;CONVERT RANDOM 2 TO ASCII CODE 88 MOV A,0C2H ;SET LINE 2 POSITION 2 89 CALL WLCMC_4 90 CALL WRITE_DIG ;DISPLAY RANDOM 2 ON LCD 91 MOV A,TEMP 92 SUB A,RANDOM 93 SZ C ;IS TEMP > RANDOM ? 94 JMP R_G_T ;NO. 95 SNZ CLICK.6 5 96 JMP BINGO 97 JMP MISS ;IS USER SELECT RANDOM > TEMP? ;YES, DISPLAY BINGO! ;NO, DISPLAY MISS! 98 R_G_T: SNZ CLICK.6 ;IS USER SELECT TEMP > RANDOM? 99 JMP MISS ;NO, DISPLAY MISS! 100 JMP BINGO ;YES, DISPLAY BINGO! 101 MISS: MOV A,80H+9 ;NO, DISPLAY "MISS!" MESSAGE 102 CALL WLCMC_4 ;SET LINE 1 POSITION 9 103 MOV A,OFFSET STR1 ;LOAD STRING START ADDRESS 104 CALL PRINT ;PRINT ON LCD 105 MOV A,200 ;DELAY 2 SEC. 106 CALL DELAY 107 JMP MAIN ;RESTART 108 BINGO: 109 MOV A,0C0H+9 ;DISPLAY "BINGO!" 110 CALL WLCMC_4 ;SET LINE 2 POSITION 9 111 MOV A,OFFSET STR2 ;LOAD STRING START ADDRESS 112 CALL PRINT ;PRINT ON LCD 113 MOV A,250 ;DELAY 2.5 SEC. 114 CALL DELAY 115 JMP MAIN ;RESTART 116 ;======================================================================================== 117 ; WRITE_DIG SUBROUTINE 118 ;======================================================================================== 119 WRITE_DIG PROC 120 MOV A,DIG2 121 CALL WLCMD_4 第五章 进阶实验篇 5-121 122 MOV A,DIG1 123 CALL WLCMD_4 124 MOV A,DIG0 125 CALL WLCMD_4 126 RET 127 WRITE_DIG ENDP 128 ;======================================================================================== 129 ; PROC : HEX2ASCII 130 ; FUNC : CONVERT HEX DATA IN Acc TO DIG2~DIG0 131 ; REG : ACC 132 ; RTN : DIG[2]~DIG[0] 133 ;======================================================================================== 134 HEX2ASCII PROC 135 MOV DIG0,A ;TEMP 136 CLR DIG1 ;INITIAL DIGIT BUFFER 137 CLR DIG2 138 SUB A,100 ;CHECK BASE 100 139 SNZ C ;ACC > 100 ? 140 JMP $+3 ;NO. 141 INC DIG2 ;YES. 142 JMP $-4 143 ADD A,100 ;RESTORE CONVERTED DATA 144 SUB A,10 ;CHECK BASE 10 5 145 SNZ C ;ACC > 10 ? 146 JMP $+3 ;NO. 147 INC DIG1 ;YES. 148 JMP $-4 149 ADD A,10 ;RESTORE CONVERTED DATA 150 MOV DIG0,A 151 MOV A,30H ;BEFORE THIS LINE HEX TO UN-PACK BCD 152 ADDM A,DIG2 153 ADDM A,DIG1 154 ADDM A,DIG0 155 RET 156 HEX2ASCII ENDP 157 ;======================================================================================== 158 ; PROC : INIT_LCM 159 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 160 ; REG : ACC 161 ;======================================================================================== 162 INIT_LCM PROC 163 CLR LCM_EN ;SET EN=0 164 CLR LCM_RW ;SET RW=0 165 CLR LCM_RS ;SET RS=0 166 CLR LCM_ENC ;CONFIG EN AS O/P MODE 167 CLR LCM_RWC ;CONFIG RW AS O/P MODE 168 CLR LCM_RSC ;CONFIG RS AS O/P MODE 5-122 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 169 170 MOV A,28H ;FUNCTION SET: 4-BIT,2-LINE,5X10 DOTS 171 CALL WLCMC_4 172 MOV A,0FH ;ON/OFF CONTR: DISPLAY ON,CURSOR BLINKING OFF 173 CALL WLCMC_4 174 MOV A,06H ;ENTRY MODE : INCREMENT,DISPLAY NOT SHIFT 175 CALL WLCMC_4 176 MOV A,01H ;CLEAR DISPLAY 177 CALL WLCMC_4 178 RET 179 INIT_LCM ENDP 180 ;======================================================================================== 181 ; PROC : PRINT 182 ; FUNC : DISPLAY STRING ON LCM, STRING END WITH NULL AND POINT BY ACC(LAST PAGE) 183 ; REG : ACC 184 ; RETN : DD RAM/CG RAM DATA IN ACC 185 ;======================================================================================== 186 PRINT PROC 187 MOV TBLP,A ;LOAD TABLE POINTER 188 PRINT_1: 189 TABRDL ACC 5 190 XOR A,NULL 191 SZ Z ;READ STRING ;END OF STRING CHARACTER? 192 RET ;YES, STOP PRINT 193 TABRDL ACC ;NO, RE-READ 194 CALL WLCMD_4 ;SEND TO LCD 195 INC TBLP ;INCREASE DATA POINTER 196 JMP PRINT_1 ;NEXT CHARACTER 197 RET ;YES, RETURN 198 PRINT ENDP 199 ;======================================================================================== 200 ; PROC : WLCMD_4/WLCMC_4 201 ; FUNC : WRITE COMMAND OR DATA TO LCM UNDER 4-BIT MODE (HIGH NIBBLE CONNECT) 202 ; PARA : ACC : COMMAND/DATA 203 ; REG : ACC,DC_FLAG,LCM_TEMP 204 ;======================================================================================== 205 WLCMD_4 PROC 206 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 207 JMP WLCM_4 208 WLCMC_4:CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 209 WLCM_4:MOV LCM_TEMP,A ;SAVED COMAND/DATA IN LCD_TEMP 210 MOV A,11110000B 211 ORM A,LCM_DATAPORTC ;CONFIG LCM_DATAPORT[7:4] AS I/P MODE 212 SET LCM_RW ;SET RW=1 (READ) 213 CLR LCM_RS ;SET RS=0 (IR) 214 NOP ;FOR TAS 215 SET LCM_EN ;SET EN=1 第五章 进阶实验篇 5-123 216 NOP ;FOR TDDR 217 WF_4: SZ LCM_DATAPORT.7 ;IS LCD BUSY? 218 JMP WF_4 ;YES, JUMP TO WAIT 219 CLR LCM_EN ;SET EN=0 220 MOV A,00001111B 221 ANDM A,LCM_DATAPORTC ;CONFIG LCM_DATAPORT[7:4] AS O/P MODE 222 ANDM A,LCM_DATAPORT ;SET LCM_DATAPORT[7:4]=0000 223 MOV A,LCM_TEMP 224 AND A,11110000B ;GET HIGH NIBBLE DATA/COMMAND 225 ORM A,LCM_DATAPORT ;LATCH DATA/COMMAND ON LCM_DATAPORT[7:4] 226 CLR LCM_RW ;SET RW=0 (WRITE) 227 CLR LCM_RS ;SET RS=0 (IR) 228 SZ DC_FLAG ;IS COMMAND WRITE? 229 SET LCM_RS ;NO, SET RS=1 (DR) 230 NOP ;FOR TAS 231 SET LCM_EN ;SET EN=1 232 NOP ;FOR PWEN 233 CLR LCM_EN ;SET EN=0 234 MOV A,00001111B 235 ANDM A,LCM_DATAPORT ;SET LCM_DATAPORT[7:4]=0000 236 SWAPA LCM_TEMP 237 AND A,11110000B ;GET LOW NIBBLE DATA/COMMAND 238 ORM A,LCM_DATAPORT ;LATCH DATA/COMMAND ON LCM_DATAPORT[7:4] 5 239 SET LCM_EN ;SET EN=1 240 NOP ;FOR PWEN 241 CLR LCM_EN ;SET EN=0 242 RET 243 WLCMD_4 ENDP 244 ;======================================================================================== 245 ; PROC : DELAY 246 ; FUNC : DEALY ABOUT ACC*10mS @fSYS=4MHz 247 ; REG : DEL1,DEL2,DEL3 248 ;======================================================================================== 249 DELAY PROC 250 MOV DEL1,A ;SET DEL1 COUNTER 251 DEL_1: MOV A,30 252 MOV DEL2,A ;SET DEL2 COUNTER 253 DEL_2: MOV A,110 254 MOV DEL3,A ;SET DEL3 COUNTER 255 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 256 JMP DEL_3 257 SDZ DEL2 ;DEL2 DOWN COUNT 258 JMP DEL_2 259 SDZ DEL1 ;DEL1 DOWN COUNT 260 JMP DEL_1 261 RET 262 DELAY ENDP 5-124 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 263 ORG 264 STR1: DC 265 STR2: DC 266 TAB_CG RAM: 267 DC 268 DC 269 DC 270 DC 271 272 DC 273 DC 274 DC 275 DC 276 END LASTPAGE 'MISS!',NULL 'BINGO!', NULL 0000010000000000B 0001010100000100B 0000010000010101B 0000000000001100B 0000010000000000B 0001111100000100B 0000101000000100B 0000000000010001B ;DEFINE STRING DATA 1 ;DEFINE STRING DATA 2 ;CHARACTER '小' ;CHARACTER '大' 程程序序解解说说:: 4 载入”5-11.INC”定义档,其内容请参考随书光盘中的档案。 7~20 依序定义变量地址。 5 23 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 24~26 关闭 CP0 功能,并设定 ADC 脚位输入为 I/O 功能。 27~29 将 PA[2:0]定义为输入模式,并使能其 Pull-high 功能。 30 设定 TM2RP 为零。 31~34 定义 TM2C0、TM2C1 控制寄存器: T2CK[2:0]:001,设定 fINT=fSYS; T2CCLR:0,设定当 TM2D[15:8]=T2RP[7:0]时(即比较器 P 比较匹配时)清除计 数器; T2M[1:0]:11,设定为 Timer/Counter 模式; T2ON:1,启动 STM 开始计数。 35 调用 INIT_LCM 子程序,对 LCM 进行定义。 46~47 设定 CG RAM 的地址为 00H,准备写入自建字型。 38~49 设定计数器 LINE_COUNT 为 16 并将 TBLP 指向自建字型数据的起始地址。接着利 用查表将自建字型的数据取出并写入 CG RAM 中,并将 TBLP 加一。其次,判断 COUNT 减一是否为 0。成立,表示所有自建字型已输入完毕;反之,则表示自建字 型尚未建立完成,继续填入字型码。 51~52 将 LCM 整个显示器清空。 第五章 进阶实验篇 5-125 53~56 利用 STM Timer/Counter 模式产生随机数存放于 RANDOM 存储器,并调用 HEX2ASCII 子程序转换成可写入 LCM 的 ASCII 码,在此产生的随机数为“题目”。 (注:详细解说请参考 HEX2ASCII 子程序的说明) 57~59 将 LCM 的 AC 值设定于第一列第二个位置,并调用 WRITE_DIG 子程序将刚刚取得 的随机数值显示在 LCM。(即将 DIG0、DIG1、DIG2 内容显示在 LCM) 60~63 在第一列第六个位置显示自建字型“小” 64~67 在第二列第六个位置显示自建字型“大” 68~72 设定 CLICK 存储器为 87h,当成光标的位置。 74~82 按键检查循环,若按下“Greater”按键,则设定 CLICK.6 为“1”让光标移至第二 列第七个位置;反之,若按下“Less”按键,则设定 CLICK.6 为“0”使光标移至 第一列第七个位置。当按下“Enter”键,则跳至 LOOP_3 进行判断程序。 84~87 利用 STM Timer/Counter 模式产生第二笔随机数存放在 TEMP 存储器,并调用 HEX2ASCII 子程序转换成可写入 LCM 的 ASCII 码,在此产生的随机数为“答案”。 88~90 将 LCM 的 AC 值设定在第二列第二个位置,并调用 WRITE_DIG 子程序将刚取得的 随机数值显示在 LCM。(即将 DIG0、DIG1、DIG2 内容显示在 LCM) 5 91~100 将答案与结果相减(TEMP-RANDOM)判断是否有借位(C=1)。若成立,则表 示题目提供的数值比结果还要小(C=1),所以 CLICK 的判断式也修改成选择“大” (BIT6=0)错误,选择“小”(BIT6=1)正确。若题目比结果还要大(C=0)则 CLICK 判断的式子也跟着相反。 101~107 显示“MISS!”在第一列后重新开始执行程序。 108~115 显示“BINGO!”在第二列后重新开始执行程序。 119~127 WRITE_DIG 子程序,此子程序负责将 DIG0、DIG1、DIG2 三个存储器的内容显示 在 LCM 上。 134~156 HEX2ASCII 子程序,此子程序的功能是将 Acc 寄存器中的十六进制数据(00h~FFh) 转换成 ASCII 码。转换后的结果分别存放于 DIG0(个位数)、DIG1(十位数)、 DIG2(百位数)三个存储器当中。 162~179 INIT_LCM 子程序,其功能是对 LCM 进行定义。 163~168 LCM_EN、LCM_RW 与 LCM_RS 定义为输出模式,并设定状态为“0”。 170~171 将 LCM 设定为双行显示(N = 1)、使用四位(DB7 ~ DB4)控制模式(DL = 0)、 5×7 点矩阵字型(F = 0)。 172~173 将 LCM 设定为显示所有数据(D = 1)、显示光标(C = 1)、光标不闪烁(B = 0)。 5-126 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 174~175 将 LCM 的地址计数器(AC)设为递加(I/D = 1)、显示器画面不因读写数据而移 动(S = 0)。 176~177 将 LCM 整个显示器清空。 186~198 PRINT 子程序,此子程序负责将定义好的字符串依序显示在 LCM 上。在调用此子 程序之前,除了必须先设定好 LCM 的位置之外,尚需先在 Acc 寄存器中指定字符 串的起始地址(字符串必须存放在最末程序页-Last Page),并请在字符串的最后 一个字符塞入 NULL,代表字符串结束。 205~243 WLCMD_4 与 WLCMC_4 子程序,请参考【实验 5-10】的说明。 249~262 DELAY 子程序,至于延迟时间的计算请参考【实验 4-1】。 264~265 字符串定义区,每一个字符串务必以 NULL 做为结束字符。 266~275 自建字型的字型码定义区。 5-11-5 动动脑+动动手: 5 修改程序,一开始提供使用者 100 分的分数,答对一次加十分、答错一次扣 五分。并将分数显示在 LCM 上;而当使用者分数小于 0 或大于 255 时,程 序就不再产生随机数。 承上题,如果允许使用者的分数超过 255,势必须要一个 16-Bit 的十六进制 转 BCD 的转换程序,请尝试完成此一子程序。 请修改程序,使产生的随机数值局限在“0”~“99”之间。 5-127 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-12 STM单元脉冲测量与LCM控制实验 5-12-1 目 的: 利用HT66F50 STM单元的“捕捉输入(Capture Input)”功能测量脉冲的宽 度、周期,并显示在LCM上。 5-12-2 学习重点: 通 过 本 实 验 , 读 者 能 熟 悉 CTM 的 PWM 输 出 控 制 与 LCM 显 示 技 巧 , 对 于 HT66F50“Capture Input”模式的操作方式与特性也应透彻了解。 5-12-3 电路图: 5 PS:若使能PA[3:2]Pull-high功能,则10kΩ电阻可省略。 【图 5-12-1】STM 单元 Input Capture 实验电路 对于HT66F50 TM单元的Timer/Counter、Compare Match、与PWM等操作模 式在前几个实验中已多有着墨,本实验将针对“捕捉输入(Capture Input)”模式 加以探讨。为了展现“捕捉输入”模式的测量功能,范例程序中以CTM“PWM Output”模式产生PWM波形由TP0_0(PA0)脚位输出,其周期可由“Period”按 键选择八种不同的变化;其占空比则由“TON”按键调整,变化的幅度与所选择的 PWM周期有关;此输出波形再接回STM单元的捕捉输入引脚-TP2_1(PC4), 并利用“捕捉输入”模式下的操作特性测量所需的参数。有关STM单元详细的介绍 请参阅【2-5-2节】,其“捕捉输入”模式的操作则参考【2-5-2-1节】;现将本实 验使用的相关寄存器简列于【表5-12-1】。 【2-5 节】 【2-6-10 节】 【2-5-1 节】 TMPC0 TMPC1 PRM2 TM0C0 TM0C1 TM0AL 【表 5-12-1】本实验相关控制寄存器 T1ACP0 T1BCP2 T1BCP1 T1BCP0 - - - - T3CP1 T3CP0 - - TP31PS TP30PS TP21PS TP20PS TP1B2PS TP1APS T0PAU T0CK2 T0CK1 T0CK0 T0ON T0RP2 T0M1 T0M0 T0IO1 T0IO0 T0OC T0POL TM0A[7:0] T0CP1 T2CP1 TP01PS T0RP1 T0DPX T0CP0 T2CP0 TP00PS T0RP0 T0CCLR 5-128 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 TM0AH - - - - - - TM0DL TM0D[7:0] TM0DH - - - - - - TM2C0 T2PAU T2CK2 T2CK1 T2CK0 T2ON - TM0A[9:8] TM0D[9:8] - - 【2-5-2 节】 TM2C1 TM2RP TM2AL TM2AH TM2DL TM2DH Bit T2M1 7 T2M0 6 T2IO1 5 T2IO0 T2OC TM2RP[7:0] TM2A[7:0] TM2A[15:8] TM2D[7:0] TM2D[15:8] 4 3 T2POL T2DPX T2CCLR 2 1 0 所谓“捕捉输入”模式是指当输入引脚3出现设定的电平变化时(1 0、0 1 或两者),TM单元会将此时的计数数值记录在MnA、TMnB(Compare/Capture Register)寄存器中;以STM单元为例,当设定T2ON=“1”时即启动TM2D计数 器由零开始计数的动作(参考【图5-12-2】),若是要测量波形的周期,则可由前、 后两次上升沿或下降沿触发的差值(即CCRA2-CCRA1或CCRA2’-CCRA1’)再配 合STM频率的选择求得。若是欲求正脉冲的宽度,则可先设定上升沿触发后再切换 为下降沿触发,并依前述的方法即可求得;反之,若欲测量负脉冲的宽度,则可先 设定下降沿触发后再切换为上升沿触发。 5 【图 5-12-2】Capture Input 脉冲测量范例 其次,本范例程序所要考虑的是如何将测量结果在LCM上显示,如【图5-12-3】 的流程图所示,由于STM单元的TM2A寄存器为十六位,所以实际上只需要写一个 16-Bit转换为十进制的子程序就可以了!还记得【实验 5-11】中的HEX2ASCII子 程序吗?由于所转换的数据仅八位(最大数值为FFh=255),因此使用循环减法 依序将结果存到DIG2~DIG0(分别代表百位数、十位数及个位数)三个存储器! 而本范例所考虑的是十六位测量值的转换(最大数值为FFFFh=65535),所以转 换结果必须以五个存储器(DIG4~DIG0)来存放,至于程序的写法与HEX2ASCII 子 程 序 的 原 理 及 作 法 大 同 小 异 , 请 读 者 参 阅 【 图 5-12-3 】 的 流 程 图 及 3 以 STM 单元为例,是指 TP2_1 或 TP2_0 脚位。 Word_HEX2ASCII子程序: 第五章 进阶实验篇 5-129 5 【图 5-12-3】五位数 HEX2ASCII 转换流程 1 ;======================================================================================== 2 ; PROC : WORD_HEX2ASCII-BIT DATA 3 ; FUNC : CONVERT 16-BIT HEX TO 5-DIGIT BCD/ASCII 4 ; PARA : WORD_ CONTAIN 16 BITS DATA TO BE CONVERT 5 ; REG : ACC,IAR0,MP0,TBLP,TBLH,TEMP 6 ; RTN : DIGIT[4]~DIGIT[0] 7 ;======================================================================================== 8 WORD_HEX2ASCII PROC 9 MOV A,TAB_HEX ;LOAD TABLE POINTER 10 MOV TBLP,A 11 MOV A,OFFSET DIGIT[4] ;LOAD DATA POINTER 12 MOV MP0,A 13 MOV A,4 ;SET DIGIT COUNT 14 MOV COUNT,A 15 NEXT_DIG: CLR IAR0 ;CLEAR BUFFER 16 TABRDL TEMP ;LOAD BASE 17 W2H: MOV A,HexWord[0] 5-130 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 18 SUB A,TEMP 19 MOV HexWord[0],A 20 MOV A,HexWord[1] 21 SBC A,TBLH 22 MOV HexWord[1],A 23 SNZ C ;WORD DATA > BASE ? 24 JMP $+3 ;NO. 25 INC IAR0 ;YES. 26 JMP W2H 27 MOV A,TEMP ;RESTORE WORD DATA 28 ADDM A,HexWord[0] 29 MOV A,TBLH 30 ADCM A,HexWord[1] 31 INC TBLP 32 DEC MP0 33 SDZ COUNT 34 JMP NEXT_DIG 35 MOV A,HexWord[0] 36 MOV IAR0,A 37 MOV A,30H ;BEFORE THIS LINE HEX TO UN-PACK BCD 38 5 39 40 ADDM ADDM ADDM A,DIGIT[4] A,DIGIT[3] A,DIGIT[2] ;CONVERT DIG4 TO ASCII ;CONVERT DIG3 TO ASCII ;CONVERT DIG2 TO ASCII 41 ADDM A,DIGIT[1] ;CONVERT DIG1 TO ASCII 42 ADDM A,DIGIT[0] ;CONVERT DIG0 TO ASCII 43 RET 44 WORD_HEX2ASCII ENDP 45 ;======================================================================================== 46 ORG LASTPAGE 47 TAB_HEX: DC 10000,1000,100,10 如果读者细心浏览此流程图及程序,应该发现写法其实很直接、很单纯。首先 把HexWord减10000,若结果大于或等于0,就将代表万位数的DIGIT[4]加一,再 继续减;当发现减10000后的结果小于0时,就先将HexWord还原(加回10000) 之后,再以相同步骤处理千位数、百位数、十位数与个位数。相减的过程中需用到 十六位的减法,这与十六位加法运算的观念差不多,所以不再赘述。读者要特别留 意“SUB”指令对进位标志的影响规则是:“有借位时C=0,没有借位时C=1”。 5-12-4 程序及流程图: 第五章 进阶实验篇 5-131 5 程序5-12 STM Capture Input Mode for Pulse Measurement 1 ;PROGRAM : 5-12.ASM (5-12.PJT) 2009.1106 2 ;FUNCTION: CTM PWM vs. STM CAPTURE MODE DEMO PROGRAM By Steven 3 ; NOTE : CONNECT PC4[TP2_1] TO PA0[TP0_0] 4 #INCLUDE HT66F50.INC 5 #INCLUDE 5-12.INC 6 ;======================================================================================== 7 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 8 DEL1 DB ? ;DELAY LOOP COUNT 1 9 DEL2 DB ? ;DELAY LOOP COUNT 2 10 DEL3 DB ? ;DELAY LOOP COUNT 3 11 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 12 COUNT DB ? ;UNIVERSAL COUNTER 13 TEMP DB ? ;BUFFER 5-132 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 14 PWMPeriod DB ? ;CTM PWM PERIOD 15 PWMTon DB 2 DUP(?) ;Ton TIME CONTROL REG. 16 TonLimit DB 2 DUP(?) ;LIMIT FOR Ton CLOCKS 17 DIGIT DB 5 DUP(?) ;ASCII BUFFER 18 HexWord DB 2 DUP(?) ;REGISTER FOR WORD_HEX2ASCII 19 ;======================================================================================== 20 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 21 ORG 000H ;HT66FXX RESET VECTOR 22 CLR ACERL ;AD DISABLE 23 MOV A,08H 24 MOV CP0C,A ;DISABLE CPO 25 SET SW_PERIODC ;CONFIG SW_PERIOD AS I/P MODE 26 SET SW_TONC ;CONFIG SW_TON AS I/P MODE 27 SET SW_PERIODPU ;ENABLE SW_PERIOD PULL-UP FUNCTION 28 SET SW_TONPU ;ENABLE SW_PERIOD PULL-UP FUNCTION 29 CLR TM2C0 ;STM fINT=fSYS/4 30 SET T2CP1 ;SET TP2 FUNCTION TO TP2_1 PIN 31 SET PCC.4 ;CONFIG I/P MODE FOR CAPTURE I/P 32 CLR TP21PS ;ENABLE TP2_1 ON PC4 33 SET T0CP0 ;ENABLE TP0_0 PIN 34 CLR PAC.0 5 35 CLR PA.0 36 MOV A,00000000B ;CONFIG PA0[TP0_0] O/P MODE FOR PWM O/P ;CTM fINT=fSYS/4 37 MOV TM0C0,A 38 MOV A,10101000B ;TM0 IN PWM O/P MODE,ACTIVE HIGH,NON-INVERT 39 MOV TM0C1,A ;TM0D IS CLEARED BY T0RP COMPARE MATCH 40 CALL INIT_LCM ;LCM INITIALIZATION 41 SET PWMPeriod ;INITIAL PERIOD INDEX 42 JMP PERIOD_PRESSED 43 CHECK_KEY: 44 SNZ SW_TON ;SW_TON PRESSED ? 45 JMP TON_PRESSED ;YES. 46 SZ SW_PERIOD ;NO. SW_PERIOD PRESSED ? 47 JMP MEASURE_PERIOD ;NO. START MEASURE 48 PERIOD_PRESSED: 49 INC PWMPeriod ;INCREASE PERIOD INDEX 50 SZ PWMPeriod.3 ;PWMPeriod < 7 ? 51 CLR PWMPeriod ;NO. RESET PWMPeriod 52 MOV A,PWMPeriod ;GET PERIOD INDEX 53 ADD A,TAB_TonLimit 54 MOV TBLP,A 55 TABRDL TonLimit[0] ;GET TON LIMIT FOR SPECIFIC PERIOD 56 MOV A,TBLH 57 MOV TonLimit[1],A 58 JMP RESET_TonSTEP ;RESET PWMTon 59 TON_PRESSED: 60 MOV A,PWMPeriod ;Ton STEP FOR PERIOD 61 ADD 62 MOV 63 TABRDL 64 ADDM 65 CLR 66 ADCM 67 MOV 68 SUB 69 MOV 70 SBC 71 SNZ 72 JMP 73 RESET_TonSTEP: 74 MOV 75 ADD 76 MOV 77 TABRDL 78 CLR 79 PWM_OUT: 80 CLR 81 MOV 82 AND 83 OR 84 MOV 85 MOV 86 MOV 87 MOV 88 MOV 89 SET 90 CALL 91 MEASURE_PERIOD: 92 MOV 93 MOV 94 CALL 95 MOV 96 CALL 97 CALL 98 MEASURE_TON: 99 MOV 100 MOV 101 SZ 102 JMP 103 CALL 104 MOV 105 CALL 106 CALL 107 JMP A,TAB_TonStep TBLP,A ACC A,PWMTon[0] ACC A,PWMTon[1] A,PWMTon[0] A,TonLimit[0] A,PWMTon[1] A,TonLimit[1] C PWM_OUT A,PWMPeriod A,TAB_TonStep TBLP,A PWMTon[0] PWMTon[1] T0ON A,TM0C0 A,11111000B A,PWMPeriod TM0C0,A A,PWMTon[0] TM0AL,A A,PWMTon[1] TM0AH,A T0ON DELAY A,01000000B TM2C1,A MEASURE A,089H WLCMC DISPLAY A,01100000B TM2C1,A PC.4 $-1 MEASURE A,0C9H WLCMC DISPLAY CHECK_KEY 第五章 进阶实验篇 5-133 ;UPDATE PWMTon ;CHECK IF PWMTon OVER RANGE? ;PWMTon > TonLimit? ;NO. ;YES, RESTORE TON TIME ;STOP CTM ;UPDATE T0RP[2:0] 5 ;UPDATE TM0A ;START PWM O/P ;CAPTURE I/P MODE, RISING EDGE ;SET LCM CURSOR ADDRESS ;CAPTURE I/P MODE, RISING/FALLING EDGE ;WAIT FOR LOW STATE ;SET LCM CURSOR ADDRESS 5-134 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 108 ;======================================================================================== 109 ; PROC : MEASURE 110 ; FUNC : USE STM TO MEASURE DURATION BETWEEN 2 EDGES 111 ; NOTE : SET EDGE TYPE IN TM2C1 BEFORE CALLING THIS PROCDURE 112 ; RET : DURATION IN HexWord[1]_HexWord[0] 113 ;======================================================================================== 114 MEASURE PROC 115 CLR T2PF 116 CLR T2AF 117 SET T2ON ;START MEASURE 118 SNZ T2AF ;WAITING FOR 1'ST EDGE 119 JMP $-1 120 SZ T2PF ;TM2RP OVERFLLOW? 121 JMP MEASURE ;YES. REMEASURE 122 MOV A,TM2AH ;NO. GET TM2A COUNT 123 MOV HexWord[1],A 124 MOV A,TM2AL 125 MOV HexWord[0],A 126 CLR T2AF 127 SNZ T2AF ;WAITING FOR 2'ND EDGE 128 JMP $-1 5 129 MOV A,TM2AH 130 MOV A,TM2AL ;LATCH COUNT TO TM2A 131 SUBM A,HexWord[0] 132 MOV A,TM2AH 133 SBCM A,HexWord[1] 134 CLR T2ON ;STOP MEASURE 135 RET 136 MEASURE ENDP 137 ;======================================================================================== 138 ; PROC : DISPLAY 139 ; FUNC : CONVERT 16-BIT HEX TO 5-DIGIT BCD/ASCII AND DISPLAY ON LCM 140 ;======================================================================================== 141 DISPLAYPROC 142 CALL WORD_HEX2ASCII 143 MOV A,5 144 MOV COUNT,A 145 MOV A,OFFSET DIGIT[4] 146 MOV MP0,A 147 MOV A,IAR0 148 CALL WLCMD 149 DEC MP0 150 SDZ COUNT 151 JMP $-4 152 RET 153 DISPLAYENDP 154 ;======================================================================================== 第五章 进阶实验篇 5-135 155 ; PROC : WORD_HEX2ASCII-BIT DATA 156 ; FUNC : CONVERT 16-BIT HEX TO 5-DIGIT BCD/ASCII 157 ; PARA : HexWord CONTAIN 16 BITS DATA TO BE CONVERT 158 ; REG : ACC,IAR0,MP0,TBLP,TBLH,TEMP 159 ; RTN : DIGIT[4]~DIGIT[0] 160 ;======================================================================================== 161 WORD_HEX2ASCII PROC 162 MOV A,TAB_HEX ;LOAD TABLE POINTER 163 MOV TBLP,A 164 MOV A,OFFSET DIGIT[4] ;LOAD DATA POINTER 165 MOV MP0,A 166 MOV A,4 ;SET DIGIT COUNT 167 MOV COUNT,A 168 NEXT_DIG: 169 CLR IAR0 ;CLEAR BUFFER 170 TABRDL TEMP ;LOAD BASE 171 W2H: MOV A,HexWord[0] 172 SUB A,TEMP 173 MOV HexWord[0],A 174 MOV A,HexWord[1] 175 SBC A,TBLH 176 MOV HexWord[1],A 177 SNZ C ;WORD DATA > BASE ? 5 178 JMP $+3 ;NO. 179 INC IAR0 ;YES. 180 JMP W2H 181 MOV A,TEMP ;RESTORE WORD DATA 182 ADDM A,HexWord[0] 183 MOV A,TBLH 184 ADCM A,HexWord[1] 185 INC TBLP 186 DEC MP0 187 SDZ COUNT 188 JMP NEXT_DIG 189 MOV A,HexWord[0] 190 MOV IAR0,A 191 MOV A,30H ;BEFORE THIS LINE HEX TO UN-PACK BCD 192 ADDM A,DIGIT[4] ;CONVERT DIG4 TO ASCII 193 ADDM A,DIGIT[3] ;CONVERT DIG3 TO ASCII 194 ADDM A,DIGIT[2] ;CONVERT DIG2 TO ASCII 195 ADDM A,DIGIT[1] ;CONVERT DIG1 TO ASCII 196 ADDM A,DIGIT[0] ;CONVERT DIG0 TO ASCII 197 RET 198 WORD_HEX2ASCII ENDP 199 ;======================================================================================== 200 ; PROC : INIT_LCM 201 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 5-136 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 202 ; REG : ACC 203 ;======================================================================================== 204 INIT_LCM PROC 205 CLR LCM_EN ;SET EN=0 206 CLR LCM_RW ;SET RW=0 207 CLR LCM_RS ;SET RS=0 208 CLR LCM_ENC ;CONFIG EN AS O/P MODE 209 CLR LCM_RWC ;CONFIG RW AS O/P MODE 210 CLR LCM_RSC ;CONFIG RS AS O/P MODE 211 212 MOV A,38H ;FUNCTION SET: 8-BIT,2-LINE,5X7 DOTS 213 CALL WLCMC 214 MOV A,0CH ;ON/OFF CONTR: DISPLAY ON,CURSOR BLINKING OFF 215 CALL WLCMC 216 MOV A,06H ;ENTRY MODE : INCREMENT,DISPLAY NOT SHIFT 217 CALL WLCMC 218 MOV A,01H ;CLEAR DISPLAY 219 CALL WLCMC 220 221 MOV A,STR_1 ;DISPLAY RELATIVE SYMBOL ON LCM 222 CALL PRINT 5 223 MOV A,0C0H 224 CALL WLCMC 225 MOV A,STR_2 226 CALL PRINT 227 RET 228 INIT_LCM ENDP 229 ;======================================================================================== 230 ; PROC : WLCMD/WLCMC 231 ; FUNC : WRITE DATA/COMMAND TO LCM 232 ; PARA : ACC : COMMAND/DATA 233 ; REG : ACC,DC_FLAG 234 ;======================================================================================== 235 WLCMD PROC 236 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 237 JMP $+2 238 WLCMC: CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 239 SET LCM_DATAPORTC ;CONFIG LCM_DATAPORT AS I/P MODE 240 CLR LCM_RS ;SET RS=0 (IR) 241 SET LCM_RW ;SET RW=1 (READ) 242 NOP ;FOR TAS 243 SET LCM_EN ;SET EN=1 244 NOP ;FOR TDDR 245 WF: SZ LCM_DATAPORT.7 ;IS LCM BUSY? 246 JMP WF ;YES, JUMP TO WAIT 247 CLR LCM_EN ;SET EN=0 248 CLR LCM_DATAPORTC ;NO, CONFIG LCM_DATAPORT AS O/P MODE 第五章 进阶实验篇 5-137 249 MOV LCM_DATAPORT,A ;LATCH DATA/COMMAND ON LCM_DATAPORT 250 CLR LCM_RW ;SET RW=0 (WRITE) 251 CLR LCM_RS ;SET RS=0 (IR) 252 SZ DC_FLAG ;IS COMMAND WRITE? 253 SET LCM_RS ;NO, SET RS=1 (DR) 254 SET LCM_EN ;SET EN=1 255 NOP ;FOR PWEN 256 CLR LCM_EN ;SET EN=0 257 RET 258 WLCMD ENDP 259 ;======================================================================================== 260 ; PROC : PRINT 261 ; FUNC : DISPLAY STRING ON LCM, STRING END WITH NULL AND POINT BY ACC(LAST PAGE) 262 ; REG : ACC 263 ; RETN : DD RAM/CG RAM DATA IN ACC 264 ;======================================================================================== 265 PRINT PROC 266 MOV TBLP,A ;LOAD TABLE POINTER 267 PRINT_1: 268 TABRDL ACC ;READ STRING 269 XOR A,NULL 270 SZ Z ;END OF STRING CHARACTER? 271 RET ;YES, STOP PRINT 5 272 TABRDL ACC ;NO, RE-READ 273 CALL WLCMD ;SEND TO LCD 274 INC TBLP ;INCREASE DATA POINTER 275 JMP PRINT_1 ;NEXT CHARACTER 276 RET ;YES, RETURN 277 PRINT ENDP 278 ;======================================================================================== 279 ; PROC : DELAY 280 ; FUNC : DEALY ABOUT DEL1*10mS 281 ; PARA : ACC : DELAY FACTOR 282 ; REG : DEL1,DEL2,DEL3 283 ;======================================================================================== 284 DELAY PROC 285 MOV A,30 286 MOV DEL1,A 287 DEL_1: MOV A,30 288 MOV DEL2,A ;SET DEL2 COUNTER 289 DEL_2: MOV A,110 290 MOV DEL3,A ;SET DEL3 COUNTER 291 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 292 JMP DEL_3 293 SDZ DEL2 ;DEL2 DOWN COUNT 294 JMP DEL_2 295 SDZ DEL1 ;DEL1 DOWN COUNT 5-138 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 296 JMP 297 RET 298 DELAY ENDP 299 ORG 300 TAB_TonLimit: 301 DC 302 TAB_TonStep: 303 DC 304 TAB_HEX:DC 305 STR_1: DC 306 STR_2: DC 307 END DEL_1 LASTPAGE 1023,127,255,383,511,639,767,895 45, 5, 15, 20, 25, 30, 35, 40 10000,1000,100,10 'Period = uS',NULL ' Ton = uS',NULL 程程序序解解说说:: 5 载入”5-12.INC”定义档,其内容请参考随书光盘中的档案。 8~18 依序定义变量地址。 21 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 22~24 关闭 CP0 功能,并设定 ADC 脚位输入为 I/O 功能。 5 25~28 定义 SW_PERIOD(PA.2)、SW_TO(PA.3)为输入模式,并使能其 Pull-high 功能。 29 定义 TM2C0 控制寄存器 T2CK[2:0]:000,设定 fINT=fSYS/4。 30 调用 INIT_LCM 子程序,对 LCM 进行定义。 30~32 设定 TP2 功能在 TP2_1(PC.4)脚位上实现,由于本例为捕捉输入的脚位,故同 时将其定义为输入模式。 33~35 设定 TP0 功能在 TP0_0(PA.0)脚位上实现,由于本例为 PWM 波形的输出脚位, 故同时将其定义为输出模式,并选定为同相输出。 36~39 定义 TM0C0、TM0C1 控制寄存器: T0CK[2:0]:000,设定 fINT=fSYS/4; T0M[1:0]:10,设定为 PWM 输出模式; T0IO[1:0]:10,设定 TP0 为 PWM Output; T0OC:1,选择 PWM 输出为 Active High; T0CCLR:0,设定当 TM0D[9:7]=T0RP[2:0]时(即比较器 P 比较匹配时)清除计 数器。 40 调用 INIT_LCM 子程序,对 LCM 进行定义。 第五章 进阶实验篇 5-139 41~42 设定 PWMPeriod 存储器的初值,并跳至 PERIOD_PRESSED 执行;PWMPeriod 存储器的内容掌控 CTM 输出的 PWM 周期。 43~47 48~58 检查按键是否按下,若未按下则至 MEASURE_PERIOD 开始测量程序;若按下, 则依“Period”或“TON”按键的状态分别跳至周期、正脉冲的调整程序。 此片段为按下“Period”按键时的处理程序;首先将 PWMPeriod 存储器加一并判 断是否已大于 7,若是则将其归零(因为本例设定周期的变化仅 0~7 共八种选项)。 接着,依 PWMPeriod 存储器之值查出该周期选项下,TON 宽度可容许的最大脉冲数 并存在 TonLimit 存储器,做为调整 TON 时的判断依据。并跳至 RESET_TonSTEP 处将 PWMTon 存储器值恢复到目前设定周期下的最小值(此做法是为了防止当 PWMPeriod 存储器更动时,发生 PWMTon 存储器设定值大于 PWM 周期,致使波 形无法正常输出)。 59~78 此片段为按下“TON”按键时的处理程序;首先依 PWMPeriod 存储器之值查出该周 期选项下,TON 宽度的递增幅度,并将其累加到控制 TON 输出宽度的 PWMTon 存储 器。接着判断 PWMTon 是否超出限定值(即大于 TonLimit 存储器设定值);若不 是,则跳至 PWM_OUT 输出波形。反之,则将 PWMTon 存储器值恢复到目前设定 周期下的最小值。 5 80~88 89~90 暂停 CTM 的 PWM 输出,并依据 PWMPeriod 存储器更改 T0RP[2:0] 的设定(此 举即改变 PWM 输出的周期)。并将 PWMTon 存储器复制到 TM0A,以设定 PWM 输出时 TON 的宽度。 启动 CTM 计数(PWM 波形开始输出);调用 DELAY 子程序延迟 0.3 秒,其目的 除避免抖动的影响之外,当使用者按下按键时也能以每隔 0.3 秒的速率自动更新选 项。 92~93 设定 STM 为“捕捉输入”模式(T2M[1:0]=10),且为上升沿触发形式(T2IO[1:0] =00)。 95~97 调用 MEASURE 子程序进行测量,并将结果显示在 LCM 上。因此时设定为上升沿 触发形式,故测量数据为 PWM 的周期(请参考【图 5-12-2】)。 99~100 设定 STM 为“捕捉输入”模式(T2M[1:0]=10),且为双沿触发形式(T2IO[1:0] =10)。 101~102 等待 PWM 输出为低电位;其目的是确认以双沿触发进行测量时,是量取正脉冲的 宽度。 5-140 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 103~106 调用 MEASURE 子程序进行测量,并将结果显示在 LCM 上。因此时设定为双沿触 发形式,故测量数据为 PWM 周期中的正脉冲宽度(请参考【图 5-12-2】)。 107 重新检查按键是否按下。 114~136 MEASURE 子程序;在清除 T2PF、T2AF 标志后启动 STM 开始计数,并等待计数 完成(T2AF=“1”);测量结束时万一 T2PF 为“1”,表示 STM 计数溢位,故 重新启动测量。否则即将 TM2A 之值保留到 HexWord 存储器,随即启动第二次测 量;并将测量结果与 HexWord 存储器相减,求出两次测量的差值。 141~153 DISPLAY 子程序;将 HexWord 存储器转换为 ASCII 码后,调用 WLCMD 子程序予 以显示。 161~198 WORD_HEX2ASCII 子程序;将 HexWord[]存储器中的十六位数据转换为 ASCII 码 存置于 DIGIT[]数组;请参考本实验前述的说明。 204~228 INIT_LCM 子程序,其功能是对 LCM 进行定义。 205~210 LCM_EN、LCM_RW 与 LCM_RS 定义为输出模式,并设定状态为“0”。 5 212~213 将 LCM 设定为双行显示(N = 1)、使用八位(DB7 ~ DB0)控制模式(DL = 1)、 5×7 点矩阵字型(F = 0)。 214~215 将 LCM 设定为显示所有数据(D = 1)、显示光标(C = 1)、光标所在位置不闪烁 (B = 0)。 216~217 将 LCM 的地址计数器(AC)设为递加(I/D = 1)、显示器画面不因读写数据而移 动(S = 0)。 218~219 将 LCM 整个显示器清空。 221~226 调用 PRINT 子程序,经由查表将字符串 STR1、STR2 分别显示于 LCM 的一、二 列。 235~258 WLCMD 与 WLCMC 子程序,请参考【实验 5-6】的说明。 265~277 PRINT 子程序,此子程序负责将定义好的字符串依序显示在 LCM 上。在调用此子 程序之前,除了必须先设定好 LCM 的位置之外,尚需先在 Acc 寄存器中指定字符 串的起始地址(字符串必须存放在最末程序页-Last Page),并请在字符串的最后 一个字符塞入 NULL,代表字符串结束。 284~297 DELAY 子程序,延迟 0.3 秒;延迟时间的计算请参考【实验 4-1】。 300~301 各 PWM 周期所允许的 TON 宽度建表区。 302~303 各 PWM 周期所对应的 TON 初始宽度与递增幅度。 第五章 进阶实验篇 5-141 304 WORD_HEX2ASCII 子程序进行转换时所需的常数建表区。 305~306 STR1、STR2 字符串建表数据,每一个字符串务必以 NULL 做为结束字符。 【程序5-12】看似冗长、复杂,但其实细心、耐心的分析之后,应该不难了解 笔者的设计理念。由于周期的变化是由CTM的T0RP[2:0]三个位控制,因此有八种 不同的选择;为了让TON宽度的递增幅度能随着周期的变化而适度调整,所以将配 合各周期的TON调整幅度以建表方式处理,方便程序随时调用。为了避免使用者调 整后的TON宽度超过PWM周期的不合理现象,因此针对各周期选项也定义了一个上 限值,每当使用者调整了TON的宽度就需先与此上限值比较,以确定其合理性。 细心的读者应该会发现,当周期设定为PWMPeriod=“001”且TON宽度为最窄 (5个脉冲宽度)时,量得的TON宽度会时而不正确的跳动;探讨其原因是【程序 5-12】中设定的CTM频率源为fINT=fSYS/4;当读者所选择的fSYS与笔者同样为4MHz 时,这意味着正脉冲的宽度仅为5µs;请读者分析一下,MEASURE子程序中有两 次测量值的读取动作,当首次测得触发信号时必须先把TM2A的值予以储存方能继 续第二次的测量,两次测量的间隔较处理捕捉值的程序(【程序5-12】第122~126 行)所耗费的时间来得短时就会出现问题!也是说TM2A的捕捉值尚未储存又被新 的捕捉值所覆盖!读者可通过fSYS的提升来改善此现象,不过无论如何可量得的脉 宽或周期还是有其上限的! 5 (a)PWMTon=5 (b)PWMTon=60 【图 5-12-4】PWMPeriod=“001”时 TP0_0 的输出 5-142 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 (a)PWMTon=45 (b)PWMTon=270 【图 5-12-5】PWMPeriod=“000”时 TP_0 的输出 【图5-12-4】与【图5-12-5】是笔者以示波器实际测量CTM输出所得的波形, 除了当脉宽小于10µs之外,其余以【程序5-12】所测得的周期与TON时间几乎与示 波器测量结果完全吻合。 5-12-5 动动脑+动动手: 5 试改变 CTM 的计数频率来源(即 TM0C0 控制寄存器的 T0CK[2:0]位),并 重新进行测量;观测测量结果与分析值是否一致。 若将【程序 5-12】第 35 行的“CLR PA.0”指令改成“SET PA.0”,输出结 果会有何不同?为什么?若能以示波器观测输出波形,将更能加深读者的印 象。(Hint:请参考【图 5-12-6】) 【图 5-12-6】HT66F30/40/50/60 TM0 功能脚位控制机制 5-143 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-13 ETM“单脉冲输出”模式与脉冲测量实验 5-13-1 目 的: 利用HT66F50 ETM单元的“单脉冲输出”模式产生脉冲,并以STM的“捕捉 输入”功能测量由TP1A、TP1B_0输出的脉冲宽度,显示在LCM上。 5-13-2 学习重点: 通过本实验,读者能熟悉HT66F50 TM单元中“Single Pulse Output”与 “Capture Input”模式的操作方式与特性、对于多功能脚位的控制也应有更深一层 的认识。 5-13-3 电路图: 5 PS:若使能PA[3:2]Pull-high功能,则10kΩ电阻可省略。 【图 5-13-1】ETM 单元 Single Pulse Output 实验电路 在【实验5-12】中,运用HT66F50 STM的“捕捉输入”模式操作特性测量方 波的宽度与周期,相信读者应该已能掌握相关的技巧;本实验继续探讨TM单元的 另一个操作方式:“单脉冲输出(Single Pulse Output)”模式。STM与ETM两组 计时单元均具备“捕捉输入”与“单脉冲输出”模式的操作功能,本实验的范例程 序将以ETM的“单脉冲输出”模式产生一个宽度可由使用者控制的脉冲,并通过 STM的“捕捉输入”模式测量方波的宽度。有关STM与ETM单元详细的介绍请参 阅【2-5-2节】、【2-5-3节】;现将本实验使用的相关寄存器简列于【表5-13-1】。 以ETM单元为例,所谓“单脉冲输出”模式是指当TCK1输入引脚或T1ON位 出现“0” “1”的电平变化时,ETM会依T1AOC、T1BOC位的状态分别设定TP1A 为Active、TP1B为Inactive的电平,并启动TM1D计数器由“000h”开始往上计数, 5-144 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 计数频率来源则取决于T1CK[2:0]的设定。当TM1D计数到TM1B所设定之值时, ETM会将TP1B输出设定为Active;当TM1D计数到TM1A时,ETM会将TP1A、TP1B 输出设定为Inactive,完成一个脉冲的输出程序。很明显地,由上述的说明可以推 断:TCK1引脚上“0” “1”的电平变化是触发脉冲开始输出的硬件信号;但请 注意,使用者也可采用由软件指令设定T1ON位为“1”的方式来启动脉冲的输出, 以下的范例程序即是以控制T1ON位的方式来达成脉冲输出的目的。 【表 5-13-1】本实验相关控制寄存器 【2-5 节】 TMPC0 T1ACP0 T1BCP2 T1BCP1 T1BCP0 - TMPC1 - - T3CP1 T3CP0 - - T0CP1 T0CP0 - T2CP1 T2CP0 【2-6-10 节】 PRM2 TP31PS TP30PS TP21PS TP20PS TP1B2PS TP1APS TP01PS TP00PS TM2C0 T2PAU T2CK2 T2CK1 T2CK0 T2ON - - - TM2C1 T2M1 T2M0 T2IO1 T2IO0 T2OC T2POL T2DPX T2CCLR TM2RP 【2-5-2 节】 TM2AL TM2RP[7:0] TM2A[7:0] TM2AH TM2A[15:8] TM2DL TM2D[7:0] TM2DH TM2D[15:8] TM1C0 T1PAU T1CK2 T1CK1 T1CK0 T1ON T1RP2 T1RP1 T1RP0 TM1C1 T1AM1 T1AM0 T1AIO1 T1AIO0 T1AOC T1APOL T1CDN T1CCLR TM1C2 T1BM1 T1BM0 T1BIO1 T1BIO0 T1BOC T1BPOL T1PWM1 T1PWM0 TM1AL TM1A[7:0] 5 【2-5-3 节】 TM1AH - - - - - - TM1BL TM1B[7:0] TM1A[9:8] TM1BH - - - - - - TM1B[9:8] TM1DL TM1D[7:0] TM1DH - - - - - - TM1D[9:8] Bit 7 6 5 4 3 2 1 0 5-13-4 程序及流程图: 第五章 进阶实验篇 5-145 5 程序5-13 ETM“单一脉冲输出”模式与STM脉冲测量实验 1 ;PROGRAM : 5-13.ASM (5-13.PJT) 2009.1106 2 ;FUNCTION: CTM PWM vs. STM CAPTURE MODE DEMO PROGRAM By Steven 3 ; NOTE : CONNECT PA1[TP1A] TO PC4[TP2_1],PC0[TP1B] TO PC3[TP2_0] 4 #INCLUDE HT66F50.INC 5 #INCLUDE 5-13.INC 6 ;======================================================================================== 7 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 8 DEL1 DB ? ;DELAY LOOP COUNT 1 9 DEL2 DB ? ;DELAY LOOP COUNT 2 10 DEL3 DB ? ;DELAY LOOP COUNT 3 11 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 12 COUNT DB ? ;UNIVERSAL COUNTER 13 TEMP DB ? ;BUFFER 14 PulseA DB 2 DUP(?) ;CTM PWM PERIOD 5-146 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 15 PulseB DB 2 DUP(?) ;Ton TIME CONTROL REG. 16 DIGIT DB 5 DUP(?) ;ASCII BUFFER 17 HexWord DB 2 DUP(?) ;REGISTER FOR WORD_HEX2ASCII 18 ;======================================================================================== 19 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 20 ORG 00H ;HT66FXX RESET VECTOR 21 CLR ACERL ;AD DISABLE 22 MOV A,08H 23 MOV CP0C,A ;DISABLE CPO 24 MOV CP1C,A ;DISABLE CP1,TP2_0 SHARED WITH C1- 25 SET SW_PulseAC ;CONFIG SW_PulseA AS I/P MODE 26 SET SW_PulseBC ;CONFIG SW_PulseB AS I/P MODE 27 SET SW_PulseAPU ;ENABLE SW_PulseA PULL-UP FUNCTION 28 SET SW_PulseBPU ;ENABLE SW_PulseB PULL-UP FUNCTION 29 30 CLR TM2C0 ;STM fINT=fSYS/4 31 SET PCC.3 ;CONFIG PCC.3 I/P MODE FOR CAPTURE I/P 32 SET PCC.4 ;CONFIG PCC.4 I/P MODE FOR CAPTURE I/P 33 34 CLR PA.1 ;TP1A NOT INVERTED 35 CLR PC.0 5 36 CLR PAC.1 37 CLR PCC.0 ;TP1B NOT INVERTED ;CONFIG PA1[TP1A] O/P MODE FOR PULSE O/P ;CONFIG PC0[TP1B_0] O/P MODE FOR PULSE O/P 38 SET T1ACP0 ;ENABLE TP1A PIN 39 SET T1BCP0 ;ENABLE TP1B_0 PIN 40 MOV A,00000000B ;ETM fINT=fSYS/4 41 MOV TM1C0,A 42 MOV A,10111000B ;TM1A IN SINGLE PULSE O/P MODE,ACTIVE HIGH 43 MOV TM1C1,A 44 MOV A,10111000B ;TM1B IN SINGLE PULSE O/P MODE,ACTIVE HIGH 45 MOV TM1C2,A 46 47 CALL INIT_LCM ;LCM INITIALIZATION 48 SET PulseA[1] ;INITIAL PERIOD INDEX 49 JMP A_PRESSED 50 CHECK_KEY: 51 SNZ SW_PulseB ;SW_PulseB PRESSED ? 52 JMP B_PRESSED ;YES. 53 SZ SW_PulseA ;NO. SW_PulseA PRESSED ? 54 JMP CHECK_KEY ;NO. START MEASURE 55 A_PRESSED: ;YES 56 MOV A,25 ;INCREASE PulseA WIDTH BY 25 57 ADDM A,PulseA[0] 58 CLR ACC 59 ADCM A,PulseA[1] 60 SNZ PulseA[1].2 ;OUT OF 10-BIT RANGE 61 JMP ResetPulseB ;NO. 第五章 进阶实验篇 5-147 62 MOV A,25 ;YES,RESET PulseA WIDTH 63 MOV PulseA[0],A 64 CLR PulseA[1] 65 JMP ResetPulseB 66 B_PRESSED: 67 MOV A,5 ;DECREASE PulseA WIDTH BY 25 68 ADDM A,PulseB[0] 69 CLR ACC 70 ADCM A,PulseB[1] 71 MOV A,PulseA[0] ;MAKE SURE TM1B < TM1A-8 72 SUB A,8 73 SBC A,PulseB[0] 74 MOV A,PulseA[1] 75 SBC A,PulseB[1] 76 SZ C 77 JMP PULSE_OUT 78 ResetPulseB: ;RESET PulseB TO MAX. WIDTH 79 CLR PulseB[0] 80 CLR PulseB[1] 81 PULSE_OUT: 82 CLR T1ON ;STOP CTM 83 MOV A,PulseA[0] ;UPDATE TM0A 84 MOV TM1AL,A 5 85 MOV A,PulseA[1] 86 MOV TM1AH,A 87 MOV A,PulseB[0] ;UPDATE TM0A 88 MOV TM1BL,A 89 MOV A,PulseB[1] 90 MOV TM1BH,A 91 92 MOV A,01100000B ;CAPTURE I/P MODE, RISING/FALLING EDGE 93 MOV TM2C1,A 94 CLR T2CP0 ;DISABLE TP2 FUNCTION ON TP2_0 95 SET T2CP1 ;SET TP2 FUNCTION TO TP2_1 PIN 96 CALL MEASURE 97 MOV A,089H ;SET LCM CURSOR ADDRESS 98 CALL WLCMC 99 CALL DISPLAY 100 CLR T2CP1 ;DISABLE TP2 FUNCTION ON TP2_1 101 SET T2CP0 ;SET TP2 FUNCTION TO TP2_0 PIN 102 CALL MEASURE 103 MOV A,0C9H ;SET LCM CURSOR ADDRESS 104 CALL WLCMC 105 CALL DISPLAY 106 CALL DELAY 107 JMP CHECK_KEY 108 ;======================================================================================== 5-148 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 109 ; PROC : MEASURE 110 ; FUNC : USE STM TO MEASURE DURATION BETWEEN 2 EDGES 111 ; NOTE : SET EDGE TYPE IN TM2C1 BEFORE CALLING THIS PROCDURE 112 ; RET : DURATION IN HexWord[1]_HexWord[0] 113 ;======================================================================================== 114 MEASURE PROC 115 CLR T2PF 116 CLR T2AF 117 SET T2ON ;START MEASURE 118 SET T1ON 119 SNZ T2AF ;WAITING FOR 1'ST EDGE 120 JMP $-1 121 SZ T2PF ;TM2RP OVERFLLOW? 122 JMP MEASURE ;YES. REMEASURE 123 MOV A,TM2AH ;NO. GET TM2A COUNT 124 MOV HexWord[1],A 125 MOV A,TM2AL 126 MOV HexWord[0],A 127 CLR T2AF 128 SNZ T2AF ;WAITING FOR 2'ND EDGE 129 JMP $-1 5 130 MOV A,TM2AH 131 MOV A,TM2AL ;LATCH COUNT TO TM2A 132 SUBM A,HexWord[0] 133 MOV A,TM2AH 134 SBCM A,HexWord[1] 135 CLR T2ON ;STOP MEASURE 136 CLR T1ON ;STOP O/P 137 RET 138 MEASURE ENDP 139 ;======================================================================================== 140 ; PROC : DISPLAY 141 ; FUNC : CONVERT 16-BIT HEX TO 5-DIGIT BCD/ASCII AND DISPLAY ON LCM 142 ;======================================================================================== 143 DISPLAYPROC 144 CALL WORD_HEX2ASCII 145 MOV A,5 146 MOV COUNT,A 147 MOV A,OFFSET DIGIT[4] 148 MOV MP0,A 149 MOV A,IAR0 150 CALL WLCMD 151 DEC MP0 152 SDZ COUNT 153 JMP $-4 154 RET 155 DISPLAYENDP 第五章 进阶实验篇 5-149 156 ;======================================================================================== 157 ; PROC : WORD_HEX2ASCII-BIT DATA 158 ; FUNC : CONVERT 16-BIT HEX TO 5-DIGIT BCD/ASCII 159 ; PARA : HexWord CONTAIN 16 BITS DATA TO BE CONVERT 160 ; REG : ACC,IAR0,MP0,TBLP,TBLH,TEMP 161 ; RTN : DIGIT[4]~DIGIT[0] 162 ;======================================================================================== 163 WORD_HEX2ASCII PROC 164 MOV A,TAB_HEX ;LOAD TABLE POINTER 165 MOV TBLP,A 166 MOV A,OFFSET DIGIT[4] ;LOAD DATA POINTER 167 MOV MP0,A 168 MOV A,4 ;SET DIGIT COUNT 169 MOV COUNT,A 170 NEXT_DIG: 171 CLR IAR0 ;CLEAR BUFFER 172 TABRDL TEMP ;LOAD BASE 173 W2H: MOV A,HexWord[0] 174 SUB A,TEMP 175 MOV HexWord[0],A 176 MOV A,HexWord[1] 177 SBC A,TBLH 178 MOV HexWord[1],A 5 179 SNZ C ;WORD DATA > BASE ? 180 JMP $+3 ;NO. 181 INC IAR0 ;YES. 182 JMP W2H 183 MOV A,TEMP ;RESTORE WORD DATA 184 ADDM A,HexWord[0] 185 MOV A,TBLH 186 ADCM A,HexWord[1] 187 INC TBLP 188 DEC MP0 189 SDZ COUNT 190 JMP NEXT_DIG 191 MOV A,HexWord[0] 192 MOV IAR0,A 193 MOV A,30H ;BEFORE THIS LINE HEX TO UN-PACK BCD 194 ADDM A,DIGIT[4] ;CONVERT DIG4 TO ASCII 195 ADDM A,DIGIT[3] ;CONVERT DIG3 TO ASCII 196 ADDM A,DIGIT[2] ;CONVERT DIG2 TO ASCII 197 ADDM A,DIGIT[1] ;CONVERT DIG1 TO ASCII 198 ADDM A,DIGIT[0] ;CONVERT DIG0 TO ASCII 199 RET 200 WORD_HEX2ASCII ENDP 201 ;======================================================================================== 202 ; PROC : INIT_LCM 5-150 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 203 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 204 ; REG : ACC 205 ;======================================================================================== 206 INIT_LCM PROC 207 CLR LCM_EN ;SET EN=0 208 CLR LCM_RW ;SET RW=0 209 CLR LCM_RS ;SET RS=0 210 CLR LCM_ENC ;CONFIG EN AS O/P MODE 211 CLR LCM_RWC ;CONFIG RW AS O/P MODE 212 CLR LCM_RSC ;CONFIG RS AS O/P MODE 213 214 MOV A,38H ;FUNCTION SET: 8-BIT,2-LINE,5X7 DOTS 215 CALL WLCMC 216 MOV A,0CH ;ON/OFF CONTR: DISPLAY ON,CURSOR BLINKING OFF 217 CALL WLCMC 218 MOV A,06H ;ENTRY MODE : INCREMENT,DISPLAY NOT SHIFT 219 CALL WLCMC 220 MOV A,01H ;CLEAR DISPLAY 221 CALL WLCMC 222 223 MOV A,STR_1 5 224 CALL PRINT 225 MOV A,0C0H ;DISPLAY RELATIVE SYMBOL ON LCM 226 CALL WLCMC 227 MOV A,STR_2 228 CALL PRINT 229 RET 230 INIT_LCM ENDP 231 ;======================================================================================== 232 ; PROC : WLCMD/WLCMC 233 ; FUNC : WRITE DATA/COMMAND TO LCM 234 ; PARA : ACC : COMMAND/DATA 235 ; REG : ACC,DC_FLAG 236 ;======================================================================================== 237 WLCMD PROC 238 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 239 JMP $+2 240 WLCMC: CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 241 SET LCM_DATAPORTC ;CONFIG LCM_DATAPORT AS I/P MODE 242 CLR LCM_RS ;SET RS=0 (IR) 243 SET LCM_RW ;SET RW=1 (READ) 244 NOP ;FOR TAS 245 SET LCM_EN ;SET EN=1 246 NOP ;FOR TDDR 247 WF: SZ LCM_DATAPORT.7 ;IS LCM BUSY? 248 JMP WF ;YES, JUMP TO WAIT 249 CLR LCM_EN ;SET EN=0 第五章 进阶实验篇 5-151 250 CLR LCM_DATAPORTC ;NO, CONFIG LCM_DATAPORT AS O/P MODE 251 MOV LCM_DATAPORT,A ;LATCH DATA/COMMAND ON LCM_DATAPORT 252 CLR LCM_RW ;SET RW=0 (WRITE) 253 CLR LCM_RS ;SET RS=0 (IR) 254 SZ DC_FLAG ;IS COMMAND WRITE? 255 SET LCM_RS ;NO, SET RS=1 (DR) 256 SET LCM_EN ;SET EN=1 257 NOP ;FOR PWEN 258 CLR LCM_EN ;SET EN=0 259 RET 260 WLCMD ENDP 261 ;======================================================================================== 262 ; PROC : PRINT 263 ; FUNC : DISPLAY STRING ON LCM, STRING END WITH NULL AND POINT BY ACC(LAST PAGE) 264 ; REG : ACC 265 ; RETN : DD RAM/CG RAM DATA IN ACC 266 ;======================================================================================== 267 PRINT PROC 268 MOV TBLP,A ;LOAD TABLE POINTER 269 PRINT_1: 270 TABRDL ACC ;READ STRING 271 XOR A,NULL 272 SZ Z ;END OF STRING CHARACTER? 5 273 RET ;YES, STOP PRINT 274 TABRDL ACC ;NO, RE-READ 275 CALL WLCMD ;SEND TO LCD 276 INC TBLP ;INCREASE DATA POINTER 277 JMP PRINT_1 ;NEXT CHARACTER 278 RET ;YES, RETURN 279 PRINT ENDP 280 ;======================================================================================== 281 ; PROC : DELAY 282 ; FUNC : DEALY ABOUT 25*10mS 283 ; REG : DEL1,DEL2,DEL3 284 ;======================================================================================== 285 DELAY PROC 286 MOV A,25 287 MOV DEL1,A 288 DEL_1: MOV A,30 289 MOV DEL2,A ;SET DEL2 COUNTER 290 DEL_2: MOV A,110 291 MOV DEL3,A ;SET DEL3 COUNTER 292 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 293 JMP DEL_3 294 SDZ DEL2 ;DEL2 DOWN COUNT 295 JMP DEL_2 296 SDZ DEL1 ;DEL1 DOWN COUNT 5-152 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 297 JMP 298 RET 299 DELAY ENDP 300 ORG 301 TAB_HEX:DC 302 STR_1: DC 303 STR_2: DC 304 END DEL_1 LASTPAGE 10000,1000,100,10 'A Width= uS',NULL 'B Width= uS',NULL 程程序序解解说说:: 5 载入”5-13.INC”定义档,其内容请参考随书光盘中的档案。 8~17 依序定义变量地址。 20 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 21~24 关闭 CP0、CP1 功能,并设定 ADC 脚位输入为 I/O 功能。 25~28 定义 SW_PulseA(PA.2)、SW_ PulseB(PA.3)为输入模式,并使能其 Pull-high 功能。 5 29~32 定义 TM2C0 控制寄存器 T2CK[2:0]:000,设定 fINT=fSYS/4;并将 TP2_1(PC.4)、 TP2_0(PC.3)定义为输入模式(本例为捕捉输入的脚位)。 34~39 设定 TP1A 功能在 TP1A(PA.1)脚位、TP1B 功能在 TP1B_0(PC.0)脚位上实 现,由于本例为 PWM 波形的输出脚位,故同时将其定义为输出模式,并选定为同 相输出。 40~45 定义 TM1C0、TM1C1、TM1C2 控制寄存器: T1CK[2:0]:000,设定 fINT=fSYS/4; T1AM[1:0]:10,设定为 PWM 或 Single Pulse 输出模式; T1AIO[1:0]:11,设定 TP1A 为 Single Pulse Output; T1AOC:1,选择 PWM 输出为 Active High; T1BM[1:0]:10,设定为 PWM 或 Single Pulse 输出模式; T1BIO[1:0]:11,设定 TP1B 为 Single Pulse Output; T1BOC:1,选择 PWM 输出为 Active High。 47 调用 INIT_LCM 子程序,对 LCM 进行定义。 48~49 设定 PusleA 存储器的初值,并跳至 A_PRESSED 执行;PusleA 存储器的内容掌控 ETM 输出的单脉冲宽度周期。 第五章 进阶实验篇 5-153 51~54 检查按键是否按下,若未按下则持续等待;若按下,则依“PulseA”或“PulseB” 按键的状态分别跳至 PulseA、PulseB 的宽度调整程序。 56~65 此段为按下“PulseA”按键时的处理程序;首先将 PulseA 存储器加 25 并判断是否 已大于 1023,若是则将其恢复到初值 25。并跳至 ResetPulseB 调整程序(此做法 是为了防止当 PulseA 存储器更动时,发生 PulseA 存储器设定值小于 PulseB 的现 象,致使 TP1B 波形无法输出)。 67~80 此段为按下“PulseB”按键时的处理程序;首先将 PulseA 存储器加 5 并判断是否 已大于、等于 PulseA 存储器的设定值减八,若是则将其恢复为零,此时为 TP1B 输出的最大宽度(其宽度将与 TP1A 的脉宽相同)。 82~90 暂停 ETM 的计数,并依据 PulseA、PulseB 存储器更改 TM1A、TM1B 的设定值, 此举即改变输出脉冲的宽度。 92~93 设定 STM 为“捕捉输入”模式(T2M[1:0]=10),且为双沿触发形式(T2IO[1:0] =10)。 94~95 将 TP2 的功能转移到 TP2_1 实现:此时 TP1A 的输出脉冲将输入到 STM 的 TP2。 96~99 调用 MEASURE 子程序进行测量,并将结果显示在 LCM 上。此时设定为双沿触发 5 形式,故测量数据为由 TP2 所输入的正脉冲宽度。 100~101 将 TP2 的功能转移到 TP2_0 实现:此时 TP1B 的输出脉冲将输入到 STM 的 TP2。 102~104 调用 MEASURE 子程序进行测量,并将结果显示在 LCM 上。此时设定为双沿触发 形式,故测量数据为由 TP2 所输入的正脉冲宽度。 89~90 调用 DELAY 子程序延迟 0.25 秒,其目的除避免抖动的影响之外,当使用者按下按 键时也能以每隔 0.25 秒的速率自动更新选项;接着重新检查按建是否按下。 114~138 MEASURE 子程序;在清除 T2PF、T2AF 标志后启动 STM 开始计数,并等待计数 完成(T2AF=“1”);测量结束时万一 T2PF 为“1”,表示 STM 计数溢位,故 重新启动测量。否则即将 TM2A 之值保留到 HexWord 存储器,随即启动第二次测 量;并将测量结果与 HexWord 存储器相减,求出两次测量的差值。 143~155 DISPLAY 子程序;将 HexWord 存储器转换为 ASCII 码后,调用 WLCMD 子程序加 以显示。 163~200 WORD_HEX2ASCII 子程序;将 HexWord[]存储器中的十六位数据转换为 ASCII 码 存置于 DIGIT[]数组;请参考本实验前述的说明。 206~230 INIT_LCM 子程序,其功能是对 LCM 进行定义。 207~212 LCM_EN、LCM_RW 与 LCM_RS 定义为输出模式,并设定状态为“0”。 5-154 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 214~215 将 LCM 设定为双行显示(N = 1)、使用八位(DB7 ~ DB0)控制模式(DL = 1)、 5×7 点矩阵字型(F = 0)。 216~219 将 LCM 设定为显示所有数据(D = 1)、显示光标(C = 1)、光标所在位置不闪烁 (B = 0);LCM 的地址计数器(AC)设为递加(I/D = 1)、显示器画面不因读写 数据而移动(S = 0)。 220~221 将 LCM 整个显示器清空。 223~228 调用 PRINT 子程序,经由查表将字符串 STR1、STR2 分别显示在 LCM 的一、二 列。 237~260 WLCMD 与 WLCMC 子程序,请参考【实验 5-6】的说明。 267~279 PRINT 子程序,此子程序负责将定义好的字符串依序显示在 LCM 上。在调用此子 程序之前,除了必须先设定好 LCM 的位置之外,尚需先在 Acc 寄存器中指定字符 串的起始地址(字符串必须存放在最末程序页-Last Page),并请在字符串的最后 一个字符塞入 NULL,代表字符串结束。 285~299 DELAY 子程序,延迟 0.3 秒;延迟时间的计算请参考【实验 4-1】。 5 300 WORD_HEX2ASCII 子程序进行转换时所需的常数建表区。 302~303 STR1、STR2 字符串建表数据,每一个字符串务必以 NULL 做为结束字符。 【程序5-13】与【实验5-12】的架构雷同,只是将测量的信号来源由CTM的 PWM输出改为ETM的Single Pulse Output,而由于ETM可同时在TP1A、TP1B输 出两个脉冲,故程序中就以切换TP2_0与TP2_1的方式,让STM单元完成两个脉冲 的宽度测量;TP1A输出的脉冲宽度为PulseA×(fINT-1),TP1B输出的脉冲宽度则 是(PulseA-PulseB)×(fINT-1)。因ETM Single Pulse Output的输出特性是:当 TCK1输入引脚或T1ON位出现“0” “1”的电平变化时,ETM会依T1AOC、T1BOC 位的状态分别设定TP1A为Active、TP1B为Inactive的电平,并启动TM1D计数器由 “000h”开始往上计数,计数频率来源则取决于T1CK[2:0]的设定。当TM1D计数 到TM1B所设定之值时,ETM会将TP1B输出设定为Active电平;当TM1D计数到 TM1A时,ETM会将TP1A、TP1B输出设定为Inactve电平,完成一个脉冲的输出程 序。为避免TP1B输出的脉冲宽度过窄,导致来不及记录测量值(如【实验5-12】 所提及的状况);因此程序中限制让TM1B的设定值至少必须小于(TM1A-8), 以确保可顺利测得脉冲宽度。 第五章 进阶实验篇 5-155 (a)PulseB=0 (b) PulseB=15 【图 5-13-2】PulseA=25 时 TP1A/TP1B 的输出 (a)PulseB=0 5 (b) PulseB=75 (c) PulseB=165 【图 5-13-3】PulseA=175 时 TP1A/TP1B 的输出 【图5-13-2】与【图5-13-3】是笔者以示波器实际测量ETM输出所得的波形(请 注意:CH1为TP1A、CH3为TP1B),以【程序5-13】所测得的脉冲宽度几乎与示 波器测量结果完全吻合。【图5-13-4】是笔者将【程序5-13】第35行指令:“CLR PC.0”改为“SET PC.0”后的输出情形,读者关应该可看出其中的端倪吧? 5-156 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 (a)PulseB=15(PC.0=“1”) (b) PulseB=0(PC.0=“1”) 【图 5-13-4】PulseA=25 时 TP1A/TP1B 的输出 5-13-5 动动脑+动动手: 试改变【程序 5-13】中 ETM 的计数频率来源(即 TM2C0 控制寄存器的 T2CK[2:0]位),并重新进行测量;观测测量结果与分析值是否一致。 5 5-157 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-14 中文显示型LCM控制实验 5-14-1 目 的: 在中文显示型LCM上显示字型,并利用程序的技巧产生字符串移动的效果。 5-14-2 学习重点: 通过本实验,读者能熟悉中文显示型LCM的控制方式,此外亦能运用LCM的 控制指令让液晶显示器展现不同的显示效果。 5-14-3 电路图: 5 【图 5-14-1】中文显示型 LCM(8-Bit)控制电路 在前几个实验中,利用LCM内部的CG RAM建立了几个简单的中文字型,由于 分辨率不佳(5×7点),若要显示笔画较多的中文字,可就必须以内建中文字型的 中文显示型LCM来实践较为恰当。目前市面上也可买到此类型的液晶显示器,虽然 价格不斐,但是其所显示的字型相当细致(如【图5-14-3】所示)。中文显示型LCM 的控制方式其实与一般文字型的LCM相当类似,所以关于其控制的部分于此不再赘 述,仅提醒读者相当重要的注意事项。 0 1 2 … 7 8 显示位置 第一列 00h 01h 02h … 07h 08h DD RAM地址 第二列 10h 11h 12h … 17h 15h DD RAM地址 【图 5-14-2】9×2 中文显示型 LCM 显示位置与 DD RAM 地址的对应关系 本实验采用9×2的中文显示型LCM(编号:LMG-14B32),此显示器共有两列, 每列可以显示九个中文字型(或18个英文字型),其显示位置与DD RAM地址的对 应关系如【图5-14-2】。请注意第一列的最后一个位置(08h)与第二列的第零个 位置(10h)的DD RAM地址并不连续。而每一个位置可以显示一个中文字型或是 两个英文字型,这表示在中文显示型LCM上,一个DD RAM地址是可以存放两个 5-158 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 Bytes的数据,当显示中文时,只需将中文的BIG-5码(2 Bytes)分成两次(若为 LCM 8-Bit 控制模式)写至LCM的DD RAM即可;显示英文时,则与一般LCM的控 制方式相同。不过要注意在写入中文时,要确定写入的BIG-5码一定要在同一个DD RAM地址内,如果是被拆成两个Byte分别存放在不同DD RAM地址的话(例如位置 00h的High Byte与01h的Low Byte),将会显示乱码(请参考本实验的【动动手+ 动动脑】部分)! 5-14-4 程序及流程图: 5 程序5-14 中文显示型LCM控制实验 1 ;PROGRAM : 5-14.ASM (5-14.PRJ) 2009.1204 2 ;FUNCTION: 9X2 CHINESE LCD CONTROL DEMO PROGRAM By Steven 3 #INCLUDE HT66F50.INC 4 #INCLUDE 5-14.INC 5 ;======================================================================================== 6 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 7 DEL1 DB ? ;DELAY LOOP COUNT 1 8 DEL2 DB ? ;DELAY LOOP COUNT 2 9 DEL3 DB ? ;DELAY LOOP COUNT 3 10 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 11 COUNT DB ? ;UNIVERSAL COUNTER 12 ;======================================================================================== 13 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 14 ORG 00H ;HT66FXX RESET VECTOR 15 CALL INIT_LCM ;LCM INITIALIZATION 16 MAIN: MOV A,01H ;CLEAR LCD SCREEN 17 CALL WLCMC 18 MOV A,8AH ;SET DD RAM ADDRESS 第五章 进阶实验篇 5-159 19 CALL WLCMC 20 MOV A,STR3 21 CALL PRINT ;COPY STRING TO DD RAM 22 MOV A,81H ;SET DD RAM ADDRESS 23 CALL WLCMC 24 MOV A,STR1 25 CALL PRINT ;COPY STRING TO DD RAM 26 MOV A,91H ;SET DD RAM ADDRESS 27 CALL WLCMC 28 MOV A,STR2 29 CALL PRINT ;COPY STRING TO DD RAM 30 SHIFT: 31 MOV A,250 ;DELAY 2.5 SEC 32 CALL DELAY 33 MOV A,8 ;SET COUNT=8 34 MOV COUNT,A 35 SCREEN_SHIFT_RIGHT: 36 MOV A,15 ;DELAY 150mS 37 CALL DELAY 38 MOV A,1CH 39 CALL WLCMC ;SET SCREEN SHIFT RIGHT 40 SDZ COUNT ;COUNT-1 = 0? 41 JMP SCREEN_SHIFT_RIGHT ;NO, SHIFT RIGHT AGAIN 5 42 MOV A,250 ;DELAY 2.5 SEC 43 CALL DELAY 44 MOV A,8 ;SET COUNT=8 45 MOV COUNT,A 46 SCREEN_SHIFT_LEFT: 47 MOV A,25 ;DELAY 250mS 48 CALL DELAY 49 MOV A,18H ;SET SCREEN SHIFT LEFT 50 CALL WLCMC 51 SDZ COUNT ;COUNT-1 = 0? 52 JMP SCREEN_SHIFT_LEFT ;NO, SHIFT RIGHT AGAIN 53 JMP SHIFT ;RESTART 54 ;======================================================================================== 55 ; PROC : INIT_LCM 56 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 57 ; REG : ACC 58 ;======================================================================================== 59 INIT_LCM PROC 60 CLR LCM_EN ;SET EN=0 61 CLR LCM_RW ;SET RW=0 62 CLR LCM_RS ;SET RS=0 63 CLR LCM_ENC ;CONFIG EN AS O/P MODE 64 CLR LCM_RWC ;CONFIG RW AS O/P MODE 65 CLR LCM_RSC ;CONFIG RS AS O/P MODE 5-160 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 66 67 MOV A,38H ;FUNCTION SET: 8-BIT,2-LINE,5X7 DOTS 68 CALL WLCMC 69 MOV A,0CH ;ON/OFF CONTR: DISPLAY ON,CURSOR BLINKING OFF 70 CALL WLCMC 71 MOV A,06H ;ENTRY MODE : INCREMENT,DISPLAY NOT SHIFT 72 CALL WLCMC 73 RET 74 INIT_LCM ENDP 75 ;======================================================================================== 76 ; PROC : WLCMD/WLCMC 77 ; FUNC : WRITE DATA/COMMAND TO LCM 78 ; PARA : ACC : COMMAND/DATA 79 ; REG : ACC,DC_FLAG 80 ;======================================================================================== 81 WLCMD PROC 82 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 83 JMP $+2 84 WLCMC: CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 85 SET LCM_DATAPORTC ;CONFIG LCM_DATAPORT AS I/P MODE 86 CLR LCM_RS 5 87 SET LCM_RW 88 NOP ;SET RS=0 (IR) ;SET RW=1 (READ) ;FOR TAS 89 SET LCM_EN ;SET EN=1 90 NOP ;FOR TDDR 91 WF: SZ LCM_DATAPORT.7 ;IS LCM BUSY? 92 JMP WF ;YES, JUMP TO WAIT 93 CLR LCM_EN ;SET EN=0 94 CLR LCM_DATAPORTC ;NO, CONFIG LCM_DATAPORT AS O/P MODE 95 MOV LCM_DATAPORT,A ;LATCH DATA/COMMAND ON LCM_DATAPORT 96 CLR LCM_RW ;SET RW=0 (WRITE) 97 CLR LCM_RS ;SET RS=0 (IR) 98 SZ DC_FLAG ;IS COMMAND WRITE? 99 SET LCM_RS ;NO, SET RS=1 (DR) 100 SET LCM_EN ;SET EN=1 101 NOP ;FOR PWEN 102 CLR LCM_EN ;SET EN=0 103 RET 104 WLCMD ENDP 105 ;======================================================================================== 106 ; PROC : PRINT 107 ; FUNC : DISPLAY STRING ON LCM, STRING END WITH NULL AND POINT BY ACC(LAST PAGE) 108 ; REG : ACC 109 ; RETN : DDRAM/CGRAM DATA IN ACC 110 ;======================================================================================== 111 PRINT PROC 112 MOV TBLP,A ;LOAD TABLE POINTER 第五章 进阶实验篇 5-161 113 PRINT_1: 114 TABRDL ACC ;READ STRING 115 XOR A,NULL 116 SZ Z ;END OF STRING CHARACTER? 117 RET ;YES, STOP PRINT 118 TABRDL ACC ;NO, RE-READ 119 CALL WLCMD ;SEND TO LCD 120 INC TBLP ;INCREASE DATA POINTER 121 JMP PRINT_1 ;NEXT CHARACTER 122 RET ;YES, RETURN 123 PRINT ENDP 124 ;======================================================================================== 125 ; PROC : DELAY 126 ; FUNC : DEALY ABOUT DEL1*10mS 127 ; PARA : ACC : DELAY FACTOR 128 ; REG : DEL1,DEL2,DEL3 129 ;======================================================================================== 130 DELAY PROC 131 MOV DEL1,A 132 DEL_1: MOV A,30 133 MOV DEL2,A ;SET DEL2 COUNTER 134 DEL_2: MOV A,110 135 MOV DEL3,A ;SET DEL3 COUNTER 5 136 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 137 JMP DEL_3 138 SDZ DEL2 ;DEL2 DOWN COUNT 139 JMP DEL_2 140 SDZ DEL1 ;DEL1 DOWN COUNT 141 JMP DEL_1 142 RET 143 DELAY ENDP 144 ORG LASTPAGE 145 STR1: DC 'HT66Fx0 Series',NULL ;DEFINE STRING DATA 1 146 STR2: DC 'MCU 原理与实务',NULL ;DEFINE STRING DATA 2 147 STR3: DC '锺启仁 编着',NULL ;DEFINE STRING DATA 3 148 END 程程序序说说明明:: 4 载入”5-14.INC”定义档,其内容请参考随书光盘中的档案。 7~11 依序定义变量地址。 14 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 15 调用 INIT_LCM 子程序,进行 LCM 相关定义。 16~17 将 LCM 整个显示器清空。 5-162 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 18~19 设定 DD RAM 的地址为 0Ah。 20~21 调用 PRINT 子程序,经由查表将字符串(STR3)写入 DD RAM 中;由于目前 LCM 的可视范围为地址 00h~08h 的 DD RAM 内容,故此时 STR3 字符串是不会显示的。 22~23 设定 DD RAM 的地址为 01h。 24~25 调用 PRINT 子程序,经由查表将字符串(STR1)写入 DD RAM 中。 26~27 设定 DD RAM 的地址为 11h。 28~29 调用 PRINT 子程序,经由查表将字符串(STR2)写入 DD RAM 中。 31~32 调用 DELAY 子程序,延迟 2.5 秒。 33~34 设定 COUNT=8。 36~37 调用 DELAY 子程序,延迟 150ms。 38~39 利用 LCM 命令,控制 LCM 屏幕右移一个字符位置,请参考【表 5-6-5】LCM 指令 表。 40~41 判断 COUNT 减一是否为 0。成立,则表示屏幕已经右移八次;反之,则继续右移 5 (JMP SCREEN_SHIFT_RIGHT)。 42~43 调用 DELAY 子程序,延迟 2.5 秒。 44~45 设定 COUNT=8。 47~48 调用 DELAY 子程序,延迟 250ms。 49~50 利用 LCM 命令,控制 LCM 屏幕左移一个字符位置,请参考【表 5-6-5】LCM 指令 表。 51~53 判断 COUNT 减一是否为 0。成立,则表示屏幕已经左移八次,重新开始右移的动 作(JMP SHIFT);反之,则继续左移(JMP SCREEN_SHIFT_LEFT)。 59~74 INIT_LCM 子程序,其功能是对 LCM 进行定义: 60~65 LCM_EN、LCM_RW 与 LCM_RS 定义为输出模式,并设定状态为“0”。 67~68 将 LCM 设定为双行显示(N = 1)、使用八位(DB7 ~ DB0)控制模式(DL = 1)、 5×7 点矩阵字型(F = 0)。 69~72 将 LCM 设定为显示所有数据(D = 1)、显示光标(C = 1)、光标所在位置不闪烁 (B = 0);LCM 的地址计数器(AC)设为递加(I/D = 1)、显示器画面不因读写 数据而移动(S = 0)。 81~104 WLCMD 与 WLCMC 子程序,请参考【实验 5-6】的说明。 第五章 进阶实验篇 5-163 111~123 PRINT 子程序,此子程序负责将定义好的字符串依序显示于 LCM 上。在调用此子 程序之前,除了必须先设定好 LCM 的位置之外,还需先于 Acc 寄存器中指定字符 串的起始地址(字符串必须存放于最末程序页-Last Page),并请于字符串的最后 一个字符塞入 NULL,代表字符串结束。 130~143 DELAY 子程序,至于延迟时间的计算请参考【实验 4-1】。 145~147 字符串定义区,每一个字符串务必以 NULL 做为结束字符。 程序一开始先对LCM做初始化的设定,接下来就是连续在不同的DD RAM填入 字符串STR3、STR2与STR1。在填入STR3之前,是将AC(LCM Address Counter) 设定为0Ah(即第十个显示位置),此时LCM的可见窗口范围为位置“0”~“8”, 因此并看不到STR3的字符串!而后是利用LCM屏幕的左、右移指令,逐一改变LCM 的可见窗口范围,再搭配上不同的延迟时间而达到字符串左、右移动的效果。 5-14-5 动动脑+动动手: 将 STR3 的定义改变如下(在字符间塞入空格符),观察 LCM 显示的字型有 何改变。 5 147 STR3: DC ‘钟 启 仁 编著',STR_END ;DEFINE STRING DATA 3 【由于在中文字间塞入了空白码(20h),致使第二个中文字的 BIG-5 码被拆 成两个 Byte 分别存放于 DD RAM 地址 0Bh(High Byte)与 0Ch(Low Byte), 因此第二个中文字型无法正常显示!而第二个空白码恰巧被塞入 0Ch High Byte 地址,使得其后的中文 BIG-5 码存放于同一个 DD RAM 地址,所以除 了第二个中文字型无法显示之外,其它字型显示均正常无误。】 试着利用 LCM 控制指令,让显示屏产生闪、灭的效果。 改变 DELAY 子程序的延迟时间,字型移动的速度变化。 【图 5-14-3】中文 LCM 显示字型 5-164 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-15 半矩阵式键盘与LCM控制实验 5-15-1 目 的: 以半矩阵式键盘(Half-Matrix Key Pad)为输入设备,让使用者可以输入大、 小写的英文字母,并显示于LCM上。 5-15-2 学习重点: 通过本实验,读者应熟悉半矩式键盘的控制方式,以便在多按键输入的应用场 合加以运用;此外对LCM的控制应更加得心应手。 5-15-3 电路图: 5 PS:务必使能PA[7:0]的Pull-high功能。 【图 5-15-1】半矩阵式键盘与 LCM 控制电路 在【实验4-7】中,相信读者应该已经明白了4×4矩阵式键盘(Matrix Keypad) 的工作原理,它是以8-Bit的I/O Port搭配程序的运作,就可以区分出16个不同的按 键!然而,在实务运用上(尤其在I/O资源弥足珍贵的单片机应用场合),如果想 要增加按键的个数,势必又得多腾出几根I/O引脚供按键扫描使用。例如本实验要 求要能够输入26个英文字母,万一单片机已经没有多余的I/O引脚可供使用的话, 该怎么办呢?以下所介绍的“半矩阵式键盘(Half-Matrix Keypad)”,是在一般 应用设计上经常使用的技巧,只要一个8-Bit的I/O Port并搭配程序的运作,就能区 分出28个不同的按键,足足比4×4矩阵式键盘多出了12个,正可满足本实验的需求! 【图5-15-2】是半矩阵式键盘的硬件连接方式,在此笔者以HT66F50的PA做控制 来做说明。 第五章 进阶实验篇 5-165 【图 5-15-2】半矩阵式键盘(Half-Matrix Key Pad) 半矩阵式键盘的扫描原理是依序让每一个I/O引脚送出(输出模式)“0”电平, 每当送出“0”之后,就读回(输入模式)其它I/O引脚的状态,如果读回的状态出 现“0”电平,就表示该行有按键被按下;至于是哪一列被按下,则可由读回的数 值加以解析。因此每一根I/O Pin都可能被定义为输入或输出模式,不像4×4矩阵式 5 键盘是四个I/O Pins固定作为输出,另四个则固定当成输入。 以【图5-15-2】为例,半矩阵式键盘的扫描是由PA.7~PA.0依序送出“0”(即 循行检查),然后再读回PA的状态判断是哪一列被按下。假若是“S15”按键被按 下(如【图 5-15-3】),首先由PA.7(输出模式)送出“0”,然后由PA.6~PA.0 (输入模式)读回的状态为“?1111111B”,表示第一行(Col 1)没有按键被按 下;接着由PA.6(输出模式)送出“0”检查Col 2,然后由PA.5~PA.0读回的状态 为“??111111B”,表示该行也没有按键被按下;当由PA.5(输出模式)送出“0” 检查Col 3时,从PA.4~PA.0读回“???11011B”的状态,表示该行第五列的按键 (即“S15”)被按下(PS.“?”表示该Pin为输出模式或者是未接上按键,其状 态不需理会。)。请读者参考HALF_READKEY程序说明与【图5-15-4】的流程图。 5-166 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 【图 5-15-3】“S15”按键被按下 1 ;======================================================================================== 2 ; SCAN HALF MATRIX ON KEY PORT AND RETURN THE CODE IN KEY REGISTER 5 3 ; IF NO KEY BEEN PRESSED, KEY=28. 4 ;======================================================================================== 5 HALF_READKEY PROC 6 MOV A,01111111B 7 MOV COLUMN,A ;SET COLUMN FOR SCANNING 8 CLR KEY ;INITIAL KEY REGISTER 9 MOV A,7 10 MOV KEY_COUNT,A ;SET COUNTER=7 FOR 7 COLUMNS 11 SCAN_KEY: 12 MOV A,COLUMN ;GET COLUMN FOR SCANNING 13 MOV KEY_PORTC,A ;CONFIG KEY_PORT 14 MOV KEY_PORT,A ;SCANNING KEY PAD 15 MOV KEY_PORTPU,A ;SCANNING KEY PAD 16 MOV A,KEY_COUNT ;GET COLUMN COUNTER 17 ADDM A,PCL ;COMPUTATIONAL JUMP 18 NOP ;OFFSET FOR KEY_COUNT=0 19 JMP $+24 ;KEY_COUNT=1 20 JMP $+20 ;KEY_COUNT=2 21 JMP $+16 ;KEY_COUNT=3 22 JMP $+12 ;KEY_COUNT=4 23 JMP $+8 ;KEY_COUNT=5 24 JMP $+4 ;KEY_COUNT=6 25 SNZ KEY_PORT.6 ;KEY_COUNT=7,ROW 1 PRESSED? 26 RET ;YES. 27 INC KEY ;NO, INCREASE KEY CODE 28 SNZ KEY_PORT.5 ;ROW 2 PRESSED? 第五章 进阶实验篇 5-167 29 RET ;YES. 30 INC KEY ;NO, INCREASE KEY CODE 31 SNZ KEY_PORT.4 ;ROW 3 PRESSED? 32 RET ;YES. 33 INC KEY ;NO, INCREASE KEY CODE 34 SNZ KEY_PORT.3 ;ROW 4 PRESSED? 35 RET ;YES. 36 INC KEY ;NO, INCREASE KEY CODE 37 SNZ KEY_PORT.2 ;ROW 5 PRESSED? 38 RET ;YES. 39 INC KEY ;NO, INCREASE KEY CODE 40 SNZ KEY_PORT.1 ;ROW 6 PRESSED? 41 RET ;YES. 42 INC KEY ;NO, INCREASE KEY CODE 43 SNZ KEY_PORT.0 ;ROW 7 PRESSED? 44 RET ;YES. 45 INC KEY ;NO, INCREASE KEY CODE 46 RR COLUMN ;SCAN CODE FOR NEXT COLUMN 47 SDZ KEY_COUNT ;HAVE ALL COULMN BEEN CHECKED? 48 JMP SCAN_KEY ;NO, NEXT COLUMN 49 RET 50 HALF_READKEY ENDP 5 HHAALLFF__RREEAADDKKEEYY 子子程程序序说说明明:: 2~3 4 5~6 8~10 11~40 设定 COLUMN=01111111b;如之前的说明,半矩阵式键盘需依序扫描 PA.7~PA.1, 因此以 COLUMN 作为扫描与 Port 定义数据寄存器。 设定 KEY 值为零。当执行完此子程序时,KEY 寄存器的值即为按键值;若按键都 没有被按,则 KEY=28。 设定 KEY_COUNT=7,做扫描七行的控制寄存器。 因为扫描的行(即送出“0”的 Port)必须定义为输出模式,而其余引脚必须为输 入模式以便判断是否有按键被按下;因此这三行指令的目的是先依据 COLUMN 寄 存器的值将 I/O Port 做适当的定义,然后再将扫描码送出。 依序检查各列是否有按键被按下,若无则将 KEY 寄存器值加一,并继续检查下一列; 若按键被按下则返回主程序(JMP END_KEY)。由于硬件结构的关系,每当送出 新的扫描码时,并不见得要检查所有的输入引脚。例如当扫描第一行时(PA.7= “0”),必须循序检查 PA.6~PA.0;而扫描第二行时(PA.6=“0”),只须循序 检查 PA.5~PA.0;于依此类推。因此在程序第 11~19 行是以 KEY_COUNT 寄存器 计算式的跳跃(Computational Jump),以避开不需检查的输入脚位。又因为 5-168 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 44 42~45 KEY_COUNT 寄存器的变化范围是由 1~7,所以在 13 行加入“NOP”指令作为补 偿。 将扫描码右移一位,准备扫描下一行。 判断 KEY_COUNT 减一是否为零,若成立表示七行均已完成扫描,返回主程序 (RET);否则继续检查下一行(JMP SCAN_KEY)。 5 【图 5-15-4】Half-Matrix Keypad 扫描子程序流程图 5-15-4 程序及流程图: 第五章 进阶实验篇 5-169 5 程序5-15 半矩阵式键盘与LCM控制程序 1 ;PROGRAM : 5-15.ASM (5-15.PJT) 2009.1109 2 ;FUNCTION: 16X2 LCD vs. HALF-MATRIX KEYPAD DEMO PROGRAM By Steven 3 #INCLUDE HT66F50.INC 4 #INCLUDE 5-15.INC 5 ;======================================================================================== 6 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 7 DEL1 DB ? ;DELAY LOOP COUNT 1 8 DEL2 DB ? ;DELAY LOOP COUNT 2 9 DEL3 DB ? ;DELAY LOOP COUNT 3 10 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 11 COUNT DB ? ;UNIVERSAL COUNTER 12 KEY_COUNT DB ? ;COLUMN COUNTER USED IN HALF_READKEY 13 COLUMN DB ? ;COLUMN SCAN CODE FOR KEY PAD 14 KEY DB ? ;KEY CODE REGISTER 15 KEY_PS DB ? 16 LCM_TEMP DB ? 17 LCM_AC DB ? 18 ;======================================================================================== 5-170 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 19 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 20 ORG 00H ;HT-66FX0 RESET VECTOR 21 CLR ACERL ;AD DISABLE 22 MOV A,08h 23 MOV CP0C,A ;CP0 DISABLE 24 MOV CP1C,A ;CP1 DISABLE 25 CLR LED_CAPITAL ;TURN-OFF LED 26 CLR LED_CAPITALC ;CONFIG LED_CAPITAL O/P MODE 27 CALL INIT_LCM 28 MAIN: MOV A,01H ;CLEAR DISPLAY 29 CALL WLCMCM 30 MOV A,80H ;SET LINE ONE, POSITION 0 31 CALL WLCMCM 32 WAIT_KEY: 33 CALL HALF_Readkey ;READ KEYPAD 34 MOV A,KEY 35 XOR A,28 36 SZ Z ;KEY PRESSED? 37 JMP WAIT_KEY ;NO, RE-READ KEYPAD 38 MOV A,KEY 39 SUB A,26 5 40 SZ Z 41 JMP MAIN ;IS "CLEAR" PRESSED? ;YES, JUMP MAIN 42 SDZ ACC ;IS "CAP" PRESSED? 43 JMP ALPHA_PRESSED ;NO. IT'S ALPHABETA KEY PRESSED 44 SNZ LED_CAPITAL ;IS CAPITAL ? 45 JMP $+3 ;NO. 46 CLR LED_CAPITAL ;YES.TURN_LED_CAPITAL_OFF 47 JMP $+2 48 SET LED_CAPITAL ;TURN_LED_CAPITAL_ON 49 CALL DELAY ;FOR DE-BOUNCING WHEN KEY PRESSED 50 JMP WAIT_KEY 51 ALPHA_PRESSED: 52 MOV A,LCM_AC ;READ LCM AC 53 XOR A,0FH 54 SNZ Z ;REACH LINE 1 ENDDING? 55 JMP CHECK_LINE2 ;NO. 56 MOV A,0C0H ;YES, SET LCD LINE 2, POSITION 0 57 CALL LCMClear1Line 58 MOV A,0C0H ;SET LCD LINE 2, POSITION 0 59 CALL WLCMCM 60 JMP DISPLAY 61 CHECK_LINE2: 62 MOV A,LCM_AC ;READ LCM AC 63 XOR A,4FH 64 SNZ Z ;REACH LINE 2 ENDDING? 65 JMP DISPLAY ;NO. 第五章 进阶实验篇 5-171 66 MOV A,080H ;YES, SET LCD LINE 1, POSITION 0 67 CALL LCMClear1Line 68 MOV A,080H ;SET LCD LINE 1, POSITION 0 69 CALL WLCMCM 70 DISPLAY: 71 MOV A,KEY ;GET KEY CODE 72 SNZ LED_CAPITAL ;IS CAPITAL? 73 ADD A,20H ;OFFSET OF ASCII "a" AND "A" 74 ADD A,41H ;ASCII OF "A" 75 CALL WLCMDM ;DISPLAY KEY IN DATA 76 CALL DELAY ;FOR DE-BOUNCING WHEN KEY PRESSED 77 JMP WAIT_KEY ;READ NEXT KEY 78 ;======================================================================================== 79 ; SCAN HALF MATRIX ON KEY PORT AND RETURN THE CODE IN KEY REGISTER 80 ; IF NO KEY BEEN PRESSED, KEY=28. 81 ;======================================================================================== 82 HALF_READKEY PROC 83 MOV A,01111111B 84 MOV COLUMN,A ;SET COLUMN FOR SCANNING 85 CLR KEY ;INITIAL KEY REGISTER 86 MOV A,7 87 MOV KEY_COUNT,A ;SET COUNTER=7 FOR 7 COLUMNS 88 SCAN_KEY: 5 89 MOV A,COLUMN ;GET COLUMN FOR SCANNING 90 MOV KEY_PORTC,A ;CONFIG KEY_PORT 91 MOV KEY_PORT,A ;SCANNING KEY PAD 92 MOV KEY_PORTPU,A ;SCANNING KEY PAD 93 MOV A,KEY_COUNT ;GET COLUMN COUNTER 94 ADDM A,PCL ;COMPUTATIONAL JUMP 95 NOP ;OFFSET FOR KEY_COUNT=0 96 JMP $+24 ;KEY_COUNT=1 97 JMP $+20 ;KEY_COUNT=2 98 JMP $+16 ;KEY_COUNT=3 99 JMP $+12 ;KEY_COUNT=4 100 JMP $+8 ;KEY_COUNT=5 101 JMP $+4 ;KEY_COUNT=6 102 SNZ KEY_PORT.6 ;KEY_COUNT=7,ROW 1 PRESSED? 103 RET ;YES. 104 INC KEY ;NO, INCREASE KEY CODE 105 SNZ KEY_PORT.5 ;ROW 2 PRESSED? 106 RET ;YES. 107 INC KEY ;NO, INCREASE KEY CODE 108 SNZ KEY_PORT.4 ;ROW 3 PRESSED? 109 RET ;YES. 110 INC KEY ;NO, INCREASE KEY CODE 111 SNZ KEY_PORT.3 ;ROW 4 PRESSED? 112 RET ;YES. 5-172 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 113 INC KEY ;NO, INCREASE KEY CODE 114 SNZ KEY_PORT.2 ;ROW 5 PRESSED? 115 RET ;YES. 116 INC KEY ;NO, INCREASE KEY CODE 117 SNZ KEY_PORT.1 ;ROW 6 PRESSED? 118 RET ;YES. 119 INC KEY ;NO, INCREASE KEY CODE 120 SNZ KEY_PORT.0 ;ROW 7 PRESSED? 121 RET ;YES. 122 INC KEY ;NO, INCREASE KEY CODE 123 RR COLUMN ;SCAN CODE FOR NEXT COLUMN 124 SDZ KEY_COUNT ;HAVE ALL COULMN BEEN CHECKED? 125 JMP SCAN_KEY ;NO, NEXT COLUMN 126 RET 127 HALF_READKEY ENDP 128 ;======================================================================================== 129 ; PROC : LCMClear1Line 130 ; FUNC : CLEAR 1 LINE LCM 131 ; REG : ACC MUST POINT TO START ADDRESS OF LINE 132 ;======================================================================================== 133 LCMClear1Line PROC 5 134 CALL WLCMCM 135 MOV A,16 136 MOV DEL1,A 137 MOV A,20H ;CLEAR LINE 2 138 CALL WLCMDM 139 SDZ DEL1 140 JMP $-2 141 RET 142 LCMClear1Line ENDP 143 ;======================================================================================== 144 ; PROC : INIT_LCM 145 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 146 ; REG : ACC 147 ;======================================================================================== 148 INIT_LCM PROC 149 CLR LCM_EN ;SET EN=0 150 CLR LCM_RW ;SET RW=0 151 CLR LCM_RS ;SET RS=0 152 CLR LCM_ENC ;CONFIG EN AS O/P MODE 153 CLR LCM_RWC ;CONFIG RW AS O/P MODE 154 CLR LCM_RSC ;CONFIG RS AS O/P MODE 155 156 MOV A,38H ;FUNCTION SET: 4-BIT,2-LINE,5X10 DOTS 157 CALL WLCMCM 158 MOV A,0CH ;ON/OFF CONTR: DISPLAY ON,CURSOR BLINKING OFF 159 CALL WLCMCM 第五章 进阶实验篇 5-173 160 MOV A,06H ;ENTRY MODE : INCREMENT,DISPLAY NOT SHIFT 161 CALL WLCMCM 162 MOV A,01H ;CLEAR DISPLAY 163 CALL WLCMCM 164 RET 165 INIT_LCM ENDP 166 ;======================================================================================== 167 ; PROC : WLCMDM/WLCMCM 168 ; FUNC : WRITE DATA/COMMAND TO LCM AND RETURN AC ADDRESS 169 ; PARA : ACC : COMMAND/DATA 170 ; REG : ACC,DC_FLAG,LCM_TEMP 171 ; RETN : LCM_AC : 1 BUSY BIT + 7-BIT AC 172 ;======================================================================================== 173 WLCMDM PROC 174 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 175 JMP $+2 176 WLCMCM: 177 CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 178 MOV LCM_TEMP,A 179 SET LCM_DATAPORTC ;CONFIG LCM_DATAPORT AS I/P MODE 180 CLR LCM_RS ;SET RS=0 (IR) 181 SET LCM_RW ;SET RW=1 (READ) 182 NOP ;FOR TAS 5 183 WF: SET LCM_EN ;SET EN=1 184 NOP ;FOR TDDR 185 MOV A,LCM_DATAPORT 186 MOV LCM_AC,A 187 CLR LCM_EN ;SET EN=0 188 SZ LCM_AC.7 ;IS LCM BUSY? 189 JMP WF ;YES, JUMP TO WAIT 190 CLR LCM_DATAPORTC ;NO, CONFIG LCM_DATAPORT AS O/P MODE 191 MOV A,LCM_TEMP 192 MOV LCM_DATAPORT,A ;LATCH DATA/COMMAND ON LCM_DATAPORT 193 CLR LCM_RW ;SET RW=0 (WRITE) 194 CLR LCM_RS ;SET RS=0 (IR) 195 SZ DC_FLAG ;IS COMMAND WRITE? 196 SET LCM_RS ;NO, SET RS=1 (DR) 197 SET LCM_EN ;SET EN=1 198 NOP ;FOR PWEN 199 CLR LCM_EN ;SET EN=0 200 RET 201 WLCMDM ENDP 202 ;======================================================================================== 203 ; PROC : DELAY 204 ; FUNC : DEALY ABOUT 20*10mS 205 ; REG : DEL1,DEL2,DEL3 206 ;======================================================================================== 5-174 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 207 DELAY PROC 208 MOV 209 MOV 210 DEL_1: MOV 211 MOV 212 DEL_2: MOV 213 MOV 214 DEL_3: SDZ 215 JMP 216 SDZ 217 JMP 218 SDZ 219 JMP 220 RET 221 DELAY ENDP 222 END A,20 DEL1,A A,30 DEL2,A A,110 DEL3,A DEL3 DEL_3 DEL2 DEL_2 DEL1 DEL_1 ;SET DEL2 COUNTER ;SET DEL3 COUNTER ;DEL3 DOWN COUNT ;DEL2 DOWN COUNT ;DEL1 DOWN COUNT 程程序序说说明明:: 4 载入”5-15.INC”定义档,其内容请参考随书光盘中的档案。 5 7~17 依序定义变量地址。 20 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 21~24 关闭 CP0、CP1 功能,并设定 ADC 脚位输入为 I/O 功能。 25~26 定义 LED_CAPITAL 为输出模式,并设定 LED_CAPITAL=“0”(Default 为大写 字型),并点亮代表大写字型的 LED。 27 调用 INIT_LCM 子程序,对 LCM 进行定义。 28~31 将 LCM 整个显示器清空,并将光标位置设为第一列首行。 32~37 检查键盘是否压下,若未压下则持续等待;若压下,则依键值的不同进行个别程序。 38~41 判断是否压下“Clear”键,若是则跳至 MAIN 清除 LCM 并将光标归位。 42~50 判断是否压下“CAP”键,若是,则将 LED_CAPITAL 状态反向并延迟 200ms 后 继续检查键盘状态(JMP WAIT_KEY);若不是则跳至 ALPHA_PRESSED 显示按 键值。 52~69 此段程序主要是判断 LCM 显示器是否已经显示到第一列或第二列的最后一个位置。 主要是利用 LCM_AC 寄存器的值进行判断(即 LCM 目前的 AC 值),52~59 行是 检查是否到达第一列的最后一个位置(本实验所采用的是 16×2 的 LCM),若是则 将第二列先予以清除,并设定 LCM DD RAM 的地址为第二行第零个位置,因此输 入的字符会改由 LCM 的第二列开始显示。62~69 行则是检查是否到达第二列的最 第五章 进阶实验篇 5-175 后一个位置(40h+16),若是则将第一列先予以清除,并设定 LCM DD RAM 地址 为第一列第零个位置,因此输入的字符会改由 LCM 的第一列开始显示。 71~75 将 按 键 值 转 换 为 ASCII 码 并 调 用 WLCMDM 子 程 序 予 以 显 示 ; 期 间 会 以 LED_CAPITAL 的状态判断目前为大写模式(LED_CAPITAL=“1”)或小写模式 (LED_CAPITAL=“0”),以便转换为大写或小写的 ASCII 码(PS.大小写英文 字型的 ASCII 码相差 20h)。 76~77 调用 DELAY 子程序,延迟 0.2 秒后重新扫描按键(JMP WAIT_KEY);延迟时间 的计算请参考【实验 4-1】。 82~127 HALF_READKEY 子程序,请参考【5-12-3 节】的说明。 133~142 LCMClear1Line 子程序,根据 ACC 指定的地址,连续填入十六个空白码(即 20h) 至 DDRAM。若 ACC 是指向第一列或第二列首行位置,则此举即是清除 LCM 的第 一列或第二列。 148~165 INIT_LCM 子程序,其功能是对 LCM 进行定义: 149~154 LCM_EN、LCM_RW 与 LCM_RS 定义为输出模式,并设定状态为“0”。 156~157 将 LCM 设定为双行显示(N = 1)、使用八位(DB7 ~ DB0)控制模式(DL = 1)、 5 5×7 点矩阵字型(F = 0)。 158~160 将 LCM 设定为显示所有数据(D = 1)、显示光标(C = 1)、光标所在位置不闪烁 (B = 0);LCM 的地址计数器(AC)设为递加(I/D = 1)、显示器画面不因读写 数据而移动(S = 0)。 161~162 将 LCM 整个显示器清空。 173~200 WLCMDM 与 WLCMCM 子程序,请参考【实验 5-6】的说明。 206~220 DELAY 子程序,延迟 0.2 秒;延迟时间的计算请参考【实验 4-1】。 由于只有28个按键,为了能够区分出大小写字母,所以将按键“S27”定义为 大/小写设定键(其功能就如PC键盘上的“Caps Lock”按键),并搭配LED_CAPITAL 的状态,决定“S0”~“S25”等26个按键究竟为大写或小写字符。如此尚剩下一 个按键“S26”,就索性将它定义为LCM的屏幕清除功能按钮。 半矩阵式键盘与4×4矩阵式键盘相较,同样是使用一个I/O Port,但前者足足多 出了12个按键数,程序代码虽然多出了几行,但并不是太复杂,读者历经了近三十 个实验单元的磨练,应该可以洞悉其工作原理才是。 5-176 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-15-5 动动脑+动动手: 请将“Clear”按键(“S26”)-“LCM 屏幕清除功能”更改为“Num Lock” 功能。也就是说通过“Num Lock”键的控制,可以选择英文字/数字模式,在 数字模式下除了可以显示“0”~“9”之外,并且还能显示“!”、“@”、“$”… 等特殊符号。 5 5-177 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-16 HT66F50内建E2PROM内存读写实验 内存也称为寄存器,是一种利用半导体技术做成的电子设备,用来储存数据。 电子电路以二进制存取数据,而内存的每一个储存单元称做储存元或储存胞 (Cell)。根据储存能力与电源的关系可概略分为两类:“挥发性内存”与“非挥 发性内存”。“挥发性(Volatile)”内存是指当电源供应中断后,内存所储存的 数据便会消失,一般称为“RAM(Random Access Memory)”;有两种主要的 类型:“DRAM(动态随机存取内存,Dynamic RAM)”以及“SRAM(静态随 机存取内存,Static RAM)”。“非挥发性(Non-Volatile)”内存即使其电源供 应中断,内存所储存的数据并不会消失,重新供电后,仍旧能取得断电前所存的数 据。种类可约略分为以下几种: ROM(Read-Only Memory,只读存储器):是一种只能读取数据的内存。在 制造过程中,将数据以一特制光罩(Mask)烧录于线路中,其数据内容在写 入后就不能更改,所以有时又称为“光罩式只读存储器”(Mask ROM)。 此内存的制造成本较低,常用于计算机中的开机启动。 PROM (Programmable ROM,可规化式只读存储器):其内部有行列式的 5 镕丝,可依使用者(厂商)的需要利用电流将其烧断,以写入所需的数据及 程序,一经烧录便无法再更改。 EPROM (Erasable Programmable ROM,可擦可规化式只读存储器):可 利用高电压将数据编程写入,抹除时将线路曝光于紫外线下,则数据可被清 空,并且可重复使用,通常在封装外壳上会预留一个石英透明窗以方便曝光。 OTP ROM (One Time Programmable ROM;OTP,可单次规化式只读存储 器):写入原理同EPROM,但是为了节省成本,数据写入之后就不再抹除, 因此不设置透明窗。 E2PROM(Electrically Erasable Programmable ROM,可电气抹除可规化式 只读存储器):运作原理类似EPROM,但是抹除的方式是使用高电场来完成, 因此不需要透明窗。 Flash memory (闪存):每一个储存胞都具有一个“控制闸”与“浮动闸”, 利用高电场改变浮动闸的临限电压即可进行写入动作。 由于E2PROM断电后仍可保存数据的特性,因此被广泛运用于各类电子产品 中。而串行接口的E2PROM仅需2~3支的I/O引脚即可完成数据保存、读取的动作, 更 适 用 于 I/O 资 源 弥 足 珍 贵 的 单 片 机 。 目 前 市 面 上 常 见 的 串 行 存 取 式 ( Serial Access)E2PROM的控制接口有以下四种方式:I2C-BUS、XI2C-BUS、SPI-BUS、 MicroWire-BUS,现将其特性简述如下: I2C-BUS:为飞利浦(Philips)公司所设计的串行总线接口,当初是针对消费 性应用产品所设计的标准界面,只需两条控制线就可达成数据传输的目的。 5-178 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 除了内存设备之外,目前许多设备都配备了I2C-BUS的传输接口。I2C-BUS的 寻 址 能 力 只 有 16K-Bit , 总 线 的 传 输 速 度 最 高 只 到 100KHz 。 而 XI2C-BUS (Extended I2C-BUS)将寻址能力提高到了4M-Bit,总线传输速度也提升到 400KHz,新的版本更已经提升到3.4MHz; SPI-BUS:Serial Peripheral Interface Bus,最早是由Motorola公司所提出的 三线式(Data Out、Data In、Clock)串行总线传输接口,但后来是由ST以 及其它公司将其整合至单片机内部,作为数据传输的独立接口单元,总线传 输速度上限为5MHz; MicroWire-BUS:由National Semiconductor所发展的串行总线传输接口,如 同SPI-BUS是以四条控制线(CS、Data Out、Data In、Clock)完成数据传 输的动作,其总线传输速度上限为1MHz。 这几种串行传输接口主要差异在于总线尺寸、总线通信协议(Bus Protocol)、 噪 声 抗 扰 性 ( Noise Immunity) 以 及 存 取 时 间 。 其 中 又 以 I2C ( Inter IC ) 与 MicroWire-BUS的应用最为广泛,因此本实验将介绍这两种接口的控制方式。串行 数据存取比并列数据存取的传送数据速度慢,但是因为所使用的I/O脚数极少,因 此当传输速度要求不是太快而I/O脚数又受限时(如小型的单芯片单片机),采用 5 此类接口可说是最正确的选择。 本实验先就HT66F50内建E2PROM的存取控制,后续的两个实验再分别以 HT24LC16与HT93C46为例,说明I2C与MicroWire-BUS两种接口E2PROM的控制 方式,以便若HT66F50内建的E2PROM不够使用时,可以采取在其外部扩充的方式 为之。不过谈到IC的控制,就必定得涉及时序的探讨;若是读者仅想直接应用而无 暇深入了解,可以直接调用实验中所提供的子程序。 5-16-1 目 的: 以4x4键盘为输入设备选择程序功能: 储存输入数值(0~9)至HT66F50内 建的E2PROM, 读出储存于HT66F50内建的E2PROM的数据,并显示于LCM上。 5-16-2 学习重点: 通过本实验,读者应熟悉HT66F50内建E2PROM的读、写控制方式与LCM的 显示技巧。 5-16-3 电路图: 第五章 进阶实验篇 5-179 PS:若使能PA[7:4]Pull-high功能,则10kΩ电阻可省略。 【图 5-16-1】HT66F50 内建 E2PROM 读/写实验电路 HT66F50内建256×8 Bits的非易失性内存(E2PROM Data Memory),可用 来储存系统断电后仍需保留的数据。E2PROM Data Memory的读、写,必须通过 EECTL、EEADDR与EEDATA三个特殊功能寄存器的控制达成,请参阅【2-3-11 节】有关这些特殊功能寄存器的详细介绍,在此仅将其列出,提供读者参考;要特 别留意的是EECTL控制寄存器是属于Bank1的内存位置。 【表 5-16-1】本实验相关控制寄存器 EEA EEA7 EEA6 EEA5 EEA4 EEA3 EEA2 EEA1 EEA0 5 【2-3-11 节】 EED EED7 EED6 EED5 EED4 EED3 EED2 EED1 EC1I EEC - - - - WETN WT RDEN RD Bit 7 6 5 4 3 2 1 0 本范例程序首先要求使用者输入功能选项,即 “WR”:写入数据至E2PROM; 或 “RD”:由E2PROM读出数据,可再指定是读取特定地址或E2PROM所有地 址的内容。选择写入模式时,使用者最多可输入十五个“0”~“9”的数字,当按 下“Enter”键后即将输入值存入E2PROM中。 5-180 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-16-4 程序及流程图: 5 第五章 进阶实验篇 5-181 5 程序5-16 HT66F50内建E2PROM读写控制实验 1 ; PROGRAM : 5-16.ASM (5-18.PJT) 2 ; FUNCTION: HT66F50 EEPROM READ/WRITE DEMO PROGRAM 3 #INCLUDE HT66F50.INC 4 #INCLUDE 5-16.INC 2009.1111 By Steven 5-182 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5 ;======================================================================================== 6 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 7 DEL1 DB ? ;DELAY LOOP COUNT 1 8 DEL2 DB ? ;DELAY LOOP COUNT 2 9 DEL3 DB ? ;DELAY LOOP COUNT 3 10 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 11 LCM_TEMP DB ? ;BUFFER FOR LCM PROCEDURE 12 LCM_AC DB ? 13 KEY DB ? ;BUFFER FOR READ_KEY PROCEDURE 14 KEY_COUNT DB ? ;BUFFER FOR READ_KEY PROCEDURE 15 KEY_PS DB ? ;BUFFER FOR READ_KEY_PRESSED PROCEDURE 16 COUNT DB ? 17 BUFFER DB 16 DUP(?) 18 BP_BACKUP DB ? 19 ;======================================================================================== 20 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 21 ORG 00H ;HT-46F23 RESET VECTOR 22 CLR ACERL ;AD DISABLE 23 MOV A,08h 24 MOV CP0C,A ;CP0 DISABLE 25 MOV CP1C,A 5 26 CALL INIT_LCM 27 MAIN: MOV A,01H ;CP1 DISABLE ;SET LCM LINE 1 28 CALL WLCMCM 29 MOV A,STR_1 ;PRINT STR_1 30 CALL PRINT 31 MOV A,0C0H ;SET LCM LINE 2 32 CALL WLCMCM 33 MENU_1:CALL READ_KEY_PRESSED ;GET MENU SELECT 1~2 34 XOR A,0 ;"0" PRESSED ? 35 SZ Z 36 JMP MENU_1 ;YES 37 SUB A,3 ;NO. "3"-"F" PRESSED ? 38 SZ C 39 JMP MENU_1 ;YES. 40 MOV A,01H ;NO. CLEAR DISPLAY 41 CALL WLCMCM 42 DECA KEY_PS 43 ADDM A,PCL ;COMPUTATIONAL JUMP 44 JMP DOWRITE ;"1" PRESSED -> WRITE 45 JMP DOREAD ;"2" PRESSED -> READ 46 DOWRITE: 47 MOV A,STR_4 ;PRINT STR_4 48 CALL PRINT 49 MOV A,0C0H 50 CALL WLCMCM 51 MOV A,STR_5 ;PRINT STR_5 52 CALL 53 CALL 54 MOV 55 MOV 56 MOV 57 CALL 58 MOV 59 CALL 60 MOV 61 CALL 62 MOV 63 CALL 64 CALL 65 MOV 66 XOR 67 SZ 68 JMP 69 MOV 70 CALL 71 MOV 72 CALL 73 MOV 74 MOV 75 DOWRITE_1: 76 MOV 77 MOV 78 CALL 79 INC 80 INC 81 SDZ 82 JMP 83 MOV 84 CALL 85 JMP 86 DOREAD: 87 MOV 88 CALL 89 DOREAD_0: 90 CALL 91 XOR 92 SZ 93 JMP 94 MOV 95 XOR 96 SNZ 97 JMP 98 DOREAD_1: PRINT GET2KEYS A,BUFFER[0] EEA,A A,80 DELAY A,01H WLCMCM A,STR_2 PRINT A,0C0H WLCMCM GETKEYS A,BUFFER[0] A,0 Z MAIN A,01H WLCMCM A,STR_6 PRINT A,OFFSET BUFFER[1] MP0,A A,IAR0 EED,A WRITE MP0 EEA BUFFER[0] DOWRITE_1 A,50 DELAY MAIN A,STR_3 PRINT READ_KEY_PRESSED A,2 Z DOREAD_2 A,KEY_PS A,1 Z DOREAD_0 第五章 进阶实验篇 5-183 ;GET SELECT ADDRESS ;SET READ ARSE_REG ;DELAY 0.8 SEC ;CLEAR DISPLAY ;PRINT STR_2 ;SET LCM LINE 2 ;GET KEYPAD INPUT CODE ;TEST IF NULL INPUT ;YES, RESTART MENU SELECT ;NO. CLEAR DISPLAY ;PRINT STR_6 5 ;GET DATA BYTE ;WRITE ONE BYTE ;UPDATE POINTER ;UPDATE POINTER ;COUNT-1 = 0 ? ;NO,NEXT BYTE ;DELAY 0.5 SEC ;RESTART MENU SELECT ;PRINT STR_3 ;GET MENU SELECT 1 OR 2 ;READ ALL? ;READ SPECIFIED ADDRESS? ;SELECCT SPECIFIED ADDRESS 5-184 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 99 MOV A,01H 100 CALL WLCMCM 101 MOV A,STR_4 ;PRINT STR_4 102 CALL PRINT 103 MOV A,0C0H 104 CALL WLCMCM 105 MOV A,STR_5 ;PRINT STR_5 106 CALL PRINT 107 CALL GET2KEYS ;GET SELECT ADDRESS 108 MOV A,BUFFER[0] ;YES. 109 MOV EEA,A ;SET READ ADDRESS 110 CALL READ ;READ 1 BYTE FROM EEPROM 111 MOV A,STR_7 ;PRINT STR_7 112 CALL PRINT 113 SWAPA EED ;GET READ DATA 114 CALL NIBBLE2ASCII ;COVERT HIGH NIBBLE TO ASCII 115 CALL WLCMDM ;DISPLAY 116 MOV A,EED ;GET READ DATA 117 CALL NIBBLE2ASCII ;COVERT LOW NIBBLE TO ASCII 118 CALL WLCMDM ;DISPLAY 119 CALL READ_KEY_PRESSED ;WAIT PRESS ANY KEY TO CONTINUE 5 120 JMP MAIN 121 DOREAD_2: 122 CLR EEA ;RESET READ_ADRS 123 DOREAD_3: 124 MOV A,EEA ;SET START ADDRESS TO BUFFER[0] 125 MOV BUFFER[0],A 126 MOV A,8 ;SET COUNT=8 127 MOV COUNT,A 128 MOV A,OFFSET BUFFER[1] ;SET BUFFER POINTER 129 MOV MP0,A 130 DOREAD_4: 131 CALL READ ;READ BYTE 132 MOV A,EED ;GET READ DATA 133 MOV IAR0,A 134 INC EEA ;UPDATE READPOINTER 135 INC MP0 ;UPDATE BUFFER POINTER 136 SDZ COUNT ;COUNT-1 = 0 ? 137 JMP DOREAD_4 ;NO,READ NEXT BYTE 138 MOV A,OFFSET BUFFER[1] ;YES, SET BUFFER POINTER 139 MOV MP0,A 140 MOV A,01H ;CLEAR LCM 141 CALL WLCMCM 142 CALL BUFFER_DISPLAY ;DISPLAY 4 BYTE DATA IN HEX FORMAT 143 MOV A,4 144 ADDM A,BUFFER[0] ;UPDATE START ADDRESS 145 MOV A,0C0H ;SET LCM AC ADDRESS 第五章 进阶实验篇 5-185 146 CALL WLCMCM 147 CALL BUFFER_DISPLAY ;DISPLAY 4 BYTE DATA IN HEX FORMAT 148 DOREAD_5: 149 CALL READ_KEY;_PRESSED 150 151 MOV A,KEY 152 XOR A,16 153 SZ Z 154 JMP DOREAD_5 155 MOV A,25 156 CALL DELAY 157 MOV A,KEY 158 SUB A,0DH 159 SNZ C ;UP/DN/ENTER KEY PRESSED ? 160 JMP DOREAD_5 ;NO. WAIT 161 ADDM A,PCL ;YES. 162 JMP DOREAD_3 ;UP-KEY 163 JMP DOREAD_DN ;DOWN-KEY 164 JMP MAIN ;ENTER/EXIT KEY 165 DOREAD_DN: 166 MOV A,EEA ;UPDATE EEA 167 SUB A,16 168 MOV EEA,A 5 169 JMP DOREAD_3 170 ;======================================================================================== 171 ; PROC : BUFFER_DISPLAY 172 ; FUNC : DISPLAY BUFFER[0] AND 4-BYTE CONTENTS SPECIFIED BY MP0 IN HEX MODE 173 ; REG : ACC,LCM_ADRS,COUNT 174 ;======================================================================================== 175 BUFFER_DISPLAY PROC 176 SWAPA BUFFER[0] 177 CALL NIBBLE2ASCII ;CONVERT HIGH BYTE TO ASCII 178 CALL WLCMDM 179 MOV A,BUFFER[0] ;CONVERT HIGH BYTE TO ASCII 180 CALL NIBBLE2ASCII 181 CALL WLCMDM 182 MOV A,2DH ;"-" 183 CALL WLCMDM 184 MOV A,4 185 MOV COUNT,A 186 BUFFER_DISPLAY_1: 187 MOV A,20H ;" " 188 CALL WLCMDM 189 SWAPA IAR0 ;CONVERT HIGH BYTE TO ASCII 190 CALL NIBBLE2ASCII 191 CALL WLCMDM 192 MOV A,IAR0 ;CONVERT HIGH BYTE TO ASCII 5-186 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 193 CALL NIBBLE2ASCII 194 CALL WLCMDM 195 INC MP0 ;UPDATE POINTER 196 SDZ COUNT ;COUNT-1 = 0? 197 JMP BUFFER_DISPLAY_1 ;NO, DISPLAY NEXT BYTE 198 RET ;YES. 199 BUFFER_DISPLAY ENDP 200 ;======================================================================================== 201 ; PROC : NIBBLE2ASCII 202 ; FUNC : CONVERT LOW NIBBLE TO ASCII CODE 203 ; REG : ACC 204 ; RETN : ACC 205 ;======================================================================================== 206 NIBBLE2ASCII PROC 207 AND A,0FH ;MASK HIGH NIBBLE 208 SUB A,10 ;CODE > 9 ? 209 SZ C 210 ADD A,40H-30H-9 ;YES, ADD OFFSET FROM "9" TO "A" 211 ADD A,30H+10 ;NO. 212 RET 213 NIBBLE2ASCII ENDP 5 214 ;======================================================================================== 215 ; PROC : READ 216 ; FUNC : READ 1 BYTE DATA FORM EEPROM 217 ; PARA : EEA : SPECIFIED ADDRESS 218 ; REG : ACC 219 ; RETN : EED : DATA READ FROM SPECIFIED ADDRESS 220 ;======================================================================================== 221 READ PROC 222 MOV A,040H ;SET EEC ADDRESS 223 MOV MP1,A 224 MOV A,BP ;BACK UP BP 225 MOV BP_BACKUP,A 226 MOV A,01H ;SELECT RAM BANK 1 227 MOV BP,A 228 SET IAR1.1 ;SET RDEN 229 SET IAR1.0 ;SET RD TO START READ 230 SZ IAR1.0 ;WAIT FOR READING 231 JMP $-1 232 CLR IAR1 ;DISABLE EEPROM READ/WRITE 233 MOV A,BP_BACKUP ;RESTORE BP 234 MOV BP,A 235 RET 236 READ ENDP 237 ;======================================================================================== 238 ; PROC : WRITE 239 ; FUNC : WRITE 1 BYTE DATA TO EEPROM 第五章 进阶实验篇 5-187 240 ; PARA : EEA : SPECIFIED ADDRESS 241 ; : EED : DATA TO BE WRITTEN 242 ; REG : ACC 243 ;======================================================================================== 244 WRITE PROC 245 MOV A,040H ;SET EEC ADDRESS 246 MOV MP1,A 247 MOV A,BP ;BACK UP BP 248 MOV BP_BACKUP,A 249 MOV A,01H ;SELECT RAM BANK 1 250 MOV BP,A 251 SET IAR1.3 ;SET WREN 252 SET IAR1.2 ;SET WR TO START WRITE 253 SZ IAR1.2 ;WAIT FOR WRITTING 254 JMP $-1 255 CLR IAR1 ;DISABLE EEPROM READ/WRITE 256 MOV A,BP_BACKUP ;RESTORE BP 257 MOV BP,A 258 RET 259 WRITE ENDP 260 ;======================================================================================== 261 ; PROC : GET2KEYS 262 ; FUNC : GET 2 HEX DIGITS KEY AND DISPLAY, THEN 2 DIGITS COMBINE TO ONE BYTE 5 263 ; REG : ACC,MP0,IAR0, BUFFER[0~1] 264 ; CALL : READ_KEY_PRESSED, WLCMD_4 265 ; RETN : BUFFER[0] : COMBIBE HEX KEY CODE 266 ;======================================================================================== 267 GET2KEYS PROC 268 CALL READ_KEY_PRESSED ;GET KEY 0~F 269 MOV BUFFER[0],A 270 CALL NIBBLE2ASCII ;CONVERTTO ASCII 271 CALL WLCMDM ;LCM DISPLAY 272 CALL READ_KEY_PRESSED ;GET KEY 0~F 273 SWAP BUFFER[0] 274 ORM A,BUFFER[0] 275 CALL NIBBLE2ASCII ;CONVERTTO ASCII 276 CALL WLCMDM ;LCM DISPLAY 277 RET 278 GET2KEYS ENDP 279 ;======================================================================================== 280 ; PROC : GETKEYS 281 ; FUNC : READ MULTIPLE KEY INPUT(0~9) UNTIL "ENTER" PRESSED OR COUNT > 15 282 ; REG : ACC,MP0,IAR0, BUFFER[0~15] 283 ; CALL : READ_KEY_PRESSED 284 ; RETN : BUFFER[0] : THE NUMBER OF KEY INPUT 285 ; : BUFFER[1~15] : INPUT KEY CODE 286 ;======================================================================================== 5-188 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 287 GETKEYS PROC 288 MOV A,OFFSET BUFFER[1] 289 MOV MP0,A 290 CLR BUFFER[0] 291 GETKEY_1: 292 CALL READ_KEY_PRESSED ;GET KEY 0~9 AND ENTER 293 XOR A,0FH 294 SZ Z 295 RET 296 MOV A,KEY_PS 297 SUB A,10 298 SZ C 299 JMP GETKEY_1 300 MOV A,KEY_PS 301 MOV IAR0,A 302 ADD A,30H ;CONVERTTO ASCII 303 CALL WLCMDM ;LCM DISPLAY 304 INC MP0 305 INC BUFFER[0] ;KEY COUNT+1 306 MOV A,BUFFER[0] 307 XOR A,16 5 308 SNZ Z 309 JMP GETKEY_1 310 RET 311 GETKEYS ENDP 312 ;======================================================================================== 313 ; PROC : READ_KEY_PRESSED 314 ; FUNC : SCAN 4x4 MATRIX ON KEY_PORT UNTIL KEY PRESSED, AND RETURN THE PRESSED KEY 315 ; NUMBER AFTER KEY RELEASED. 316 ; REG : ACC,KEY_PS 317 ; CALL : DELAY 318 ; RETN : A AND KEY_PS(0~F FOR PRESSED KEY NUMBER) 319 ;======================================================================================== 320 READ_KEY_PRESSED PROC 321 CALL READ_KEY ;SCAN KEYPAD 322 MOV A,16 323 XOR A,KEY 324 SZ Z ;IS KEY BEEN PRESSED? 325 JMP READ_KEY_PRESSED ;NO, RE-SCAN KEYPAD 326 MOV A,KEY 327 MOV KEY_PS,A ;RESERVED KEY CODE 328 MOV A,5 329 CALL DELAY ;DELAY 50mS 330 WAIT_KEY_RELEASED: 331 CALL READ_KEY ;SCAN KEYPAD 332 MOV A,16 333 XOR A,KEY 第五章 进阶实验篇 5-189 334 SZ ACC ;IS KEY BEEN RELEASED? 335 JMP WAIT_KEY_RELEASED ;NO, RE-SCAN KEYPAD 336 MOV A,5 337 CALL DELAY ;DELAY 50mS 338 MOV A,KEY_PS 339 RET 340 READ_KEY_PRESSED ENDP 341 ;======================================================================================== 342 ; PROC : READ_KEY 343 ; FUNC : SCAN 4x4 MATRIX ON KEY PORT AND RETURN THE CODE IN KEY REGISTER 344 ; REG : ACC,KEY_COUNT 345 ; RETN : KEY(0~F FOR PRESSED KEY NUMBER, IF NO KEY BEEN PRESSED, KEY=10h.) 346 ;======================================================================================== 347 READ_KEY PROC 348 MOV A,11110000B 349 MOV KEY_PORTC,A ;CONFIG KEY_PORT 350 MOV KEY_PORTPU,A ;CONFIG KEY_PORT PULL-HIGH 351 SET KEY_PORT ;INITIAL KEY PORT 352 CLR KEY ;INITIAL KEY REGISTER 353 MOV A,04 354 MOV KEY_COUNT,A ;SET ROW COUNTER 355 CLR C ;CLEAR CARRY FLAG 356 SCAN_KEY: 5 357 RLC KEY_PORT ;ROTATE SCANNING BIT 358 SET C ;MAKE SURE C=1 359 SNZ KEY_PORT.4 ;COLUMN 0 PRESSED? 360 JMP END_KEY ;YES. 361 INC KEY ;NO, INCREASE KEY CODE. 362 SNZ KEY_PORT.5 ;COLUMN 1 PRESSED? 363 JMP END_KEY ;YES. 364 INC KEY ;NO, INCREASE KEY CODE. 365 SNZ KEY_PORT.6 ;COLUMN 2 PRESSED? 366 JMP END_KEY ;YES. 367 INC KEY ;NO, INCREASE KEY CODE. 368 SNZ KEY_PORT.7 ;COLUMN 3 PRESSED? 369 JMP END_KEY ;YES. 370 INC KEY ;NO, INCREASE KEY CODE. 371 SDZ KEY_COUNT ;HAVE ALL ROWs BEEN CHECKED? 372 JMP SCAN_KEY ;NO, NEXT ROW. 373 END_KEY:RET 374 READ_KEY ENDP 375 ;======================================================================================== 376 ; PROC : PRINT 377 ; FUNC : PRINT THE STRING POINTED BY ACC AT LCM CURRENT ADRESS . STRING MUST END WITH 0 378 ; PARA : ACC : POINTER FOR STRING START ADDRESS (LAST PAGE) 379 ; REG : TBLP 380 ;======================================================================================== 5-190 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 381 PRINT PROC 382 MOV TBLP,A ;LOAD TABLE POINTER 383 PRINT_1:TABRDL ACC ;READ STRING 384 XOR A,NULL 385 SZ Z ;END OF STRING CHARACTER? 386 RET ;YES, STOP PRINT 387 TABRDL ACC ;NO, RE-READ 388 CALL WLCMDM ;SEND TO LCD 389 INC TBLP ;INCREASE DATA POINTER 390 JMP PRINT_1 ;NEXT CHARACTER 391 PRINT ENDP 392 ;======================================================================================== 393 ; PROC : INIT_LCM 394 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 395 ; REG : ACC 396 ;======================================================================================== 397 INIT_LCM PROC 398 CLR LCM_EN ;SET EN=0 399 CLR LCM_RW ;SET RW=0 400 CLR LCM_RS ;SET RS=0 401 CLR LCM_ENC 5 402 CLR LCM_RWC 403 CLR LCM_RSC ;CONFIG EN AS O/P MODE ;CONFIG RW AS O/P MODE ;CONFIG RS AS O/P MODE 404 405 MOV A,38H ;FUNCTION SET: 4-BIT,2-LINE,5X10 DOTS 406 CALL WLCMCM 407 MOV A,0CH ;ON/OFF: DISPLAY ON,CURSOR BLINKING OFF 408 CALL WLCMCM 409 MOV A,06H ;ENTRY MODE : INCREMENT,DISPLAY NOT SHIFT 410 CALL WLCMCM 411 MOV A,01H ;CLEAR DISPLAY 412 CALL WLCMCM 413 RET 414 INIT_LCM ENDP 415 ;======================================================================================== 416 ; PROC : WLCMDM/WLCMCM 417 ; FUNC : WRITE DATA/COMMAND TO LCM AND RETURN AC ADDRESS 418 ; PARA : ACC : COMMAND/DATA 419 ; REG : ACC,DC_FLAG,LCM_TEMP 420 ; RETN : LCM_AC : 1 BUSY BIT + 7-BIT AC 421 ;======================================================================================== 422 WLCMDM PROC 423 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 424 JMP $+2 425 WLCMCM: 426 CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 427 MOV LCM_TEMP,A 第五章 进阶实验篇 5-191 428 SET LCM_DATAPORTC ;CONFIG LCM_DATAPORT AS I/P MODE 429 CLR LCM_RS ;SET RS=0 (IR) 430 SET LCM_RW ;SET RW=1 (READ) 431 NOP ;FOR TAS 432 WF: SET LCM_EN ;SET EN=1 433 NOP ;FOR TDDR 434 MOV A,LCM_DATAPORT 435 MOV LCM_AC,A 436 CLR LCM_EN ;SET EN=0 437 SZ LCM_AC.7 ;IS LCM BUSY? 438 JMP WF ;YES, JUMP TO WAIT 439 CLR LCM_DATAPORTC ;NO, CONFIG LCM_DATAPORT AS O/P MODE 440 MOV A,LCM_TEMP 441 MOV LCM_DATAPORT,A ;LATCH DATA/COMMAND ON LCM_DATAPORT 442 CLR LCM_RW ;SET RW=0 (WRITE) 443 CLR LCM_RS ;SET RS=0 (IR) 444 SZ DC_FLAG ;IS COMMAND WRITE? 445 SET LCM_RS ;NO, SET RS=1 (DR) 446 SET LCM_EN ;SET EN=1 447 NOP ;FOR PWEN 448 CLR LCM_EN ;SET EN=0 449 RET 450 WLCMDM ENDP 5 451 ;======================================================================================== 452 ; PROC : DELAY 453 ; FUNC : DEALY ABOUT ACC*10mS 454 ; PARA : ACC : DELAY FACTOR 455 ; REG : DEL1,DEL2,DEL3 456 ;======================================================================================== 457 DELAY PROC 458 MOV DEL1,A ;SET DEL1 COUNTER 459 DEL_1: MOV A,30 460 MOV DEL2,A ;SET DEL2 COUNTER 461 DEL_2: MOV A,110 462 MOV DEL3,A ;SET DEL3 COUNTER 463 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 464 JMP DEL_3 465 SDZ DEL2 ;DEL2 DOWN COUNT 466 JMP DEL_2 467 SDZ DEL1 ;DEL1 DOWN COUNT 468 JMP DEL_1 469 RET 470 DELAY ENDP 471 ORG LASTPAGE 472 STR_1: DC '1.WRITE 2.READ',NULL ;STRING DEFINE 1 473 STR_2: DC 'WR: PRESS 0-9, ENTER',NULL ;STRING DEFINE 2 474 STR_3: DC 'SELECT 1)ADDRS 2)ALL',NULL ;STRING DEFINE 3 5-192 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 475 STR_4: DC 476 STR_5: DC 477 STR_6: DC 478 STR_7: DC 479 END 'I/P ADDRS(2-DIG HEX)',NULL 'ADDRS=>',0 'EEPROM WRITTING.....',NULL ' DATA=',NULL ;STRING DEFINE 4 ;STRING DEFINE 5 ;STRING DEFINE 6 ;STRING DEFINE 7 程程序序说说明明:: 4 载入”5-16.INC”定义档,其内容请参考随书光盘中的档案。 7~18 依序定义变量地址。 21 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 22~25 关闭 CP0、CP1 功能,并设定 ADC 脚位输入为 I/O 功能。 26 调用 INIT_LCM 子程序,对 LCM 进行定义。 27~32 将 LCM 整个显示器清空,并将光标位置设为第一列首行;其次在 LCM 第一、第二 列分别显示"1.WRITE 2.READ" 、” PRESS 0-9, ENTER"信息提示使用者进 行功能选择。 5 33~45 46~85 47~52 检查键盘的“1”、“2”按键是否压下,若未压下或压下为其它按键则持续等待; 若压下“1”或“2”按键,则依键值的不同进行个别程序:DOWRITE 或 DOREAD。 此段程序是压下“1”按键的处理程序;即使用者选择“WRITE”功能,欲将数据 写入 E2PROM。请参考下列各细项的说明: 在 LCM 第一、第二列分别显示"I/P ADDRS(2-DIG HEX)" 、” ADDRS=>"信息, 提示使用者输入两位数的十六进制数值,指定所欲写入 E2PROM 的地址。 53~57 58~63 调用 GET2KEYS 子程序读取使用者输入的地址信息,将其暂存于 EEA 寄存器,并 调用 DELAY 子程序延迟 0.8 秒。 在 LCM 第一列显示"WR: PRESS 0-9, ENTER"信息,提示使用者输入 0~9 的数 值,输入的数值稍后将写入至 E2PROM。同时将 LCM DDRAM 地址设为第二列首 行。 第五章 进阶实验篇 5-193 64 65~68 70~72 调用 GETKEYS 子程序读取使用者输入的数据;此数据将存入 BUFFER[]数组并显 示于 LCM 第二列,BUFFER[0]代表使用者输入的数字总数。 判断使用者是否输入按键,若 BUFFER[0]为零表示使用者为输入数字,故跳至 MAIN 重新选项选择的程序。 清除 LCM 并于第一列显示"EEPROM WRITTING....."信息,表示准备开始数据写 入 E2PROM 的程序。 73~82 搭配间接寻址法,将 BUFFER[]数组中的数值逐一写入 E2PROM(调用 WRITE 子 程序)。 78~85 调用 DELAY 子程序延迟 0.5 秒,随即跳至 MAIN 重新选项选择的程序。 86~171 此段程序是压下“2”按键的处理程序;即使用者选择“READ”功能,欲读取 E2PROM 5 内存的数据。请参考下列各细项的说明: 87~88 在 LCM 显示"SELECT 1)ADDRS 2)ALL"信息,提示使用者选择读取模式。本范 例程序提供两种读取模式,即“特定地址”(ADDRS)读取与“全部地址”(ALL) 读取。 90~97 98~120 99~106 检查键盘的“1”、“2”按键是否压下,若未压下或压下为其它按键则持续等待; 若压下“1”或“2”按键,则依键值的不同进行个别程序:DOREAD_1 或 DOREAD_2。 此段程序是压下“1”按键的处理程序;即使用者选择“ADDRS”(即“特定地址” 读取模式),欲读取特定地址的 E2PROM 数据。 在 LCM 第一、第二列分别显示"I/P ADDRS(2-DIG HEX)" 、” ADDRS=>"信息, 提示使用者输入两位数的十六进制数值,指定所欲读取的 E2PROM 地址。 5-194 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 107~110 调用 GET2KEYS 子程序读取使用者输入的地址信息,将其暂存于 EEA 寄存器,并 调用 READ 子程序读取该地址的 E2PROM 内容。 111~118 在 LCM 显示"DATA="信息,并将由 E2PROM 所读取的内容显示于 LCM。 119~120 等待使用者压下键盘,以重新功能选项的选择程序(JMP MAIN)。 121~171 此段程序是压下“2”按键的处理程序;即使用者选择“ALL”(即“全部地址”读 取模式),欲读取 E2PROM 内所有地址的数据。 122 设定 EEA 为零,即准备由 E2PROM 的第零个地址开始读取数据。 124~137 搭配间接寻址法,以一次八个地址为单位(起始地址由 EEA 指定),将数据由 5 E2PROM 逐一读出(调用 READ 子程序),并存于 BUFFER[]数组中。 138~147 通过调用 BUFFER_DISPLAY 子程序,将 BUFFER[1]~BUFFER[8]数组中的数据 以十六进制的方式显示于 LCM 的一、二列。下列的图示中,各列首行的两位数是代 表地址;地址之后的是代表连续四个地址的内容。 149~169 等待使用者按下按键,若压下“F.WD(Forword)”键,则跳至 DOREAD_3 继续 下八个地址的读取程序;若压下“B.WD(Backword)”键,则跳至 DOREAD_DN 读取前八个地址的读取程序;若压下“Enter”键,则结束“全部地址”读取模式, 并重新开始功能选项的选择程序(JMP MAIN)。 175~199 BUFFER_DISPLAY 子程序,负责在 LCM 上显示读取的 E2PROM 地址及其内容。 在“全部地址”读取模式中是先搭配间接寻址法(程序第 124~137 行),以一次八 个地址为单位(起始地址由 EEA 指定),将数据由 E2PROM 读出并存于 BUFFER[] 数组中,而此子程序则利用间接寻址法,将地址或数据转换成 ASCII 码(调用 NIBBLE2ASCII 子程序)后丢至 LCM 显示。 206~213 NIBBLE2ASCII 子程序,其功能是将 ACC 的低四位转换成 ASCII 码。 第五章 进阶实验篇 5-195 221~236 READ 子程序,其将根据 EEA 寄存器所指定的地址读取 E2PROM 的内容。请注意, 控制 E2PROM 存取的 EEC 控制寄存器是位于 Bank 1 地址 40h 处,所以必须做 Bank 的切换并搭配 MP1 的间接寻址方能正确的进行位状态的设定,顺利完成读写程序 (请参阅【2-3-12 节】的详细介绍)。 244~259 WRITE 子程序,其负责将 EED 寄存器内的数据写入由 EEA 寄存器所指定的 E2PROM 地址内。请注意,掌控 E2PROM 存取的 EEC 控制寄存器是位于 Bank 1 地址 40h 处,所以必须做 Bank 的切换并搭配 MP1 的间接寻址方能正确的进行位状 态的设定,顺利完成读写程序(请参阅【2-3-12 节】的详细介绍)。 267~278 GET2KEYS 子程序,其由键盘读取(调用 READ_KEY_PRESSED 子程序)使用 者输入的两个键值,并将其转换成 ASCII 码(调用 NIBBLE2ASCII 子程序)后显示 于 LCM;两个键值整合后存置于 BUFFER[0]。 287~311 GETKEYS 子程序,其由键盘读取(调用 READ_KEY_PRESSED 子程序)使用者 输入的键值,并存置于 BUFFER[1]~BUFFER[15]数组;当输入的按键数达 15 个, 或使用者压下“ENTER”键时将结束本子程序,而 BUFFER[0]则存放输入的键值 个数。 320~340 READ_KEY_PRESSED 子程序,其由键盘读取(调用 READ_KEY 子程序)使用 5 者输入的键值,并存置于 KEY_PS 寄存器;本子程序与 READ_KEY 子程序不同的 是:除非使用者压下按键,且放开按键后才会返回原调用处。 347~374 READ_KEY 子程序,请参阅【实验 4-7】的详细说明。 381~391 PRINT 子程序,此子程序负责将定义好的字符串依序显示于 LCM 上。在调用此子 程序之前,除了必须先设定好 LCM 的位置之外,尚需先于 Acc 寄存器中指定字符 串的起始地址(字符串必须存放于最末程序页-Last Page),并请于字符串的最后 一个字符塞入 NULL,代表字符串结束。 397~414 INIT_LCM 子程序,其功能是对 LCM 进行定义: 398~403 LCM_EN、LCM_RW 与 LCM_RS 定义为输出模式,并设定状态为“0”。 405~406 将 LCM 设定为双行显示(N = 1)、使用八位(DB7 ~ DB0)控制模式(DL = 1)、 5×7 点矩阵字型(F = 0)。 407~408 将 LCM 设定为显示所有数据(D = 1)、显示光标(C = 1)、光标所在位置的字会 闪烁(B = 1)。 409~410 将 LCM 的地址计数器(AC)设为递加(I/D = 1)、显示器画面不因读写数据而移 动(S = 0)。 5-196 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 411~412 将 LCM 整个显示器清空。 422~449 WLCMDM 与 WLCMCM 子程序,请参考【实验 5-6】中的说明。 456~469 DELAY 子程序,延迟时间的计算请参考【实验 4-1】中的说明。 471~477 字符串定义区,请注意每一个字符串必须以 NULL 做为结束。 程序一开始首先对LCM做初始化的设定,并显示功能选项表: “WR”:Write Data to E2PROM、 “RD”:Read Data from E2PROM。紧接着等待使用者输 入功能选项,若选择“WR”,则于LCM显示提示信息,并将输入的键值显示于 LCM,待使用者输入15个数值或压下“Enter”键后就进行将数据写入E2PROM 的动作,并结束输入程序,回至程序功能选项画面。若选择“RD”,则在LCM显 示“特定地址”与“全部地址”的功能选项,接着进行由E2PROM读出数据的动 作,并将读回的数据显示于LCM,待使用者压下任何按键后终止程序,回至程序 主功能选项画面。在此要特别留意的是EEC是位于Bank1的控制寄存器,所以务 必搭配MP1、IAR1间接寻址与BP的适当设定,方能达成正确的读、写动作! 为了验证E2PROM的非易失(Non-Volatile)特性,读者可以先选择写入的选 5 项,将数据存入E2PROM;关闭电源后再执行【程序5-16】,并选取读取的功能读 出E2PROM内存数据。 5-16-5 动动脑+动动手: 本范例程序当输入 15 个“0”~“9”的按键或使用者压下“Enter”键后, 即进入 E2PROM 的写入程序。试将输入 15 个按键就自动启动写入程序的限 制上限至 20 个。 承上题,请以”A” 键做为 Back-Delete Key,让使用者于输入过程中可以删、 改已输入的数值。 5-197 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-17 I2C接口E2PROM读写控制实验 5-17-1 目 的: 以4x4键盘为输入设备,选择程序功能: BYTE_WR、 PAGE_WR、 SRR、 RCR与 RSCR,此五个选项分别代表Byte Write、Page Write、Sequential Random Read、Random Read+Current Read以及Random Read+Sequential Current Read。当选择 、 时则将输入数值(0~9)分别以Byte Write或Page Write 方式储存至HT24LC16;当选择 ~ 时,则依其对应的数据读取模式,读出储存 于HT24LC16的数据,并显示于LCM上。 5-17-2 学习重点: 通过本实验,读者应熟悉I2C串行界面E2PROM-HT24LC16的读、写控制方 式;对于本实验所提供相关子程序的原理与运用方式也应了如指掌。 5-17-3 电路图: 5 PS:若使能 PA[7:4]Pull-high 功能,则 4×4 Keypad 上的四颗 10kΩ电阻可省略。 【图 5-17-1】I2C 串行界面 E2PROM 实验电路 I2C(Inter IC)又可称为I2C-Bus,它是由飞利浦公司(Philips Comp.)制定 出来的串行存取方式,目前有许多厂商制造提供此一标准界面的相关产品,其相关 介绍请读者参考【实验4-17】的内容。【表5-17-1】为盛群半导体股份有限公司的 I2C E2PROM产品型号,以下将以HT24LC16为例说明I2 C接口的控制方式。 【表 5-17-1】Holtek I2C E2PROM 产品型号(截至:2008.12.15) Part No. Capacity VDD Clock Rate Write Speed Operating Current Standby Current 5-198 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 HT24LC02 HT24LC04 HT24LC08 HT24LC16 HT24LC32 HT24LC64 HT2201 256x8 512x8 1024x8 2048x8 4096x8 8192x8 128x8 2.2V~5.5V 2.2V~5.5V 2.2V~5.5V 2.2V~5.5V 2.4V~5.5V 2.4V~5.5V 2.2V~5.5V (kHz) 400 400 400 400 400 400 400 @2.4V (ms) 5 5 5 5 5 5 5 @5V (mA) 5 5 5 5 5 5 5 @5V (uA) 5 5 5 5 5 5 4 【图5-17-2】为HT24LC16的引脚及其功能概述,完整的电气特性还是请读者 参考光盘片中的IC数据手册。由引脚的特性来看,所有的数据控制及读写动作,都 是通过SDA、SCL引脚来完成,因此有关学习I2C接口的传输方式,其实等于是在 研究这两个信号间的关系。不过首先要注意,使用I2C接口SDA、SCL两支引脚必 须接上上拉电阻,如【图5-17-3】所示。 引脚 功能 概 述 5 A0 做为增加内存时的控制信号,也就是说利用此三支引脚的信号编码可以同时并联多 A1 Chip Enable 个 I2C 内存。本专题使用 HT24LC16(2k×8),已达 I2C 的最大容许范围,因此无须 A2 使用这三支使能脚位。 SDA Serial Data 此引脚是用来传输连续的数据,但是要注意此引脚也是属于双向传输的方式。当在 执行写入数据时,若接收完一笔数据时此引脚将会输出一个 Acknowledge 信号表示 己接收到数据。当在执行读取数据时,若送完一笔数据,要由接收数据端送出一个 Acknowledge 或 Not Acknowledge 代表是否继续下一个地址的数据读取。 SCL Serial Clock 串行时钟输入引脚。 WP Write Protect 若该引脚接为高电平,此时 IC 将禁止写入数据的动作,但是可以读取数据;若该 引脚为低电平时,则可以进行写入及读取数据的动作。 VCC Supply Voltage VSS Ground 工作电压输入端,工作电压 2.2~5.5V。 接地。 【图 5-17-2】HT24LC16 的引脚及功能 注意: WP:此引脚要接地,若为高电平则只 能进行读取的动作 RC:电阻值大约 10K~5KΩ 左右 【图 5-17-3】SDA、SCL 两支引脚的上拉电阻 接下来就需要了解SDA、SCL的控制时序,I2C Bus的任何读写控制动作,都 必须以“START Condition”与“STOP Condition”做为起始与结束,因为只有使 用SCL、SDA两根信号,所以就以其电位的高低状态来区分,请参考【图5-17-4】: 第五章 进阶实验篇 5-199 【图 5-17-4】START 与 STOP Condition 观察【图5-17-4】:当SCL=“1”时,如果SDA由“1” “0”,则为“START Condition”,I2C设备将准备开始进行数据的读写动作;而当SCL=“1”时若SDA 由“0” “1”,则为“STOP Condition”,表示结束此笔数据的传输程序。因 此,在I2C Bus的传输过程中,数据的改变一定要在SCL=“0”的状态时进行(如 【图5-17-4】的”Set SDA”期间),否则很容易被I2C设备误认为是“START”或 “STOP”Condition,如此可能不正常的终止目前的传输,而导致存取的数据错误, 读者不得不小心!另外,数据的接收是在SCL信号由“1” “0”时,也就是说 Receiver是在SCL信号的下降沿去侦测SDA的逻辑状态,以决定数据位是1或0。在 程序中分别以“I2CStart”与“I2CStop”子程序来产生这两种状态,现将其一并 列出,其中的DELAY_10子程序大约延迟10个指令周期,主要是为了让此子程序可 5 以适用于更高的工作频率。请读者配合【图5-17-4】时序图与程序的说明稍做分析, 应该不难洞悉其原理。 I2CStart与I2CStop”子程序: 1 ;======================================================================================== 2; GENERATE I2C START CONDITION 3 ;======================================================================================== 4 I2C_START PROC 5 CLR SCL ;SET SCL=0 6 CLR SDA ;SET SDA=0 7 CLR SCLC ;CONFIG SLC AS OUTPUT MODE 8 CLR SDAC ;CONFIG SDA AS OUTPUT MODE 9 CALL DELAY_10 ;DELAY 10 SET SCL ;SET SCL=1 11 SET SDA ;SET SDA=1 12 CALL DELAY_10 ;DELAY 13 CLR SDA ;SET SDA=0 14 CALL DELAY_10 ;DELAY 15 CLR SCL ;SET SCL=0 16 CALL DELAY_10 ;DELAY 17 RET 18 I2C_START ENDP 19 ;======================================================================================== 20 ; GENERATE I2C STOP CONDITION 5-200 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 21 ;======================================================================================== 22 I2C_STOP PROC 23 CLR SDA ;SET SDA=0 24 CLR SDAC ;CONFIG SDA AS OUTPUT MODE 25 CLR SCL ;SET SCL=0 26 CALL DELAY_10 ;DELAY 27 SET SCL ;SET SCL=1 28 CALL DELAY_10 ;DELAY 29 CLR SDA ;SET SDA=0 30 CALL DELAY_10 ;DELAY 31 SET SDA ;SET SDA=1 32 RET 33 I2C_STOP ENDP 34 ;======================================================================================== 35 ; DELAY 10 uS FOR TIMING CONSIDERATION 36 ;======================================================================================== 37 DELAY_10: 38 JMP $+1 39 JMP $+1 40 JMP $+1 41 JMP $+1 5 42 RET 其次就是如何让I2C设备分辨读或写的动作了,请参考【图5-17-5】HT24LC16 “Byte Write”模式时序的示意图;所谓“Byte Write”是指写入一个字节的数据 至I2C设备,当然也必须指定此一字节要存放至从机内的哪一个地址。如【图5-17-5】 所示,在送出“START”状态之后,接着要送出从机选择地址码(Device Select Code)、八位地址(Byte Address)以及要写入的数据(Data In),请参考【表 5-17-2】。 【图 5-17-5】HT24LC16“Byte Write”模式 【表 5-17-2】HT24LC16 从机选择地址码 Part No. Device Type ID Chip Enable R/W b7 b6 b5 b4 b3 b2 b1 b0 HT24LC02 HT24LC04 HT24LC08 HT24LC16 1 0 1 0 E2 E1 1 0 1 0 E2 E1 1 0 1 0 E2 A9 1 0 1 0 A10 A9 E0 R/W A8 R/W A8 R/W A8 R/W 目前有数百种不同的I2C设备,每一种从机都定义了不同的从机辨识码,而内 存设备的辨识码为“1010”。b3~b1为使能控制引脚,当送出的使能信号与引脚 第五章 进阶实验篇 5-201 上所设定状态相同时,该从机才会动作。因为I2C Bus所能接受的最大存储容量为 2K Bytes,而本实验所采用的HT24LC16恰为2K Bytes的存储容量,因此A2、A1、 A0硬件引脚实际上是没有用的,此时的b3 ~ b1就代表A10~A8的地址选择信号。如 果在电路中使用两个HT24LC08(每颗存储器容量为1K Bytes),此时就可以将其 中一颗A2接至VCC,另一颗接至VSS即可,不需再外加任何译码电路,而在使用时 只要以b3位来区分就可以了(如【图5-17-6】)。b0则是表示要对该从机进行读出 (1)或写入(0)的动作。 【图 5-17-6】Device Select Code 图例 紧接在从机选择地址码之后的就是要写到内存的地址信息,其次就是真正要写 入的数据。请注意,所有的字节数据都是从最高位开始传送接收。当然,最后别忘 5 记以“STOP Condition”来结束这一次的写入动作。笔者再以实例来说明【图5-17-5】 Byte Write模式的整个过程,假设欲以单片机写入一个字节的数据至HT24LC16地 址38h时,则必须经过如下的步骤: Step1:送出 START Condition; Step2:送出从机码、地址(A10~A8)与 R/W=0 (10100000b); Step3:等待 HT24LC16(Slave)回复 ACK; Step4:送出 Byte Address (00111000b,即 38h); Step5:等待 HT24LC16(Slave)回复 ACK; Step6:将 Data(8-Bit)由 SDA 串行送出; Step7:等待 HT24LC16(Slave)回复 ACK; Step8:送出 STOP Condition,结束传输程序。 在上述的步骤中,请注意Step3、Step5与Step7的ACK信号均是由HT24LC16 (Slave)负责送出,其次将SDA拉至低态,表示已收到单片机(Master)所送来 的命令或数据;而最后并在Step8由单片机(Master)送出“STOP Condition”结 束此笔数据写入的程序。 5-202 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 【图 5-17-7】HT24LC16 “Random Read”模式 请读者接着观察HT24LC16的“Random Read”模式(【图5-17-7】),所谓 “Random Read”是指可以读取任意一个地址的数据,这跟刚刚Byte Write可以写 数据到任何地址的意义差不多,但请比较【图5-17-5】与【图5-17-7】的差异,为 什么Random Read模式的从机选择地址码要送两次呢?为什么明明要由从机读回 数据,可是第一个从机选择地址码的R/W位却是“0”呢?请读者留意,HT24LC16 的 Random Read模式中,第一个从机选择地址码的R/W=“0”是表示要写入地 址(Byte Address),以便让内存(Slave)知道该把哪一个地址的数据送出来, 而第二个从机选择地址码的R/W=“1”才是真正启动内存将指定地址内数据串行 送出。假设欲从HT24LC16的地址38h读回一个字节的数据时,则单片机(Master) 必须经过如下的步骤: Step1:送出 START Condition; Step2:送出从机码、地址(A10~A8)与 R/W=0 (10100000b); Step3:等待 HT24LC16(Slave)回复 ACK; Step4:送出 Byte Address (00111000b,即 38h); Step5:等待 HT24LC16(Slave)回复 ACK; Step6:再次送出 START Condition; Step7:送出从机码、地址与 R/W=1 (10100001b); 5 Step8:等待 HT24LC16(Slave)回复 ACK; Step9:由 SDA 串行读回 Data(8-Bit); Step10:送出 No ACK 讯号; Step11:送出 STOP Condition,结束传输程序。 在此提醒读者的是Step2与Step7所送出的从机码、地址必须一致,否则就无 法正确完成数据的读取了! 在Byte Write与Random Read的读写程序中,可以归纳出几个共同的需求,首 先是由单片机(Master)控制SDA与SCL串行送出八位的从机码、地址或数据至 HT24LC16;其次是由单片机(Master)控制SCL并由SDA串行读回HT24LC16所 传回的八位数据;再来就是检查、等待HT24LC16送出的ACK信号,以确认是否完 成有效的命令或数据传输!在程序中就以WriteByte、ReadByte与CheckACK三个 子程序来达成上述的三个需求,以下是这三个子程序的流程图与说明。 WRITE_BYTE:此子程序利用I2C_DATA.7的状态决定SDA脚位的逻辑电平, 并搭配SCL信号送至HT24LC16。由于每送出一个位I2C_DATA即左移一次, 所以数据是由MSB至LSB位分成八次串行由SDA搭配SCL信号逐一传送至 HT24LC16;附带一提的是:HT24LC16是在SCL由“1”变“0”的瞬间将 SDA的逻辑电平视为欲写入的位状态(0或1)。 READ_BYTE:在读取HT24LC16时,必须先了解其是在SCL由“0”变“1” 后将数据位的状态送至SDA,而且是由MSB开始传送。程序中每当送出SCL 由“0”变“1”后,即借由SDA状态决定I2C_DATA.0该为1或0,而且每读 第五章 进阶实验篇 5-203 入一个位即右移一次,因此ReadByte程序是由MSB至LSB逐一按照SDA回传 的逻辑状态决定I2C_DATA各位的值。 CHECK_ACK:当HT24LC16正确的接收到Master送出的从机码、地址或数 据时,会以SDA=0的讯号响应Master端;因此Master每次送出上述的信息时, 必须将SCL拉至高态并等待HT24LC16将SDA拉至低态,以确认其已正确接 收到Master所送出的信息。 5 【图 5-17-8】WRITE_BYTE 子程序流程图 【图 5-17-9】READ_BYTE 子程序流程图 5-204 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 【图 5-17-10】CHECK_ACK 子程序流程图 经过上述的说明,大概可以写程序来控制M24C16。首先是在“START” Condition之后必须送出从机选择地址码,然后是地址、…等等。仔细观察【图5-17-5】 与【图5-17-7】,前面两组送的信息都一样,而“Random Read”模式时,前、 后两个从机选择地址码也只有最后一个位(R/W)不同而已。因此,笔者想把它整 合成一个子程序模块,以方便读者调用使用。请参考【图5-17-11】的流程图,并 配合【图5-17-5】与【图5-17-7】的时序要求: 5 【图 5-17-11】I2C_DEV_SEL_R 与 I2C_DEV_SEL_W 子程序流程图 在HT24LC16数据手册中,对于SCL与SDA的状态变化有一定的时间要求(实 时序关系),在程序中是以DELAY10子程序来达成,但是为了避免使流程图看起 来过于复杂,在图中并未特别标示出来,请读者特别留意! 再来就是送出地址,让HT24LC16知道该针对哪一个存储器位置做动作,其实 与【图5-17-11】所述的流程大同小异,请参考【图5-17-12】的流程图: 【图 5-17-12】I2C_SET_ADRS 子程序流程图 第五章 进阶实验篇 5-205 【图 5-17-13】I2C_BYTE_WRITE 子程序流程图 最后就是数据读或写的动作,写数据的动作和写入地址是一样的,读者可以把 I2C_SET_ADRS子程序中的地址(I2C_ADRS)改成数据就行了。不过在写入数 据之前,是不是该让HT24LC16知道该把数据放到哪一个位置呢?所以必须先由单 片机把地址信息送给它,读者应该可以了解【图5-17-13】流程图所代表的意义了 吧?其次依照【图5-17-5】HT24LC16“Write Byte”模式所要求的时序,完成写 入一个Byte数据至指定地址的程序。 从Byte Write与Random Read的读、写过程中发现,每次的读、写动作都要送 出地址告知HT24LC16,不是既浪费时间又麻烦吗?其实在HT24LC16内部有一个 5 地址计数器(Internal Address Counter;AC),每执行完一次读、写动作时,AC 就会自动加一。所以,如果是读、写连续的存储器地址的话,其实是不需要每次都 重新设定AC值的,如此可以提高单位时间的数据吞吐量。这也是读者在HT24LC16 数据手册中可以发现有好几种不同读写模式的原因,请参考【图5-17-14】的“Page Write”模式与以下的说明。 【图 5-17-14】HT24LC16 “Page Write”模式 所谓的“Page Write”模式,就是在告知HT24LC16地址之后连续写N个Byte 的数据,而且只需在最后一笔数据写完之后,再以STOP Condition结束Page Write 的动作即可。如此可以省去“Byte Write”模式中每次都送地址的时间,不过有以 下两个规则须遵守: N不得大于16、 AC递增时若低四位有进位时,其并不会 累进至下一位。由于E2PROM的写入速度较慢,所以在HT24LC16内部有一块存取 速度较快的RAM Buffer,外界写入的数据其实都是先暂时存放在RAM Buffer内, 待进入STOP Condition后,HT24LC16再把RAM Buffer内的数据复制到E2PROM 上。如此的作法是为了提升与外部传输的速度,但是因为内部的RAM Buffer只有 5-206 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 16 Bytes,所以外界一次最多只能连续写入16 Bytes的数据就必须进入“STOP Condition”,否则将会覆盖前面写入RAM Buffer的数据;亦即只有最后写入的16 Bytes才会被真正复制到E2PROM。另外,由于HT24LC16内部地址计数器递增时 的限制,使用Page Write模式时要特别注意,如果地址跨越16的界限(如00Fh递 增至010h、1FFh递增至200h、…等等)时必须重新设定AC的地址!附带一提的是 HT24LC16把RAM Buffer内的数据复制到E2PROM需要一定的时间,因此当Master 发出STOP Condition必须间隔一定的时间才能再下达写入的命令,由【表5-17-1】 可知HT24LC16将Buffer的数据复制到E2PROM约需5ms左右。然而E2PROM的读 取速度与RAM相当,在连续读取时是直接由E2PROM中读出数据,所以就无此限 制。当单片机欲以“Page Write”方式写入数据至E2PROM时须采取以下步骤(流 程图请参考【图5-17-15】): Step1:送出 START Condition; Step2:送出从机码、地址(A10~A8)与 R/W=0 (10100000b); Step3:等待 HT24LC16(Slave)回复 ACK; Step4:送出 Byte Address(A7~A0); Step5:等待 HT24LC16(Slave)回复 ACK; Step6:由 SDA 串行送出一个字节数据; Step7:等待 HT24LC16(Slave)回复 ACK。若尚有数据要传送则至 Step6; 5 Step8:送出 STOP Condition,结束传输程序。 【图 5-17-15】I2C_PAGE_WRITE 子程序流程图 在Page Write模式的步骤中,Step3、Step5与Step7的ACK信号是由HT24LC16 (Slave)将SDA拉至低态,表示其已收到Master所送来的命令或数据;而单片机 则是在送出最后一笔数据后,以STOP Condition结束Page Write的传输程序。 第五章 进阶实验篇 5-207 前述的说明过程中,笔者曾提及HT24LC16 内部有一个地址计数器-AC (Address Counter),它掌控着HT24LC16数据读、写的位置;前面所介绍的几 种读、写模式都牵涉到地址的设定,其实就是在设定AC的值!不管是读或写, HT24LC16内部都是针对AC值所指定的地址执行读取或写入的动作。而AC有一个 自动增值的特性(Auto Increment),亦即每当完成一次的读或写后会自动加一; 所以,若是要由前一次存取的位置继续读、写动作的话,就无须再重新设定AC值 了。请见【图5-17-16(b)】的“Current Address Read”模式,所谓“Current Address Read”是指直接读取目前AC值所指示的地址数据,因此不需在读取前先设定欲读 取的地址! (a)Random Read 模式 (b) Current Address Read 模式 【图 5-17-16】HT24LC16 “Random Read”与“Current Address Read”模式 在【图5-17-7】已经介绍过HT24LC16的“Random Read”数据读取模式,其 与“Current Address Read”差异不大,比较【图5-17-16】的(a)与(b)时序 5 格式,图中已标示出差异之处,读者应该可以很容易了解两者的区别。Current Address Read仅需传送一次DEV SEL信息,因此单位时间的数据传输量要比 Random Read要来的高!既然两者的差异不大,同样将其整合于一个程序模块以 方便使用,请参考【图5-17-17】的流程图。 5-208 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 I2C_RM_READ子程序 I2C_CT_READ子程序程式 Call I2C_START to Set Start Condition Call I2C_DEV_SEL_W to Set Device Sel. Code Call I2C_SET_ADRS to Set Memory Address Call I2C_START to Set Start Condition Call I2C_DEV_SEL_R to Set Device Sel. Code Call READ_Byte Read 1 Byte Data from Device Configure SDA as Output Mode SET SDA=1 SET SCL=1 SET SCL=0 HT66F50 Send No ACK. Signal for Not Reading Next Byte Call I2C_STOP to Set Stop Condition 表示有时序上的考量 RETURN 5 【图 5-17-17】I2C_RM_READ 与 I2C_CT_READ 子程序流程图 ACK(Acknowledge;逻辑0)与NoACK(Not Acknowledge;逻辑1)信号 在传输过程中扮演相当重要的角色,它并非固定由Master或Slave发送,而是由负 责接收信息(Receiver)的从机所送出的!如【图5-17-16(a)】的Random Read 模式,前三个ACK信号是HT24LC16分别用以回应已正确接收单片机所送出的两组 从 机 选 择 地 址 码 以 及 一 组 地 址 数 据 ; 而 第 四 个 No_ACK 则 是 单 片 机 接 收 完 HT24LC16回送的数据后,告知其不需再继续回送下一个地址数据的信号!有了这 个概念之后,接下来介绍HT24LC16最后两种数据读取模式。 【图 5-17-18】HT24LC16 “Sequential Random Read”模式 【图5-17-18】为“Sequential Random Read”模式,即在告知HT24LC16地 址之后,连续读取n个Byte的数据,而且只需在最后一笔数据读完之后,单片机先 以No_ACK响应HT24LC16,再以“STOP Condition”结束读取的动作即可。读取 数 据 时 , n 并 没 有 限 制 , 不 过 要 注 意 的 是 当 读 到 HT24LC16 的 最 后 一 个 地 址 时 ( 7FFh ) , AC 会 重 新 归 零 , 所 以 又 会 从 第 0 个 地 址 开 始 读 起 。 当 单 片 机 欲 以 Sequential Random Read方式读取HT24LC16的数据时,须采取以下步骤: Step1:送出 START Condition; 第五章 进阶实验篇 5-209 Step2:送出从机码、地址(A10~A8)与 R/W=0 (10100000b); Step3:等待 HT24LC16(Slave)回复 ACK; Step4:送出 Byte Addres(A7~A0); Step5:等待 HT24LC16(Slave)回复 ACK; Step6:再次送出 START Condition; Step7:送出从机码、位(A10~A8)址与 R/W=1 (10100001b); Step8:等待 HT24LC16(Slave)回复 ACK; Step9:由 SDA 串行读回 Data(8-Bit); Step10:若尚要读取数据则送出 ACK 信号并执行 Step9;否则至 Step11。 Step11:送出 No ACK 讯号; Step12:送出 STOP Condition,结束传输程序。 读者可以很清晰的看出,HT24LC16是以Master所送出ACK或NoACK信号来 分辨是否还要继续读取的动作;综合上述的说明,ACK与NoACK信号是由接收信 息的一端负责送出,而传送信息者必须等待接收端送出的ACK或NoACK信号以决 定是否继续传送的动作! 【图 5-17-19】HT24LC16“Sequential Current Read”模式 5 【图5-17-19】为“Sequential Current Read”模式,是依目前AC所指的地址, 连 续 读 取 n 个 Byte 的 数 据 , 而 且 只 需 在 最 后 一 笔 数 据 写 完 之 后 , 再 以 “ STOP Condition”结束读取的动作。与【图5-17-18】相比之下其减少了第一阶段的地址 设定程序,可说是Sequential Random Read的简化版!当单片机欲以Sequential Current Read方式读取HT24LC16数据时的步骤如下(两者整合后的程序流程请参 考【图5-17-20】): Step1:送出 START Condition; Step2:送出从机码、位(A10~A8)址与 R/W=1 (10100001b); Step3:等待 HT24LC16(Slave)回复 ACK; Step4:由 SDA 串行读回 Data(8-Bit); Step5:若尚要读取数据则送出 ACK 信号并执行 Step4;否则至 Step6。 Step6:送出 No ACK 讯号; Step7:送出 STOP Condition,结束传输程序。 5-210 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5 【图 5-17-20】I2C_SQ_RM_READ 与 I2C_SQ_CT_READ 子程序流程图 5-17-4 程序及流程图: 第五章 进阶实验篇 5-211 5 5-212 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5 程序5-17 HT66F50 I2C-Bus E2PROM读写控制实验 1 ;PROGRAM : 5-17.ASM (5-17.PJT) 2 ;FUNCTION: IIC EEPROM - HT24LC16 READ/WRITE CONTROL 3 #INCLUDE HT66F50.INC 2009.1109 By Steven 第五章 进阶实验篇 5-213 4 #INCLUDE 5-17.INC 5 ;==================================================================================== ==== 6 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 7 DEL1 DB ? ;DELAY LOOP COUNT 1 8 DEL2 DB ? ;DELAY LOOP COUNT 2 9 DEL3 DB ? ;DELAY LOOP COUNT 3 10 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 11 LCM_TEMP DB ? ;BUFFER FOR LCM PROCEDURE 12 LCM_AC DB ? 13 KEY DB ? ;BUFFER FOR READ_KEY PROCEDURE 14 COUNT DB ? ;BUFFER FOR READ_KEY PROCEDURE 15 KEY_PS DB ? ;BUFFER FOR READ_KEY_PRESSED PROCEDURE 16 BYTE_COUNT DB ? ;BIT COUNTER FOR I2C R/W 17 PAGE_COUNT DB ? ;COUNT FOR I2C R/W BIT 18 I2C_PAGE_IDX DB ? ;I2C DEVICE START ADDRESS (A10~A8) 19 I2C_ADRS DB ? ;I2C DEVICE START ADDRESS (A7~A0) 20 I2C_DATA DB ? ;I2C BYTE R/W DATA BUFFER 21 BYTE_DATA DB ? ;R/W BUFFER FOR I2C DATA 22 BUFFER DB 16 DUP(?) 23 BUFFER_COUNTDB ? 5 24 ;==================================================================================== ==== 25 26 ;==================================================================================== ==== 27 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 28 ORG 00H ;HT-46RXX RESET VECTOR 29 CLR ACERL ;AD DISABLE 30 MOV A,08h 31 MOV CP0C,A ;CP0 DISABLE 32 MOV CP1C,A ;CP1 DISABLE 33 CALL INIT_LCM 34 MAIN: MOV A,80H ;SET LCM LINE 1 35 CALL WLCMCM 36 MOV A,STR_1 ;PRINT STR_1 37 CALL PRINT 38 MOV A,0C0H ;SET LCM LINE 2 39 CALL WLCMCM 40 MOV A,STR_2 ;PRINT STR_1 41 CALL PRINT 42 43 MENU_1: CALL READ_KEY_PRESSED ;GET MENU SELECT 1~5 44 XOR A,0 45 SZ Z 5-214 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 5 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 JMP MENU_1 SUB A,6 SZ C JMP MENU_1 MOV A,01H CALL WLCMCM DECA KEY_PS ADDM A,PCL JMP BYTEWR JMP PAGEWR JMP SRR JMP RCR JMP RSCR BYTEWR: MOV A,STR_3 CALL PRINT MOV A,0C0H CALL WLCMCM CALL GETKEYS MOV A,BUFFER[0] XOR A,0 SZ Z JMP MAIN MOV A,01H CALL WLCMCM MOV A,STR_8 CALL PRINT CLR I2C_PAGE_IDX CLR I2C_ADRS INCA BUFFER[0] MOV PAGE_COUNT,A MOV A,OFFSET BUFFER[0] MOV MP0,A RANDOMWR_1: MOV A,IAR0 MOV BYTE_DATA,A CALL I2C_BYTE_WRITE INC MP0 INC I2C_ADRS SDZ PAGE_COUNT JMP RANDOMWR_1 MOV A,100 CALL DELAY JMP MAIN PAGEWR: MOV A,STR_4 ;CLEAR DISPLAY ;COMPUTATIONAL JUMP ;BYTE WRITE ;PAGE WRITE ;SEQUENTIALRANDOM READ ;RANDOM READ+CURRENT READ ;RANDOM READ+SEQUENTIAL CURRENT READ ;RANDOM WRITE ;PRINT STR_3 ;SET LCM LINE 2 ;GET KEYPAD INPUT CODE ;TEST IF NULL INPUT ;YES, RESTART MENU SELECT ;CLEAR DISPLAY ;PRINT STR_8 ;SET I2C_PAGE_IDX(A10~A8)=00H ;SET I2C_ADRS(A7~A0)=00H ;SET I2C WRITE COUNT ;SET POINTER TO BUFFER START ADDRESS ;GET BUFFER DATA ;I2C BYTE WRITE ;INCREASE BUFFER POINTER ;INCREASE I2C DEVIDE ADDRESS ;COUNT-1 = 0 ? ;NO. ;YES, DELAY FOR STRING DISPLAY ;RESTART MENU SELECT ;PAGE WRITE ;PRINT STR_4 93 CALL PRINT 94 MOV A,0C0H 95 CALL WLCMCM 96 CALL GETKEYS 97 MOV A,BUFFER[0] 98 XOR A,0 99 SZ Z 100 JMP MAIN 101 MOV A,01H 102 CALL WLCMCM 103 MOV A,STR_8 104 CALL PRINT 105 106 CLR I2C_PAGE_IDX 107 CLR I2C_ADRS 108 INCA BUFFER[0] 109 MOV PAGE_COUNT,A 110 MOV A,OFFSET BUFFER[0] 111 MOV MP0,A 112 CALL I2C_PAGE_WRITE 113 MOV A,100 114 CALL DELAY 115 JMP MAIN 116 SRR: RANDOM READ 117 MOV A,STR_5 118 CALL PRINT 119 CLR I2C_PAGE_IDX 120 CLR I2C_ADRS 121 CALL I2C_RM_READ 122 MOV A,BYTE_DATA 123 MOV BUFFER[0],A 124 MOV PAGE_COUNT,A 125 MOV A,OFFSET BUFFER[1] 126 MOV MP0,A 127 INC I2C_ADRS 128 CALL I2C_SQ_RM_READ 129 JMP RSCR_1 130 RCR: 131 MOV A,STR_6 132 CALL PRINT 133 CLR I2C_PAGE_IDX 134 CLR I2C_ADRS 135 CALL I2C_RM_READ 136 MOV A,BYTE_DATA 137 MOV BUFFER[0],A 138 MOV PAGE_COUNT,A 第五章 进阶实验篇 5-215 ;SET LCM LINE 2 ;TEST IF NULL INPUT ;YES, RESTART MENU SELECT ;CLEAR DISPLAY ;PRINT STR_8 ;SET I2C_PAGE_IDX(A10~A8)=00H ;SET I2C_ADRS(A7~A0)=00H ;SET I2C WRITE COUNT ;SET POINTER TO BUFFER START ADDRESS ;I2C PAGE WRITE ;RESTART MENU SELECT 5 ;RANDOM READ AND SEQUENTIAL ;PRINT STR_5 ;SET I2C_PAGE_IDX(A10~A8)=00H ;SET I2C_ADRS(A7~A0)=00H ;READ 1 BYTE BUFFER COUNT ;SET LENGTH FOR DISPLAY AND SEQ. RM. READ ;SET READ BACK BUFFER POINTER ;SET I2C_ADRS(A7~A0) ;READ ;RANDOM READ AND CURRENT READ ;PRINT STR_5 ;SET I2C_PAGE_IDX(A10~A8)=00H ;SET I2C_ADRS(A7~A0)=00H ;READ 1 BYTE BUFFER COUNT ;SET LENGTH FOR DISPLAY AND CURRENT READ 5-216 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 139 MOV A,OFFSET BUFFER[1] ;SET READ BACK BUFFER POINTER 140 MOV MP0,A 141 RCR_1: CALL I2C_CT_READ ;READ 142 MOV A,BYTE_DATA ;COPY DATA TO BUFFER 143 MOV IAR0,A 144 INC MP0 145 SDZ PAGE_COUNT ;COUNT-1 = 0? 146 JMP RCR_1 ;NO. 147 JMP RSCR_1 ;YES. 148 RSCR: ;RNADOM READ AND SEQUENTIAL CURRENT READ 149 MOV A,STR_7 ;PRINT STR_5 150 CALL PRINT 151 CLR I2C_PAGE_IDX ;SET I2C_PAGE_IDX(A10~A8)=00H 152 CLR I2C_ADRS ;SET I2C_ADRS(A7~A0)=00H 153 CALL I2C_RM_READ ;READ 1 BYTE BUFFER COUNT 154 MOV A,BYTE_DATA ;SET LENGTH FOR DISPLAY AND SEQ. CT. READ 155 MOV BUFFER[0],A 156 MOV PAGE_COUNT,A 157 MOV A,OFFSET BUFFER[1] ;SET READ BACK BUFFER POINTER 158 MOV MP0,A 5 159 CALL I2C_SQ_CT_READ 160 RSCR_1: MOV A,BUFFER[0] ;READ 161 XOR A,0 ;TEST IF NULL INPUT 162 SZ Z 163 JMP MAIN ;YES, RESTART MENU SELECT 164 MOV A,0C0H ;SET LCM LINE 2 165 CALL WLCMCM 166 MOV A,OFFSET BUFFER[1] 167 MOV MP0,A 168 RSCR_2: MOV A,IAR0 169 ADD A,30H 170 CALL WLCMDM 171 INC MP0 172 SDZ BUFFER[0] 173 JMP RSCR_2 174 RSCR_3: CALL READ_KEY_PRESSED 175 XOR A,16 ;ANY KEY PRESSED ? 176 SZ Z ;NO. WAIT 177 JMP RSCR_3 178 JMP MAIN ;YES, RESTART MENU SELECT 179 ;==================================================================================== ==== 180 ; PROC : I2C_START 181 ; FUNC : GENERATE I2C START CONDITION 182 ; CALL : DELAY10 183 ;==================================================================================== 第五章 进阶实验篇 5-217 ==== 184 I2C_START PROC 185 CLR SCL ;SET SCL=0 186 CLR SDA ;SET SDA=0 187 CLR SCLC ;CONFIG SLC AS OUTPUT MODE 188 CLR SDAC ;CONFIG SDA AS OUTPUT MODE 189 CALL DELAY_10 ;DELAY 190 SET SCL ;SET SCL=1 191 SET SDA ;SET SDA=1 192 CALL DELAY_10 ;DELAY 193 CLR SDA ;SET SDA=0 194 CALL DELAY_10 ;DELAY 195 CLR SCL ;SET SCL=0 196 CALL DELAY_10 ;DELAY 197 RET 198 I2C_START ENDP 199 ;==================================================================================== ==== 200 ; PROC : I2C_DEV_SEL_W/I2C_DEV_SEL_R 201 ; FUNC : SEND I2C DEVICE SELECT CODE (R/W) TO DEVICE 202 ; PARA : I2C_PAGE_IDX : DEVICE ADDRESS A10~A8 203 ; REG : ACC 204 ; CALL : WRITE_BYTE, CHECK_ACK 5 205 ;==================================================================================== ==== 206 I2C_DEV_SEL_W PROC ;WRITE MODE 207 RLA I2C_PAGE_IDX 208 AND A,00001110B ;TAKE A10~A8 209 OR A,DEVSEL_W ;LOAD A WITH DEVICE SELECT CODE 210 JMP DEV_SEL 211 I2C_DEV_SEL_R: ;READ MODE 212 RLA I2C_PAGE_IDX 213 AND A,00001110B ;TAKE A10~A8 214 OR A,DEVSEL_R ;LOAD A WITH DEVICE SELECT CODE 215 DEV_SEL: CALL WRITE_BYTE ;SEND OUT 1 BYTE DATA IN Acc 216 CALL CHECK_ACK ;WAIT FOR DEVICE ACK SIGNAL 217 RET 218 I2C_DEV_SEL_W ENDP 219 ;==================================================================================== ==== 220 ; PROC : I2C_SET_ADRS 221 ; FUNC : SET STARTING ADDRESS OF I2C DEVICE 222 ; PARA : I2C_ADRS : DEVICE ADDRESS A7~A0 223 ; REG : ACC 224 ; CALL : WRITE_BYTE, CHECK_ACK 225 ;==================================================================================== ==== 5-218 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 226 I2C_SET_ADRS PROC 227 MOV A,I2C_ADRS 228 CALL WRITE_BYTE ;WRITE ADRESS TO I2C DEVICE 229 CALL CHECK_ACK 230 RET 231 I2C_SET_ADRS ENDP 232 ;==================================================================================== ==== 233 ; PROC : I2C_RM_READ/I2C_CT_READ (I2C RANDOM/CURRENT ADDRESS READ) 234 ; FUNC : READ 1 BYTE DATA FROM I2C DEVICE 235 ; PARA : I2C_PAGE_IDX : DEVICE ADDRESS A10~A8 236 ; I2C_ADRS : DEVICE ADDRESS A7~A0 (FOR I2C_RM_READ ONLY) 237 ; REG : ACC 238 ; CALL : I2C_START, I2C_DEV_SEL_W, I2C_SET_ADRS, I2C_DEV_SEL_R,READ_BYTE, DELAY_10, 239 ; I2C_STOP 240 ; RETN : BYTE_DATA 241 ;==================================================================================== ==== 242 I2C_RM_READ PROC 243 CALL I2C_START ;START SIGNAL 244 CALL I2C_DEV_SEL_W 5 245 CALL I2C_SET_ADRS 246 I2C_CT_READ: ;SET DEVICE CODE AND WRITE MODE ;I2C START ADDRESS SET IN I2C_ADRS 247 CALL I2C_START ;START SIGNAL 248 CALL I2C_DEV_SEL_R ;SET DEVICE CODE AND READ MODE 249 CALL READ_BYTE ;READ 1 BYTE 250 MOV BYTE_DATA,A ;SAVE TO DATA BUFFER 251 SET SDA ;SET SDA=1 252 CLR SDAC ;CONFIG SDA AS OUTPUT MODE 253 CALL DELAY_10 ;DELAY 254 SET SCL ;SET SCL1, NO_ACK SIGNAL TO I2C DEVIC 255 CALL DELAY_10 ;DELAY 256 CLR SCL ;SET SCL=0 257 CALL DELAY_10 ;DELAY 258 CALL I2C_STOP ;STOP SIGNAL 259 RET 260 I2C_RM_READ ENDP 261 ;==================================================================================== ==== 262 ; PROC : I2C_SQ_RM_READ/I2C_SQ_CT_READ (I2C SEQUENTIQL RANDOM/CURRENT READ) 263 ; FUNC : READ CONSITIVE BYTES FROM I2C DEVICE TO BUFFER 264 ; PARA : I2C_PAGE_IDX : DEVICE ADDRESS A10~A8 265 ; I2C_ADRS : DEVICE ADDRESS A7~A0 (FOR I2C_SQ_RM_READ ONLY) 266 ; : PAGE_COUNT : NUMBER OF BYTES TO BE READ (MUST BE <= BUFFER SIZE) 267 ; : MP0 : BUFFER POINTER 268 ; REG : ACC, MP0, IAR0 269 ; CALL : I2C_START, I2C_DEV_SEL_W, I2C_SET_ADRS, I2C_DEV_SEL_R,READ_BYTE, DELAY_10, 第五章 进阶实验篇 5-219 270 ; I2C_STOP 271 ; RETN : DATA IN BUFFER SPECIFIED BY MP0 WHEN CALLING 272 ;==================================================================================== ==== 273 I2C_SQ_RM_READ PROC 274 CALL I2C_START ;START SIGNAL 275 CALL I2C_DEV_SEL_W ;SET DEVICE CODE AND WRITE MODE 276 CALL I2C_SET_ADRS ;I2C START ADDRESS SET IN I2C_ADRR 277 I2C_SQ_CT_READ: 278 CALL I2C_START ;START SIGNAL 279 CALL I2C_DEV_SEL_R ;SET DEVICE CODE AND READ MODE 280 READ_NEXT_BYTE: 281 CALL READ_BYTE ;READ 1 BYTE 282 MOV IAR0,A ;SAVE TO DATA BUFFER 283 INC MP0 ;INCREASE BUFFER POINTER BY 1 284 CLR SCL ;MAKE SURE SCL IS LOW 285 SET SDA ;SUPPOSE NO ACK IS INVOKED 286 CLR SDAC ;CONFIG SDA AS OUTPUT MODE 287 SDZ PAGE_COUNT ;PAGE_COUNT-1 = 0? 288 CLR SDA ;NO, INVOKE ACK (SDA=0)FOR NEXT BYTE 289 CALL DELAY_10 ;DELAY 290 SET SCL ;SET SCL=1, ACK SIGNAL TO I2C DEVICE 291 CALL DELAY_10 ;DELAY 5 292 CLR SCL ;SET SCL=0 293 CALL DELAY_10 ;DELAY 294 SNZ SDA ;PAGE_COUNT = 0? 295 JMP READ_NEXT_BYTE ;NO, READ NEXT BYTE 296 CALL I2C_STOP ;STOP SIGNAL 297 RET 298 I2C_SQ_RM_READ ENDP 299 ;==================================================================================== ==== 300 ; PROC : I2C_BYTE_WRITE 301 ; FUNC : WRITE 1 BYTE(BYTE_DATA) TO I2C DEVICE ADRS SPECIFIED BY I2C_ADRS 302 ; PARA : I2C_PAGE_IDX : DEVICE ADDRESS A10~A8 303 ; I2C_ADRS : DEVICE ADDRESS A7~A0 304 ; BYTE_DATA : DATA TO BE WRITTEN 305 ; REG : ACC 306 ; CALL : I2C_START, I2C_DEV_SEL_W, I2C_SET_ADRS, WRITE_BYTE, DELAY_10, I2C_STOP,DELAY_10 307 ; DELAY 308 ;==================================================================================== ==== 309 I2C_BYTE_WRITE PROC 310 CALL I2C_START ;START SIGNAL 311 CALL I2C_DEV_SEL_W ;DEV. SELECT CODE WITH WRITE 312 CALL I2C_SET_ADRS ;SET DEVICE START ADDRESS 313 MOV A,BYTE_DATA 5-220 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 314 CALL WRITE_BYTE 315 SET SDAC ;CONFIG SDA AS INPUT MODE 316 CALL DELAY_10 ;DELAY 317 SET SCL ;SCL=1 318 CALL DELAY_10 ;DELAY 319 RP_WAIT:SZ SDA ;SDA = 0(DEV. ACK)? 320 JMP RP_WAIT ;NO, WAIT NO_ACK SIGNAL FROM I2C_DEVICE 321 CALL DELAY_10 ;DELAY 322 CLR SCL ;SCL=0 323 CALL I2C_STOP ;STOP CONDITION 324 MOV A,1 325 CALL DELAY ;DELAY 5mS FOR tW 326 RET 327 I2C_BYTE_WRITE ENDP 328 ;==================================================================================== ==== 329 ; PROC : I2C_PAGE_WRITE 330 ; FUNC : WRITE CONSITIVE BYTES TO I2C DEVICE FORM BUFFER(PINTED BY MP0) 331 ; PARA : I2C_PAGE_IDX : DEVICE ADDRESS A10~A8 332 ; I2C_ADRS : DEVICE ADDRESS A7~A0 (FOR I2C_SQ_RM_READ ONLY) 333 ; : PAGE_COUNT : NUMBER OF BYTES TO BE READ (MUST BE <= 16) 5 334 ; : MP0 : BUFFER POINTER 335 ; REG : ACC, MP0, IAR0 336 ; CALL : I2C_START, I2C_DEV_SEL_W, I2C_SET_ADRS, WRITE_BYTE, DELAY_10, I2C_STOP 337 ;==================================================================================== ==== 338 I2C_PAGE_WRITE PROC 339 CALL I2C_START ;START SIGNAL 340 CALL I2C_DEV_SEL_W ;DEV. SELECT CODE WITH WRITE 341 CALL I2C_SET_ADRS ;SET DEVICE START ADDRESS 342 WRITE_NEXT_BYTE: 343 MOV A,IAR0 ;READ BUFFER DATA 344 INC MP0 ;INCREASE DATA POINTER BY 1 345 CALL WRITE_BYTE ;SERIAL OUT 1 BYTE IN Acc 346 SET SDAC ;CONFIG SDA AS INPUT MODE 347 CALL DELAY_10 ;DELAY 348 SET SCL ;SCL=1 349 CALL DELAY_10 ;DELAY 350 WP_WAIT: SZ SDA ;SDA = 0(DEV. ACK)? 351 JMP WP_WAIT ;NO, WAIT NO_ACK SIGNAL FROM I2C_DEVICE 352 CALL DELAY_10 ;DELAY 353 CLR SCL ;SCL=0 354 CALL DELAY_10 ;DELAY 355 SDZ PAGE_COUNT ;PAGE_COUNT-1 = 0? 356 JMP WRITE_NEXT_BYTE ;NO, WRITE NEXT BYTE 357 CALL I2C_STOP ;STOP CONDITION 358 MOV A,1 第五章 进阶实验篇 5-221 359 CALL DELAY ;DELAY 5mS FOR tW 360 RET 361 I2C_PAGE_WRITE ENDP 362 ;==================================================================================== ==== 363 ; PROC : I2C_STOP 364 ; FUNC : GENERATE I2C STOP CONDITION 365 ; CALL : DELAY10 366 ;==================================================================================== ==== 367 I2C_STOP PROC 368 CLR SCL ;SET SCL=0 369 CLR SDA ;SET SDA=0 370 CLR SDAC ;CONFIG SDA AS OUTPUT MODE 371 CALL DELAY_10 ;DELAY 372 SET SCL ;SET SCL=1 373 CALL DELAY_10 ;DELAY 374 CLR SDA ;SET SDA=0 375 CALL DELAY_10 ;DELAY 376 SET SDA ;SET SDA=1 377 RET 378 I2C_STOP ENDP 379 ;==================================================================================== 5 ==== 380 ; PROC : WRITE_BYTE 381 ; FUNC : SERIAL OUT DATA IN Acc VIA SDA & SCL 382 ; PARA : ACC : DATA TO BE WRITTEN 383 ; REG : I2C_DATA, BYTE_COUNT 384 ; CALL : DELAY10 385 ;==================================================================================== ==== 386 WRITE_BYTE PROC 387 CLR SCL ;SET SCL=0 388 CLR SDAC ;CONFIG SDA AS OUTPUT MODE 389 MOV I2C_DATA,A ;RESERVED DATA IN TX BUFFER 390 MOV A,8 ;SET 8 BIT COUNTER 391 MOV BYTE_COUNT,A 392 WRITE_0: CLR SDA ;SET SDA=0 393 SZ I2C_DATA.7 ;IS DATA BIT = 0? 394 SET SDA ;NO, SET SDA=1 395 CALL DELAY_10 ;DELAY 396 SET SCL ;SET SCL=1 397 CALL DELAY_10 ;DELAY 398 CLR SCL ;SET SCL=0 399 CALL DELAY_10 ;DELAY 400 RL I2C_DATA ;SHIFT TX BUFFER 401 SDZ BYTE_COUNT ;BYTE_COUNT-1 = 0? 5-222 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 402 JMP WRITE_0 ;NO, WRITE NEXT BIT 403 RET ;YES, RETURN. 404 WRITE_BYTE ENDP 405 ;==================================================================================== ==== 406 ; PROC : READ_BYTE 407 ; FUNC : SERIAL IN DATA TO Acc VIA SDA & SCL 408 ; REG : BYTE_COUNT 409 ; CALL : DELAY10 410 ; RETN : I2C_DATA : DATA READ BACK FROM I2C DEVICE 411 ;==================================================================================== ==== 412 READ_BYTE PROC 413 SET SDAC ;CONFIG SDA AS INTPUT MODE 414 MOV A,8 ;SET 8 BIT COUNTER 415 MOV BYTE_COUNT,A 416 CLR I2C_DATA ;SET DATA=0 417 READ_0: SET SCL ;SET SCL=0 418 CALL DELAY_10 ;DELAY 419 RLC I2C_DATA ;SHIFT DATA BUFFER 420 5 421 422 SZ SDA SET I2C_DATA.0 CALL DELAY_10 ;SDA = 0 ;NO, SET DATA BIT =1 ;DELAY 423 CLR SCL ;SET SCL=0 424 CALL DELAY_10 ;DELAY 425 SDZ BYTE_COUNT ;BYTE_COUNT-1 = 0? 426 JMP READ_0 427 MOV A,I2C_DATA ;RELOAD RX DATA TO Acc 428 RET ;YES, RETURN 429 READ_BYTE ENDP 430 ;==================================================================================== ==== 431 ; PROC : CHECK_ACK 432 ; FUNC : WAIT FOR ACK SIGNAL FROM I2C DEVICE 433 ; CALL : DELAY10 434 ;==================================================================================== ==== 435 CHECK_ACK PROC 436 SET SDAC ;CONFIG SDA AS INPUT MODE 437 CALL DELAY_10 ;DELAY 438 SET SCL ;SET SCL=1 439 CALL DELAY_10 ;DELAY 440 WAIT_ACK: 441 SZ SDA ;ACK SINGLE SET ? 442 JMP WAIT_ACK ;NO, WAIT ACK 443 CALL DELAY_10 ;YES, DELAY 444 CLR SCL ;SET SCL=0 第五章 进阶实验篇 5-223 445 CALL DELAY_10 ;DELAY 446 RET 447 CHECK_ACK ENDP 448 ;==================================================================================== ==== 449 ; PROC : DELAY_10 450 ; FUNC : DELAY 10 uS(@ 4MHZ Fsys) FOR TIMING CONSIDERATION 451 ;==================================================================================== ==== 452 DELAY_10: 453 JMP $+1 454 JMP $+1 455 JMP $+1 456 RET 457 ;==================================================================================== ==== 458 ; PROC : GETKEYS 459 ; FUNC : READ MULTIPLE KEY INPUT(0~9) UNTIL "ENTER" PRESSED OR COUNT > 15 460 ; REG : ACC,MP0,IAR0, BUFFER[0~15] 461 ; CALL : READ_KEY_PRESSED 462 ; RETN : BUFFER[0] : THE NUMBER OF KEY INPUT 463 ; : BUFFER[1~15] : INPUT KEY CODE 464 ;==================================================================================== 5 ==== 465 GETKEYS PROC 466 MOV A,OFFSET BUFFER[1] 467 MOV MP0,A 468 CLR BUFFER[0] 469 GETKEY_1: 470 CALL READ_KEY_PRESSED ;GET KEY 0~9 AND ENTER 471 XOR A,0FH 472 SZ Z 473 RET 474 MOV A,KEY_PS 475 SUB A,10 476 SZ C 477 JMP GETKEY_1 478 MOV A,KEY_PS 479 MOV IAR0,A 480 ADD A,30H ;CONVERTTO ASCII 481 CALL WLCMDM ;LCM DISPLAY 482 INC MP0 483 INC BUFFER[0] ;KEY COUNT+1 484 MOV A,BUFFER[0] 485 XOR A,15 486 SNZ Z 487 JMP GETKEY_1 5-224 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 488 RET 489 GETKEYS ENDP 490 ;==================================================================================== ==== 491 ; PROC : READ_KEY_PRESSED 492 ; FUNC : SCAN 4x4 MATRIX ON KEY_PORT UNTIL KEY PRESSED, AND RETURN THE PRESSED KEY 493 ; NUMBER AFTER KEY RELEASED. 494 ; REG : ACC,KEY_PS 495 ; RETN : A AND KEY_PS(0~F FOR PRESSED KEY NUMBER) 496 ;==================================================================================== ==== 497 READ_KEY_PRESSED PROC 498 CALL READ_KEY ;SCAN KEYPAD 499 MOV A,16 500 XOR A,KEY 501 SZ Z ;IS KEY BEEN PRESSED? 502 JMP READ_KEY_PRESSED ;NO, RE-SCAN KEYPAD 503 MOV A,KEY 504 MOV KEY_PS,A ;RESERVED KEY CODE 505 MOV A,5 506 CALL DELAY 5 507 WAIT_KEY_RELEASED: 508 CALL READ_KEY ;DELAY 50mS ;SCAN KEYPAD 509 MOV A,16 510 XOR A,KEY 511 SZ ACC ;IS KEY BEEN RELEASED? 512 JMP WAIT_KEY_RELEASED ;NO, RE-SCAN KEYPAD 513 MOV A,5 514 CALL DELAY ;DELAY 50mS 515 MOV A,KEY_PS 516 RET 517 READ_KEY_PRESSED ENDP 518 ;==================================================================================== ==== 519 ; SCAN 4x4 MATRIX ON KEY PORT AND RETURN THE CODE IN KEY REGISTER 520 ; IF NO KEY BEEN PRESSED, KEY=16. 521 ;==================================================================================== ==== 522 READ_KEY PROC 523 MOV A,11110000B 524 MOV KEY_PORTC,A ;CONFIG PORT 525 MOV KEY_PORTPU,A 526 SET KEY_PORT ;INITIAL PORT 527 CLR KEY ;INITIAL KEY REGISTER 528 MOV A,04 529 MOV COUNT,A ;SET ROW COUNTER 530 CLR C ;CLEAR CARRY FLAG 第五章 进阶实验篇 5-225 531 SCAN_KEY: 532 RLC KEY_PORT ;ROTATE SCANNING BIT 533 SET C ;MAKE SURE C=1 534 SNZ KEY_PORT.4 ;COLUMN 0 PRESSED? 535 JMP END_KEY ;YES. 536 INC KEY ;NO, INCREASE KEY CODE. 537 SNZ KEY_PORT.5 ;COLUMN 1 PRESSED? 538 JMP END_KEY ;YES. 539 INC KEY ;NO, INCREASE KEY CODE. 540 SNZ KEY_PORT.6 ;COLUMN 2 PRESSED? 541 JMP END_KEY ;YES. 542 INC KEY ;NO, INCREASE KEY CODE. 543 SNZ KEY_PORT.7 ;COLUMN 3 PRESSED? 544 JMP END_KEY ;YES. 545 INC KEY ;NO, INCREASE KEY CODE. 546 SDZ COUNT ;HAVE ALL ROWs BEEN CHECKED? 547 JMP SCAN_KEY ;NO, NEXT ROW. 548 END_KEY: 549 RET 550 READ_KEY ENDP 551 ;==================================================================================== ==== 552 ; PROC : PRINT 5 553 ; FUNC : PRINT THE STRING POINTED BY ACC AT LCM CURRENT ADRESS . STRING MUST END WITH 0 554 ; PARA : ACC : POINTER FOR STRING START ADDRESS (LAST PAGE) 555 ; REG : TBLP 556 ;==================================================================================== ==== 557 PRINT PROC 558 MOV TBLP,A ;LOAD TABLE POINTER 559 PRINT_1:TABRDL ACC ;READ STRING 560 XOR A,NULL 561 SZ Z ;END OF STRING CHARACTER? 562 RET ;YES, STOP PRINT 563 TABRDL ACC ;NO, RE-READ 564 CALL WLCMDM ;SEND TO LCD 565 INC TBLP ;INCREASE DATA POINTER 566 JMP PRINT_1 ;NEXT CHARACTER 567 PRINT ENDP 568 ;==================================================================================== ==== 569 ; PROC : INIT_LCM 570 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 571 ; REG : ACC 572 ;==================================================================================== ==== 5-226 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 573 INIT_LCM PROC 574 CLR LCM_EN ;SET EN=0 575 CLR LCM_RW ;SET RW=0 576 CLR LCM_RS ;SET RS=0 577 CLR LCM_ENC ;CONFIG EN AS O/P MODE 578 CLR LCM_RWC ;CONFIG RW AS O/P MODE 579 CLR LCM_RSC ;CONFIG RS AS O/P MODE 580 581 MOV A,38H ;FUNCTION SET: 4-BIT,2-LINE,5X10 DOTS 582 CALL WLCMCM 583 MOV A,0CH ;ON/OFF CONTR: DISPLAY ON,CURSOR BLINKING OFF 584 CALL WLCMCM 585 MOV A,06H ;ENTRY MODE : INCREMENT,DISPLAY NOT SHIFT 586 CALL WLCMCM 587 MOV A,01H ;CLEAR DISPLAY 588 CALL WLCMCM 589 RET 590 INIT_LCM ENDP 591 ;==================================================================================== ==== 592 ; PROC : WLCMDM/WLCMCM 5 593 ; FUNC : WRITE DATA/COMMAND TO LCM AND RETURN AC ADDRESS 594 ; PARA : ACC : COMMAND/DATA 595 ; REG : ACC,DC_FLAG,LCM_TEMP 596 ; RETN : LCM_AC : 1 BUSY BIT + 7-BIT AC 597 ;==================================================================================== ==== 598 WLCMDM PROC 599 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 600 JMP $+2 601 WLCMCM: CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 602 MOV LCM_TEMP,A 603 SET LCM_DATAPORTC ;CONFIG LCM_DATAPORT AS I/P MODE 604 CLR LCM_RS ;SET RS=0 (IR) 605 SET LCM_RW ;SET RW=1 (READ) 606 NOP ;FOR TAS 607 WF: SET LCM_EN ;SET EN=1 608 NOP ;FOR TDDR 609 MOV A,LCM_DATAPORT 610 MOV LCM_AC,A 611 CLR LCM_EN ;SET EN=0 612 SZ LCM_AC.7 ;IS LCM BUSY? 613 JMP WF ;YES, JUMP TO WAIT 614 CLR LCM_DATAPORTC ;NO, CONFIG LCM_DATAPORT AS O/P MODE 615 MOV A,LCM_TEMP 616 MOV LCM_DATAPORT,A ;LATCH DATA/COMMAND ON LCM_DATAPORT 617 CLR LCM_RW ;SET RW=0 (WRITE) 第五章 进阶实验篇 5-227 618 CLR LCM_RS ;SET RS=0 (IR) 619 SZ DC_FLAG ;IS COMMAND WRITE? 620 SET LCM_RS ;NO, SET RS=1 (DR) 621 SET LCM_EN ;SET EN=1 622 NOP ;FOR PWEN 623 CLR LCM_EN ;SET EN=0 624 RET 625 WLCMDM ENDP 626 ;==================================================================================== ==== 627 ; PROC : DELAY 628 ; FUNC : DEALY ABOUT ACC*10mS 629 ; PARA : ACC : DELAY FACTOR 630 ; REG : DEL1,DEL2,DEL3 631 ;==================================================================================== ==== 632 DELAY PROC 633 MOV DEL1,A ;SET DEL1 COUNTER 634 DEL_1: MOV A,30 635 MOV DEL2,A ;SET DEL2 COUNTER 636 DEL_2: MOV A,110 637 MOV DEL3,A ;SET DEL3 COUNTER 638 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 5 639 JMP DEL_3 640 SDZ DEL2 ;DEL2 DOWN COUNT 641 JMP DEL_2 642 SDZ DEL1 ;DEL1 DOWN COUNT 643 JMP DEL_1 644 RET 645 DELAY ENDP 646 ORG LASTPAGE 647 STR_1: DC '1.BYTE_WR 2.PAGE_WR', NULL ;STRING DEFINE 1 648 STR_2: DC '3.SRR 4.RCR 5.RSCR', NULL ;STRING DEFINE 2 649 STR_3: DC 'BW: PRESS 0-9, ENTER', NULL ;STRING DEFINE 3 650 STR_4: DC 'PW: PRESS 0-9, ENTER', NULL ;STRING DEFINE 4 651 STR_5: DC 'SEUQENTIAL RANDOM RD', NULL ;STRING DEFINE 5 652 STR_6: DC 'CURRENT RANDOM READ', NULL ;STRING DEFINE 6 653 STR_7: DC 'SEQ. CURRENT READ', NULL ;STRING DEFINE 7 654 STR_8: DC 'EEPROM WRITTING.....',NULL ;STRING DEFINE 8 655 END 程程序序说说明明:: 4 载入”5-17.INC”定义档,其内容请参考随书光盘中的内容。 7~23 依序定义变量地址。 5-228 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 27 30~32 33 34~41 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 关闭 CP0、CP1 功能,并设定 ADC 脚位输入为 I/O 功能。 调用 INIT_LCM 子程序,对 LCM 进行定义。 将光标位置设为第一列首行,其次在 LCM 上显示主功能选单,显示效果如下: 1.BYTE_WR:以 Byte Write 方式将输入数据写至 HT24LC16; 2.PAGE_WR:以 Page Write 方式将输入数据写至 HT24LC16; 3.SRR:以 Sequential Random Read 方式读取 HT24LC16 的数据; 4.RCR:以 Random Read 与 Current Read 方式读取 HT24LC16 的数据; 5.RSCR:以 Random Read 与 Sequential Current Read 方式读取 HT24LC16 数据; 43~58 调用 READ_KEY_PRESSED 子程序,并依使用者选择的功能(“1”~“5”)以 计算式跳跃的方式(ADDM A,PCL)跳至各功能对应的程序进入点;若使用者压下 5 非 1~5 的按键将不予理会。 59~90 “Byte Write”功能程序进入点:首先 60~63 行在 LCM 显示如下的文字,提示使 用者输入“0”~“9”的数字或“ENTER”键结束输入。 64 行调用 GETKEYS 子程序读取键值,此子程序会将使用者压下的按键值存于 BUFFER[]数组并显示于 LCM 的第二列,BUFFER[0]则代表压下的按键个数;所以 65~68 行的程序若发现 BUFFER[0]=0,则不予理会并跳回 MAIN 处重新执行。69~ 72 行在 LCM 显示如下画面,提示使用者 HT24LC16 正准备进入烧录程序。 74、75 行分别将 I2C_PAGE_IDX、I2C_ADRS 寄存器清除为零,此目的是在设定 写 入 HT24LC16 的 起 始 地 址 A10 ~ A0 为 000h; 接 着 设 定 写 入 的 Byte 数 为 BUFFER[0]+1(因为除了写入使用者输入的按键值之外,尚需再包含输入的按键个 数)。78~90 行是在设定 MP0 指向 BUFFER[0]后,以间接寻址法将使用者输入的 数据以 Byte Write 方式逐一写至 HT24LC16,待所有数据均写入后跳回 MAIN 处重 第五章 进阶实验篇 5-229 91~115 新执行。请注意,此处采用的是 Byte Write 方式,所以在每笔数据的写入都需调用 一次 I2C_BYTE_WRITE 子程序。 “Page Write”功能程序进入点: 92~95 行首先在 LCM 显示如下的文字,提示使 用者输入“0”~“9”的数字或“ENTER”键结束输入。 96 行调用 GETKEYS 子程序读取键值,此子程序会将使用者压下的按键值存于 BUFFER[]数组并显示于 LCM 的第二列,BUFFER[0]则代表压下的按键个数;所以 87~100 行的程序若发现 BUFFER[0]=0,则不予理会并跳回 MAIN 处重新执行。 101~104 行在 LCM 显示如下画面,提示使用者 HT24LC16 正准备进入烧录程序。 106、107 行分别将 I2C_PAGE_IDX、I2C_ADRS 寄存器清除为零,此目的是在设 定写入 HT24LC16 的起始地址 A10~A0 为 000h;接着设定写入的 Byte 数为 BUFFER[0]+1(因为除了写入使用者输入的按键值之外,尚需再包含输入的按键个 5 数)。110~115 行是在设定 MP0 指向 BUFFER[0]后,以间接寻址法将使用者输入 的数据以 Page Write 方式写至 HT24LC16,并跳回 MAIN 处重新执行。请注意,此 处采用的是 Page Write 方式,所以只需调用一次 I2C_PAGE_WRITE 子程序就可将 输入数据写至 HT24LC16。 116~129 “Sequential Random Read”功能程序进入点: 117~118 行首先在 LCM 显示如 下的文字,提示使用者此功能所采取的读取方法为 Sequential Random Read。 119~120 行将 I2C_PAGE_IDX、I2C_ADRS 寄存器清除为零,此目的是在设定读 取 HT24LC16 的起始地址 A10~A0 为 000h;接着调用 I2C_RM_READ 子程序读取 当初所存数据的字节总数。123~127 行则重新设定 I2C_ADRS 为 001h 与读取的 字 节 个 数 , 并 将 MP0 指 向 BUFFER[1] 的 起 始 地 址 , 紧 接 着 就 调 用 I2C_SQ_RM_READ 子程序读取 HT24LC16 的数据并跳至 RSCR_1 进行数据显示 的程序。 5-230 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 130~147 “Random Read”与“Current Read”功能程序进入点: 131~132 行首先在 LCM 显示如下的文字,提示使用者此功能所采取的读取方法为 Random Read 与 Current Read 的结合。 133~134 行将 I2C_PAGE_IDX、I2C_ADRS 寄存器清除为零,此目的是在设定读 取 HT24LC16 的起始地址 A10~A0 为 000h;接着调用 I2C_RM_READ 子程序读取 当初所存数据的字节总数,经此次读取后,HT24LC16 内部的地址计数器为 01h, 恰可做为 Current Read 读取数据时的起始地址。137~140 行则设定读取的字节总 数,并将 MP0 指向 BUFFER[1]的起始地址,紧接着就调用 I2C_CT_READ 子程序 逐一读取 HT24LC16 的数据并跳至 RSCR_1 进行数据显示的程序。请注意,此处 采用的是 Current Read 方式,所以每笔数据的读取都需调用一次 I2C_CT_READ 子程序。 5 148~179 “Sequential Current Read”功能程序进入点: 149~150 行首先在 LCM 显示如 下的文字,提示使用者此功能所采取的读取方法为 Sequential Current Read。 151~152 行将 I2C_PAGE_IDX、I2C_ADRS 寄存器清除为零,此目的是在设定读 取 HT24LC16 的起始地址 A10~A0 为 000h;接着调用 I2C_RM_READ 子程序读取 当初所存数据的字节总数,经此次读取后,HT24LC16 内部的地址计数器为 01h, 恰可做为 Sequential Current Read 读取数据时的起始地址。154~159 行则设定读 取 的 字 节 总 数 , 并 将 MP0 指 向 BUFFER[1] 的 起 始 地 址 , 紧 接 着 就 调 用 I2C_SQ_CT_READ 子程序读取 HT24LC16 的数据并跳至 RSCR_1 进行数据显示 的程序。请注意,此处采用的是 Sequential Current Read 方式,所以只调用一次 I2C_SQ_CT_READ 子程序即可读取所储存的数据。 161~174 将读回的数值显示于 LCM 上;此时 BUFFER[0]代表读回的字节总数,所以 161~ 164 行若判断 BUFFER[0]为零时将不予理会,并跳至 MAIN 处重新执行程序。否则, 以间接寻址法将读回的数据逐一由 BUFFER 取出,并转换为 ASCII 码后显示于 LCM 上。 175~179 等待使用者压下“ENTER”键后跳至 MAIN 处重新执行程序。 第五章 进阶实验篇 5-231 185~199 I2C_START 子程序,产生 I2C-BUS 传输中的“START”Condition,参考【图 5-17-4】 本实验前述的说明。 207~219 I2C_DEV_SEL_W 与 I2C_DEV_SEL_R 子程序,送出从机选择地址码、R/W 句柄 以及 A10~A8 地址信息;请参考本实验前述的说明。 227~232 I2C_SET_ADRS 子程序,送出 A7~A0 地址信息;并调用 CHECK_ACK 子程序以 确认是否有从机对此地址产生响应,详情请参考本实验前述的说明。 243~261 I2C_RM_READ、I2C_CT_READ 子程序,实现 HT24LC16 Random Read 与 Current Read 读取程序,其间的差异仅在与后者不需送出地址信息,其所读取的地址由 HT24LC16 内部的 AC(地址计数器)决定;请参考【图 5-17-17】本实验前述的说 明。 274~299 I2C_SQ_RM_READ、I2C_SQ_CT_READ 子程序,实现 HT24LC16 Sequential Random Read 与 Sequential Current Read 读取程序,其间的差异仅在与后者不需 送出地址信息,其所读取的地址由 HT24LC16 内部的 AC(地址计数器)决定;请 参考【图 5-17-20】本实验前述的说明。这两个读取子程序与 I2C_RM_READ、 I2C_CT_READ 子程序其实大同小异,灌上 Sequential 是代表其连续读取数个(由 PAGE_COUNT 指定)地址的内容;而 I2C_RM_READ、I2C_CT_READ 则仅读取 5 一个地址的内容。 310~328 I2C_BYTE_WRITE 子程序,实现 HT24LC16 Byte Write 写入程序;请参考【图 5-17-5】本实验前述的说明。 339~362 I2C_PAGE_WRITE 子程序,实现 HT24LC16 Byte Write 写入程序;请参考【图 5-17-20】本实验前述的说明。写入个数由 PAGE_COUNT 寄存器指定,但注意 PAGE_COUNT≦16 的限制。 368~379 I2C_STOP 子程序,产生 I2C-BUS 传输中的“STOP”Condition,参考【图 5-17-4】 本实验前述的说明。 387~405 WRITE_BYTE 子程序,搭配 SCL、SDA 控制脚位的状态变化,将 8-Bit 数据 (I2C_DATA)传送给 HT24LC16;请参考【图 5-17-8】本实验前述的说明。 413~430 READ_BYTE 子程序,搭配 SCL、SDA 控制脚位的状态变化,由 HT24LC16 读回 8-Bit 数据(I2C_DATA);请参考【图 5-17-9】本实验前述的说明。。 436~448 CHECK_ACK 子程序,搭配 SCL、SDA 控制脚位的状态变化,等待从机回传 ACK 信号;请参考本实验前述的说明。 453~457 DELAY_10 子程序,在工作频率为 4MHz 时延迟 10μS。 5-232 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 466~490 GETKEYS 子程序,调用 READ_KEY_PRESSED 读取按键值(0~9)存放至 BUFFER[1]~BUFFER[15] 寄存器,并显示于 LCM。当压下“F”键或输入键值已 达 15 个则跳离程序并将输入按键个数存于 BUFFER[0]寄存器;若压下“0”~“9” 与“F”以外的按键将不予理会。 498~518 READ_KEY_PRESSED 子程序,调用 READ_KEY 读取按键值当有键压下时则将 键值存至 KEY_PS 寄存器,在确认压下的键放开后始返回原调用处。 523~551 READ_KEY 子程序,请参考【实验 4-7】的说明。 558~568 PRINT 子程序,此子程序负责将定义好的字符串依序显示于 LCM 上。在调用此子 程序之前,除了必须先设定好 LCM 的位置之外,尚需先于 Acc 寄存器中指定字符 串的起始地址(字符串必须存放于最末程序页-Last Page),并请于字符串的最后 一个字符塞入 NULL,代表字符串结束。 574~591 INIT_LCM 子程序,其功能是对 LCM 进行定义: 575~580 LCM_EN、LCM_RW 与 LCM_RS 定义为输出模式,并设定状态为“0”。 582~583 将 LCM 设定为双行显示(N = 1)、使用八位(DB7 ~ DB0)控制模式(DL = 1)、 5 5×7 点矩阵字型(F = 0)。 584~585 将 LCM 设定为显示所有数据(D = 1)、显示光标(C = 1)、光标所在位置的字会 闪烁(B = 1)。 586~587 将 LCM 的地址计数器(AC)设为递加(I/D = 1)、显示器画面不因读写数据而移 动(S = 0)。 588~589 将 LCM 整个显示器清空。 599~626 WLCMDM 与 WLCMCM 子程序,请参考【实验 5-6】中的说明。 633~646 DELAY 子程序,延迟时间的计算请参考【实验 4-1】中的说明。 647~655 最末页数据键表区,存放本实验所使用的字符串数据。 【程序5-17】将近700行的指令,乍看之下无不令人震慑!尤其,若您是单片 机的初学者,很可能因此却步而踌躇不前。不过,若读者是由【实验4-1】按部就 班的依循笔者安排的实验内容学习,在历经近40个程序的洗礼之后,应该也能就本 实验的原理说明,对【程序5-17】抽丝剥茧、逐一了解才是! I2C-BUS是由PHILIPS公司开发的两线式串行传输接口,用于连接单片机及其 接口从机。I2C-BUS产生于80年代,最初是为音频和视频设备开发,如今主要在服 务器管理中使用,其中包括从机状态的通信。例如管理员可对各个从机进行查询, 第五章 进阶实验篇 5-233 以管理系统的配置或掌握各从机的功能状态,如电源和系统风扇,可随时监控硬盘、 网络、系统温度等多种参数,增加了系统的安全性,更提升系统管理的方便性。 I2C-BUS最主要的优点是其简单、并具备高效性。由于 I2C接口可直接附加于从机 之上,占用的空间非常小,减少了电路板的面积及芯片引脚数,降低了从机间互联 的成本。I2C-BUS的长度可达25英尺,并且能够以10Kbps的最大传输速率支持四 十个从机。 I2C-BUS的另一个优点支持“多主控(Multimastering)”, Bus上任 何能够进行发送和接收的从机都可以成为主控者(Master)。主控者可控制信号的 传输和频率;当然,在同一时间点上只能有一个主控者。 本实验虽是以HT24LC16 E2PROM做为I2C-BUS的学习对象,然而【程序5-17】 中许多与I2C-BUS相关的子程序只需稍加修改,有些甚至可以直接应用至其它具备 I2C-BUS接口从机的数据传输,如CAT5270、CAT5271(安森美半导体公司的数 字可程序电位计-DPP IC)、IR3725(International Rectifier的功率监控器IC)、 LTC2301、LTC2305、LTC2309(Linear Technology的12位模拟数字转换器)、 APDS-9300(Avago Technology的数字式环境光传感器)、MSi002(Mirics发表 的多波段调谐器IC)、…,具备I2C-BUS的从机只能以“足繁不及备载”来形容! 提出这些说明,无非是希望激发读者学习的动力,对本实验的所介绍的内容能完全 的消化、吸收。 5-17-5 动动脑+动动手: 5 参考【图 5-17-1】与【程序 5-17】,请以”E” 键做为 Back-Delete Key,让 使用者于输入过程中可以删、改已输入的数值。 若将【图 5-17-1】电路中的 J1 排针设定,由原来的“1-2”改为“2-3”短路; 请问执行结果有何差异? 5-234 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5-18 MicroWire-BUS接口E2PROM读写控制实验 5-18-1 目 的: 以4x4键盘为输入设备,选择程序功能: WRITE 、 WRITE ALL、 ERASE .、 ERAL与 RD,这五个选项分别代表HT93LC46的“WRITE”、“WRAL”、 “ERASE” 、“ERAL”以及“Read”指令。当选择 、 时则可将输入数值储 存至HT93LC46;当选择 则可读出储存于HT93LC46的数据并显示于LCM上; 、 选项则可清除特定地址或所有地址内的储存数据。 5-18-2 学习重点: 通过本实验,读者应熟悉MicroWire-BUS串行界面E2PROM-HT93LC46的 读、写控制方式;对于本实验所提供相关子程序的原理与运用方式也应了如指掌。 5-18-3 电路图: 5 PS:若使能PA[7:4]Pull-high功能,则10kΩ电阻可省略。 【图 5-18-1】HT93LC46 读写控制实验电路 MicroWire-BUS系由National Semiconductor所发展的串行总线传输接口,以 四条控制线(CS、Clock、Data In、Data OUT)完成数据传输的动作,其总线传 输速度上限为1MHz。【表5-18-1】为盛群半导体股份有限公司3-Wire E2PROM产 品型号,以下将以HT93LC46为例说明MicroWire-BUS接口的控制方式。【图5-18-2】 为HT93LC46的引脚及其功能概述,完整的电气特性还是请读者参考光盘片中的原 厂IC数据手册。 第五章 进阶实验篇 5-235 Part No. HT93LC46 HT93LC66 HT93LC86 【表 5-18-1】Holtek 3-Wire E2PROM 产品型号 Capacity 64x16/128x8 VDD 2.2V~5.5V Clock Rate (MHz) 2 Write Speed @2.4V (ms) 5 Operating Current @5V (mA) 5 256x16/512x8 2.2V~5.5V 2 5 5 1024x16/2048x8 2.2V~5.5V 2 5 5 Standby Current @5V (uA) 10 10 10 所有MicroWire-BUS的控制动作及数据读写,都是通过CS、SK、DI、DO信号 来完成,为了适用各种型态的存储器数组读取(Memory Array)方式,HT93LC46 提供七种不同的指令(如【表5-18-2】)。HT93LCxx系列的存储器架构可由ORG 脚位定义成8-Bit(ORG=0)或16-Bit(ORG=1)的组织型态,以HT93LC46为例, 其容量为1K Bits但可定义为128×8-Bit或64×16-Bit两种组织型态。 引脚 功能 概 述 芯片选择信号;当 CS=“High”方能进行数据的读、写、清除等动作。但请注意, CS Chip Select CS 不能一直维持在“High”,因为 HT93LC46 是以 CS 信号的上升沿(Rising Edge) 来重置内部的系统状态以便开始接受新的指令;而其下降沿(Falling Edge)除了代表 指令周期的结束之外,同时也是启动内部数据开始烧录至 E2PROM 的重要依据。 串行时钟输入引脚:Master 与 HT93LC46 间的数据传输同步信号;在写入模式时, SK Serial Data Clock HT93LC46 是在 SK 信号的上升沿将 DI 上的数据抓入内部的寄存器中。在读出模 5 式时,HT93LC46 是在 SK 信号的上升沿将寄存器中的数据移至 DO。 DI Seria Data Input 串行数据输入端,搭配 SK 信号将数据串行移至 HT93LC46 的内部寄存器。 DO Serial Data Ouput 串行数据输出端,搭配 SK 信号 HT93LC46 会将的内部寄存器数据串行送出至 DO。 ORG Internal Organization 内存结构型态。若接地则为 8 位内存组织型态:当浮接或接至 VCC 时则为 16 位 内存组织型态。 VSS Ground 接地。 NC No Connect VCC Supply Voltage 工作电压输入端,工作电压 2.7~5.5V。 【图 5-18-2】HT93LCxx 的引脚及功能 【表 5-18-2】HT93LC46 Instruction Set Instruction Comments Start Opcode Address Field Data Field Bit Field ORG=0 ORG=1 ORG=0 ORG=1 READ Read data 1 ERASE Erase data 1 WRITE Write data 1 EWEN Erase/Write Enable 1 EWDS Erase/Write Disable 1 ERAL Erase All 1 WRAL Write All 1 10 A6~A0 A5~A0 D7~D0 D15~D0 11 A6~A0 A5~A0 - - 01 A6~A0 A5~A0 D7~D0 D15~D0 00 11xxxxx 11xxxx - - 00 00xxxxx 00xxxx - - 00 10xxxxx 10xxxx - - 00 01xxxxx 01xxxx D7~D0 D15~D0 所有的指令都必须在CS引脚信号为High的情况下方可有效执行,接下来就一 一介绍这七种指令的功能: “READ”指令:可用来读取HT93LC46内部的数据,至于是读取哪一个位置则 是由Address Field的A5~A0(ORG=“1”)或A6~A0(ORG=“0”)决 5-236 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 定,请参考【图5-18-3】。在CS由Low拉为High后,接着要循序将Start、Op-Code 与AN~A0等位送至HT93LC46,请注意HT93LC46是在SK的Rising Edge将DI 上的数据抓入内部的寄存器。所以在将SK信号拉为High之前,一定要确定所 要写入的位值已经稳定的呈现在DI脚位上。当接收完A0位的同时,DO脚位会 呈现低电位状态(此即所谓“无效位(Dummy Bit)”);接着HT93LC46就 会开始将AN~A0所指定的地址内容依序(MSB先送)在SK的Rising Edge由 DO串行移出。 【图 5-18-3】HT93LC46 Normal READ Cycle 另外,由于 HT93LC46 可定义成 128×8-Bit 或 64×16-Bit 两种组织型态,所 5 以【图 5-18-3】中的 AN 可为 A6(ORG=0,128×8-Bit 型态)或 A5(ORG =1,64×16-Bit 型态);DX 则可能为 D7 或 D15。由于 HT93LC46 内部的地 址寄存器具有自动递增的功能,如果是要读取连续地址的多笔数据,可以在读 取完第一笔数据后继续将读取频率送至 SK 脚位即可。 “EWEN”指令:执行任何写入指令(“WRITE”、“WRALL”)或清除动作 (“ERASE”、“ERAL”)之前都必须先以“EWEN”(Erase/Write Enable) 指 令 来 使 能 HT93LC46 的 写 入 功 能 。 一 旦 执 行 过 “ EWEN ” 指 令 之 后 , HT93LC46的写入功能将一直处于使能状态,除非执行“EWDS”指令或将电 源(Vcc)完全移除才能回复至禁止写入的状态;请参考【图5-18-4】的时序。 【图 5-18-4】HT93LC46 Erase/Write Enable Cycle 请注意在【图5-18-4】中,地址字段(Address Field)的最高两位一定要为“11”, 而其余位则可任意为“1”或“0”。“EWEN”指令是使能整个芯片的写入与 清除功能,此时Address Field的内容并非代表地址,其最高两位与Op-Code 字 段 组 成 一 个 完 整 的 指 令 让 HT93LC46 的 内 部 控 制 电 路 得 以 辨 识 ; 而 且 第五章 进阶实验篇 5-237 Address Field内的位总数一定要补足七(ORG=「0”)或六(ORG=「1”) 个位。 「WRITE”指令:此指令可将数据(D15~D0或D7~D0)写入HT93LC46的 特定地址(A5~A0或A6~A0),不过请读者注意只有在HT93LC46处于写入 使能的状态时才能完成有效的数据写入动作;所以在执行「WRITE”指令之前, 必须先执行过「EWEN”指令,让HT93LC46处于写入使能状态;请参考【图 5-18-5】的时序。 【图 5-18-5】HT93LC46 Write Cycle 再次提醒读者:HT93LC46是在SK的Rising Edge将DI上的数据抓入内部的寄 存器,所以在将SK信号拉至High前,务必确定所要写入的位状态已稳定的呈 现在DI脚位上。当数据串行移至HT93LC46时,并非直接写到E2PROM存储器 数组,而是先暂存于内部的寄存器中,待CS降为Low时才真正启动寄存器数据 5 烧录至E2PROM的动作。在时序中明确标示出HT93LC46至少需要tPR(Write Cycle Time;约5mS)的时间来完成烧录的动作,在此之前HT93LC46将处于 内部忙碌状态(Busy)。使用者可以再次将CS信号拉为High,并经由DO脚位 来判定HT93LC46是处于忙碌(DO=“0”)或非忙碌(DO=“1”)状态, 参考【图5-18-5】中的Verify阶段,务必确认是在非忙碌(Ready)状态后方能 给HT93LC46新的指令。 “WRAL”指令:其实与“WRITE”指令类似,不过“WRAL”(Write All) 指令会将指定数据(DX~D0)复制到HT93LC46内部所有的存储器数组,请 参考【图5-18-6】。 【图 5-18-6】HT93LC46 Write All Cycle 请注意在【图5-18-6】中, Address Field的最高两位一定要为“01”,而其 5-238 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 余位则可任意为“1”或“0”。“WRAL”指令是将DX~D0写入所有存储器 数组而非某一特定地址,所以此时Address Field的内容并非代表地址,其最高 两位与Op-Code字段组成一个完整的指令让HT93LC46的内部控制电路得以 辨识;而且Address Field内的位总数一定要补足7(ORG=0)或6(ORG=1) 个位。 “EWDS”指令:此指令用来停止HT93LC46的写入以及清除功能,一旦执行 “EWDS”(Erase/Write Disable)指令之后,任何写入(“WRITE”、“WRALL”) 或清除(“ERASE”、“ERAL”)指令都无法对HT93LC46内存的数据产生 影响,唯有再执行一次“EWEN”指令方能重新使能其写入或清除功能。通常 在写入数据至HT93LC46之后会执行“EWDS”指令,以避免因意外的操作或 电路上的噪声改变了原存放的数据。 5 【图 5-18-7】HT93LC46 Erase/Write Disable Cycle 请注意在【图5-18-7】中, Address Field的最高两位一定要为“00”,而其 余位则可任意为“1”或“0”。“EWDS”指令是禁止整个芯片的写入与清除 功能,所以此时Address Field的内容并非代表地址,其最高两位与Opcode字 段组成一个完整的指令让HT93LC46的内部控制电路得以辨识;而且Address Field内的位总数一定要补足七(ORG=“0”)或六(ORG=“1”)个位。 “ERASE”指令:清除特定地址(AN~A0)的数据内容,而所谓“清除”其 实是将“1”写入指定地址的各个位(DX~D0),所以“ERASE”就等同是 “WRITE”指令,只不过DX~D0的位内容全部为“1”,请参考【图5-18-8】。 【图 5-18-8】HT93LC46 Erase Cycle “ERAL”指令:“ERAL”(Erase All)指令用来清除整个芯片内部的存储器 第五章 进阶实验篇 5-239 数组,其实“ERAL”就等同是“WRALL”指令,只不过DX~D0的位内容全 部为“1”,请参考【图5-18-9】: 【图 5-18-9】HT93LC46 Erase All Cycle 请注意在【图5-18-9】中, Address Field的最高两位一定要为“00”,而其 余位则可任意为“1”或“0”。“ERAL”指令是清除HT93LC46内部所有的 存储器数组,所以此时Address Field的内容并非代表地址,其最高两位与 Op-Code字段组成一个完整的指令让HT93LC46的内部控制电路得以辨识;而 且Address Field内的位总数一定要补足七(ORG=“0”)或六(ORG=“1”) 个位。 【 图 5-18-2 】 为 本 实 验 的 电 路 连 接 方 式 , 是 以 HT66F50 的 PE7 ~ PE4 控 制 MicroWire-BUS接口所需的传输信号;电路中是将HT93LC46的ORG脚位接地,因 5 此数据的读写是以Byte的架构进行;根据【表5-18-2】以及指令的说明,此模式下 单片机与HT93LC46间的传输过程可约略区分为: 三位命令码写入(含起始位)、 七位地址字段写入、 八位数据写入与 八位数据读取四大区块,以下的几个子 程序就是以此区块为架构,再搭配前述说明中的时序所撰写,于本范例中经常调用 使用,现就这些子程序的功能与原理加以说明。 WLCMD_93LC46子程序:负责送出起始位、命令码及地址字段至HT93LC46 1 WCMD_93LC46 2 SET 3 MOV 4 MOV 5 WCMD_93LC46_1: 6 CLR 7 SZ 8 SET 9 NOP 10 SET 11 RL 12 CLR 13 SDZ 14 JMP 15 MOV PROC MICORW_CS A,3 COUNT_93LC46,A MICORW_DI OPCODE_REG.2 MICORW_DI MICORW_SK OPCODE_REG MICORW_SK COUNT_93LC46 WCMD_93LC46_1 A,7 ;SET CS=1 ;SET DI=0 ;IF BIT=1, SET DI=1 ;DELAY ;SET SK=1 ;SET SK=0 ;NEXT OPCODE BIT 5-240 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 16 MOV COUNT_93LC46,A 17 WCMD_93LC46_2: 18 CLR MICORW_DI ;SET DI=0 19 SZ ADRS_REG.6 ;IF BIT=1, SET DI=1 20 SET MICORW_DI 21 NOP ;DELAY 22 SET MICORW_SK ;SET SK=1 23 RL ADRS_REG 24 CLR MICORW_SK ;SET SK=0 25 SDZ COUNT_93LC46 26 JMP WCMD_93LC46_2 ;NEXT ADDRESS BIT 27 RL ADRS_REG ;KEEP ADRS_REG UNCHANGED 28 RET 29 WCMD_93LC46 调用时的参数: ENDP OPCODE_REG:OPCODE_REG[2]固定为“1”(Start Bit),OPCODE_REG[1:0]则 为各指令的两位Op-Code。 ADRS_REG:ADRS_REG[6:0]为七位的Address Field。 程序说明: OPCODE_REG的低三位是由一位的Start Bit、两位OP-Code所组成,ADRS_REG的低 5 七位则为Address Field(ORG=0;Byte Mode,128×8 Bits)。在第2行令CS=“1”后, 就依序通过SK与DI引脚电平变化将上述两个寄存器中的10-Bit数据一一送至HT93LC46。 或许读者感到疑惑,在第6行使能HT93LC46后不是应该在完成10-Bit的数据传送后(第27 行)将其除能(Disable)吗?这主要是因为像READ、WRITE与WRAL指令当完成Op-Code 码与地址的传送后,还有后续的数据传输程序需进行。因此笔者并未将除能的动作安排在 此子程序内,以增加其通用性。 WDAT_93LC46子程序:负责将八位数据写至HT93LC46 1 WDAT_93LC46 2 MOV 3 MOV 4 WDAT_93LC46_1: 5 CLR 6 SZ 7 SET 8 NOP 9 SET 10 RL 11 CLR 12 SDZ 13 JMP 14 RET 15 WDAT_93LC46 PROC A,8 COUNT_93LC46,A MICORW_DI DATA_REG.7 MICORW_DI MICORW_SK DATA_REG MICORW_SK COUNT_93LC46 WDAT_93LC46_1 ENDP ;SET DI=0 ;IF BIT=1, SET DI=1 ;DELAY ;SET SK=1 ;SET SK=0 ;NEXT DATA BIT 第五章 进阶实验篇 5-241 调用时的参数: DATA_REG:欲写入 HT93LC46 的数据。 程序说明: WDAT_93LC46 与 WLCMD_93LC46 子程序其实是完全相同的撰写方式,差异在于 WDAT_93LC46 只传送 DATA_REG 内所存放的 8-Bit 的数据(ORG=0,128 ×8 Bits)。 READ_93LC46子程序:负责由HT93LC46读取八位数据 1 READ_93LC46 PROC 2 MOV A,8 3 CLR DATA_REG ;SET DATA_REG=0 4 MOV COUNT_93LC46,A 5 READ_93LC46_1: 6 SET MICORW_SK ;SET SK=1 7 SZ MICORW_DO ;IF DO=1, SET BIT=1 8 SET DATA_REG.7 9 RL DATA_REG 10 CLR MICORW_SK ;SET SK=0 11 SDZ COUNT_93LC46 12 JMP READ_93LC46_1 ;NEXT DATA BIT 5 13 RET 14 READ_93LC46 ENDP 回传参数: DATA_REG:由 HT93LC46 读回的八位数据。 程序说明: 首先将寄存器 DATA_REG 清除为 00h(第 3 行),其次将 SK 引脚设为 High(第 6 行), 此时 HT93LC46 会将数据位由 DO 引脚输出;接着在第 7 行判断 DO 脚位的 状态,若为 High 则将 Data_REG.7 设定为“1”,否则就维持该位原为“0” 的状态,请参考【图 5-18-3】。 WAIT_93LC46子程序:等待HT93LC46结束忙碌状态 1 WAIT_93LC46 2 SET 3 WAIT_93LC46_1: 4 SET 5 NOP 6 CLR 7 SNZ 8 JMP 9 CLR 10 RET PROC MICORW_CS MICORW_SK MICORW_SK MICORW_DO WAIT_93LC46_1 MICORW_CS ;SET CS=1 ;SET SK=1 ;SET SK=0 ;SET CS=0 5-242 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 11 WAIT_93LC46 ENDP 在执行“ERASE”、“ERAL”、“WRITE”与“WRAL”命令之后,可以通过读取 DO 脚位的状态判定 HT93LC46 是否已经完成动作以便进行后续的命令。子程序 中首先将其使能(第 2 行),接着 4~6 行于 SK 引脚产生 High Low 的脉波, 此时 HT93LC46 会将内部状态由 DO 引脚输出,若为“0”则表示其内部尚在 处理,若为“1”则表示其可接受新的命令。 洞悉这四个子程序的原理之后,请读者务必搭配前述有关命令的说明,彻底明 了如何将其搭配运用;例如,若要实现HT93LC46的“EWEN”命令,可采用下列 的程序代码完成: EWEN PROC MOV A,00000100B ;SET EWEN OPCODE MOV OPCODE_REG,A MOV A,01100000B ;SET EWEN OPCODE MOV ADRS_REG,A CALL WCMD_93LC46 ;WRITE OPCODE AND ADDRESS TO 93LC46 CLR MICORW_CS ;SET CS=0 RET 5 EWEN ENDP 又例,若欲实现“WRITE”命令,则程序编码如下,在调用此程序之前只要先在 ADRS_REG设定地址,并将写入的数据置于DATA_REG寄存器就可以了: WRITE PROC MOV MOV CALL CALL CLR A, 00000101B OPCODE_REG,A WCMD_93LC46 WDAT_93LC46 MICORW_CS ;SET WRITE OPCODE ;WRITE OPCODE AND ADDRESS TO 93LC46 ;WRITE DATA TO 93LC46 ;SET CS=0 RET WRITE ENDP 在调用WRITE程序之前,读者别忘了要确认已执行过“EWEN”命令使能 HT93LC46的写入功能;当然啰,在执行完WRITE程序后还需调用WAIT_93LC46 等待其完成写入的动作才能再下达新的指令。以下的范例程序是以4×4键盘输入搭 配LCM显示为主体展现HT93LC46的读写控制;因为多了按键输入以及LCM显示上 的处理程序,所以看起来有点冗长、繁复,但其基本上还是架构在上述几个子程序 的运用上,读者若能耐心体会,相信必能掌握MicroWire-BUS的操作方式了。 5-18-4 程序及流程图: 第五章 进阶实验篇 5-243 5 5-244 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 5 程序5-18 HT93LC46 MICROWire-BUS E2PROM读写控制实验 1 ; PROGRAM : 5-18.ASM (5-18.PJT) 2 ; FUNCTION: LED SCANNING DEMO PROGRAM 3 #INCLUDE HT66F50.INC 2009.1109 By Steven 第五章 进阶实验篇 5-245 4 #INCLUDE 5-18.INC 5 ;======================================================================================== 6 MY_DATA .SECTION 'DATA' ;== DATA SECTION == 7 DEL1 DB ? ;DELAY LOOP COUNT 1 8 DEL2 DB ? ;DELAY LOOP COUNT 2 9 DEL3 DB ? ;DELAY LOOP COUNT 3 10 DC_FLAG DBIT ;LCD DATA/COMMAND FLAG 11 LCM_TEMP DB ? ;BUFFER FOR LCM PROCEDURE 12 LCM_AC DB ? 13 KEY DB ? ;BUFFER FOR READ_KEY PROCEDURE 14 KEY_COUNT DB ? ;BUFFER FOR READ_KEY PROCEDURE 15 KEY_PS DB ? ;BUFFER FOR READ_KEY_PRESSED PROCEDURE 16 COUNT DB ? 17 OPCODE_REG DB ? 18 ADRS_REG1 DB ? 19 ADRS_REG DB ? 20 DATA_REG DB ? 21 COUNT_93LC46 DB ? 22 BUFFER DB 16 DUP(?) 23 BUFFER_COUNT DB ? 24 ;======================================================================================== 25 MY_CODE .SECTION AT 0 'CODE' ;== PROGRAM SECTION == 26 ORG 00H ;HT-46F23 RESET VECTOR 5 27 CLR ACERL ;AD DISABLE 28 MOV A,08h 29 MOV CP0C,A ;CP0 DISABLE 30 MOV CP1C,A ;CP1 DISABLE 31 CALL INIT_93LC46 32 CALL INIT_LCM 33 MAIN: MOV A,80H ;SET LCM LINE 1 34 CALL WLCMCM 35 MOV A,STR_1 ;PRINT STR_1 36 CALL PRINT 37 MOV A,0C0H ;SET LCM LINE 2 38 CALL WLCMCM 39 MOV A,STR_2 ;PRINT STR_1 40 CALL PRINT 41 MENU_1: CALL READ_KEY_PRESSED ;GET MENU SELECT 1~5 42 XOR A,0 43 SZ Z 44 JMP MENU_1 45 SUB A,6 46 SZ C 47 JMP MENU_1 48 MOV A,01H ;CLEAR DISPLAY 49 CALL WLCMCM 50 DECA KEY_PS 5-246 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 51 ADDM A,PCL ;COMPUTATIONAL JUMP 52 JMP DOWRITE ;WRITE 53 JMP DOWRITEALL ;WRITE ALL 54 JMP DOERASE ;ERASE 55 JMP DOERASEALL ;ERASEALL 56 JMP DOREAD ;READ 57 DOWRITE: ;RANDOM WRITE 58 MOV A,STR_3 ;PRINT STR_3 59 CALL PRINT 60 MOV A,0C0H ;SET LCM LINE 2 61 CALL WLCMCM 62 CALL GETKEYS ;GET KEYPAD INPUT CODE 63 MOV A,BUFFER[0] 64 XOR A,0 ;TEST IF NULL INPUT 65 SZ Z 66 JMP MAIN YES, RESTART MENU SELECT 67 68 MOV A,01H ;CLEAR DISPLAY 69 CALL WLCMCM 70 MOV A,STR_B ;PRINT STR_B 71 CALL PRINT 5 72 MOV A,OFFSET BUFFER[1] 73 MOV MP0,A 74 CALL EWEN ;WRITE ENABLE 75 CLR ADRS_REG ;INITIAL EEPROM ADDRESS 76 DOWRITE_1: 77 MOV A,IAR0 78 MOV DATA_REG,A ;GET DATA BYTE 79 CALL WRITE ;WRITE ONE BYTE 80 CALL WAIT_93LC46 ;WAIT READY 81 INC MP0 ;UPDATE POINTER 82 INC ADRS_REG ;UPDATE POINTER 83 SDZ BUFFER[0] ;COUNT-1 = 0 ? 84 JMP DOWRITE_1 ;NO,NEXT BYTE 85 CALL EWDS ;YES,WRITE DISABLE 86 MOV A,100 87 CALL DELAY 88 JMP MAIN ;RESTART MENU SELECT 89 DOWRITEALL: 90 MOV A,STR_4 ;PRINT STR_4 91 CALL PRINT 92 MOV A,0C0H 93 CALL WLCMCM 94 MOV A,STR_D ;PRINT STR_D 95 CALL PRINT 96 CALL GET2KEYS 97 MOV A,80H 98 CALL 99 MOV 100 CALL 101 CALL 102 MOV 103 MOV 104 CALL 105 CALL 106 CALL 107 MOV 108 CALL 109 JMP 110 DOERASE: 111 MOV 112 CALL 113 MOV 114 CALL 115 CALL 116 MOV 117 SUB 118 SZ 119 JMP 120 121 MOV 122 CALL 123 MOV 124 CALL 125 126 CALL 127 MOV 128 MOV 129 CALL 130 CALL 131 CALL 132 MOV 133 CALL 134 JMP 135 DOERASEALL: 136 MOV 137 CALL 138 CALL 139 CALL 140 CALL 141 CALL 142 MOV 143 CALL 144 JMP WLCMCM A,STR_B PRINT EWEN A,BUFFER[0] DATA_REG,A WRAL WAIT_93LC46 EWDS A,100 DELAY MAIN A,01H WLCMCM A,STR_5 PRINT GET2KEYS A,BUFFER[0] A,80H C DOERASE A,0C0H WLCMCM A,STR_A PRINT EWEN A,BUFFER[0] ADRS_REG,A ERASE WAIT_93LC46 EWDS A,100 DELAY MAIN A,STR_6 PRINT EWEN ERAL WAIT_93LC46 EWDS A,100 DELAY MAIN 第五章 进阶实验篇 5-247 ;PRINT STR_B ;WRITE ENABLE ;GET DATA BYTE ;RESTART MENU SELECT ;ERASE ;PRINT STR_5 ;MAKE SURE CODE RANGE FROM 0~7F 5 ;RANDOM READ AND CURRENT READ ;PRINT STR_6 ;WRITE ENABLE ;RESTART MENU SELECT 5-248 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 145 DOREAD: ; READ 146 MOV A,STR_7 ;PRINT STR_7 147 CALL PRINT 148 DOREAD_0: 149 CALL READ_KEY_PRESSED ;GET MENU SELECT 1 OR 2 150 XOR A,2 151 SZ Z 152 JMP DOREAD_3 153 MOV A,KEY_PS 154 XOR A,1 155 SNZ Z 156 JMP DOREAD_0 157 DOREAD_1: ;SELECCT SPECIFIED ADDRESS 158 MOV A,01H 159 CALL WLCMCM 160 MOV A,STR_8 ;PRINT STR_8 161 CALL PRINT 162 MOV A,0C0H 163 CALL WLCMCM 164 MOV A,STR_9 ;PRINT STR_9 165 CALL PRINT 5 166 CALL GET2KEYS 167 MOV A,BUFFER[0] ;GET SELECT ADDRESS 168 SUB A,80H ;MAKE SURE CODE RANGE FROM 0~7F 169 SZ C ;ADDRESS < 80H ? 170 JMP DOREAD_1 ;NO, RE-INPUT 171 MOV A,BUFFER[0] ;YES. 172 MOV ADRS_REG,A ;SET READ ARSE_REG 173 CALL READ ;READ 1 BYTE FROM HT93LC46 174 MOV A,STR_C ;PRINT STR_C 175 CALL PRINT 176 SWAPA DATA_REG ;GET READ DATA 177 CALL NIBBLE2ASCII ;COVERT HIGH NIBBLE TO ASCII 178 CALL WLCMDM ;DISPLAY 179 MOV A,DATA_REG ;GET READ DATA 180 CALL NIBBLE2ASCII ;COVERT LOW NIBBLE TO ASCII 181 CALL WLCMDM ;DISPLAY 182 DOREAD_2: 183 CALL READ_KEY_PRESSED 184 XOR A,0FH ;ENTER KEY PRESSED ? 185 SNZ Z ;NO. WAIT 186 JMP DOREAD_2 ;YES 187 JMP MAIN 188 DOREAD_3: 189 CLR ADRS_REG ;RESET READ_ADRS 190 DOREAD_4: 191 MOV A,ADRS_REG ;SET START ADDRESS TO BUFFER[0] 第五章 进阶实验篇 5-249 192 MOV BUFFER[0],A 193 MOV A,8 ;SET COUNT=8 194 MOV COUNT,A 195 MOV A,OFFSET BUFFER[1] ;SET BUFFER POINTER 196 MOV MP0,A 197 DOREAD_5: 198 CALL READ ;READ BYTE 199 MOV A,DATA_REG ;GET READ DATA 200 MOV IAR0,A 201 INC ADRS_REG ;UPDATE READPOINTER 202 INC MP0 ;UPDATE BUFFER POINTER 203 SDZ COUNT ;COUNT-1 = 0 ? 204 JMP DOREAD_5 ;NO,READ NEXT BYTE 205 MOV A,OFFSET BUFFER[1] ;YES, SET BUFFER POINTER 206 MOV MP0,A 207 MOV A,01H ;CLEAR LCM 208 CALL WLCMCM 209 CALL BUFFER_DISPLAY ;DISPLAY 4 BYTE DATA IN HEX FORMAT 210 MOV A,4 211 ADDM A,BUFFER[0] ;UPDATE START ADDRESS 212 MOV A,0C0H ;SET LCM AC ADDRESS 213 CALL WLCMCM 214 CALL BUFFER_DISPLAY ;DISPLAY 4 BYTE DATA IN HEX FORMAT 5 215 DOREAD_6: 216 CALL READ_KEY_PRESSED 217 SUB A,0DH 218 SNZ C ;UP/DN/ENTER KEY PRESSED ? 219 JMP DOREAD_6 ;NO. WAIT 220 ADDM A,PCL ;YES. 221 JMP DOREAD_UP ;UP-KEY 222 JMP DOREAD_DN ;DOWN-KEY 223 JMP MAIN ;ENTER/EXIT KEY 224 DOREAD_UP: 225 SZ ADRS_REG.7 ;CROSS 7FH BOUNDARY ? 226 CLR ADRS_REG ;YES, RESET POINTER 227 JMP DOREAD_4 ;NO. 228 DOREAD_DN: 229 MOV A,ADRS_REG ;UPDATE ADRES_REG 230 SUB A,16 231 SZ ACC.7 ;CROSS 00H BOUNDARY ? 232 MOV A,78H ;YES, RESET POINTER 233 MOV ADRS_REG,A ;NO. 234 JMP DOREAD_4 235 ;======================================================================================== 236 ; PROC : BUFFER_DISPLAY 237 ; FUNC : DISPLAY BUFFER[0] AND 4-BYTE CONTENTS SPECIFIED BY MP0 IN HEX MODE 5-250 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 238 ; REG : ACC,LCM_ADRS,COUNT 239 ;======================================================================================== 240 BUFFER_DISPLAY PROC 241 SWAPA BUFFER[0] 242 CALL NIBBLE2ASCII ;CONVERT HIGH BYTE TO ASCII 243 CALL WLCMDM 244 MOV A,BUFFER[0] ;CONVERT HIGH BYTE TO ASCII 245 CALL NIBBLE2ASCII 246 CALL WLCMDM 247 MOV A,2DH ;"-" 248 CALL WLCMDM 249 MOV A,4 250 MOV COUNT,A 251 BUFFER_DISPLAY_1: 252 MOV A,20H ;" " 253 CALL WLCMDM 254 SWAPA IAR0 ;CONVERT HIGH BYTE TO ASCII 255 CALL NIBBLE2ASCII 256 CALL WLCMDM 257 MOV A,IAR0 ;CONVERT HIGH BYTE TO ASCII 258 CALL NIBBLE2ASCII 5 259 CALL WLCMDM 260 INC MP0 ;UPDATE POINTER 261 SDZ COUNT ;COUNT-1 = 0? 262 JMP BUFFER_DISPLAY_1 ;NO, DISPLAY NEXT BYTE 263 RET ;YES. 264 BUFFER_DISPLAY ENDP 265 ;======================================================================================== 266 ; PROC : NIBBLE2ASCII 267 ; FUNC : CONVERT LOW NIBBLE TO ASCII CODE 268 ; REG : ACC 269 ; RETN : ACC 270 ;======================================================================================== 271 NIBBLE2ASCII PROC 272 AND A,0FH ;MASK HIGH NIBBLE 273 SUB A,10 ;CODE > 9 ? 274 SZ C 275 ADD A,40H-30H-9 ;YES, ADD OFFSET FROM "9" TO "A" 276 ADD A,30H+10 ;NO. 277 RET 278 NIBBLE2ASCII ENDP 279 ;======================================================================================== 280 ; PROC : INIT_93LC46 281 ; FUNC : SET HT93LC46 CONTROL PINs TO INITIAL STATE 282 ;======================================================================================== 283 INIT_93LC46 PROC 284 CLR MICORW_CS ;SET CS=0 第五章 进阶实验篇 5-251 285 CLR MICORW_SK ;SET SK=0 286 CLR MICORW_DI ;SET DI=0 287 CLR MICORW_CSC ;CONFIG CS AS O/P 288 CLR MICORW_SKC ;CONFIG SK AS O/P 289 CLR MICORW_DIC ;CONFIG DI AS O/P 290 SET MICORW_DOC ;CONFIG DO AS I/P 291 RET 292 INIT_93LC46 ENDP 293 ;======================================================================================== 294 ; PROC : READ 295 ; FUNC : READ COMMAND FOR HT93LC46 296 ; PARA : ADRS_REG[6:0] : SPECIFIED ADDRESS 297 ; REG : ACC,OPCODE_REG 298 ; CALL : WCMD_93LC46, READ_93LC46 299 ; RETN : DATA_REG : DATA READ FROM SPECIFIED ADDRESS 300 ;======================================================================================== 301 READ PROC 302 MOV A,OPCODE_READ ;SET READ OPCODE 303 MOV OPCODE_REG,A 304 CALL WCMD_93LC46 ;WRITE OPCODE AND ADDRESS TO 93LC46 305 CALL READ_93LC46 ;READ DATA FORM 93LC46 306 CLR MICORW_CS ;SET CS=0 307 RET 5 308 READ ENDP 309 ;======================================================================================== 310 ; PROC : EWEN 311 ; FUNC : EWEN COMMAND FOR HT93LC46 312 ; REG : ACC,OPCODE_REG,ADRS_REG 313 ; CALL : WCMD_93LC46 314 ;======================================================================================== 315 EWEN PROC 316 MOV A,OPCODE_ ;SET EWEN OPCODE 317 MOV OPCODE_REG,A 318 MOV A,01100000B ;SET EWEN OPCODE 319 MOV ADRS_REG,A 320 CALL WCMD_93LC46 ;WRITE OPCODE AND ADDRESS TO 93LC46 321 CLR MICORW_CS ;SET CS=0 322 RET 323 EWEN ENDP 324 ;======================================================================================== 325 ; PROC : WRITE 326 ; FUNC : WRITE COMMAND FOR HT93LC46 327 ; PARA : ADRS_REG[6:0] : SPECIFIED ADDRESS 328 ; : DATA_REG : DATA TO BE WRITTEN 329 ; REG : ACC,OPCODE_REG 330 ; CALL : WCMD_93LC46, WDAT_93LC46 331 ;======================================================================================== 5-252 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 332 WRITE PROC 333 MOV A,OPCODE_WRITE ;SET WRITE OPCODE 334 MOV OPCODE_REG,A 335 CALL WCMD_93LC46 ;WRITE OPCODE AND ADDRESS TO 93LC46 336 CALL WDAT_93LC46 ;WRITE DATA TO 93LC46 337 CLR MICORW_CS ;SET CS=0 338 RET 339 WRITE ENDP 340 ;======================================================================================== 341 ; PROC : WRAL 342 ; FUNC : WRAL COMMAND FOR HT93LC46 343 ; PARA : DATA_REG : DATA TO BE WRITTEN 344 ; REG : ACC,OPCODE_REG,ADRS_REG 345 ; CALL : WCMD_93LC46, WDAT_93LC46 346 ;======================================================================================== 347 WRAL PROC 348 MOV A,OPCODE_ ;SET WRAL OPCODE 349 MOV OPCODE_REG,A 350 MOV A,00100000B ;SET WRAL OPCODE 351 MOV ADRS_REG,A 352 CALL WCMD_93LC46 5 353 CALL WDAT_93LC46 354 CLR MICORW_CS ;WRITE OPCODE TO 93LC46 ;WRITE DATA TO 93LC46 ;SET CS=0 355 RET 356 WRAL ENDP 357 ;======================================================================================== 358 ; PROC : EWDS 359 ; FUNC : EWDS COMMAND FOR HT93LC46 360 ; REG : ACC,OPCODE_REG,ADRS_REG 361 ;; CALL : WCMD_93LC46 362 ;======================================================================================== 363 EWDS PROC 364 MOV A,OPCODE_ ;SET EWDS OPCODE 365 MOV OPCODE_REG,A 366 MOV A,00000000B ;SET EWDS OPCODE 367 MOV ADRS_REG,A 368 CALL WCMD_93LC46 ;WRITE OPCODE AND ADDRESS TO 93LC46 369 CLR MICORW_CS ;SET CS=0 370 RET 371 EWDS ENDP 372 ;======================================================================================== 373 ; PROC : ERASE 374 ; FUNC : ERASE COMMAND FOR HT93LC46 375 ; PARA : ADRS_REG : SPECIFIED ADDRESS TO BE ERASED 376 ; REG : ACC,OPCODE_REG 377 ; CALL : WCMD_93LC46 378 ;======================================================================================== 第五章 进阶实验篇 5-253 379 ERASE PROC 380 MOV A,OPCODE_ERASE ;SET ERASE OPCODE 381 MOV OPCODE_REG,A 382 CALL WCMD_93LC46 ;WRITE OPCODE AND ADDRESS TO 93LC46 383 CLR MICORW_CS ;SET CS=0 384 RET 385 ERASE ENDP 386 ;======================================================================================== 387 ; PROC : ERAL 388 ; FUNC : ERAL COMMAND FOR HT93LC46 389 ; REG : ACC,OPCODE_REG,ADRS_REG 390 ; CALL : WCMD_93LC46 391 ;======================================================================================== 392 ERAL PROC 393 MOV A,OPCODE_ ;SET ERAL OPCODE 394 MOV OPCODE_REG,A 395 MOV A,01000000B ;SET ERAL OPCODE 396 MOV ADRS_REG,A 397 CALL WCMD_93LC46 ;WRITE OPCODE TO 93LC46 398 CLR MICORW_CS ;SET CS=0 399 RET 400 ERAL ENDP 401 ;======================================================================================== 5 402 ; PROC : WLCMD_93LC46 403 ; FUNC : WRITE START(1-BIT) + OPCODE(2-BIT) + ADDRESS(7-BIT) TO HT93LC46 404 ; PARA : OPCODE_REG[2:0] : START BIT + OPCODE 405 ; : ADRS_REG[6:0] : ADDRESS FIELD 406 ; REGS : ACC,COUNT_93LC46 407 ;======================================================================================== 408 WCMD_93LC46 PROC 409 SET MICORW_CS ;SET CS=1 410 MOV A,3 411 MOV COUNT_93LC46,A 412 WCMD_93LC46_1: 413 CLR MICORW_DI ;SET DI=0 414 SZ OPCODE_REG.2 ;IF BIT=1, SET DI=1 415 SET MICORW_DI 416 NOP ;DELAY 417 SET MICORW_SK ;SET SK=1 418 RL OPCODE_REG 419 CLR MICORW_SK ;SET SK=0 420 SDZ COUNT_93LC46 421 JMP WCMD_93LC46_1 ;NEXT OPCODE BIT 422 MOV A,7 423 MOV COUNT_93LC46,A 424 WCMD_93LC46_2: 425 CLR MICORW_DI ;SET DI=0 5-254 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 426 SZ ADRS_REG.6 ;IF BIT=1, SET DI=1 427 SET MICORW_DI 428 NOP ;DELAY 429 SET MICORW_SK ;SET SK=1 430 RL ADRS_REG 431 CLR MICORW_SK ;SET SK=0 432 SDZ COUNT_93LC46 433 JMP WCMD_93LC46_2 ;NEXT ADDRESS BIT 434 RL ADRS_REG ;KEEP ADRS_REG UNCHANGED 435 RET 436 WCMD_93LC46 ENDP 437 ;======================================================================================== 438 ; PROC : WDAT_93LC46 439 ; FUNC : WRITE 8-BIT DATA TO HT93LC46 440 ; PARA : DATA_REG : 8-BIT DATA 441 ; REGS : ACC,COUNT_93LC46 442 ;======================================================================================== 443 WDAT_93LC46 PROC 444 MOV A,8 445 MOV COUNT_93LC46,A 446 WDAT_93LC46_1: 5 447 CLR MICORW_DI 448 SZ DATA_REG.7 ;SET DI=0 ;IF BIT=1, SET DI=1 449 SET MICORW_DI 450 NOP ;DELAY 451 SET MICORW_SK ;SET SK=1 452 RL DATA_REG 453 CLR MICORW_SK ;SET SK=0 454 SDZ COUNT_93LC46 455 JMP WDAT_93LC46_1 ;NEXT DATA BIT 456 RET 457 WDAT_93LC46 ENDP 458 ;======================================================================================== 459 ; PROC : READ_93LC46 460 ; FUNC : READ 8-BIT DATA FROM HT93LC46 461 ; REGS : ACC,COUNT_93LC46 462 ; RETN : DATA_REG : 8-BIT DATA READ FROM HT93LC46 463 ;======================================================================================== 464 READ_93LC46 PROC 465 MOV A,8 466 CLR DATA_REG ;SET DATA_REG=0 467 MOV COUNT_93LC46,A 468 READ_93LC46_1: 469 SET MICORW_SK ;SET SK=1 470 SZ MICORW_DO ;IF DO=1, SET BIT=1 471 SET DATA_REG.7 472 RL DATA_REG 第五章 进阶实验篇 5-255 473 CLR MICORW_SK ;SET SK=0 474 SDZ COUNT_93LC46 475 JMP READ_93LC46_1 ;NEXT DATA BIT 476 RET 477 READ_93LC46 ENDP 478 ;======================================================================================== 479 ; PROC : WAIT_93LC46 480 ; FUNC : WAIT 93LC46 READY, AFTER ERASE,ERAL,WRITE,WRAL COMMAND 481 ;======================================================================================== 482 WAIT_93LC46 PROC 483 SET MICORW_CS ;SET CS=1 484 WAIT_93LC46_1: 485 SET MICORW_SK ;SET SK=1 486 NOP 487 CLR MICORW_SK ;SET SK=0 488 SNZ MICORW_DO 489 JMP WAIT_93LC46_1 490 CLR MICORW_CS ;SET CS=0 491 RET 492 WAIT_93LC46 ENDP 493 ;======================================================================================== 494 ; PROC : GET2KEYS 495 ; FUNC : GET 2 HEX DIGITS KEY AND DISPLAY, THEN 2 DIGITS COMBINE TO ONE BYTE 5 496 ; REG : ACC,MP0,IAR0, BUFFER[0~1] 497 ; CALL : READ_KEY_PRESSED, WLCMD_4 498 ; RETN : BUFFER[0] : COMBIBE HEX KEY CODE 499 ;======================================================================================== 500 GET2KEYS PROC 501 CALL READ_KEY_PRESSED ;GET KEY 0~F 502 MOV BUFFER[0],A 503 CALL NIBBLE2ASCII ;CONVERTTO ASCII 504 CALL WLCMDM ;LCM DISPLAY 505 CALL READ_KEY_PRESSED ;GET KEY 0~F 506 SWAP BUFFER[0] 507 ORM A,BUFFER[0] 508 CALL NIBBLE2ASCII ;CONVERTTO ASCII 509 CALL WLCMDM ;LCM DISPLAY 510 RET 511 GET2KEYS ENDP 512 ;======================================================================================== 513 ; PROC : GETKEYS 514 ; FUNC : READ MULTIPLE KEY INPUT(0~9) UNTIL "ENTER" PRESSED OR COUNT > 15 515 ; REG : ACC,MP0,IAR0, BUFFER[0~15] 516 ; CALL : READ_KEY_PRESSED 517 ; RETN : BUFFER[0] : THE NUMBER OF KEY INPUT 518 ; : BUFFER[1~15] : INPUT KEY CODE 519 ;======================================================================================== 5-256 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 520 GETKEYS PROC 521 MOV A,OFFSET BUFFER[1] 522 MOV MP0,A 523 CLR BUFFER[0] 524 GETKEY_1: 525 CALL READ_KEY_PRESSED ;GET KEY 0~9 AND ENTER 526 XOR A,0FH 527 SZ Z 528 RET 529 MOV A,KEY_PS 530 SUB A,10 531 SZ C 532 JMP GETKEY_1 533 MOV A,KEY_PS 534 MOV IAR0,A 535 ADD A,30H ;CONVERTTO ASCII 536 CALL WLCMDM ;LCM DISPLAY 537 INC MP0 538 INC BUFFER[0] ;KEY COUNT+1 539 MOV A,BUFFER[0] 540 XOR A,16 5 541 SNZ Z 542 JMP GETKEY_1 543 RET 544 GETKEYS ENDP 545 ;======================================================================================== 546 ; PROC : READ_KEY_PRESSED 547 ; FUNC : SCAN 4x4 MATRIX ON KEY_PORT UNTIL KEY PRESSED, AND RETURN THE PRESSED KEY 548 ; NUMBER AFTER KEY RELEASED. 549 ; REG : ACC,KEY_PS 550 ; CALL : DELAY 551 ; RETN : A AND KEY_PS(0~F FOR PRESSED KEY NUMBER) 552 ;======================================================================================== 553 READ_KEY_PRESSED PROC 554 CALL READ_KEY ;SCAN KEYPAD 555 MOV A,16 556 XOR A,KEY 557 SZ Z ;IS KEY BEEN PRESSED? 558 JMP READ_KEY_PRESSED ;NO, RE-SCAN KEYPAD 559 MOV A,KEY 560 MOV KEY_PS,A ;RESERVED KEY CODE 561 MOV A,5 562 CALL DELAY ;DELAY 50mS 563 WAIT_KEY_RELEASED: 564 CALL READ_KEY ;SCAN KEYPAD 565 MOV A,16 566 XOR A,KEY 第五章 进阶实验篇 5-257 567 SZ ACC ;IS KEY BEEN RELEASED? 568 JMP WAIT_KEY_RELEASED ;NO, RE-SCAN KEYPAD 569 MOV A,5 570 CALL DELAY ;DELAY 50mS 571 MOV A,KEY_PS 572 RET 573 READ_KEY_PRESSED ENDP 574 ;======================================================================================== 575 ; PROC : READ_KEY 576 ; FUNC : SCAN 4x4 MATRIX ON KEY PORT AND RETURN THE CODE IN KEY REGISTER 577 ; REG : ACC,KEY_COUNT 578 ; RETN : KEY(0~F FOR PRESSED KEY NUMBER, IF NO KEY BEEN PRESSED, KEY=10h.) 579 ;======================================================================================== 580 READ_KEY PROC 581 MOV A,11110000B 582 MOV KEY_PORTC,A ;CONFIG KEY_PORT 583 MOV KEY_PORTPU,A ;CONFIG KEY_PORT PULL-HIGH 584 SET KEY_PORT ;INITIAL KEY PORT 585 CLR KEY ;INITIAL KEY REGISTER 586 MOV A,04 587 MOV KEY_COUNT,A ;SET ROW COUNTER 588 CLR C ;CLEAR CARRY FLAG 589 SCAN_KEY 5 590 RLC KEY_PORT ;ROTATE SCANNING BIT 591 SET C ;MAKE SURE C=1 592 SNZ KEY_PORT.4 ;COLUMN 0 PRESSED? 593 JMP END_KEY ;YES. 594 INC KEY ;NO, INCREASE KEY CODE. 595 SNZ KEY_PORT.5 ;COLUMN 1 PRESSED? 596 JMP END_KEY ;YES. 597 INC KEY ;NO, INCREASE KEY CODE. 598 SNZ KEY_PORT.6 ;COLUMN 2 PRESSED? 599 JMP END_KEY ;YES. 600 INC KEY ;NO, INCREASE KEY CODE. 601 SNZ KEY_PORT.7 ;COLUMN 3 PRESSED? 602 JMP END_KEY ;YES. 603 INC KEY ;NO, INCREASE KEY CODE. 604 SDZ KEY_COUNT ;HAVE ALL ROWs BEEN CHECKED? 605 JMP SCAN_KEY ;NO, NEXT ROW. 606 END_KEY: RET 607 READ_KEY ENDP 608 ;======================================================================================== 609 ; PROC : PRINT 610 ; FUNC : PRINT THE STRING POINTED BY ACC AT LCM CURRENT ADRESS . STRING MUST END WITH 0 611 ; PARA : ACC : POINTER FOR STRING START ADDRESS (LAST PAGE) 612 ; REG : TBLP 613 ;======================================================================================== 5-258 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 614 PRINT PROC 615 MOV TBLP,A ;LOAD TABLE POINTER 616 PRINT_1: TABRDL ACC ;READ STRING 617 XOR A,NULL 618 SZ Z ;END OF STRING CHARACTER? 619 RET ;YES, STOP PRINT 620 TABRDL ACC ;NO, RE-READ 621 CALL WLCMDM ;SEND TO LCD 622 INC TBLP ;INCREASE DATA POINTER 623 JMP PRINT_1 ;NEXT CHARACTER 624 PRINT ENDP 625 ;======================================================================================== 626 ; PROC : INIT_LCM 627 ; FUNC : SET LCM CONTROL PINs AND LCM TO INITIAL STATE 628 ; REG : ACC 629 ;======================================================================================== 630 INIT_LCM PROC 631 CLR LCM_EN ;SET EN=0 632 CLR LCM_RW ;SET RW=0 633 CLR LCM_RS ;SET RS=0 634 CLR LCM_ENC 5 635 CLR LCM_RWC 636 CLR LCM_RSC ;CONFIG EN AS O/P MODE ;CONFIG RW AS O/P MODE ;CONFIG RS AS O/P MODE 637 638 MOV A,38H ;FUNCTION SET: 4-BIT,2-LINE,5X10 DOTS 639 CALL WLCMCM 640 MOV A,0CH ;ON/OFF : DISPLAY ON,CURSOR BLINKING OFF 641 CALL WLCMCM 642 MOV A,06H ;ENTRY MODE : INCREMENT,DISPLAY NOT SHIFT 643 CALL WLCMCM 644 MOV A,01H ;CLEAR DISPLAY 645 CALL WLCMCM 646 RET 647 INIT_LCM ENDP 648 ;======================================================================================== 649 ; PROC : WLCMDM/WLCMCM 650 ; FUNC : WRITE DATA/COMMAND TO LCM AND RETURN AC ADDRESS 651 ; PARA : ACC : COMMAND/DATA 652 ; REG : ACC,DC_FLAG,LCM_TEMP 653 ; RETN : LCM_AC : 1 BUSY BIT + 7-BIT AC 654 ;======================================================================================== 655 WLCMDM PROC 656 SET DC_FLAG ;SET DC_FLAG=1 FOR DATA WRITE 657 JMP $+2 658 WLCMCM: CLR DC_FLAG ;SET DC_FLAG=0 FOR COMMAND WRITE 659 MOV LCM_TEMP,A 660 SET LCM_DATAPORTC ;CONFIG LCM_DATAPORT AS I/P MODE 第五章 进阶实验篇 5-259 661 CLR LCM_RS ;SET RS=0 (IR) 662 SET LCM_RW ;SET RW=1 (READ) 663 NOP ;FOR TAS 664 WF: SET LCM_EN ;SET EN=1 665 NOP ;FOR TDDR 666 MOV A,LCM_DATAPORT 667 MOV LCM_AC,A 668 CLR LCM_EN ;SET EN=0 669 SZ LCM_AC.7 ;IS LCM BUSY? 670 JMP WF ;YES, JUMP TO WAIT 671 CLR LCM_DATAPORTC ;NO, CONFIG LCM_DATAPORT AS O/P MODE 672 MOV A,LCM_TEMP 673 MOV LCM_DATAPORT,A ;LATCH DATA/COMMAND ON LCM_DATAPORT 674 CLR LCM_RW ;SET RW=0 (WRITE) 675 CLR LCM_RS ;SET RS=0 (IR) 676 SZ DC_FLAG ;IS COMMAND WRITE? 677 SET LCM_RS ;NO, SET RS=1 (DR) 678 SET LCM_EN ;SET EN=1 679 NOP ;FOR PWEN 680 CLR LCM_EN ;SET EN=0 681 RET 682 WLCMDM ENDP 683 ;======================================================================================== 5 684 ; PROC : DELAY 685 ; FUNC : DEALY ABOUT ACC*1mS 686 ; PARA : ACC : DELAY FACTOR 687 ; REG : DEL1,DEL2,DEL3 688 ;======================================================================================== 689 DELAY PROC 690 MOV DEL1,A ;SET DEL1 COUNTER 691 DEL_1: MOV A,30 692 MOV DEL2,A ;SET DEL2 COUNTER 693 DEL_2: MOV A,110 694 MOV DEL3,A ;SET DEL3 COUNTER 695 DEL_3: SDZ DEL3 ;DEL3 DOWN COUNT 696 JMP DEL_3 697 SDZ DEL2 ;DEL2 DOWN COUNT 698 JMP DEL_2 699 SDZ DEL1 ;DEL1 DOWN COUNT 700 JMP DEL_1 701 RET 702 DELAY ENDP 703 ORG LASTPAGE 704 STR_1: DC '1.WRITE 2.WRITE ALL',NULL ;STRING DEFINE 1 705 STR_2: DC '3.ERASE 4.ERAL 5.RD',NULL ;STRING DEFINE 2 706 STR_3: DC 'WR: PRESS 0-9, ENTER',NULL ;STRING DEFINE 3 707 STR_4: DC 'I/P 2-DIG HEX DATA',NULL ;STRING DEFINE 8 5-260 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 708 STR_5: 709 STR_6: 710 STR_7: 711 STR_8: 712 STR_9: 713 STR_A: 714 STR_B: 715 STR_C: 716 STR_D: 717 DC DC DC DC DC DC DC DC DC END 'I/P 2-DIG ADDRESS:',NULL 'ERASING ALL ........',NULL 'SELECT 1)ADDRS 2)ALL',NULL 'I/P ADDRS(2-DIG HEX)',NULL 'ADDRS=>',0 'ERASING 1 LOCATION..',NULL 'EEPROM WRITTING.....',NULL ' DATA=',NULL 'DATA=>',NULL ;STRING DEFINE 5 ;STRING DEFINE 6 ;STRING DEFINE 7 ;STRING DEFINE 8 ;STRING DEFINE 9 ;STRING DEFINE A ;STRING DEFINE B ;STRING DEFINE C ;STRING DEFINE 9 程程序序说说明明:: 4 载入”5-18.INC”定义档,其内容请参考随书光盘中的档案。 7~23 依序定义变量地址。 26 声明内存地址由 00h 开始(HT66Fx0 复位向量)。 37~30 关闭 CP0、CP1 功能,并设定 ADC 脚位输入为 I/O 功能。 5 31 调用 INIT_93LC46 子程序,对 HT93LC46 进行初始设定。 32 调用 INIT_LCM 子程序,对 LCM 进行定义。 33~40 在 LCM 上显示主功能选单,LCM 的显示效果如下: 41~56 57~88 1. WRITE:以 WRITE 指令将输入数据写至 HT93LC16; 2. WRITEALL:以 WRAL 指令将输入的一笔数据写至 HT93LC46 所有地址; 3.ERASE:以 ERASE 指令清除 HT93LC46 特定地址的数据; 4.ERAL:以 ERAL 指令清除 HT93LC46 所有地址的数据; 5.RD:以 READ 指令读取 HT93LC46 的数据; 调用 READ_KEY_PRESSED 子程序,并依使用者选择的功能(“1”~“5”)以 计算式跳跃的方式(ADDM A,PCL)跳至各功能对应的程序进入点;若使用者压下 非“1”~“5”的按键将不予理会。 “WRITE”功能程序进入点:首先 58~61 行在 LCM 显示如下的文字,提示使用者 输入“0”~“9”的数字或“ENTER”键结束输入。 第五章 进阶实验篇 5-261 62 行调用 GETKEYS 子程序读取键值,此子程序会将使用者压下的按键值存于 BUFFER[]数组并显示于 LCM 的第二列,BUFFER[0]则代表输入的按键个数;所以 63~66 行的程序若发现 BUFFER[0]=0,则不予理会并跳回 MAIN 处重新执行。68~ 71 行在 LCM 显示如下画面,提示使用者 HT93LC46 正准备进入烧录程序。 72~84 行是在设定 MP0 指向 BUFFER[1]并以 EWEN 程序使能写入功能后,以间 接 寻 址 法 逐 一 将 使 用 者 输 入 的 数 据 写 至 HT93LC46 , 每 写 完 一 次 并 调 用 WAIT_93LC46 子程序以确认 HT93LC46 已完成写入动作。当所有输入数据都烧写 完毕后,在第 85 行以 EWDS 程序禁能写入功能,并跳回 MAIN 处重新执行。 89~109 “WRITEALL”功能程序进入点: 90~95 行首先在 LCM 显示如下的文字,提示使 用者输入两位数的十六进制数值。 5 96 行调用 GET2KEYS 子程序读取键值,此子程序会将使用者压下的两个按键值显 示于 LCM 的第二列并将按键值整合于 BUFFER[0]寄存器。97~100 行在 LCM 显示 如下画面,提示使用者 HT93LC46 正准备进入烧录程序(假设使用者输入:“8” 与“C”)。 101~109 行是以 EWEN 程序使能写入功能后,以“WRAL”指令将使用者输入的 数据写至 HT93LC46 所有的地址空间,并调用 WAIT_93LC46 子程序以确认 HT93LC46 已完成写入动作;最后再禁能写入功能后跳回 MAIN 处重新执行。 110~134 “ERASE”功能程序进入点: 112~114 行首先在 LCM 显示如下的文字,提示使 用者输入两位数的十六进制数值,此数值代表要清除的内存地址。 5-262 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 114 行调用 GET2KEYS 子程序读取键值,此子程序会将使用者压下的两个按键值 显示于 LCM 并将按键值整合于 BUFFER[0]寄存器。116~119 行则判断输入的数值 是否超出 HT93LC46 的地址范围(当 ORG=“0”时为 00h~7Fh),若是则不予 理会,并跳至 DOERASE 重新要求输入。121~124 行在 LCM 显示如下画面,提示 使用者 HT93LC46 正准备进入清除单一地址程序(假设使用者输入:“6”与“B”)。 126~134 行是以 EWEN 程序使能写入功能后,以“ERASE”指令清除指定地址的 内容,并调用 WAIT_93LC46 子程序以确认 HT93LC46 已完成清除动作;最后再禁 能写入功能后跳回 MAIN 处重新执行。 135~144 “ERAL”功能程序进入点: 136~137 行在 LCM 显示如下的文字,提示使用者 HT93LC46 正准备进入内存全部清除程序: 5 1387~144 行是以 EWEN 程序使能写入功能后,以“ERAL”指令清除所有内存内 容,并调用 WAIT_93LC46 子程序以确认 HT93LC46 已完成清除动作;最后跳回 MAIN 处重新执行。 145~234 “READ”功能程序进入点: 145~146 行在 LCM 显示如下的文字,提示使用者输 入 “特定地址”读取或 “全部地址”读取: 148~156 行调用 READ_KEY_PRESSED 子程序,并依使用者选择的功能(“1” 或“2”)跳至各对应的程序进入点;若使用者压下“1”、“2”以外的按键将不 予理会。 157~187 使用者选择 “特定地址”读取功能的程序进入点,158~165 行首先在 LCM 显示 如下的文字,提示使用者输入两位数的十六进制数值,此数值代表要读取的内存地 址: 第五章 进阶实验篇 5-263 166 行调用 GET2KEYS 子程序读取键值,此子程序会将使用者压下的两个按键值 显示于 LCM 并将按键值整合于 BUFFER[0]寄存器。167~170 行则判断输入的数值 是否超出 HT93LC46 的地址范围(当 ORG=“0”时为 00h~7Fh),若是则不予 理会,并跳至 DOREAD_1 重新要求输入。171~173 行则根据使用者输入的地址执 行 READ 程序读取数据;174~181 行将读回的数据转换为 ASCII 码后显示于 LCM 上,显示画面如下(假设使用者输入:“3”与“B”,而 3Bh 的内容为 55h): 183~187 行是调用 READ_KEY_PRESSED 子程序,若使用者压下“ENTER”键, 则结束 READ 程序并跳回 MAIN 处重新执行;压下非“ENTER”的按键将不予理 会。 188~234 使用者选择 “全部地址”读取功能的程序计入点,189 行首先清除 ADRS_REG 寄存器,以确定执行 READ 程序时是由 HT93LC46 的地址 00h 开始读取。190~204 行则为读取循环,此段程序根据 ADRS_REG 为起始地址至 HT93LC46 连续读取八 个地址的数据,并以间接寻址法依序将其存放于 BUFFER[1]~BUFFER[8] 寄存器 5 中。205~214 行则在 LCM 显示地址与所读出的八笔数据,请参考以下的范例画面: 在”-“之前所显示的为地址,其后是四笔连续地址内的数据;每次只在 LCM 显示八笔 数据。 216 行调用 READ_KEY_PRESSED 子程序,若使用者压下“ENTER”键(Forward), 则结束“全部地址”读取程序并跳回 MAIN 处重新执行。若压下“F.WD”键,则表 示继续读取,此时会跳至 224 行执行程序,判断是否已读至最末笔数据,若是则重 新设定 ADRS_REG 为零,然后跳至 DOREAD_4 重新读取并显示。 若压下“B.WD”键(Backward),则表示读取前八个地址的数据,此时会跳至 228 行执行程序,判断是否已读至第一笔数据,若是则重新设定 ADRS_REG 为 78h, 然后跳至 DOREAD_4 重新读取并显示。 240~264 BUFFER_DISPLAY 子程序,以十六进制显示 BUFFER[0]的数值,接着印出”-”分 隔符;接着再以间接寻址法连续印出 MP0 所指示的四笔数据,每笔数据间并以空白 符号为间隔。 5-264 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 271~278 NIBBLE2ASCII 子程序,将 ACC 的低四位转换为 ASCII 码,请参考【表 5-18-3】 字符码与字型对应表。其基本原理是:若数值为 0~9 则直接加上 30h 即可转换成 ASCII 码(30h~39h);若为 0Ah~0Fh 则直接加上 37h 即可转换成 ASCII 码(41h~ 46h)。 283~292 INIT_93LC46 子程序,定义控制 HT93LC46 的脚位的输入/输出模式,并将输出脚 位状态设为低电位。 301~308 READ 子程序,实现 HT93LC46“READ”指令功能;请参考本实验前述的说明。 315~323 EWEN 子程序,实现 HT93LC46“EWEN”指令功能;请参考本实验前述的说明。 332~339 WRITE 子程序,实现 HT93LC46“WRITE”指令功能;请参考本实验前述的说明。 347~356 WRAL 子程序,实现 HT93LC46“WRAL”指令功能;请参考本实验前述的说明。 363~371 EWDS 子程序,实现 HT93LC46“EWDS”指令功能;请参考本实验前述的说明。 379~385 ERASE 子程序,实现 HT93LC46“ERASE”指令功能;请参考本实验前述的说明。 392~400 ERAL 子程序,实现 HT93LC46“ERAL”指令功能;请参考本实验前述的说明。 5 480~436 WLCMD_93LC46 子程序,搭配 CS、DI、SK 控制脚位的状态变化,将 3-Bit OPCODE_REG 与 7-Bit ADRS_REG 所组合的“命令”或“命令+地址”传送给 HT93LC46;请参考本实验前述的说明。 443~457 WDAT_93LC46 子程序,搭配 CS、DI、SK 控制脚位的状态变化,将 8-Bit DATA_REG 的数据传送至 HT93LC46;请参考本实验前述的说明。 464~477 READ_93LC46 子程序,搭配 CS、DO、SK 控制脚位的状态变化,由 HT93LC46 读回 8-Bit 的数据 并存置于 DATA_REG 寄存器;请参考本实验前述的说明。 482~492 WAIT_93LC46 子程序,搭配 CS、DO、SK 控制脚位的状态变化,读回 HT93LC46 8-Bit 的状态,并持续此动作至其回复至 Ready 状态止;请参考本实验前述的说明。 500~511 GET2KEYS 子程序,调用 READ_KEY_PRESSED 读取按键值,并显示于 LCM, 再将前后两次读取的键值整合于 BUFFER[0]寄存器中。 520~544 GETKEYS 子程序,调用 READ_KEY_PRESSED 读取按键值(0~9)存放至 BUFFER[1]~BUFFER[15] 寄存器,并显示于 LCM。当压下“F”键或输入键值已 达 15 个则跳离程序并将输入按键个数存于 BUFFER[0]寄存器;若压下“0”~“9” 与“F”以外的按键将不予理会。 553~573 READ_KEY_PRESSED 子程序,调用 READ_KEY 读取按键值当有键压下时则将 键值存至 KEY_PS 寄存器,在确认压下的键放开后即返回原调用处。 580~607 READ_KEY 子程序,请参考【实验 4-7】的说明。 第五章 进阶实验篇 5-265 614~624 PRINT 子程序,此子程序负责将定义好的字符串依序显示于 LCM 上。在调用此子 程序之前,除了必须先设定好 LCM 的位置之外,尚需先于 Acc 寄存器中指定字符 串的起始地址(字符串必须存放于最末程序页-Last Page),并请于字符串的最后 一个字符塞入 NULL,代表字符串结束。 630~647 INIT_LCM 子程序,其功能是对 LCM 进行定义: 631~636 LCM_EN、LCM_RW 与 LCM_RS 定义为输出模式,并设定状态为“0”。 638~639 将 LCM 设定为双行显示(N = 1)、使用八位(DB7 ~ DB0)控制模式(DL = 1)、 5×7 点矩阵字型(F = 0)。 640~641 将 LCM 设定为显示所有数据(D = 1)、显示光标(C = 1)、光标所在位置的字会 闪烁(B = 1)。 642~643 将 LCM 的地址计数器(AC)设为递加(I/D = 1)、显示器画面不因读写数据而移 动(S = 0)。 644~645 将 LCM 整个显示器清空。 655~682 WLCMDM 与 WLCMCM 子程序,请参考【实验 5-6】中的说明。 689~701 DELAY 子程序,延迟时间的计算请参考【实验 4-1】中的说明。 5 703~716 最末页数据建表区,存放本实验所使用的字符串数据。 “Microwire-Bus”是由美国国家半导体公司开发的一种三线同步接口,原使 用于该公司的COP8处理器系列产品。Microwire-Bus也是一种主/从(Master/Slave) 总线,包括主控端发出的“串行数据(DO)”、主控端接收的“串行数据(DI)” 及“信号频率(SK)”等三路信号;此外还有一个“芯片选择信号( )”。Microwire-Bus 是一种“全双工(Full-deplux)”总线,速度可达625Kbps。 “串行周边接口(Serial Port Interface;SPI)”是由摩托罗拉公司(Motorola) 开发的一种同步串行总线,用于该公司的多种单片机中;SPI-Bus的传输方式与 Microwire-Bus相当类似;其由四个信号组成,分别是“主出从入(MOSI)”、“主 入从出(MISO)”、“串行时钟(SCK)”及“芯片选择信号( ) “;分别对 应于Microwire-Bus的DO、DI、SK及 。SPI也是一种Multu-master/Slave设备的 通信协议,Master与选定的Slave间使用单向MISO和MOSI线进行通信,速率可达 1Mbps,亦为全双工模式。由Master产生SCK脉冲,数据以同步方式传输于Master 与Slave间。SPI协议有四种不同的频率类型,视SCK信号的极性和相位而定(读者 可以参考【实验4-18】或【2-8-2节】的内容);必须确保这些信号在主控端和Slave 间相互兼容。尽管在电容配置得当且速率较低时,SPI-Bus和Microwire-Bus通信距 5-266 A/D Flash MCU HT66F 系列单片机原理与实务-汇编语言实例说明 离可长达10英尺,但它们通常都局限于板内数据传输,距离不超过六英寸。 又是一个相当冗长的程序,为了让读者在研读本书的学习过程中,能有“倒吃 甘蔗”的成就感,【程序5-18】主程序的架构几乎与【实验5-16】、【实验5-17】 的程序完全一致,因此只要通过前两个实验的考验,对于【程序5-18】应该也能 驾轻就熟、如鱼得水才是! 5-18-5 动动脑+动动手: 【程序 5-18】当选择“全部读取”模式时,若使用者每压一次“F.WD”、“B.WD” 按键,LCM 的显示地址就会以四笔数据为单位递增、递减,以方便使用者 观察 E2PROM 地址的内容。试将其改为“自动卷动”型式;亦即当压下 “F.WD”、“B.WD”按键时,即自动每隔 0.8 秒依次递增、递减的地址显示 E2PROM 的内容,卷动过程若按下任何键时即暂停画面。再次按下 F.WD”、 “B.WD”按键则恢复卷动,但若压下“ENTER”键,则跳至 MAIN 处,重新 进行功能选项的程序。 5 若将【图 5-18-1】电路中的 J2 排针设定,由原来的“1-2”改为“2-3”短路; 并改写【程序 5-18】,使读、写的数据宽度为 16 位模式。 第五章 进阶实验篇 5-267 5-1 直流马达控制实验 ............................................................................錯誤! 尚未定義書籤。 5-2 马表-多颗七段显示器控制实验......................................................錯誤! 尚未定義書籤。 5-3 静态点矩阵 LED 控制实验 .................................................................錯誤! 尚未定義書籤。 5-4 动态点矩阵 LED 控制实验 .................................................................錯誤! 尚未定義書籤。 5-5 LCD 界面实验.....................................................................................錯誤! 尚未定義書籤。 5-6 LCM 字型显示实验 ............................................................................錯誤! 尚未定義書籤。 5-7 LCM 自建字型实验 ............................................................................錯誤! 尚未定義書籤。 5-8 LCM 与 4×4 键盘控制实验.................................................................錯誤! 尚未定義書籤。 5-9 LCM 的 DD/CG RAM 读取控制实验 ...................................................錯誤! 尚未定義書籤。 5-10 LCM 的四位控制模式实验.................................................................錯誤! 尚未定義書籤。 5-11 比大小游戏实验 ................................................................................錯誤! 尚未定義書籤。 5 5-12 TPU 单元脉波量测与 LCM 控制实验 .................................................錯誤! 尚未定義書籤。 5-13 TPU“单一脉波输出”模式与脉波量测实验....................................錯誤! 尚未定義書籤。 5-14 中文显示型 LCM 控制实验................................................................錯誤! 尚未定義書籤。 5-15 半矩阵式键盘与 LCM 控制实验 ........................................................錯誤! 尚未定義書籤。 5-16 HT66F40 内建 E2PROM 内存读写实验...............................................錯誤! 尚未定義書籤。 5-17 I2C 接口 E2PROM 读写控制实验 ........................................................錯誤! 尚未定義書籤。 5-18 MICROWIRE-BUS 接口 E2PROM 读写控制实验..................................錯誤! 尚未定義書籤。

Top_arrow
回到顶部
EEWORLD下载中心所有资源均来自网友分享,如有侵权,请发送举报邮件到客服邮箱bbs_service@eeworld.com.cn 或通过站内短信息或QQ:273568022联系管理员 高进,我们会尽快处理。