在Ti的DSP程序中使用C++编程

在嵌入式开发中,年长的开发人员都比较习惯使用C语言;而年轻人在学习时,接受的培训很多也是使用C语言教授的。其实,使用C++做嵌入式开发也是很不错的选择,也许是将来嵌入式编程的一种趋势。

下面就将在嵌入式开发中使用C++的一些方式罗列一下,主要是在Ti公司的CCS5以上的开发环境中。

欢迎交流:turner_gao@163.com


  •  inline函数的使用

对于简短的函数调用,一般在头文件中声明成内联函数。

调用内联函数的代码,被编译时,会直接插入内联函数的执行代码,而不会有函数调用的发生。

虽然宏替代也可以实现内联的功能和性能,但是编译器对内联函数进行严格的类型检查,从而减少程序中的错误。

例如:

封装简单的语句,简化调用代码的书写。

	/**
	 * 使能全局中断
	 */
	inline void eint(){
		asm(" clrc INTM");
	}

	/**
	 * 禁用全局中断
	 */
	inline void dint(){
		asm(" setc INTM");
	}

	/**
	 * 使能全局实时中断
	 * 一般在eint()之后调用
	 */
	inline void ertm(){
		asm(" clrc DBGM");
	}

对函数调用的参数封装,使功能一目了然。

	inline void enableInt1(){
		enableInt(0);
	}

	inline void enableInt2(){
		enableInt(1);
	}

	inline void enableInt3(){
		enableInt(2);
	}

	inline void enableInt4(){
		enableInt(3);
	}

	inline void enableInt5(){
		enableInt(4);
	}

	inline void enableInt6(){
		enableInt(5);
	}

	inline void enableInt7(){
		enableInt(6);
	}

	inline void enableInt8(){
		enableInt(7);
	}

	inline void enableInt9(){
		enableInt(8);
	}

	inline void enableInt10(){
		enableInt(9);
	}

	inline void enableInt11(){
		enableInt(10);
	}

	inline void enableInt12(){
		enableInt(11);
	}


  • 使用常量

程序中往往要定义一些系统常数,一般将其定义成常量。

同样,宏定义也可以定义常量,但是编译器对宏也是不进行类型检查的。


  • 函数参数使用引用

嵌入式中内存往往是比较重要的资源,程序编写过程中,尽量减少内存的占用。

	inline void set( const int& i ){
		m_set |= (0x0001<<i);
	}

	inline void clear( const int& i ){
		m_clr |= (0x0001<<i);
	}

	inline void toggle( const int& i ){
		m_toggle |= (0x0001<<i);
	}


  • 使用模板编程
  • 使用类

面向对象的编程思想和方法在当代程序设计中已经非常普及。嵌入式中各种外设的使用,就像面向对象是为其而生的。比如2812有两个串口,两个串口的用法是一模一样的,就可以为其定义一个串口类。

但是类的继承和动态联编的特性给人的印象是执行效率低,占用程序空间的。

其实在嵌入式中使用类,还是应该有限制的。一般只是用类来封装,继承时不使用基类的虚函数调用,而是直接使用子类的函数调用。

当然,我们在编写复杂的应用程序时,或者编写一类应用程序的框架时,还是会使用虚函数的。算是牺牲部分性能和空间换取可复用的可靠代码吧。

比如我们做了一个基于串口的用户控制台程序框架。就是基于抽象的串口类实现的,可以运行在281x,283x,674x等平台。这样的话,只要写一份程序,就可以保证在不同硬件上通用,为后续的应用开发提供基础构件。

  • 使用类的静态对象

一般地,我们为每个外设申明一个类。比如串口是一个CSci基类,而串口A,会申明位CSciA:public CSci。

事实上,系统只有一个SCIA设备,这样我们会定义一个静态对象static CSciA& CSciA::ins()接口来获取SCIA设备的对象。

这样有多个方面的考虑:有一个统一的封装方式;有些同类外设的不同对象之间是有细微差别的;如果某个对象要频繁的访问,减少构造函数的开销。

  • 使用命名空间

命名空间真是个好东西。在Java中有包的概念,这样在不同包之间可以有同名的类和对象。在C++中使用名字空间也能实现的。

比如:281x的串口类就可以声明成这样

namespace NF281x{

/**
 * SCI基类
 */
class CSci{
public:
	CSci( volatile unsigned int& ccr,volatile unsigned int& ctl1 );
};
}

而同时可以声明283x的串口类

namespace NF283x{

/**
 * SCI基类
 */
class CSci{
public:
	CSci( volatile unsigned int& ccr,volatile unsigned int& ctl1 );
};
}

虽然,这两款芯片的串口可以认为是一样的,这样我们可以什么一个更加基本的类

namespace NF28x{

/**
 * SCI基类
 */
class CSci{
public:
	CSci( volatile unsigned int& ccr,volatile unsigned int& ctl1 );

};
}

这样我们可以在281x和283x中直接引用28x中的定义即可


  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SPWM(正弦波脉宽调制)是一种常见的交流电变频调速技术,常用于交流电机驱动等领域。在TI DSP上实现SPWM产生程序可以通过以下步骤完成: 1. 初始化IO口和定时器:根据具体的DSP型号和开发板,使用相应的头文件和函数库初始化IO口和定时器。 2. 计算SPWM的占空比:根据所需输出的正弦波频率和振幅,计算每个采样周期的占空比。具体计算方法可以参考SPWM的原理,也可以通过查找相关资料进行了解。 3. 设置定时器自动重载模式:在每个采样周期结束时,使用定时器自动重载模式重新加载占空比值,以实现连续的SPWM波形输出。 4. 运行SPWM产生程序:将SPWM的占空比值写入定时器的比较寄存器,启动定时器,并在每个采样周期结束时更新占空比值,实现连续的SPWM波形输出。 以下是一个简单的C语言SPWM产生程序示例: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #include "DSP2833x_Device.h" #include "DSP2833x_Examples.h" #define PI 3.1415926 #define SAMPLING_FREQ 20000 //采样频率,单位为Hz #define PWM_FREQ 50 //SPWM波形频率,单位为Hz #define PWM_AMPLITUDE 1 //SPWM波形振幅,取值范围为0~1 Uint16 spwm_duty[100]; //SPWM占空比数组 Uint16 spwm_index; //当前SPWM占空比在数组的索引 //计算SPWM占空比值 void calc_spwm_duty(void) { int i; float freq_ratio = PWM_FREQ / (float)SAMPLING_FREQ; //计算频率比值 for(i = 0; i < 100; i++) { spwm_duty[i] = (Uint16)(PWM_AMPLITUDE * sin(2 * PI * freq_ratio * i) * 1000 + 1000); //计算SPWM占空比值 } } void main() { InitSysCtrl(); //初始化系统时钟 InitPieCtrl(); //初始化PIE断 IER = 0x0000; //禁止所有断 IFR = 0x0000; InitPieVectTable(); //初始化PIE断向量表 EALLOW; GpioCtrlRegs.GPAMUX1.all = 0; //将GPIO口设置为普通IO口模式 GpioCtrlRegs.GPADIR.all = 0xFF; //将GPIO口设置为输出模式 EDIS; InitCpuTimers(); //初始化定时器 ConfigCpuTimer(&CpuTimer0, 150, 1000000 / SAMPLING_FREQ); //配置定时器 PieVectTable.TINT0 = &cpu_timer0_isr; //设置定时器断向量 IER |= M_INT1; //使能PIE断 PieCtrlRegs.PIEIER1.bit.INTx7 = 1; //使能定时器断 EINT; //使能全局断 calc_spwm_duty(); //计算SPWM占空比值 spwm_index = 0; //初始化SPWM占空比索引 while(1) { //等待定时器断 } } //定时器断服务函数 interrupt void cpu_timer0_isr(void) { CpuTimer0Regs.TCR.bit.TIF = 1; //清除定时器断标志位 GpioDataRegs.GPASET.all = 0xFF; //设置所有GPIO口为高电平 GpioDataRegs.GPADAT.all = spwm_duty[spwm_index]; //设置当前SPWM占空比值 spwm_index++; //更新SPWM占空比索引 if(spwm_index >= 100) { spwm_index = 0; //超过数组长度时,重置SPWM占空比索引 } } ``` 注意:以上代码仅供参考,在实际应用需要根据具体的DSP型号和开发板进行适当的修改。同时,由于SPWM产生程序需要高精度的定时控制,因此需要注意系统时钟的设置和定时器的溢出时间等参数的配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值