310 likes | 432 Views
第四章 普通 I/O 及第一个汇编工程. 主要内容 通用 I/O 接口基本概念及连接方法 MC68HC908GP32 的并行 I/O 端口 汇编工程文件组织 I/O 口的输入和输出电流以及端口上拉问题. 4.1 通用 I/O 接口基本概念及连接方法. I/O 接口,即输入输出接口,是微控制器同外界进行交互的重要通道。这些接口千变万化,种类繁多,有显而易见的人机交互接口,如操纵杆、键盘、显示器;也有无人介入的接口,如网络接口、机器设备接口。
E N D
第四章 普通I/O及第一个汇编工程 主要内容 • 通用I/O接口基本概念及连接方法 • MC68HC908GP32的并行I/O端口 • 汇编工程文件组织 • I/O口的输入和输出电流以及端口上拉问题
4.1 通用I/O接口基本概念及连接方法 I/O接口,即输入输出接口,是微控制器同外界进行交互的重要通道。这些接口千变万化,种类繁多,有显而易见的人机交互接口,如操纵杆、键盘、显示器;也有无人介入的接口,如网络接口、机器设备接口。 通用I/O: GPIO(General Purpose I/O),是I/O的最基本形式,它是一组输入或输出引脚,有时也称为并行I/O(parallel I/O)。
R2 VCC I1 上拉电阻R2 K1 R1 R3 I2 MCU VCC 下拉电阻R4 K2 R4 R5 I3悬空状态 I3 VCC K3 输入引脚有三种不同的连接方式:带上拉电阻的连接、带下拉电阻的连接和“悬空”连接。 返回
输出引脚的基本接法 作为通用输出引脚,MCU内部程序向该引脚输出高电平或低电平来驱动器件工作,即开关量输出。如图4-2所示。其中O1引脚是发光二极管LED的驱动引脚,当O1引脚输出高电平时,LED不亮;当O1引脚输出低电平时,LED点亮。O2引脚接蜂鸣器驱动电路,当O2脚输出高电平时,蜂鸣器响;O2脚输出低电平时,蜂鸣器不响。 这里只是原理性说明,关于电流方向与大小等问题,作为进一步讨论放在4.4节。
4.2 MC68HC908GP32的并行I/O端口 MC68HC908GP32单片机有5个普通I/O口,分别是A口、B口、C口、D口、E口。它们中的大部分具有双功能,本节仅讨论它们作为普通I/O功能时的编程方法。
4.2.1 A口 A口的8根引脚与键盘中断模块的引脚复用,这里只讨论A口作为普通I/O口的功能。 (1)A口的寄存器 A口作为普通I/O口时,具有三个寄存器,它们是:A口数据方向寄存器(DDRA)、A口数据寄存器(PTA)、A口上拉电阻允许寄存器(PTAPUE)。 ① A口数据方向寄存器(Data Direction Register A,DDRA) A口数据方向寄存器(DDRA)的地址是:$0004,DDRA的第7~0位分别记为DDRA7~DDRA0,这些位分别控制着A口引脚PTA7 ~PTA0是输入还是输出,若DDRAx=0,则引脚PTAx为输入,若DDRAx=1,则引脚PTAx为输出。复位时DDRA为$00。 记忆要点:数据方向寄存器的一位:0—定义输入,1—定义输出
《嵌入式技术基础与实践》课件 ② A口数据寄存器(Port A Data Register,PTA) A口数据寄存器(PTA)的地址是:$0000,PTA的第7~0位分别记为PTA7~PTA0。若A口的某一引脚PTAx被定义成输出,程序使A口数据寄存器PTA的相应位PTAx=0,则引脚PTAx输出“低电平”;程序使PTAx=1,则引脚PTAx输出“高电平”。若A口的某一引脚PTAx被定义成输入,程序通过读取A口数据寄存器PTA,获得输入情况,0表示输入为“低电平”,1表示输入为“高电平”。 记忆要点: 输出时:数据寄存器的一位:0—输出低电平 1—输出高电平 输入时:数据寄存器的一位:0—代表外部输入低电平 1—代表外部输入高电平
③ A口上拉电阻允许寄存器(Port A Input Pullup Enable Register,PTAPUE) A口上拉电阻允许寄存器(PTAPUE)的地址是:$000D。PTAPUE的第7~0位分别记为PTAPUE7~PTAPUE0。若A口的某一引脚PTAx 被定义成输入,则可通过置PTAPUE的相应位PTAPUEx为1来定义其内接上拉电阻,即引脚PTAx已经通过内部电阻与电源VDD相接,此时若引脚PTAx若通过开关接地,则开关闭合时为低电平。那么寄存器PTA的相应位PTAx=0,开关断开时为高电平,寄存器PTA的相应位PTAx=1,通过读取寄存器PTA获得开关状态。 记忆要点: 在引脚被定义成输入时,可通过上拉电阻允许寄存器定义有无内部上拉电阻: 0—没有内部上拉电阻 1—有内部上拉电阻
读DDRA($0004) 写DDRA($0004) 复位 写PTA($0000) 引脚 PTAx VDD PTAPUEx 内部上拉电阻 读PTA($0000) A口的一个引脚内部逻辑电路框图 A口数据方向寄存器 DDRAx位 内部数据总线 A口数据寄存器 PTAx位 (2)A口逻辑电路框图 下图给出了A口作为普通I/O使用时,一个外部引脚的相应内部逻辑电路框图。当DDRAx=1时,读地址$0000就是读PTAx。当DDRAx=0时,读地址$0000就是读引脚PTAx 电平。
4.2.2 B口 B口的8根引脚与8路A/D转换模块的引脚复用,这里只讨论B口作为普通I/O口的功能。 (1)B口的寄存器 B口作为普通I/O口时,具有二个寄存器,它们是:B口数据方向寄存器(DDRB)和B口数据寄存器(PTB)。 ① B口数据方向寄存器(Data Direction Register B,DDRB) B口数据方向寄存器(DDRB)的地址是:$0005,DDRB的第7~0位分别记为DDRB7~DDRB0,这些位分别控制着B口引脚PTB7~PTB0是输入还是输出,若DDRBx=0,则引脚PTBx为输入,若DDRBx=1,则引脚PTBx为输出。复位时DDRB为$00。 记忆要点:数据方向寄存器的一位:0—定义输入,1—定义输出
② B口数据寄存器(Port B Data Register,PTB) B口数据寄存器(PTB)的地址是:$0001,PTB的第7~0位分别记为PTB7~PTB0。若B口的某一引脚PTBx被定义成输出,程序使B口数据寄存器PTB的相应位PTBx=0,则引脚PTBx输出“低电平”,程序使PTBx=1,则引脚PTBx输出“高电平”。若B口的某一引脚PTBx被定义成输入,程序通过读取B口数据寄存器PTB,获得输入情况,0表示输入为“低电平”,1表示输入为“高电平”。 注意:B口被定义成输入时,没有内部上拉电阻
读DDRB($0005) 写DDRB($0005) 复位 写PTB($0001) 引脚 PTBx 读PTB($0001) B口的一个引脚内部逻辑电路框图 内部数据总线 B口数据方向寄存器 DDRBx位 B口数据寄存器 PTBx位 (2)B口逻辑电路框图 下图给出了B口作为普通I/O使用时,一个外部引脚的相应内部逻辑电路框图。
4.2.3 C口、D口和E口 作为通用I/O口使用时,C口、D口的功能以及用法与A口类似,E口与B口类似。 表4-1描述了C、D、E这3个通用I/O口。
4.3 汇编工程文件组织 GP32映像寄存器名定义头文件(GP32ASM.h) 芯片初始化文件(MCUinit.s) 中断处理子程序与中断向量表文件(Vectors08.s) 芯片相关的程序文件 小灯驱动头文件(LED.h) 小灯驱动文件(LED.s) 硬件对象控制文件 PrgFrame.prj 总头文件(Includes.h) 通用函数文件(GeneralFun.s) 通用程序 文件 主函数文件(Main.s)
1.芯片相关的程序文件 PrgFrame.prj工程中芯片相关类的程序文件包括:GP32映像寄存器名定义头文件(GP32ASM.h)、芯片初始化文件(MCUinit.s)和中断处理子程序与中断向量表文件(Vectors08.s)。 (1) GP32ASM.h 本文件为MC908GP32 MCU映象寄存器名定义头文件,它是GP32的汇编工程的映像寄存器名与其地址的对应表, (2) MCUinit.s 芯片初始化文件,主要包含与芯片有关的设置,如总线频率、看门狗模块的使用等。
(3) Vectors08.s 该文件包含了中断处理程序和中断矢量表。中断处理程序是当中断发生后执行的子程序,中断子程序在返回时需要使用RTI指令。中断矢量表实质是在MCU的矢量区写入一些常量值,这些常量值就是相应的中断处理程序的入口地址。当系统发生中断时,从中断向量表获得相应的中断处理子程序的入口地址,使程序流转向中断服务例程,执行相应的中断处理动作,处理结束后,从中断返回。 //[Vectors08.s]中断处理子程序与中断向量表---------------* //功能: * // (1)定义中断处理子程序 * // (2)放置中断向量表 * //说明:该文件与芯片具体型号有关 * // (1)芯片型号MC68HC908GP32 * // (2)注意本文件内容的顺序不能变动 * //-----------------------------------------------------------------------------------*
//此处为用户中断处理子程序的存放处 //未定义的中断处理子程序,本子程序不能删除 isrDummy:: RTI //中断矢量表,用户若需开放某中断,可修改下表中的相应项目 //(interrupt service routine,isr 中断处理程序) .area memory(abs) .org 0xffdc //中断向量表起始地址(注意:与芯片型号有关) vectab:: .word isrDummy //时基中断 .word isrDummy //AD转换中断 .word isrDummy //键盘中断 .word isrDummy //SCI发送中断 .word isrDummy //SCI接收中断 .word isrDummy //SCI错误中断 .word isrDummy //SPI发送中断
.word isrDummy //SPI错误中断 .word isrDummy //TIM2溢出中断 .word isrDummy //TIM2通道1输入捕捉/输出比较中断 .word isrDummy //TIM2通道0输入捕捉/输出比较中断 .word isrDummy //TIM1溢出中断 .word isrDummy //TIM1通道1输入捕捉/输出比较中断 .word isrDummy //TIM1通道0输入捕捉/输出比较中断 .word isrDummy //CGM的PLL锁相状态变化中断 .word isrDummy //IRQ引脚中断 .word isrDummy //SWI指令中断 .word MainInit //RESET(见主程序定位处)复位被认为是一种特殊 中断
2.硬件对象控制文件 MCU 工程编程是面向硬件对象的。PrgFrame.prj工程用普通I/O口控制小灯(LED)闪烁。 (1) LED.h 文件“LED.h”中包含小灯控制引脚宏定义。 //[LED.h]小灯驱动头文件----------------------------------//小灯控制引脚宏定义 Light_P = PTA //灯(Light)接在PTA口 Light_D = DDRA //相应的方向寄存器 Light_Pin = 1 //所在的引脚 (2) LED.s 文件“LED.s”中包含: ①文件描述:文件中的子程序的索引、硬件对象及其与MCU的连接描述 ②头文件:小灯控制所需用到的头文件和小灯控制引脚定义及小灯控制子程序中用到的其他常量声明可全部存放在“LED.h”中,“LED.s”只要包含该头文件即可。 ③小灯驱动子程序定义:每个子程序前要有相应的程序描述,包括子程序名,子程序的功能、入口和出口,必要时加上相关说明。
//[LED.s]小灯驱动---------------------------------------*//[LED.s]小灯驱动---------------------------------------* //本文件包含: * // (1)LEDinit:定义控制小灯的MCU的I/O引脚为输出 * // (2)LED_L_A:驱动小灯"亮","暗" * //硬件连接: * // (1)本处的小灯是一个发光二极管,由MCU的I/O引脚控制 * // (2)控制引脚为高电平时,小灯"暗";反之,小灯"亮" * //------------------------------------------------------* //小灯驱动头文件 .include "LED.h" //LEDinit:定义控制小灯的MCU引脚为输出-------------------* //功能:定义控制小灯的MCU引脚为输出,并使小灯初始为暗 * //入口:无 * //出口:无 * //堆栈深度:2 * //------------------------------------------------------* LEDinit:: BSET #Light_Pin,Light_D //令小灯引脚为输出 BSET #Light_Pin,Light_P //初始时,小灯"暗" RTS //LED_L_A:驱动小灯"亮","暗"-----------------------------* //功能:根据A的值控制小灯的亮和暗 * //入口:A(A = 'L',小灯亮;A = 'A',小灯暗) * //出口:无 * //堆栈深度:2 * //------------------------------------------------------*
LED_L_A:: CMP #'A' BNE LED_L_A_1 BSET #Light_Pin,Light_P //小灯"暗" BRA LED_L_A_Exit LED_L_A_1: CMP #'L' BNE LED_L_A_Exit //入口非'L'/'A',程序无响应 BCLR #Light_Pin,Light_P //小灯"亮" LED_L_A_Exit: RTS
3.通用程序文件 通用程序文件中可以定义一些与硬件无关、可以在不同工程项目中直接引用的子程序。它还可以是与这些通用子程序文件相对应的头文件。 在工程PrgFrame.prj中,有通用子程序文件GeneralFun.s,它定义了延时子程序DelayHX,这个程序不依赖于任何硬件模块,只是完成一个延时动作。 工程PrgFrame.prj中,还有一个比较特殊的文件——总头文件(Includes.h),它也属于通用程序文件。Includes.h用于声明全局变量和包含主程序文件中需要的头文件,宏定义等。它使得主函数文件能够尽量避免改动,结构更加清晰。在Includes.h中声明内存变量,通常称为“开辟内存变量”,内存变量的初始化在主程序开始部分完成。 4.主程序文件 一个汇编工程中包含一个汇编主程序文件,文件名固定为main.s。汇编主程序的主体是程序的主干流程,要尽可能简洁、清晰,流程中的各个环节由子程序去完成,主程序仅仅是完成对子程序的调用。 返回
//-------------------------------------------------------------------------------*//-------------------------------------------------------------------------------* //工 程 名:PrgFrame.prj * //硬件连接: * // (1)MCU的I/O口引脚接小灯(见“LED.s”文件中的说明) * //程序描述:用I/O口控制小灯闪烁 * //目 的:第1个freescale HC08系列MCU 汇编语言程序框架 * //说 明:提供Motorola MCU的编程框架,供教学入门使用 * //注 意:如果延时不够长的话,会发觉灯不会闪烁,而是一直 * // 亮,这是由于人的视觉引起的 * //--------清华2007版《嵌入式技术基础与实践》实例-------------* //总头文件 .include "Includes.h" //主程序 //以下两条语句的详细解释见"工程说明.txt" .area flash(abs) .org FlashStartAddr MainInit:: //复位后从此处执行(见Vectors08.s文件末尾处) SEI //关总中断 //1. 堆栈初始化为RAM最高端 LDHX #RAMendAddr + 1 //HX = #RAMEndAddr + 1
TXS //HX - 1 -> SP //2. 系统初始化 JSR MCUinit //初学时跳过此处 //3. 模块初始化 JSR LEDinit //(1) I/O口小灯控制引脚初始化 //程序总循环入口 MainLoop: LDA #'L' //小灯亮 JSR LED_L_A LDHX #$02FF //延时 JSR DelayHX LDA #'A' //小灯暗 JSR LED_L_A LDHX #$02FF //延时 JSR DelayHX JMP MainLoop //包含本工程的其他文件----------------------------------- .include "GeneralFun.s" //通用子程序 .include "MCUinit.s" //芯片初始化 .include "LED.s" //小灯驱动 //包含中断处理子程序与中断向量表文件"Vectors08.s"-------- .include "Vectors08.s" //中断处理子程序与中断向量表
4.4进一步讨论 4.4.1 I/O口的输入和输出电流 1.输出电流 输出电流是由芯片提供给外围设备,驱动外围设备,电流通过芯片引脚从芯片内‘流出’,也称为拉电流。 如果输出电流大于驱动设备的工作电流,就需要串联一个限流电阻;相反地,输出电流小于驱动设备的工作电流,需要增加放大电路,提高驱动电流。
2.输入电流 外部电流通过芯片引脚向芯片内“流入”称为输入电流。如果芯片主动接纳外部电流,这种输入电流称为吸收电流;芯片被动接纳外部电流,这种输入电流称为灌电流。在实际使用I/O口时,如果有输入电流要特别注意I/O口所能承受的最大值。 例如:用I/O口驱动四位一体数码管(数码管的具体介绍参见第10章)如下图4-6所示,如果引脚分配是:a~h接PTA0~PTA7口,CS0~CS3接PTC0~PTC3口,如果希望第0位显示数字时,CS0置低,即PTC0为低,PTA口为相应的数,则PTA口输出电流,芯片通过PTC0口吸收电流,假如数码管上某段亮所需的驱动电流是10mA,1段亮时,PTC0的吸收电流是10mA,但是如果8段都亮,PTC0的吸收电流将会是80mA,而微控制器的I/O口通常只有10~20mA的吸纳电流能力(如GP32的PTC0口的吸纳电流上限为15mA)。基于这种情况,实际通过PTC0的电流是15mA,也就是数码管每段上通过的电流只有2mA左右,远远小于其工作电流,最终数码管显示的亮度很低。同时,如果使用这种连接方法,工作时间长,很容易损坏芯片。
对于图4-6所示的电路的改进方法是:MCU的I/O端仅仅作为控制作用,将输入电流流向吸纳电路大的器件。如由NPN达林顿晶体管构成的MC1413芯片。对于图4-6所示的电路的改进方法是:MCU的I/O端仅仅作为控制作用,将输入电流流向吸纳电路大的器件。如由NPN达林顿晶体管构成的MC1413芯片。 MC1413采用NPN达林顿复合晶体管的结构,因此有很高的电流增益和很高的输入阻抗,可直接接受MOS或CMOS集成电路的输出信号,并把电压信号转换成足够大的电流信号驱动各种负载。该电路内含有7个集电极开路反相器(也称OC门)。MC1413电路结构和引脚排列如图4-7所示,它采用16引脚的双列直插式封装。每一驱动器输出端均接有一释放电感负载能量的抑制二极管,每一路的驱动电流最高可达500mA。
图4-8 MC1413工作原理图 VI1 VO1 VI2 VO2 VO3 VI3 VO4 VI4 VO5 VI5 VI6 VO6 Vout VO7 VI7 Vin GND Vcc VCC 图4-7 MC1413管脚图
a b c d e f g h dp dp g g dp dp g a g a a a b c d e b c d e f f b c d e b c d e f f MCU I/O口 CS1 CS0 CS2 CS3 MC1413 MCU I/O口 PTC2 PTC0 PTC3 PTC1 图4-9 改进后的4连排共阴极8段数码管连接图
4.4.2 端口上拉问题 1.端口需要上拉的情况 ① 当TTL电路驱动COMS电路时,如果TTL电路输出的高电平低于COMS电路的最低高电平(一般为3.5V),这时就需要在TTL的输出端接上拉电阻,以提高输出高电平的值。 ② OC门电路必须加上拉电阻,才能使用。 ③ 为加大输出引脚的驱动能力,有的单片机管脚上也常使用上拉电阻。 ④ 在COMS芯片上,为了防止静电造成损坏,不用的管脚不能悬空,一般接上拉电阻产生降低输入阻抗,提供泄荷通路。 ⑤ 芯片的管脚加上拉电阻来提高输出电平,从而提高芯片输入信号的噪声容限增强抗干扰能力。 ⑥ 提高总线的抗电磁干扰能力。管脚悬空就比较容易接受外界的电磁干扰。 ⑦ 长线传输中电阻不匹配容易引起反射波干扰,加上下拉电阻是电阻匹配,有效的抑制反射波干扰。
2.上拉电阻阻值选择 上拉电阻阻值也需要根据实际情况进行选择,主要需要考虑以下几个因素: ① 驱动能力与功耗的平衡。一般地说,上拉电阻越小,驱动能力越强,但功耗越大,设计是应注意两者之间的均衡。 ② 下级电路的驱动需求。当输出高电平时,开关管断开,上拉电阻应适当选择以能够向下级电路提供足够的电流。 ③ 高低电平的设定。不同电路的高低电平的门槛电平会有不同,电阻应适当设定以确保能输出正确的电平。当输出低电平时,开关管导通,上拉电阻和开关管导通电阻分压值应确保在零电平门槛之下。 ④ 频率特性。上拉电阻和开关管漏源级之间的电容和下级电路之间的输入电容会形成RC延迟,电阻越大,延迟越大。上拉电阻的设定应考虑电路在这方面的需求。 3.集电极开路输出和漏极开路输出 集电极开路(OC,open collector)输出的结构如图4-10所示,三极管D2的集电极什么都不接,所以叫做集电极开路(三极管D1为反相之用)。对于图4-10,当左端的输入为“0”时,D1截止(即集电极C跟发射极E之间相当于断开),所以Vcc电源通过电阻R2加到D2上,D2导通(即相当于一个开关闭合);当左端的输入为“1”时,D1导通,而D2截止(相当于开关断开)。