1、汇编实验报告 定时器 一. 工作原理 1.时钟部分 1.1 C55x时钟发生器的原理和配置方法 TMS320VC5509A的时钟发生器从CLKIN引脚输入,在内部修改这个信号(通过一个数字锁相环,PLL),来产生希望频率的输出时钟。时钟发生器将这个输出时钟(即CPU时钟)送给CPU、外设和其他C55的内部模块。也可以用可编程的时钟分频器对CPU时钟分频,在CLKOUT引脚上输出。 时钟发生器有一个时钟模式寄存器CLKMD,用来控制和监视时钟发生器。通过修改该寄存器可以触发两种主要的操作模式: 1) 旁路模式。 PLL被旁路掉,输出时钟的频率就等于输入时钟频率除以1、2、4。因为
2、PLL模块关闭,因此该模式可以用来降低功耗。 2)锁定模式。 输入时钟既可以乘以或除以一个系数来获得期望的输出频率,并且输入时钟相位与输入信号锁定。本实验采用该模式。 2.定时器部分 2.1通用定时器介绍及其控制方法 2.1.1定时器的工作时钟 l DSP内部的CPU时钟,本实验采用该方式。 l 引脚TIN/TOUT 利用定时器控制寄存器(TCR)中的字段FUNC可以确定时钟源和TIN/TOUT引脚的功能。 2.1.2控制方法介绍 预定标计数寄存器(PSC)由输入时钟驱动,PSC在每个输入时钟周期减1;当其减到0时,TIM减1,当TIM减到0,定时器向CPU发送一个中
3、断请求(TINT)或向DMA控制器发送同步事件。 定时器发送中断信号或同步事件信号的频率可用下式计算: 通过设置定时器控制寄存器(TCR)中的自动重装控制位ARB,可使定时器工作于自动重装模式: 当TIM减到0,重新将周期寄存器(TDDR,PRD)的内容复制到计数寄存器(PSC,TIM)中,继续定时。 本实验的具体设置见后面寄存器设置部分。 2.2定时器的使用 l 初始化定时器 l 停止/启动定时器 l DSP复位后定时器寄存器的值 3.中断部分 3.1中断定义 由硬件或软件驱动的信号,使DSP将当前的程序挂起,执行另一个称为中断服务子程序(ISR)的任务。 3.2
4、 TMS320C55x的中断系统 C55x支持32个ISR。有些ISR可以由软件或硬件触发,有些只能由软件触发。 3.3 DSP处理中断的步骤 (1)接收中断请求。 软件和硬件都要求DSP将当前程序挂起 (2)响应中断请求。 CPU必须响应中断。如果是可屏蔽中断,响应必须满足某些条件。如果是不可屏蔽中断,则CPU立即响应。 (3)准备进入中断服务子程序。 CPU要执行的主要任务有: l 完成当前指令的执行,并冲掉流水线上还未解码的指令 l 自动将某些必要的寄存器的值保存到数据堆栈和系统堆栈 l 从用户实现设置好的向量地址获取中断向量,该中断向量指向中断服务子程序 (4)
5、执行中断服务子程序。 CPU执行用户编写的ISR。ISR以一条中断返回指令结束,自动恢复步骤(3)中自动保存的寄存器值。 3.4中断向量表 4.汇编程序 4.1链接命令文件 TMS320C55x链接器有两个功能强大的指令,即MEMORY和SECTIONS。 MEMORY指令允许用户定义一个目标系统的存储器映射,可以命名存储器的各个部分,并且指定开始地址和大小。 SECTIONS指令告诉链接器合成输入段为输出段,并且告诉链接器把这些
6、输出段放在存储器的某个位置。 4.2中断向量表及中断程序 a) 程序中应包含中断向量表,VC5509A 默认向量表从程序区0 地址开始存放,根据IPVD 和IPVH 的值确定向量表的实际地址。 b) 向量表中每项为8 个字,存放一个跳转指令,跳转指令中的地址为相应服务程序入口地址。第一个向量表的首项为复位向量,即CPU 复位操作完成后自动进入执行的程序入口。 c) 服务程序在服务操作完成后,清除相应中断标志,返回,完成一次中断服务。 4.3汇编源程序(见后) 二. 寄存器配置 1. 时钟模式寄存器(CLKMD),I/O端口地址0x1c00 MOV #0x5467,PORT(#
7、CLKMD);0101 0100 0110 0111 工作在锁定模式下,输出时钟频率如下: PLLMULT/PLLDIV*输入频率=20*20M=400M; 具体配置如下黑体部分: 位 字 段 说 明 15 Rsvd 保留 14 IAI 退出Idle状态后,决定PLL是否重新锁定 0 PLL将使用与进入Idle状态之前相同的设置进行锁定 1 PLL将重新锁定过程 13 IOB 处理失锁 0 时钟发生器不中断PLL,PLL继续输出时钟 1 时钟发生器切换到旁路模式,重新开始PLL锁相过程 12 TEST 必须保持为0 1
8、1~7 PLL MULT 锁定模式下的PLL倍频值,0~31(10100) 6~5 PLL DIV 锁定模式下的PLL分频值,0~3(01) 4 PLL ENABLE 使能或关闭PLL 0 关闭PLL,进入旁路模式 1 使能PLL,进入锁定模式 3~2 BYPASS DIV 旁路下的分频值 00 一分频 01 二分频 10或11 四分频 1 BREAKLN PLL失锁标志 0 PLL已经失锁 1 锁定状态或有对CLKMD寄存器的写操作 0 LOCK 锁定模式标志 0 时钟发生器处于旁路模式 1 时钟发生器处于锁定模式
9、2. 定时器包括4个寄存器 2.1定时器预定标寄存器PRSC MOV #0x0002,PORT(#PRSC0);0000 0000 0000 0010 位 字 段 数 值 说 明 15~10 Rsvd — 保留 9~6 PSC 0h~Fh 预定标计数寄存器 5~4 Rsvd — 保留 3~0 TDDR 0h~Fh 当PSC重新装入时,将TDDR的内容复制到PSC中 2.2主计数寄存器TIM MOV #0x0000,PORT(#TIM0);0 位 字 段 数 值 说 明 15~0 TIM 0000h~FFFFh 主计
10、数寄存器 2.3主周期寄存器PRD MOV #0x1fff,PORT(#PRD0);0001 1111 1111 1111 PRD0=0X1FFF;TDDR=0X0010; 中断信号频率: 内部时钟频率:400M TINT频率=400M/(8M*5)=10hz; 改变该寄存器的初始值,可以改变灯亮灭快慢。 位 字 段 数 值 说 明 15~0 PRD 0000h~FFFFh 主周期寄存器。当TIM必须重新装入时,将PRD的内容复制到TIM中 2.4定时器控制寄存器TCR 设置定时器寄存器前,关闭定时器 MOV #0x04f0,PORT(#TCR0);0
11、000 0100 1111 0000 设置完成后,开启定时器 MOV #0x00e0,PORT(#TCR0);0000 0000 1110 0000 具体配置如下黑体部分: 位 字 段 数 值 说 明 15 IDLEEN 0 1 定时器的Idle使能位。 定时器不能进入idle状态 如果idle状态寄存器中的PERIS=1,定时器进入idle状态 14 INTEXT 0 1 时钟源从内部切换到外部标志位 定时器没有准备好使用外部时钟源 定时器准备使用外部时钟源 13 ERRTIM 0 1 定时器错误标志 没有监测到错误
12、或ERRTIM已被读取 出错 12~11 FUNC FUNC=00b FUNC=01b FUNC=10b FUNC=11b 定时器工作模式选择位 TIN/TOUT为高阻态,时钟源是内部CPU时钟 TIN/TOUT为定时器输出,时钟源是内部CPU时钟 TIN/TOUT为通用输出,引脚电平反映的是DATOUT位的值 TIN/TOUT为定时器输入,时钟源是外部时钟 10 TLB 0 1 定时器装载位 TIM、PSC不重新装载 将PRD、TDDR分别复制到TIM、PSC中 9 SOFT 在调试中遇到断点时定时器的处理方法 8 FRE
13、E 7~6 PWID 00 01 10 11 定时器输出脉冲的宽度 1个CPU时钟周期 2个CPU时钟周期 4个CPU时钟周期 8个CPU时钟周期 5 ARB 0 1 自动重装控制位 ARB清0 每次TIM减为0,PRD装入TIM中,TDDR装入PSC中 4 TSS 0 1 定时器停止状态位 启动定时器 停止定时器 3 C/P 0 1 定时器输出时钟/脉冲模式选择 输出脉冲。脉冲宽度由PWID定义,极性由POLAR定义 输出时钟。引脚上信号的占空比为50%。 2 POLAR 0 1 时钟输出极
14、性位 正极性 负极性 1 DATOUT 0 1 当TIN/TOUT作为通用输出引脚,该位控制引脚上的电平 低电平 高电平 0 Rsvd 0 保留 3.中断相关寄存器 定时器中断属于可屏蔽中断需要设置以下寄存器: 因为采用定时器0中断,中断向量地址0x20h; 5000系列dsp的中断向量可以重新定位。但是它只能被重新定位Page0范围内的任何空间;(在cmd文件中给出) 3.1 IVPD(dsp向量的中断向量指针) 3.2 IVPH(主机向量的中断向量指针) 3.3 IER0(中断使能寄存器) 3.4 IEF0(中断标志寄存器)
15、 3.5 DBIER0(调试中断寄存器) 汇编指令: MOV #0x0d00,mmap(IVPD) MOV #0x0d00,mmap(IVPH) MOV #0x10,mmap(IER0) MOV #0x10,mmap(DBIER0) MOV #0xffff,mmap(IFR0) ;中断标志寄存器清零 三. 应用举例 本实验要实现的功能是:在定时器中断到来时,改变实验板上led灯的亮灭状态,同时,在中断服务程序中,设置了一个变量,可以控制亮灭的时间长短。 实现过程: (1)对处理器及一些寄存器的初始化,包括
16、时钟,定时器,中断等 .def start .global ldbs .global ncount lbds .set 0x400001 TIM0 .set 0x1000 PRD0 .set 0x1001 TCR0 .set 0x1002 PRSC0 .set 0x1003 CLKMD .set 0x1c00 ;时钟控制器地址 ;自定义 ncount .usect "vars",1 .sect
17、"TimerStart" start: ;处理器初始化 BCLR C54CM BCLR AR0LC BCLR AR1LC BCLR AR2LC BCLR C54CM .C54CM_off BCLR ARMS .ARMS_off ;ncount初始化 MOV #0,*(#ncount) ;灯亮 初始状态 AMAR *(#lbds),XAR3 MOV #0,*AR3 BSET INTM ;I
18、nitialization of Interrupt MOV #0X0d00,mmap(IVPD) MOV #0x0d00,mmap(IVPH) MOV #0x0010,mmap(IER0) MOV #0x0010,mmap(DBIER0) MOV #0xffff,mmap(IFR0) ;Initialization of Clk MOV #0 5467h,PORT(#CLKMD) ;Initialization of Timer0
19、 MOV #0x04f0,PORT(#TCR0) MOV #0x0000,PORT(#TIM0) MOV #0x1fff,PORT(#PRD0) MOV #0x0002,PORT(#PRSC0) MOV #0x00e0,PORT(#TCR0) loop: B loop .end (2)中断服务程序的编写。 本实验只是简单地通过定时器定时长短来控制led灯的亮灭时间。在中断程序中主要完成对led等的控制,
20、为了增加可视性,在中断程序中通过一个计数器来延长led的亮灭变化。 具体程序编写如下: TINT0_Isr: ;ncount++ MOV *(#ncount),AR0 ADD #1,AR0 ;nCount%=16 MOV #16,AR1 ;改变该数,可以控制灯亮灭快慢 RPT #(16-1) SUBC *AR1,AC0,AC0 MOV HI(AC0),*AR3 ;AR3-->余数
21、 BCC TINT0_Isr_end,AR3 == #0 L1: BCLR INTM ;开中断 NOP RETI TINT0_Isr_end: AMAR *(#400001h),XAR3 XOR #1,*AR3 MOV #0,*(#ncount) ;商 B L1 (3)cmd文件的编写,完成对目标存储器结构的定位和各控制段的构成和地址分配。 本实验中timer.cmd文件具体安排如下: main.obj -o timer.
22、out -m timer.map MEMORY { DARAM: o=0x100, l=0x07f00 /*On-chip DRAM*/ SARAM: o=0x10000, l=0x30000 /*On-chip SRAM*/ VECT : o=0x0d000, l=0x100 } SECTIONS { .vars : {} > DARAM .vectors : {} > VECT TimerInit : {} > SARAM Ti
23、merStart : {} > SARAM } 在上面介绍原理及寄存器时,已经把该程序的具体硬件结构和寄存器配置详细说明,在此就不在赘述。 实验程序流程图如下: 四. 系统演示及调试 4.1实验调试及结果 l 指示灯在定时器的定时中断中按照设计定时闪烁。通过改变ncount以及定时器的定时时间可以控制闪烁。 l 在对程序编译时,总出现“Remarks”错误,这是CCS中最轻级别的提示,不影响程序的正常运行。 l 在汇编语言中写入.mmregs语句后,就可以省去对存储器映射寄存器的定义,而且在TI的文档中也有寄存器名和对应地址的表,用的时候直接
24、用即可。 l 出现如下错误:Illegal directive or mnemonic(非法指令) l 汇编指令不能直接顶头写,需要与行首有一定间隔。 l 用途1:使用定时器和中断服务程序可以完成许多需要定时完成的任务,比如DSP 定时启动A/D 转换,日常生活中的计时器计数、空调的定时启动和关闭等。 l 用途2:在调试程序时,有时需要指示程序工作的状态,可以利用指示灯的闪烁来达到,指示灯灵活的闪烁方式可表达多种状态信息。 4.2 对实验的扩展 l SIN信号发生器的实现 1)采用查表法,从AD输出任意幅度,任意频率的正弦波与余弦波。 在中断中,写查表变换函数: C程序如下:
25、中断服务程序) uiData = SIN_Table[Table_Index]; //读表 uiData = uiData<<6; //移位 *P_DAC1 = uiData&0xffc0; Table_Index+=uiStep; //加上步进值 if(Table_Index>=256)Table_Index-=256; //索引溢出 *P_INT_Clear = 0x0400; //清中断标志 2)正弦表的产生 l 数的定标 许多DSP芯片只支持整数运算,如果现在这些芯片上进行小数运算的话,定点小数运算应该是最佳选择了,
26、此外即使芯片支持浮点数,定点小数运算也是最佳的速度选择。 在DSP 世界中,由于DSP芯片的限制,经常使用定点小数运算。所谓定点小数,实际上就是用整数来进行小数运算。下面先介绍定点小数的一些理论知识,然后以C语言为例,介绍一下定点小数运算的方法。在TI C5000 DSP系列中使用16比特为最小的储存单位,所以我们就用16比特的整数来进行定点小数运算。 现在进入二进制。我们的定点小数用16位二进制表达,最高位是符号位,那么有效位就是15位。小数点之后可以有0 - 15位。我们把小数点之后有n位叫做Qn,例如小数点之后有12位叫做Q12格式的定点小数,而Q0就是我们所说的整数。 Q1
27、2 的正数的最大值是 0 111 . 111111111111,第一个0是符号位,后面的数都是1,那么这个数是十进制的多少呢,很好运算,就是 0x7fff / 2^12 = 7.999755859375。对于Qn格式的定点小数的表达的数值就它的整数值除以2^n。在计算机中还是以整数来运算,我们把它想象成实际所表达的值的时候,进行这个运算。 反过来把一个实际所要表达的值x转换Qn型的定点小数的时候,就是x*2^n了。例如 0.2的Q12型定点小数为:0.2*2^12 = 819.2,由于这个数要用整数储存,所以是819 即 0x0333。因为舍弃了小数部分,所以0x0333不是精确的0.2,
28、实际上它是819/2^12 =0.199951171875。 l 下面是MATLAB产生cos表的过程: >> pi=3.1415926; >> aa=1:256; >> bb=cos(pi/256*aa); >> BB=[1,bb]; >> CC=BB*2^15;%共257个数据 Q15 将MATLAB产生的数据导出,存放在SIN_Table中。 3)DA转换原理 利用专用的数模转换芯片,可以实现将数字信号转换成模拟量输出的功能。在ICETEK–VC5509-A 板上,使用的是TLV7528 数模芯片,它可以实现同时转换四路模拟信号输出,并有10 位精度,转换时间
29、0.1μs。其控制方式较为简单:首先将需要转换的数值通过数据 总线传送到TLV7528 上相应寄存器,再发送转换信号,经过一个时间延迟,转换后的模拟量就从TLV7528 输出引脚输出。 2.TLV7528 与TMS320VC5509A 的连接: 由于TMS320VC5509A DSP 没有数模转换输出设备,采用外扩数模转换芯片的方法。在ICETEK–VC5509-A 板上选用的是TLV7528。TLV7528 的转换寄存器被映射到了DSP的I/O 空间,地址是0-3,控制转换由I/O 端口4 的写信号控制,这部分在硬件上由译码电路(GAL 芯片)完成。在TLV7528 的输出端,为了增加
30、输出功率,经过一级运放再输出到板上插座上。 4)汇编程序大致编写步骤如下: (1) 变量初始化 .ref SIN_Table DA_DATA_1 .set 0x400006 Table_Index .int 1 uiStep .int 1 (2) 中断服务程序 .sect "TimerInit" .ref index ;在main中定义,在该模块中使用的变量 .def TINT0_Isr ;定义中断程序标识,方便其它模块(中断向量表)调用 .ref COSOFF .ref uiStep TIN
31、T0_Isr: MOV *(#index),AR0 ;更新index ADD #uiStep,AR0 MOV AR0,T0 AMAR *(#0x400006),XAR3 ;启动da转换 MOV T0,*AR3 ;取表中数送到da口 AND #0X100,AR3 ;判断索引溢出 BCC TINT0_Isr_end,AR3==#0 L1: BCLR INTM ;开中断 NOP RETI TINT0_Isr_end: MOV #0,*(#uiStep) ;索引溢出,清零 B L1 .end 上述程序由于时间原因,暂时写到这里,在不断改进中。 5)预期实验结果可通过示波器或模拟示波器观察:






