540 likes | 704 Views
第 8 章 数字量 I/O 模块. 8.1 数字量 I/O 端口概述. F2407 系列有 41 个通用、双向的数字量 I/O ( GPIO )引脚,其中大多数都是基本功能和一般 I/O 复用引脚。. 9 个 16 位控制寄存器:设置专用 I/O 和复用 I/O 引脚的功能。. · I/O 端口复用控制寄存器( MCRx ) · 数据和方向控制寄存器( PxDATDIR ). 控制寄存器. I/O 端口复用控制寄存器( MCRx ) :选择 I/O 端口作为基本功能方式还是一般 I/O 引脚功能。.
E N D
8.1 数字量I/O端口概述 F2407系列有41个通用、双向的数字量I/O(GPIO)引脚,其中大多数都是基本功能和一般I/O复用引脚。 9个16位控制寄存器:设置专用I/O和复用I/O引脚的功能。 · I/O端口复用控制寄存器(MCRx) · 数据和方向控制寄存器(PxDATDIR)
控制寄存器 I/O端口复用控制寄存器(MCRx) :选择I/O端口作为基本功能方式还是一般I/O引脚功能。 数据和方向控制寄存器(PxDATDIR): 当I/O端口用作一般I/O引脚功能时,用数据和方向控制寄存器可控制数据和双向I/O引脚的数据方向。
8.2 数字量I/O端口寄存器 1. 数字量I/O控制寄存器地址 寄存器映射到存储器数据空间,地址为7090h~709Fh。
8.2.1 I/O端口复用输出控制寄存器 1.I/O端口复用控制寄存器A(MCRA) 地址7090h
注意: • 斜体表示的位必须配置成1,这几个引脚是系统的专用引脚,用作与硬件仿真器接口(JTAG)相连,实现DSP的在线仿真功能。对以上的任一位写0将会引起不可预测的结果。 • 寄存器单元中保留的位是无效的,读时为0,写对它无影响。
8.2.2 I/O端口数据和方向寄存器 F2407系列共有6个数据和方向控制寄存器(PxDATDIR)。 数据和方向控制寄存器:可控制数据和到双向通用I/O引脚的数据方向。 寄存器直接与I/O引脚相连。 当I/O用作基本功能时,寄存器的设置对相应的引脚无影响。
1.端口A数据和方向控制寄存器(PADATDIR)――地址7098h1.端口A数据和方向控制寄存器(PADATDIR)――地址7098h
位15~8 AnDIR 0 配置相应的引脚为输入方式 1 配置相应的引脚为输出方式 位7~0 IOPAn 当AnDIR=0,即引脚为输入方式时 0 读相应引脚的值为低电平 1 读相应引脚的值为高电平 当AnDIR=1,即引脚为输出方式时 0 设置相应的引脚,使其输出为低电平; 1 设置相应的引脚 使其输出为高电平。 如果I/O端口用作一般I/O,则在对端口初始化时就必须对数据和方向控制寄存器进行设置,规定其为输入还是为输出。
2.端口B数据和方向控制寄存器(PBDATDIR)――地址709Ah2.端口B数据和方向控制寄存器(PBDATDIR)――地址709Ah
3.端口C数据和方向控制寄存器(PCDATDIR)――地址709Ch3.端口C数据和方向控制寄存器(PCDATDIR)――地址709Ch
4.端口D数据和方向控制寄存器(PDDATDIR)――地址709Eh4.端口D数据和方向控制寄存器(PDDATDIR)――地址709Eh
5.端口E数据和方向控制寄存器(PEDATDIR)――地址7095h5.端口E数据和方向控制寄存器(PEDATDIR)――地址7095h
6.端口F数据和方向控制寄存器(PFDATDIR) ——地址7096h
8.3 I/O端口应用 例:循环点亮8个发光二极管
工作原理 • 74HC273用于驱动8个发光二极管。 • CLR接F2407的复位引脚,使在复位时74HC273输出为低电平,不点亮发光二极管。 • F2407的IOPCA3、IOPCA4及IOPCA5分别接74LVC138的A、B及C输入,通过它的选通CLK作为74HC273的控制信号; • 当输出为高时,74HC273的输出有效即输出信号反映输入的内容;当输出为低时,输出无效即输入变化时输出不变。 • 用IOPB端口来控制发光二极管的亮灭:某位为高则相应的LED发光;某位为低则相应的LED熄灭。
软件设计 • 先向IOPB端口发送需要显示的数据,再通过发送一个脉冲,循环点亮8个发光二极管。 • 用软件延时的方法来调节发光二极管的延时间隔。
汇编语言 1. 主程序 IOSFT_REG .usect ".data0",1 ;要显示的数据寄存器 .include “F2407REGS.H” ;引用头部文件 .def _c_int0 .text
_c_int0: ;相当于主程序的入口 CALL SYSINIT ;调系统初始化程序 LDP #DP_PF2 ;指向7080h~7100h区 LACL MCRA AND #000FFH ;IOPB端口配置为一般I/O功能 SACL MCRA LACL MCRA AND #0FF00H ;IOPA 配置为一般I/O功能 SACL MCRA LACL PBDATDIR OR #0FF00H ;IOPB端口设置为输出方式 SACL PBDATDIR LACL PADATDIR OR #0FF00H SACL PADATDIR ;IOPA 设置为输出方式 LDP #5H ;指向0280h~0300h区 SPLK #80H,IOSFT_REG ;给显示的数据赋初值
LOOP: LDP #DP_PF2 LACL PADATDIR AND #0FFC7H ;138 select ch0,ledclk==1 SACL PADATDIR ;开74HC273片选信号 LDP #5H LACL IOSFT_REG LDP #DP_PF2 OR #0FF00H SACL PBDATDIR ;送要显示的数据到IOPB端口 LACL PADATDIR OR #0038H ;138 select ch7,ledclk=0 SACL PADATDIR ;关74HC273片选信号 CALL DELAY ;调延时程序 LDP #5H LACL IOSFT_REG BIT IOSFT_REG,BIT0;是否循环完一次(已点亮第8个发光二极管) ROR ;左移一位 SACL IOSFT_REG BCND LOOP1,TC B WAIT LOOP1: LDP #5H SPLK #80H,IOSFT_REG;如循环完一次则显示数据赋初值 WAIT: NOP B LOOP
系统初始化程序 SYSINIT: SETC INTM CLRC SXM CLRC OVM CLRC CNF ;B0 被配置为数据存储空间 LDP #0E0H SPLK #81FEH,SCSR1 ;CLKIN=6 M,CLKOUT=24 M SPLK #0E8H,WDCR ;不使能WDT LDP #0 SPLK #0000H,IMR ;不使能 SPLK #0FFFFH,IFR ;清全部中断标志 RET
软件延时程序 DELAY: MAR *,AR4 LAR AR4,#0FFFEH LAR AR0,#00H DELAY1: SBRK #1 NOP CMPR 00 BCND DELAY1,NTC RET
C语言 说明: (1)程序中所有与DSP硬件有关的寄存器都用指针方式寻址。 (2)SXM、OVM、 CNF和INTM等的位操作嵌入汇编语句。 (3)寄存器PBDATDIR: 高8位是IOPB端口数据流动方向的设置,设置完成后一般不再改变; 低8位是数据内容,改变其内容,则可实现LED的循环显示。 (4)移位的实现:其程序中设置了一个寄存器led,其高8位为0,低8位存储需要显示的数据。用C语言指令led=led>>1 实现数据右移一位。 (5)每次须改变LED的显示内容时,用指令PBDATDIR=PBDATDIR&0x0FF00屏蔽掉其数据位,再用指令PBDATDIR=PBDATDIR|led把需要显示的数据赋给IOPB端口即可。
#include "register.h" main( ) // 初始化子程序 { int led; int i,k; asm(" setc SXM"); // 抑制符号位扩展 asm(" clrc OVM"); // 累加器中结果正常溢出 asm(" clrc CNF"); // B0被配置为数据存储空间 asm(" setc INTM"); // 禁止所有中断 *SCSR1=0x81FE; // CLKIN=10M,CLKOUT=4*CLKIN=40M *WDCR=0x0E8; // 不使能看门狗,因为SCSR2中的WDOVERRIDE // 可以用软件禁止看门狗 *IMR=0x0000; // 禁止所有中断 * IFR=0x0FFFF; // 清除全部中断标志,"写1清0" *MCRA=*MCRA&0x00c7; // IOPA3,IOPA4,IOPA5,IOPB端口配置为一般的I/O功, // F240x的端口均为8位,MCRA为16位 //因此控制了IOPA和IOPB的设置 * PBDATDIR=0x0FF00; // IOPB端口设置为输出方式,熄灭全部的LED *PADATDIR=*PADATDIR&0x0FF00; *PADATDIR=*PADATDIR|0x0FF38;// IOPA3,IOPA4,IOPA5 设置为输出方式, //且LEDCLK=1
while(1) { for(led=0x0080,i=0;i<8;led=led>>1,i++) { *PBDATDIR=*PBDATDIR&0x0FF00; //首先屏蔽B端口的各位 *PBDATDIR=*PBDATDIR|led; //把需要显示的值给IOPB端口 *PADATDIR=*PADATDIR&0x0FF00; *PADATDIR=*PADATDIR|0x0FF38; // LEDCLK=1 for(k=0;k<0x0fffe;k++) k=k; } } } 直接返回中断服务程序 void interrupt nothing( ) { return; }
8.3.2 键盘与发光二极管配合使用程序 • 硬件说明: • 有8个键和8个发光二极管,键盘的值先用IOPB端口直接读取,即相应的I/O用作输入方式; • 把IOPB端口作为输出方式去点亮8个发光二极管。 • 键盘K1-K8分别对应于I/O端口IOPB0-IOPB7。 • 按下8个键盘中的某个按键则相应的第几个发光二极管点亮。
软件说明 • 用查询的方式来读取键值; • 当S1键按下时,点亮发光二极管LED0; • S1键对应的输入I/O引脚为IOPB0,在IOPB0作为一般I/O输入的情况下,如S1键按下则端口B数据和方向控制寄存器(PBDATDIR)的第0位为0; • 经过延时消抖动后如PFDATDIR.0仍为0则表示S1键按下; • 程序中如S1键按下,就点亮发光二极管LED0。
1.汇编程序 KEYXS .usect ".data0",1 ;LED显示的数据 KEYDATA .usect ".data0",1 ;前次LED显示的数据 DP_USER .set 5 .include "F2407REGS.H" ;引用头部文件 .def _c_int0
(2)主程序 .text _c_int0 CALL SYSINIT;调系统初始化程序 LDP #DP_USER;指向0280h~0300h区 SPLK #0000H,KEYXS ;给要显示的数据赋初值 B LED ;使LED全部熄灭 LOOP: CALL KEY ;调键盘程序,即扫描键盘 LED: LDP #DP_PF2;选数据页 LACL PADATDIR ;将PADATDIR装载到ACC的低16位 OR #00038H ;LEDCLK=0 SACL PADATDIR ;开74HC273片选信号 LDP #DP_USER LACL KEYXS OR #0FF00H;IOPB端口为输出方式
LDP #DP_PF2 SACL PBDATDIR;送要显示的数据到IOPB端口 LACL PADATDIR OR #0ff10H;LEDCLK=1 AND #0ff10H SACL PADATDIR;关74HC273片选信号 CALL KEYDELAY WAIT: RPT #7 ;延时 NOP B LOOP ;跳转,循环查键
(3)系统初始化程序 SYSINIT: SETC INTM CLRC SXM SETC OVM CLRC CNF ;B0 被配置为数据存储空间 LDP #0E0H SPLK #81FEH,SCSR1 ;CLKIN=6 MHz,CLKOUT=24 MHz SPLK #0E8H,WDCR;不使能看门狗 WDT LDP #0 SPLK #0000H,IMR;不使能中断 SPLK #0FFFFH,IFR;清全部中断标志 RET
(4)键盘初始化程序 KEYINIT: LDP #DP_PF2 LACL MCRA AND #000c7H ;IOPA3,IOPA4,IOPA5,IOPB端口配置为一般的I/O功能 SACL MCRA LACL PBDATDIR AND #0000H;IOPB端口设置为输入方式 SACL PBDATDIR LACL PADATDIR OR #0FF10H;IOPA3,IOPA4,IOPA5设置为输出方式,且KEYC=1 AND #0FF10H SACL PADATDIR RET
(5)键盘程序 KEY: CALL READKEY ;调读键程序 LACL KEYXS BCND KEY,EQ ;没有键按下跳转到KEY,循环查键 CALL KEYDELAY ;延时消抖动 CALL READKEY ;再一次读键值 LACL KEYXS BCND KEY,EQ ;没有键按下跳转到KEY,循环查键 B LED ;有键按下,跳转到LED,进行显示
(6)读键子程序 READKEY: CALL KEYINIT ;调键盘初始化程序 LDP #DP_PF2 LACL PBDATDIR ;取出键值PBDATDIR.0~PBDATDIR.3 OR #0FF00H ;屏蔽高8位 CMPL ;取反 LDP #DP_USER SACL KEYXS ;存放键值 RET ;返回
(7)用软件延时30mS消抖动 KEYDELAY: LACC #6000 KEYD1: SUB #1 RPT #80 NOP BCND KEYD1,NEQ RET
(10)假中断程序 PHANTOM KICK_DOG ;复位看门狗 RET END
2.C语言程序 #include "register.h" int j,k; main() // 初始化子程序 { asm(" setc SXM"); // 抑制符号位扩展 asm(" clrc OVM");// 累加器中结果正常溢出 asm(" clrc CNF"); // B0被配置为数据存储空间 asm(“ setc INTM”); // 禁止所有中断 SCSR1=0x81FE; // CLKIN=10MHz,CLKOUT=4xCLKIN=40MHz WDCR=0x0E8; // 不使能看门狗,可以用软件禁止看门狗
IMR=0x0000; // 禁止所有中断 IFR=0x0FFFF; // 清除全部中断标志,"写1清0" MCRA=MCRA&0x00c7; // OPA3,IOPA4,IOPA5,IOPB端口配置为一般的I/O功能,F240x的端口均为8位,MCRA为16位因此控制了IOPA和IOPB的设置 PBDATDIR=0x0FF00; // IOPB端口设置为输出方式 PADATDIR=PADATDIR|0x0FF38; PADATDIR=PADATDIR&0x0FF00; //IOPA3,IOPA4,IOPA5 设置为输出方式,且LEDCLK=1 PADATDIR=PADATDIR|0x0FF10; // IOPA3,IOPA4,IOPA5 设置为输出方式,选通KEYC
while(1) { PBDATDIR=PBDATDIR&0x00ff; k=PBDATDIR&0x00FF; if(k==0x00FF) k=0; else k=1; if(k==1) { for(j=0;j<3000;j++) ; k=PBDATDIR&0x00FF; if(k==0x00FF) k=0; else k=1; }
if(k==1) { k=PBDATDIR&0x00FF; switch(k) { case 0x00FE:PBDATDIR=(PBDATDIR&0x0FF00)|0x0FF01; break; //按下S1点亮LED0 case 0x00FD:PBDATDIR=(PBDATDIR&0x0FF00)|0x0FF02; break; //按下S2点亮LED1 case 0x00FB:PBDATDIR=(PBDATDIR&0x0FF00)|0x0FF04; break; //按下S3点亮LED2 case 0x00F7:PBDATDIR=(PBDATDIR&0x0FF00)|0x0FF08; break; //按下S4点亮LED3 case 0x00EF:PBDATDIR=(PBDATDIR&0x0FF00)|0x0FF10; break; //按下S5点亮LED4 case 0x00DF:PBDATDIR=(PBDATDIR&0x0FF00)|0x0FF20; break; //按下S6点亮LED5 case 0x00BF:PBDATDIR=(PBDATDIR&0x0FF00)|0x0FF40; break; //按下S7点亮LED6 case 0x007F:PBDATDIR=(PBDATDIR&0x0FF00)|0x0FF80; break; //按下S8点亮LED7
default: PBDATDIR=PBDATDIR; } PADATDIR=PADATDIR|0x0FF38; PADATDIR=PADATDIR&0x0FF00; //IOPA3,IOPA4,IOPA5 设置为输出方式且LEDCLK=1 PADATDIR=PADATDIR|0x0FF10; } } }
// 直接返回中断服务程序 void interrupt nothing( ) { return; }
8.3.3 光电隔离的8路开关量输入与8路开关量输出电路 • 用DSP的I/O端口IOPB0~7与74LVC245构成8路开关量输入通道; • DSP 的I/O端口IOPB0~7与74HC273锁存器构成8路开关量输出通道; • DSP的I/O端口IOPA3~5作为74LVC138的输入信号; • 该信号经138译码后输出一个信号来使能74LVC245从而控制I/O端口IOPB0~7输入8路开关量信号; • 或者经138译码后输出一个信号来控制74HC273锁存器从而使I/O端口IOPB0~7输出8路开关量信号锁存到74HC273的寄存器中。
说明 调试时,可以适当地选择连接光电耦合二极管串联的电阻值,使光电耦合器件可靠导通,实现不同电压等级下的电平匹配与电气隔离,从而模拟实际控制过程中的光电隔离型开关量输入。 光电耦合器件的VIN接5V电平; IN0~7为8路开关量输入; OUT0~7为8路开关量输出; 开关量输入为低电平时,输出也为低电平信号。