- 前言
- 实验须知
- 概述
- 实验一 TMS320LF2407 DSP 实验开发系统及CC软件应用
- 实验二 常用指令操作实验
- 实验三 追灯式电路控制
- 实验四 按键计数器
- 实验五 键盘和 LED 发光二极管显示电路
- 实验六 模/数转换器 ADC 应用
- 实验七 串行外围接口 SPI 的应用
- 实验八 串行通信接口模块(SCI)
- 实验九 TMS320LF2407 与图形液晶显示模块接口及应用
- 实验十 I2C 串行日历时钟与 TMS320LF2407 的接口应用
- 附录一 DSP 器件仿真开发技术基础
- 附录二 TMS320LF2407 DSP 实验开发系统
- 附录三 TMS320LF2407 DSP 器件简介
- 附录四 XDS510 仿真开发系统的基本操作技术
- 附录五 程序开发平台 Code Composer
- 参考文献
实验五 键盘和 LED 发光二极管显示电路
一.实验说明
在DSP的应用系统中,为实现人――机对话,显示和键盘是两个必不可少的功能配置。在本实验程序设计中,用键盘的响应作I/O端口的输入,用I/O端口的输出点亮发光二极管,形成的键盘、LED电路如图4.1所示。
二.实验目的
1. 学会配合使用键盘与发光二极管的编程方法。
2. 进一步认识TMS320LF2407芯片的I/O端口的功能及控制方法。
三.实验内容
1.用TMS320LF2407芯片设计并调试一个能使8只发光二极管按8种花样显示。
2.给按键定义各种不同功能,以实现对发光二极管循环顺序和点亮个数的控制。
四.实验参考程序清单
通过编程,使8只发光二极管实现如下显示功能:按下K1键,可点亮8种不同组合的发光二极管花样模式显示,按8次为一个循环周期;当按下一次K2键,将使设定的发光二极管显示的个数加1;当按下一次K3键,将使设定的发光二极管的位置往右移1位;当按下K4键或不按键时,返回到循环点亮发光二极管模式。
用通用定时器1产生10ms作为时基,用中断编程方法实现延时,再用软件计数得到10s延时。
C程序
I/O端口作为输入和输出使用
源程序代码:
(2) 所需的复位和中断向量定义文件“vectors.asm”同于前。在这以后的所有例程中,如果没有特别说明,vectors.asm都是相同的。
(3) 主程序
// 该程序用于键盘的识别,按键情况通过LED表示.
#include "register.h"
// 初始化子程序
initial()
{
asm(" setc SXM"); // 抑制符号位扩展
asm(" clrc OVM"); // 累加器中结果正常溢出
asm(" clrc CNF"); // B0被配置为数据存储空间
*SCSR1=0x81FE; // CLKIN=6M,CLKOUT=4*CLKIN=24M
*WDCR=0x0E8; // 不使能看门狗,因为SCSR2中的WDOVERRIDE
// 即WD保护位复位后的缺省值为1,故可以用
// 软件禁止看门狗
*IMR=0x0000; // 禁止所有中断
*IFR=0x0FFFF; // 清除全部中断标志,"写1清0"
*MCRA=*MCRA&0x0FF; // IOPB端口配置为一般的I/O功能
*PBDATDIR=*PBDATDIR|0x0FF00;// IOPB端口设置为输出方式
*MCRC=*MCRC&0x03FF; // IOPF2端口和IOPF3~6配置为一般的I/O功能
*PFDATDIR=*PFDATDIR|0x0400;// IOPF2端口为输出端口,IOPF3-IOPF6为输入端口
*PBDATDIR=*PBDATDIR&0x0FF00; // 熄灭全部的LED灯
*PFDATDIR=*PFDATDIR|0x0404; // IOPF2 设置为输出方式,且IOPF2=1
*PFDATDIR=*PFDATDIR&0x0FFFB; // IOPF2=0
// 以上的操作产生一个脉冲,使LED全部熄灭
}
// 屏蔽中断子程序
void inline disable()
{
asm(" setc INTM");
}
int keyscan( )
{
int k,j; // 定义局部变量
k=*PFDATDIR&0x0078; // 读入键盘状态并屏蔽掉相应的位
if(k == 0x0078) k=0;
else k=1; // 有键按下,则k=1
if(k == 1) // 若无键按下,则直接返回
{
for(j=30000;j>0;j--) j=j; // 若有键按下,则延时消抖动
k=*PFDATDIR&0x0078; // 读入键盘状态并屏蔽掉相应的位
if(k == 0x0078) k=0;
else k=1; // 有还有键按下,则k=1
}
return(k); // 返回K值
}
int keyserve( ) // 键服务子程序
{
int k; // 定义局部变量
k=*PFDATDIR&0x0078; // 读入键盘状态并屏蔽掉相应的位
switch(k)
{
case 0x0070:*PBDATDIR=(*PBDATDIR&0xFF00)|0X0001;break;
// 若按下K1键,则显示"1"
case 0x0068:*PBDATDIR=(*PBDATDIR&0xFF00)|0X0002;break;
// 若按下K2键,则显示"2"
case 0x0058:*PBDATDIR=(*PBDATDIR&0xFF00)|0X0003;break;
// 若按下K3键,则显示"3"
case 0x0038:*PBDATDIR=(*PBDATDIR&0xFF00)|0X0004;break;
// 若按下K4键,则显示"4"
default:*PBDATDIR=*PBDATDIR;
}
*PFDATDIR=*PFDATDIR|0x0404; // IOPF2 设置为输出方式,且IOPF2=1
*PFDATDIR=*PFDATDIR&0x0FFFB; // IOPF2=0
// 以上给一个脉冲,使B端口的值显示出来
}
main( )
{
disable( ); // 屏蔽所有中断
initial( ); // 系统初始化
while(1)
{
int i; // 定义局部变量
i=0;
i=keyscan(); // 键盘扫描,若有键按下,则返回值为"1",否则返回值为"0"
if(i==1) keyserve(); // 如果有键按下,则进行键服务程序
}
}
// 直接返回中断服务子程序
void interrupt nothing()
{
return;
}
汇编程序
st0_temp .usect ".b20",1 ;60
st1_temp .usect ".b20",1 ;61
context .usect ".b20",7 ;62-68
STACK . usect ".stack",40
IOSFT_REG .usect ".data0",1 ;280 ; IOPB SHIFT REG
IO_COUNT .usect ".data0",1 ;281 ; IO COUNT REG
IO_DATA .usect ".data0",1 ;282 ; I/O临时数据缓冲区
LEDXS .usect ".data0",1 ;283 ; LED显示的数据
LEDFLAG .usect ".data0",1 ;284 ; LED显示标志
K1FLAG .usect ".data0",1 ;285 ; K1 标志寄存器
KEYDATA .usect ".data0",1 ;286
KEYTIMER .usect ".data0",1 ;287
DP_USER .set 5
.include "F2407REGS.H"
.def _c_int0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.sect ".vectors" ;定义主向量段
RSVECT B _c_int0 ; PM 0 Reset Vector 1
INT1 B PHANTOM ;GISR1 ; PM 2 Int level 1 4
INT2 B GISR2 ; PM 4 Int level 2 5
INT3 B PHANTOM ; PM 6 Int level 3 6
INT4 B PHANTOM ; PM 8 Int level 4 7
INT5 B PHANTOM ;GISR5; PM A Int level 5 8
INT6 B PHANTOM ; PM C Int level 6 9
RESERVED B PHANTOM ; PM E (Analysis Int) 10
SW_INT8 B PHANTOM ; PM 10 User S/W int -
SW_INT9 B PHANTOM ; PM 12 User S/W int -
SW_INT10 B PHANTOM ; PM 14 User S/W int -
SW_INT11 B PHANTOM ; PM 16 User S/W int -
SW_INT12 B PHANTOM ; PM 18 User S/W int -
SW_INT13 B PHANTOM ; PM 1A User S/W int -
SW_INT14 B PHANTOM ; PM 1C User S/W int -
SW_INT15 B PHANTOM ; PM 1E User S/W int -
SW_INT16 B PHANTOM ; PM 20 User S/W int -
TRAP B PHANTOM ; PM 22 Trap vector -
NMI B PHANTOM ; PM 24 Non maskable Int3
EMU_TRAP B PHANTOM ; PM 26 Emulator Trap 2
SW_INT20 B PHANTOM ; PM 28 User S/W int -
SW_INT21 B PHANTOM ; PM 2A User S/W int -
SW_INT22 B PHANTOM ; PM 2C User S/W int -
SW_INT23 B PHANTOM ; PM 2E User S/W int -
SW_INT24 B PHANTOM ; PM 30 User S/W int -
SW_INT25 B PHANTOM ; PM 32 User S/W int -
SW_INT26 B PHANTOM ; PM 34 User S/W int -
SW_INT27 B PHANTOM ; PM 36 User S/W int -
SW_INT28 B PHANTOM ; PM 38 User S/W int -
SW_INT29 B PHANTOM ; PM 3A User S/W int -
SW_INT30 B PHANTOM ; PM 3C User S/W int -
SW_INT31 B PHANTOM ; PM 3E User S/W int -
;===========================================================
;中断子向量入口定义pvecs
;===========================================================
.sect ".pvecs" ;定义子向量段
PVECTORS B PHANTOM ; 保留向量地址偏移量-00
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量-05
B PHANTOM ;SCI_RX_ISR ; 保留向量地址偏移量
B PHANTOM ;SCI_TX_ISR ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量-0a
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量-10
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量-15
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量-1a
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量-20
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量-25
B PHANTOM ; 保留向量地址偏移量
B T1GP_ISR ; 保留向量地址偏移量-0027 T1PINT
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量-2a
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; pvector addr offset 0x02f - T3PINT
B PHANTOM ; 保留向量地址偏移量-30
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量-35
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量-3a
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量-3f
B PHANTOM ;CANMBX_ISR ; 保留向量地址偏移量
B PHANTOM ; 保留向量地址偏移量-41
;程序段
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; 引脚定义:键盘K1=IOPF3,K2=IOPF4, K3=IOPF5, K4=IOPF6, LED的片选信号:IOP
; 此程序为4个键盘与8个发光二极管组合程序,再无键按下或K4按下时用定时器1的方式,循环点亮8个发光二极管
; K1 按下则为功能模式,按键的次数不同显示的发光二极管也不同
; K2 按下则为“+”键模式,按一次加一,点亮不同的发光二极管
; K3 按下则为移位模式,按一次往右移一位,即 LED7=LED6....LED1=LED0, LED0=LED7
; 注意 LED 显示时要关闭 LCD 的块选 E1和E2
.text
_c_int0
CALL INIT
CALL KEYLEDINIT
LDP #DP_USER
SPLK #01H,IOSFT_REG ;显示数据移位寄存器
SPLK #00H,IO_COUNT ;延时计数寄存器
SPLK #001H,IO_DATA ;I/O临时数据缓冲区
SPLK #001H,LEDXS ;LED显示的数据
SPLK #00H,LEDFLAG ; LED显示标志寄存器LEDFLAG.0=1表示
; K1,K2,K3 按下
; LEDFLAG.0=0表示 K4 按下
SPLK #01H,K1FLAG ;K1标志寄存器
CALL INIT_TIME1
LOOP:
CALL KEY
LDP #DP_USER
BIT LEDFLAG,15
BCND LEDBD1,TC
LACL IO_COUNT
SUB #030H
BCND WAIT,LEQ
LEDBD1:
SPLK #00H,IO_COUNT
LDP #DP_PF2
LACL PFDATDIR
OR #0004H ; IOPF2 输出1
SACL PFDATDIR ;开74HC273片选信号
LDP #DP_USER
LACL LEDXS
OR #0FF00H ; IOPB 是输出
LDP #DP_PF2
SACL PBDATDIR ; 送要显示的数据
LDP #DP_PF2
LACL PFDATDIR
AND #0FFFBH ;IOPF2 输出0
SACL PFDATDIR ;关74HC273片选信号
LDP #DP_USER
BIT LEDFLAG,15
BCND LEDBD2,TC
LACL LEDXS
SFL ;要显示的数左移一位
SACL LEDXS
LACL IOSFT_REG
SFL
SACL IOSFT_REG
BIT IOSFT_REG,BIT8 ;判是否循环完一次
BCND LOOP1,TC
B WAIT
LOOP1:
LDP #DP_USER
SPLK #01H,IOSFT_REG
LEDBD2:
LACL IO_DATA
SACL LEDXS
WAIT:
NOP
B LOOP
INIT: ;系统初始化
SETC INTM ;关全局中断
CLRC SXM ;抑止符号扩展
CLRC OVM
CLRC CNF ; B0 配置为数据空间
LDP #0E0H
SPLK #81FEH,SCSR1 ; CLKIN=6M,CLKOUT=24M
SPLK #0E8h,WDCR ; 关闭看门狗 WDT
LDP #0
SPLK #0002h,IMR ; 使能 interrupt 2
SPLK #0FFFFh,IFR ; 清中断标志
RET
INIT_TIME1: ;定时器1初始化子程序
LDP #DP_EVA
SPLK #80H,EVAIMRA ;开定时器1周期中断
SPLK #0FFFFh,EVAIFRA;清EVA所有的中断标志(写1清除)
SPLK #0,GPTCONA ;不启动AD,禁止定时器1比较输出
SPLK #0BBH,T1PR ;使定时器每1ms产生一次中断
SPLK #00H,T1CNT ;清定时器1计数单元
SPLK #0174CH,T1CON ;TMODE=10(连续增模式),
;TPS=111 X/128,,CLOCK=Internal, 启动定时器1
CLRC INTM
RET
KEYLEDINIT: ;键盘LED初始化子程序
LDP #DP_PF2
LACL MCRC
AND #083FFH ; IOPF2--IOPF6 配置为一般的I/O口
SACL MCRC
LACL MCRA
AND #000FFH ; IOPB[0-7] 配置为一般的I/O口
SACL MCRA
LACL PFDATDIR
OR #0400H ; IOPF2 为输出方式
AND #087FBH ;IOPF[3-6] 为输入方式
SACL PFDATDIR
LACL #0FF00H ;IOPB[0-7] 为输出方式
SACL PBDATDIR
RET
;********************************************************************
KEY:
CALL READKEY ;读键盘值
LACL KEYDATA
BCND KEYRET,EQ ; ACC=0?
CALL KEYDELAY ; KEYDATA不等于0,表示有键按下,延时消抖动
CALL READKEY ;键盘软件延时子程序
BCND KEYRET,EQ
LDP #DP_USER ;判断按键情况(考虑只有一个键按下)
BIT KEYDATA,15
BCND KEY1,NTC
CALL K1 ; KEY1功能键
B KEYRET
KEY1:
BIT KEYDATA,14
BCND KEY2,NTC
CALL K2 ;KEY2"+"键
B KEYRET
KEY2:
BIT KEYDATA,13
BCND KEY3,NTC
CALL K3 ;KEY3 "移位"键
B KEYRET
KEY3:
BIT KEYDATA,12 ;KEY4 确认键
BCND KEYRET,NTC
CALL K4
KEYRET:
LACL KEYDATA ;清KEYDATA的低4位
AND #0fff0h
SACL KEYDATA
RET
;*****************读键盘子程序*******************************************
READKEY: ; 判键盘状态子程序
LDP #DP_PF2 ; DP-->7080h-70FFh
LACL PFDATDIR ; 取出键值PFDATDIR.3--PFDATDIR.6
RPT #2
SFR ;右移3位
OR #0fff0h ; 屏蔽高4位(用到4个键)
CMPL ;有键盘按下时对应位为低,按位取反之后为高
LDP #DP_USER
SACL KEYDATA ;键值保存在KEYDATA中
RET
KEYDELAY:
LACC #6000 ; 键盘延时子程序 86ms(20000) 30mS(6000)
KEYD1:
SUB #1 ; 延时30mS消抖动
RPT #080H
NOP
BCND KEYD1, NEQ
LDP #5
RET
; ******************** 功能键子程序 *****************************
K1:
NOP
READK1:
CALL READKEY
CALL KEYDELAY
LDP #DP_USER ; 判断按键 K1 是否松开
BIT KEYDATA,15
BCND READK1,TC
LDP #DP_USER ; 可扩展成16个或更多分支
SPLK #01H,LEDFLAG
BIT K1FLAG,15
BCND GN_KEY1,TC
BIT K1FLAG,14
BCND GN_KEY2,TC
BIT K1FLAG,13
BCND GN_KEY3,TC
BIT K1FLAG,12
BCND GN_KEY4,TC
BIT K1FLAG,11
BCND GN_KEY5,TC
BIT K1FLAG,10
BCND GN_KEY6,TC
BIT K1FLAG,9
BCND GN_KEY7,TC
BIT K1FLAG,8
BCND GN_KEY8,TC
B K1_RET
GN_KEY1:
SPLK #01H,IO_DATA ;K1按第1次时显示1H
B K1_LOOP1
GN_KEY2:
SPLK #03H,IO_DATA ;K1按第2次时显示3H
B K1_LOOP1
GN_KEY3:
SPLK #05H,IO_DATA ;K1按第3次时显示5H
B K1_LOOP1
GN_KEY4:
SPLK #007H,IO_DATA ;K1按第4次时显示7H
B K1_LOOP1
GN_KEY5:
SPLK #11H,IO_DATA ;K1按第5次时显示11H
B K1_LOOP1
GN_KEY6:
SPLK #33H,IO_DATA ;K1按第6次时显示33H
B K1_LOOP1
GN_KEY7:
SPLK #55H,IO_DATA ;K1按第7次时显示55H
B K1_LOOP1
GN_KEY8:
SPLK #77H,IO_DATA ;K1按第8次时显示77H
B K1_LOOP1
K1_LOOP1:
LACL K1FLAG
SFL ;K1FLAG左移一位
SACL K1FLAG
BIT K1FLAG,7
BCND K1_LOOP2,TC
B K1_RET
K1_LOOP2:
SPLK #01H,K1FLAG
K1_RET:
NOP
RET
;======= "+"键子程序 ===========================
K2:
NOP
READK2:
CALL READKEY
CALL KEYDELAY
LDP #DP_USER ; 判断按键 K2 是否松开
BIT KEYDATA,14
BCND READK2,TC
LDP #DP_USER
SPLK #01,LEDFLAG ; 关闭LED左移标志,即LED对同一个数不刷新
LACL IO_DATA
ADD #1
SACL IO_DATA
RET
;======= "移位"键子程序 ===========================
K3:
NOP
READK3:
CALL READKEY
CALL KEYDELAY
LDP #DP_USER ; 判断按键 K3 是否松开
BIT KEYDATA,13
BCND READK3,TC
LDP #DP_USER
SPLK #01H,LEDFLAG
LACL IO_DATA
SFR
SACL IO_DATA
BCND K3_LOOP1,NC ; C=1 则IO_DATA+80H
LACL #80H
ADD IO_DATA
K3_LOOP1:
SACL IO_DATA
RET
;======= 确认键子程序 ===========================
K4:
NOP
READK4:
CALL READKEY
CALL KEYDELAY
LDP #DP_USER ; 判断按键 K4 是否松开
BIT KEYDATA,12
BCND READK4,TC
LDP #DP_USER
SPLK #00H, LEDFLAG ; 恢复LED左移标志
SPLK #01H, IO_DATA
RET
;*************************定时器中断子程序*******************************
GISR2: LDP #0 ; 保存机器上下文
SST #0, st0_temp ; 使用自动寻址,DP-0
SST #1, st1_temp ; 保存状态寄存器到B2 DARAM.
SACL context ; 保存ACC的低16位
SACH context+1 ; 保存ACC的高16位
SAR AR1,context+2
SAR AR2,context+3
SAR AR3,context+4
SAR AR4,context+5
SAR AR5,context+6
LDP #0E0h ; 为PIVR控制寄存器改变DP
LACC PIVR,1 ; 读 EVIVRB, 左移1位
ADD #PVECTORS ; 加偏移向量到基向量
BACC
T1GP_ISR:
LDP #DP_USER
LACL IO_COUNT
ADD #1
SACL IO_COUNT
GISR2_RET:
LDP #DP_EVA
SPLK #0FFFFH,EVAIFRA
LDP #0
LAR AR5,context+6
LAR AR4,context+5
LAR AR3,context+4
LAR AR2,context+3
LAR AR1,context+2
LACC context+1,16
ADDS context
LST #1, st1_temp
LST #0, st0_temp
CLRC INTM
RET
;*******************************************************************
PHANTOM
KICK_DOG ; Resets WD counter
RET
END
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论