DSP_TMS320F28377D_算法加速方法4_C语言编程优化

前面3篇的优化思路是从硬件本身和函数库这些方向去加速, 本文则仅从代码本身的效率去考虑加速的方法。

1、用全局变量比用局部变量快

void testfunction1(){  // 局部变量int i;double s,a,b;a = 1.023;b = 12.23;for(i = 0; i < 1000; i++){s = __divf32(a,b);}
}int i1;
double s1,a1,b1;
void testfunction2(){   // 全局变量a1 = 1.023;b1 = 12.23;for(i1 = 0; i1 < 1000; i1++){s1 = __divf32(a1,b1);}
}

2、用指针增量操作代替数组下标寻址

double a[10] = {0.1,0.2,0.3,0.4,0.5,0.1,0.2,0.3,0.4,0.5};
double *p = a;
void testfunction1(){  // 数组下标int i,j;double s;for(i = 0; i < 1000; i++){for(j = 0; j < 10; j++){s = __sqrt(a[j]);}}
}void testfunction2(){   // 指针增量int i,j;double s;for(i = 0; i < 1000; i++){p = a;for(j = 0; j < 10; j++){s = __sqrt(*p++);}}
}

 3、尽量少用函数,用宏函数或者直接实现来替代函数

double a = 1.0;
double b = 2.0;
double c = 3.0;
double d = 4.0;
double e = 0;#define TEST(a,b,c,d) (__divf32((__sqrt(a*b)+c),d))double testfun(double a, double b,double c, double d){return __divf32((__sqrt(a*b)+c),d);
}

注:直接实现和用宏定义的函数应该时间是一样或者说是很接近的,没有优劣之分。 18001900的差别应该是测试方法有些不可控因素导致的。如果把直接实现的代码放在第三个部分,它也1800us。
 

4 多重循环长循环放在层,短循环放在

在系统的多重循环过程中,需要程序员将最长的循环内容设置在系统的最内层,同时需要将最短的循环内容设置在系统的最外层。这样,能够有效提升CPU的运行效率,促进CPU的跨切循环次数。

5 从算法本身的复杂度去优化

假设我要计算 1+2+…+100

6 整数的乘除用位移运算替代

DSP的测试结果来看,位移运算和乘法时间一模一样,根本没区别。不推荐使用。

7 通信优化

DSP经常会用到串口通信,串口发送主要优化思路是去掉多余的赋值语句循环语句。

float fDrivex = 0.15;
float fDrivey = -0.3;
Uint16 FSM_TxBuffer[9]={0,0,0,0,0,0,0,0,0};struct _FSM_com_struct_
{Uint16  sHeader;Uint16  controlmode;int     iEddyx;int     iEddyy;Uint16  Check;Uint16  tail;
}FSM_Tx_struct;
void testfunction(){ // 优化前int i = 0;FSM_Tx_struct.iEddyx = (int16)(fDrivex * 21333.33);FSM_Tx_struct.iEddyy = (int16)(fDrivey * 21333.33);FSM_TxBuffer[0] = 0x55;FSM_TxBuffer[1] = 0xAA;FSM_TxBuffer[2] = 0x10;FSM_TxBuffer[8] = 0xCC;FSM_TxBuffer[3] = ( (Uint16)(FSM_Tx_struct.iEddyx) >> 8);FSM_TxBuffer[4] = ( (Uint16)(FSM_Tx_struct.iEddyx) & 0x00FF);FSM_TxBuffer[5] = ( (Uint16)(FSM_Tx_struct.iEddyy) >> 8);FSM_TxBuffer[6] = ( (Uint16)(FSM_Tx_struct.iEddyy) & 0x00FF);FSM_TxBuffer[7] = 0xFF ^ FSM_TxBuffer[2] ^ FSM_TxBuffer[3] ^ FSM_TxBuffer[4] ^ FSM_TxBuffer[5] ^ FSM_TxBuffer[6];for(i = 0; i < 9; i++){ScicRegs.SCITXBUF.all   = FSM_TxBuffer[i];while (ScicRegs.SCICTL2.bit.TXRDY == 0);}}
float fDrivex = 0.15;
float fDrivey = -0.3;
Uint16 FSM_TxBuffer[9]={0,0,0,0,0,0,0,0,0};struct _SCI_TX_struct_
{int     iEddyx;int     iEddyy;
};struct _TxBUF_struct_
{Uint16  Low:8;Uint16  High:8;
};union sciTxunion {struct  _TxBUF_struct_  TxBUF[2];struct  _SCI_TX_struct_ bit;
} FSM_Tx_union;void testfunction1(){ // 优化后FSM_Tx_union.bit.iEddyx = (int16)(fDrivex * 21333.33);FSM_Tx_union.bit.iEddyy = (int16)(fDrivey * 21333.33);ScicRegs.SCITXBUF.all   = 0x55;while (ScicRegs.SCICTL2.bit.TXRDY == 0);ScicRegs.SCITXBUF.all   = 0xAA;while (ScicRegs.SCICTL2.bit.TXRDY == 0);ScicRegs.SCITXBUF.all   = 0x10;while (ScicRegs.SCICTL2.bit.TXRDY == 0);ScicRegs.SCITXBUF.all   = FSM_Tx_union.TxBUF[0].High;while (ScicRegs.SCICTL2.bit.TXRDY == 0);ScicRegs.SCITXBUF.all   = FSM_Tx_union.TxBUF[0].Low;while (ScicRegs.SCICTL2.bit.TXRDY == 0);ScicRegs.SCITXBUF.all   = FSM_Tx_union.TxBUF[1].High;while (ScicRegs.SCICTL2.bit.TXRDY == 0);ScicRegs.SCITXBUF.all   = FSM_Tx_union.TxBUF[1].Low;while (ScicRegs.SCICTL2.bit.TXRDY == 0);ScicRegs.SCITXBUF.all   = 0xEF ^ FSM_Tx_union.TxBUF[0].High ^ FSM_Tx_union.TxBUF[0].Low ^ FSM_Tx_union.TxBUF[1].High ^ FSM_Tx_union.TxBUF[1].Low;while (ScicRegs.SCICTL2.bit.TXRDY == 0);ScicRegs.SCITXBUF.all   = 0xCC;while (ScicRegs.SCICTL2.bit.TXRDY == 0);}

串口接收主要优化思路也是去掉多余的赋值语句,另外,去掉多余的逻辑判断

// 优化前
interrupt void getScic(void){int i = 0;FSMRxCheck = 0xFF;for(i = 0; i < 9; i++){FSM_RxBuffer[i]         = ScicRegs.SCIRXBUF.all;if(i > 1 && i<7){FSMRxCheck ^= FSM_RxBuffer[i];}}FSMRxCheck = FSMRxCheck & 0x00FF;FSM_Rx_Cnt  = FSM_Rx_Cnt + 1;ScicRegs.SCIFFRX.bit.RXFIFORESET    = 0;    // 0: Write 0 to reset the FIFO pointer to zero, and hold in reset.ScicRegs.SCIFFRX.bit.RXFIFORESET    = 1;    // 1: Re-enable receive FIFO operationScicRegs.SCIFFRX.bit.RXFFINTCLR     = 1;    // 1: Write 1 to clear RXFFINT flag in bit 7PieCtrlRegs.PIEACK.all  = PIEACK_GROUP8;    // Writing a 1 to the respective interrupt bit clears the bit and enables the PIE block to drive a pulse into// the CPU interrupt input if an interrupt is pending for that group.
}void getEddy(void){FSM_Rx_struct.sHeader       =   ( FSM_RxBuffer[0] << 8 ) + FSM_RxBuffer[1];FSM_Rx_struct.controlmode   =   FSM_RxBuffer[2];FSM_Rx_struct.iEddyx        =   (int)( ( FSM_RxBuffer[3] << 8) +  FSM_RxBuffer[4] );FSM_Rx_struct.iEddyy        =   (int)( ( FSM_RxBuffer[5] << 8) +  FSM_RxBuffer[6] );FSM_Rx_struct.Check         =   FSM_RxBuffer[7];FSM_Rx_struct.tail          =   FSM_RxBuffer[8];if(FSM_Rx_struct.sHeader == 0x55AA && FSM_Rx_struct.tail == 0xCC && FSMRxCheck == FSM_Rx_struct.Check){fEddyx  = (float)FSM_Rx_struct.iEddyx * 0.000046875;fEddyy  = (float)FSM_Rx_struct.iEddyy * 0.000046875;//asm ("      ESTOP0");}}
// 优化后
Uint16 FSMRxCheck = 0x00FF;
interrupt void getScic(void){int i = 0;for(i = 0; i < 9; i++){FSM_RxBuffer[i]         = ScicRegs.SCIRXBUF.all;if(i > 1 && i<7){FSMRxCheck ^= FSM_RxBuffer[i];}}DecodeEn = 1;ScicRegs.SCIFFRX.bit.RXFIFORESET    = 0;    // 0: Write 0 to reset the FIFO pointer to zero, and hold in reset.ScicRegs.SCIFFRX.bit.RXFIFORESET    = 1;    // 1: Re-enable receive FIFO operationScicRegs.SCIFFRX.bit.RXFFINTCLR     = 1;    // 1: Write 1 to clear RXFFINT flag in bit 7PieCtrlRegs.PIEACK.all  = PIEACK_GROUP8;    // Writing a 1 to the respective interrupt bit clears the bit and enables the PIE block to drive a pulse into// the CPU interrupt input if an interrupt is pending for that group.
}void getEddy(void){if( FSMRxCheck==FSM_RxBuffer[7] ){fEddyx  = (float)( (FSM_RxBuffer[3]<<8) + FSM_RxBuffer[4] ) * 0.000046875;fEddyy  = (float)( (FSM_RxBuffer[5]<<8) + FSM_RxBuffer[6] ) * 0.000046875;FSMRxCheck  = 0x00FF;}}

 

 

 后续暂时是不会再写DSP算法加速的方法了。 感谢您的阅读,如果您还有什么优化的方法和思路,欢迎留言分享、收藏点赞

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/120816.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

消灭怪物的最大数量【力扣1921】

一、题目分析 需要满足的条件&#xff1a; 只能在每分钟的开始使用武器武器能杀死距离城市最近的怪兽怪兽到达城市就会输掉游戏 游戏最优策略&#xff1a;我们可以在每分钟的开始都使用一次武器&#xff0c;用来杀死距离城市最近的怪兽。这样可以在力所能及的范围内&#xf…

Lesson4-3:OpenCV图像特征提取与描述---SIFT/SURF算法

学习目标 理解 S I F T / S U R F SIFT/SURF SIFT/SURF算法的原理&#xff0c;能够使用 S I F T / S U R F SIFT/SURF SIFT/SURF进行关键点的检测 SIFT/SURF算法 1.1 SIFT原理 前面两节我们介绍了 H a r r i s Harris Harris和 S h i − T o m a s i Shi-Tomasi Shi−Tomasi…

JVM垃圾回收机制和常用算法(简洁版)

垃圾收集 (Garbage Collection,GC) 垃圾收集主要是针对堆和方法区进行。程序计数器、虚拟机栈和本地方法栈这三个区域属于线程私有的&#xff0c;只存在于线程的生命周期内&#xff0c;线程结束之后就会消失&#xff0c;因此不需要对这三个区域进行垃圾回收。 判断一个对象是…

QT day5

服务器&#xff1a; #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//给服务器指针实例化对象server new QTcpServer(this); }Widget::~Widget() {delete ui…

vue3中TCplayer应用

环境win10:vitevue3elementUI 1 安装 npm install tcplayer.js2 使用 <template><div><video id"player-container-id" width"414" height"270" preload"auto" playsinline webkit-playsinline></video>&l…

【数据结构练习】栈的面试题集锦

目录 前言&#xff1a; 1.进栈过程中可以出栈的选择题 2.将递归转化为循环 3.逆波兰表达式求值 4.有效的括号 5. 栈的压入、弹出序列 6. 最小栈 前言&#xff1a; 数据结构想要学的好&#xff0c;刷题少不了&#xff0c;我们不仅要多刷题&#xff0c;还要刷好题&#x…

大模型 Dalle2 学习三部曲(二)clip学习

clip论文比较长48页&#xff0c;但是clip模型本身又比较简单&#xff0c;效果又奇好&#xff0c;正所谓大道至简&#xff0c;我们来学习一下clip论文中的一些技巧&#xff0c;可以让我们快速加深对clip模型的理解&#xff0c;以及大模型对推荐带来革命性的变化。 clip结构 首选…

Python+Selenium4环境搭建

很久没有了解自动化了&#xff0c;最近发现项目中沉淀了很多东西&#xff0c;回归测试效率很低&#xff0c;所以必须要考虑构建自动化来提供各个环节的小效率。由于忙于需求以及产品的流程规范&#xff0c;现在对于测试技术方面的研究也相对少了很多。不过不管做什么&#xff0…

Arduino驱动LX1972传感器(光照传感器篇)

LX1972环境光(可见光)传感器,对可见光照度的反应特性与人眼的特性类似,可以模拟人对环境光线的强度的判断,从而方便做出与人友好互动的应用,可应用于照明控制、屏幕背光控制等。 1、传感器特性 传感器技术指标如下: 工作温度: -40~80C照度范围: 1 – 800Lux输出信号:…

CSS中如何实现文字描边效果(Text Stroke)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 文字描边效果&#xff08;Text Stroke&#xff09;⭐ 示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个…

nas汇编程序的调试排错方法

nas汇编程序的调试排错方法&#xff1a; 1、查找是哪一步错了 2、查看对应的*.lst文件&#xff0c;本例中是"asmhead.lst" 3、根据*.lst文件的[ERROR #002]提示查看源码&#xff0c;改错。 4、重新运行编译&#xff0c;OK 1、查找是哪一步错了&#xff1a; nask.ex…

黑盒测试方法论—边界值

边界值分析法是一种很实用的黑盒测试用例方法&#xff0c;它具有很强的发现故障的能力。边界值分析法也是作为对等价类划分法的补充&#xff0c;测试用例来自等价类的边界。 这个方法其实是在测试实践当中发现&#xff0c;Bug 往往出现在定义域或值域的边界上&#xff0c;而不…

结构体(个人学习笔记黑马学习)

1、结构体的定义和使用 #include <iostream> using namespace std; #include <string>struct Student {string name;int age;int score; }s3;int main() {//1、struct Student s1;s1.name "张三";s1.age 18;s1.score 100;cout << "姓名&a…

css 选择器

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>/* ~ 表示的h…

FPGA输出lvds信号点亮液晶屏

1 概述 该方案用于生成RGB信号&#xff0c;通过lvds接口驱动逻辑输出&#xff0c;点亮并驱动BP101WX-206液晶屏幕。 参考&#xff1a;下面为参考文章&#xff0c;内容非常详细。Xilinx LVDS Output——原语调用_vivado原语_ShareWow丶的博客http://t.csdn.cn/Zy37p 2 功能描述 …

如何在你的Android工程中启用K2编译器?

如何在你的Android工程中启用K2编译器&#xff1f; K2编译器是用于Kotlin代码编译的最新、高效编译器&#xff0c;你现在可以尝试使用了。 Kotlin编译器正在为Kotlin 2.0进行重写&#xff0c;新的编译器实现&#xff08;代号K2&#xff09;带来了显著的构建速度改进&#xff…

10 mysql tiny/small/medium/big int 的数据存储

前言 这里主要是 由于之前的一个 datetime 存储的时间 导致的问题的衍生出来的探究 探究的主要内容为 int 类类型的存储, 浮点类类型的存储, char 类类型的存储, blob 类类型的存储, enum/json/set/bit 类类型的存储 本文主要 的相关内容是 int 类类型的相关数据的存储 …

Vue3 学习 组合式API setup语法糖 响应式 指令 DIFF(一)

文章目录 前言一、Composition Api二、setup语法糖三、响应式refreactive 四、其他一些关键点v-prev-oncev-memov-cloak 五、虚拟Dom五、diff算法 前言 本文用于记录学习Vue3的过程 一、Composition Api 我觉得首先VUE3最大的改变就是对于代码书写的改变&#xff0c;从原来选择…

购物商场项目实践

1.项目开始 1&#xff09;此项目为在线电商项目 2&#xff09;包含首页&#xff0c;搜索列表&#xff0c;商品详情&#xff0c;购物车&#xff0c;订单&#xff0c;支付&#xff0c;用户登录/注册等多个子模块 3&#xff09;使用Vue全家桶ES6webpackAxios等前端技术 4&…

MySQL主从复制与读写分离 及其实例

目录 主从复制与读写分离 1、MySQL主从复制原理 1.1、MySQL的复制类型 1.2、MySQL主从复制的工作过程 1.3、mysq支持的复制类型 1.4、 数据流向 1.5、主从复制的工作过程 2、读写分离 2.1、什么是读写分离&#xff1f; 2.2、为什么要读写分离呢&#xff1f; 2.3、什么…