这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » TMS320C5402 新手用C写TMS320C5402输出方波,问题多多,各位

共2条 1/1 1 跳转至

TMS320C5402 新手用C写TMS320C5402输出方波,问题多多,各位高手帮忙!

院士
2006-09-17 18:14:16     打赏
TMS320C5402 新手用C写TMS320C5402输出方波,问题多多,各位高手帮忙!



关键词: TMS320C5402     新手用     手用     输出方     问题    

院士
2006-12-22 22:43:00     打赏
2楼

小弟刚接触DSP不久,用的是TI的320C54X系列,苦于没有C语言编程方面的教程和例程,做试验那个费劲啊~~

下面是我自己写的利用定时器发生方波的程序(XF口),一直通不过编译,烦各位高手指点一二!!



/*头文件:timer_reg.h*/
#define TIM 0x0024/*数据存储寄存器,减1计数器*/
#define PRD 0x0025/*存放定时常数*/
#define TCR 0x0026/*控制、状态寄存器*/

#define IMR 0x0000/*中断屏蔽寄存器IMR*/
#define IFR 0x0001/*中断标志寄存器IFR*/
#define ST1 0x0007/*状态控制寄存器ST1*/


/*源程序*/

#include "timer_reg.h"
void main()      /*main*/
{
unsigned int flag=1;
while(1);
{
init_timer();
init_int();
}
}

void init_timer()/*定时器初始化*/
{
TCR=0x0010;     /*TCR中TSS位置1,停定时器*/

TIM=9999;
PRD=9999;       /*定时常数,10MHz系统时钟下定时1ms*/

TCR=0x0061;     /*TCR中TSS=0,TRB=1,TDDR=1,启动、加载定时器*/

}

void init_int()  /*中断初始化*/
{
IFR=0x0008;      /*TINT0=1,清除定时器1未处理完的中断*/
IMR=0x0008;      /*TINT0=1,开放定时器1的中断*/
ST1=0x0000;      /*中断标志位INTM=0*/
}

interrupt void int_ser()   /*中断子程序*/
{
if(flag=1)
{
  asm("SSBX XF");
  flag=0;
}
else
{
  asm("RSBX XF");
  flag=1;
}
}


/*cmd文件*/

-stack 0x400

MEMORY
{
    PAGE 0: EPROG:      origin = 0x1000,        len = 0x3000
            VECT:       origin = 0x0080,        len = 0x80

    PAGE 1: USERREGS:   origin = 0x60,          len = 0x1c
            BIOSREGS:   origin = 0x7c,          len = 0x4
            IDATA:      origin = 0x80,          len = 0x1380
            EDATA:      origin = 0x1400,        len = 0x8000
            EDATA1:     origin = 0x9400,        len = 0x4c00
}

SECTIONS
{
    .vectors: {} > VECT PAGE 0
    .sysregs: {} > BIOSREGS PAGE 1
    .trcinit: {} > EPROG PAGE 0
    .gblinit: {} > EPROG PAGE 0
     frt:     {} > EPROG PAGE 0
    .data:      {} > EPROG PAGE 0
    .text:    {} > EPROG PAGE 0
    .cinit:   {} > EPROG PAGE 0
    .pinit:   {} > EPROG PAGE 0
    .sysinit: {} > EPROG PAGE 0
    .macro:   {} > EPROG PAGE 0
    .bss:     {} > IDATA PAGE 1
    .far:     {} > IDATA PAGE 1
    .const:   {} > IDATA PAGE 1
    .switch:  {} > IDATA PAGE 1
    .sysmem:  {} > IDATA PAGE 1
    .cio:     {} > IDATA PAGE 1
    .MEM$obj: {} > IDATA PAGE 1
    .sysheap: {} > IDATA PAGE 1
    .stack:   {} > IDATA PAGE 1
}



编译结果如下:
-----------------------------  timer.pjt - Debug  -----------------------------
"d:\ti\c5400\cgtools\bin\cl500" -g -q -fr"D:/ti/myprojects/timer/Debug" -d"_DEBUG" -@"Debug.lkf" "time.c"
"time.c", line 18: warning: statement is unreachable
"time.c", line 15: warning: variable "flag" was declared but never referenced
"time.c", line 23: error: declaration is incompatible with previous "init_timer" (declared at line 18)
"time.c", line 25: error: expression must be a modifiable lvalue
"time.c", line 27: error: expression must be a modifiable lvalue
"time.c", line 28: error: expression must be a modifiable lvalue
"time.c", line 30: error: expression must be a modifiable lvalue
"time.c", line 34: error: declaration is incompatible with previous "init_int" (declared at line 19)
"time.c", line 36: error: expression must be a modifiable lvalue
"time.c", line 37: error: expression must be a modifiable lvalue
"time.c", line 38: error: expression must be a modifiable lvalue
"time.c", line 43: error: identifier "flag" is undefined
10 errors detected in the compilation of "time.c".

Build Complete,
  10 Errors, 2 Warnings, 0 Remarks.


对于该程序,自己尚有几点不明:
1、是否定时器初始化后立刻开始计时?
2、是否在函数前声明interrupt即表示该程序为中断子程序?
3、CMD文件是拷贝TI例程“hello word”的,不知道对于本程序要做什么修改?
4、用C写,是否要加入一些指定的头文件?

跪谢各位指点!要是可以的话,希望能给一些C的例程、关于DSP C的电子书,感激涕零阿!~~~~~





1: 我来啰嗦几句1:头文件中的定义不对,TIM PRD TCR等是地址的代表符号,从楼主的下文引用中来看,应该定义为 #define TIM *(volatile unsigned int*)0x0024//
其它几个就不再赘述。如此在下文中展开的宏就相当于 *add = xxxx; 这是一种访问DSP寄存器和数据空间的常规方法
2:在main()函数中,定时器和中断我想应该是在开始时初始化吧?楼主一个在死循环后操作,这个中断恐怕到世界末日也未必能发生。
3:函数应该在调用之前有声明,可以在头文件中加入,或把函数移到调用函数之前。
4:要注意变量的作用域,不可以在作用域之外访问。此处修改的简单方法是,把flage修改为全局变量或在中断程序中声明为static类型。
5:在C中使用中断,还需要写中断向量文件,声明中断服务程序的入口和在正确的中断地址处加入正确的调转指令使用,找一个例子修改一下就可以了。
6:在工程中加入适当的C支持库,以便在系统引导时能正确的初始化操作环境。
…………



2: 好,好~~~~  感谢二楼,不是罗嗦,都很有道理咯,很有启发~~
  
  恨当初C没学好,我下午再调调,有问题再来请教

  不知道哪位好心人有《C与C++编程——基于TMS320C54X》(大概的书名吧)
的电子书呢,能否发给我一下,我的邮箱:feipeng0792@sina.com,
  
  帮帮好学的孩子啊,再谢! 3: 学习学习... 4: 还有问题,请指教!根据二楼的建议,做了如下修改,现在通过编译了,可喜可贺!

由于嵌套汇编有问题,先不考虑输出方波,改为在中断子程序中输出yes和no,并随定时器的启、停不断交替,但调试时发现进不了中断,不知道是什么问题啊?

1、中断向量表有问题?
2、按我的理解,初始化定时器后即开始计时,到了设定时间后即溢出即触发中断,进入中断子程序,然后在中断中改变flag,由此输出yes,no,并在主程序中利用for循环重复1000次,不知道程序和我的本意有没有出入?
3、定时器和中断的初始化有问题?
4、cmd文件的配置,有中断则需将VECT的origin要改成0x0080,是这样的吗?




;Vector.asm,中断向量表,套用模版,只作相应修改,定义了中断子程序及其入口

        .sect ".vectors"

        .ref _c_int00           ; C entry point
        
        .ref _int_ser           ;中断服务程序
        
        .align  0x80            ; must be aligned on page boundary

RESET:                          ; reset vector
        BD _c_int00                             ; branch to C entry point
        STM #200,SP                             ; stack size of 200
nmi:    RETE                    ; enable interrupts and return from one
                NOP
                NOP
                NOP                                     ;NMI~

                ; software interrupts
sint17 .space 4*16
sint18 .space 4*16
sint19 .space 4*16
sint20 .space 4*16
sint21 .space 4*16
sint22 .space 4*16
sint23 .space 4*16
sint24 .space 4*16
sint25 .space 4*16
sint26 .space 4*16
sint27 .space 4*16
sint28 .space 4*16
sint29 .space 4*16
sint30 .space 4*16

int0:   RETE
                NOP
                NOP
                NOP
int1:   RETE
                NOP
                NOP
                NOP
int2:   RETE
                NOP
                NOP
                NOP
tint:   B    _int_ser
                NOP
                NOP
                NOP
rint0:  RETE
                NOP
                NOP
                NOP
xint0:  RETE
                NOP
                NOP
                NOP
rint1:  RETE
                NOP
                NOP
                NOP
xint1:  RETE
                NOP
                NOP
                NOP
int3:   RETE
                NOP
                NOP
                NOP
                .end



/*time_reg.h*/

#define TIM *(volatile unsigned int*) 0x0024/*数据存储寄存器,减1计数器*/
#define PRD *(volatile unsigned int*) 0x0025/*存放定时常数*/
#define TCR *(volatile unsigned int*) 0x0026/*控制、状态寄存器*/

#define IMR *(volatile unsigned int*) 0x0000/*中断屏蔽寄存器IMR*/
#define IFR *(volatile unsigned int*) 0x0001/*中断标志寄存器IFR*/
#define ST1 *(volatile unsigned int*) 0x0007/*状态控制寄存器ST1*/



/*time_init.h*/

void init_timer()/*定时器初始化*/
{
TCR=0x0010;     /*TCR=0000,0000,0001,0000B;TCR中TSS位置1,停定时器*/

TIM=9999;
PRD=9999;       /*定时常数,10MHz系统时钟下定时1ms*/

TCR=0x0021;     /*TCR=0000,0000,0010,0001B;TCR中TSS=0,TRB=1,TDDR=1,启动、加载定时器*/

}

void init_inter()  /*中断初始化*/
{
ST1=0x0000;      /*中断标志位INTM=0,开放全部中断*/
IFR=0x0008;      /*IFR=0000,0000,0000,1000B;TINT0=1,清除定时器1未处理完的中断*/
IMR=0x0008;      /*IMR=0000,0000,0000,1000B;TINT0=1,开放定时器1的中断*/

}


/*主程序*/
#include "time_reg.h"
#include "time_init.h"
#include <stdio.h>

unsigned int flag=1;/* 定义flag全局变量*/

void main()      /*main*/
{
  int i;
  for(i=1;i<=1;i++);
{
  init_inter();
  init_timer();
}
}



interrupt void int_ser()   /*中断子程序*/
{
if(flag==1)
{
  puts("yes!\n");
  flag=0;
}
else
{
  puts("no!\n");
  flag=1;
}
}

MEMORY
{
    PAGE 0: EPROG:      origin = 0x1400,        len=0x7c00
            VECT:       origin = 0x0080,        len = 0x80/*引入中断这里origin要改成0x0080?原来是0xff80*/

    PAGE 1: USERREGS:   origin = 0x60,          len = 0x1c
            BIOSREGS:   origin = 0x7c,          len = 0x4
            IDATA:      origin = 0x80,          len = 0x1380
            EDATA:      origin = 0x1400,        len = 0x8000
            EDATA1:     origin = 0x9400,        len = 0x4c00
}

SECTIONS
{
    .vectors: {} > VECT PAGE 0
    .sysregs: {} > BIOSREGS PAGE 1
    .trcinit: {} > EPROG PAGE 0
    .gblinit: {} > EPROG PAGE 0
     frt:     {} > EPROG PAGE 0
    .text:    {} > EPROG PAGE 0
    .cinit:   {} > EPROG PAGE 0
    .pinit:   {} > EPROG PAGE 0
    .sysinit: {} > EPROG PAGE 0
    .bss:     {} > IDATA PAGE 1
    .far:     {} > IDATA PAGE 1
    .const:   {} > IDATA PAGE 1
    .switch:  {} > IDATA PAGE 1
    .sysmem:  {} > IDATA PAGE 1
    .cio:     {} > IDATA PAGE 1
    .MEM$obj: {} > IDATA PAGE 1
    .sysheap: {} > IDATA PAGE 1
    .stack:   {} > IDATA PAGE 1
}



烦高手指点,帮人帮到底阿!!!


5: 再来说两句楼主需要理解这里的main()函数的意义。一般的有操作系统支持的环境中,用户的应用程序执行完毕后,需要将系统所有权归还给操作系统,操作系统负责任务调度、内存管理、意外事件(中断)处理等;而在没有操作系统的环境里,这些工作就需要应用程序相应的操作,因此如果留意一下的话,都会发现一个在死循环中进行操作,或操作完毕后进入待机或死机模式。楼主的主程序中没有这种死循环或者待机模式,所以如果调试一下的话会发现,初始化程序在反复执行,这是因为PC指针递增到溢出后再进入main()函数。
void main()
{
//初始化
  init_timer();
  init_inter();

//死循环
  while(1)
  {
     //用户任务
  }
}

中断向量表中,如果我没记错的话B _int_ser 是占用两个字的空间,如果再下面用了中断服务程序,会因为位置错位而无法正常进入中断,所以后面应该删除一个NOP指令。中断向量表的位置与硬件的程序分配空间有关,要对相应的寄存器进行适当配置才能正常操作。

对5XXX系列的我觉得比较好的书是 西安电子科技大学出版社 张勇编著的《C/C++语言硬件程序设计 —基于TMS320C500系列DSP》。


6: 谢谢理解楼上的意思了,非常感谢! 7: 很受教育 8: hotpower学习还蛮认真的  ^_^ 9: 不错!
zgl7903的讲解很不错,向他学习!

共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]