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

news2024/12/27 11:21:07

前面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 operation

    ScicRegs.SCIFFRX.bit.RXFFINTCLR     = 1;    // 1: Write 1 to clear RXFFINT flag in bit 7

    PieCtrlRegs.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 operation
    ScicRegs.SCIFFRX.bit.RXFFINTCLR     = 1;    // 1: Write 1 to clear RXFFINT flag in bit 7
    PieCtrlRegs.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.coloradmin.cn/o/974212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

这3个教学难题,你中招了吗?

在当今教育领域&#xff0c;提高教育质量和学生学习成果是学校和教育机构的首要任务之一。教育管理者、教师和政策制定者都在寻求创新的方法来监督和改进教育过程。 在线巡课系统应运而生&#xff0c;成为教育界的一项重要工具&#xff0c;旨在帮助学校管理者更好地理解教育实践…

无涯教程-JavaScript - ISOWEEKNUM函数

描述 ISOWEEKNUM函数返回给定日期的年份的ISO周编号。 语法 ISOWEEKNUM (date)争论 Argument描述Required/OptionalDateDate is the date-time code used by Excel for date and time calculation.Required Notes Microsoft Excel将日期存储为连续数字,因此可以在计算中使…

【网络教程】记一次使用Docker手动搭建BT宝塔面板的全过程(包含问题解决如:宝塔面板无法开启防火墙,ssh,nginx等)

文章目录 准备安装安装宝塔面板开启ssh和修改ssh的密码导出镜像问题解决宝塔面板无法开启防火墙无法启动ssh设置密码nginx安装失败设置开机启动相关服务准备 演示的系统环境:Ubuntu 22.04.3 LTS更新安装/升级docker到最新版本升级docker相关命令如下# 更新软件包列表并自动升级…

期权交易策略及案例的基本策略有哪些?

目前我国上市交易的期权品种日益丰富&#xff0c;期权的基础的交易方法是建立相应头寸再反向平仓&#xff0c;赚取权利金差价&#xff0c;也可以持有期权到期行权。除了基础的交易方法之外&#xff0c;期权还有一些组合策略&#xff0c;下文介绍期权交易策略及案例的基本策略有…

K210-AI视觉

1、颜色识别 image.find_blobs( thresholds, invertFalse, roi, x_stride2, y_stride1, area_threshold10, pixels_threshold10, mergeFalse, margin0, threshold_cbNone, merge_cbNone)thresholds : 必须是元组列表。 [(lo, hi), (lo, hi), …, (lo, hi)] 定义你想追踪…

Python数据分析实战-Series转DataFrame并将index设为新的一列(附源码和实现效果)

实现功能 Series转DataFrame并将index设为新的一列 实现代码 import pandas as pd# 创创建series series pd.Series([1, 2, 3, 4, 5])# 创建一个DataFrame对象 data {column_name: series} df pd.DataFrame(data)# 重新设置索引&#xff0c;将原有的索引作为新的一列 df.r…

计算机的 bit(比特)和Byte(字节)

我们来说说和数据有关的单位 bit 和 Byte。 在说这这个数据当我之前&#xff0c;大家应该都知道计算机实际上只能处理0和1。 计算机能够把0和1转换为电路中的信号来进行计算&#xff0c;这个其实就是计算机的本质。 单位定义 我们先对需要使用的单位进行一些定义。 bit&…

Swift 周报 第三十六期

文章目录 前言新闻和社区消息称苹果公司和印度财政部官员磋商&#xff0c;扩大在印度的制造产能iPhone 15 Pro 机型新增泰坦灰iPhone 15 全系配 USB-C 苹果拒绝接口和安卓互通 提案正在审查的提案 Swift论坛推荐博文话题讨论关于我们 前言 本期是 Swift 编辑组整理周报的第三十…

AcWing 787:归并排序

【题目来源】https://www.acwing.com/problem/content/789/【题目描述】 给定你一个长度为 n 的整数数列。 请你使用归并排序对这个数列按照从小到大进行排序。 并将排好序的数列按顺序输出。【输入格式】 输入共两行&#xff0c;第一行包含整数 n。 第二行包含 n 个整数&#…

鼠标知识系列之星闪鼠标

随着 2023.8.4 华为 HDC 大会的落幕&#xff0c;一个新的名词开始进入了人们的视线&#xff1a;星闪 NaerLink&#xff0c;随着星闪技术引入键鼠圈子的还有一个名词&#xff1a;星闪鼠标。 正如我们之前鼠标知识分享系列提到过的&#xff0c;目前市面上的鼠标主要是有线鼠标和…

数据库原理及应用(MySQL)

建议大屏观看&#xff0c;避免格式错误&#xff0c;影响观感 目录 第一章 数据库系统概述 1.数据库系统概述 1.1.信息 1.2.数据 1.3.信息和数据之间的联系 1.4.数据库&#xff08;DB&#xff09; 1.5.数据库管理系统&#xff08;DBMS&#xff09; 1.6.数据库管理系统的…

简单了解ARP协议

目录 一、什么是ARP协议&#xff1f; 二、为什么需要ARP协议&#xff1f; 三、ARP报文格式 四、广播域是什么&#xff1f; 五、ARP缓存表是什么&#xff1f; 六、ARP的类型 6.1 ARP代理 6.2 免费ARP 七、不同网络设备收到ARP广播报文的处理规则 八、ARP工作机制原理 …

楠姐技术漫话:接着唠唠社区发现 | 京东云技术团队

★ halo&#xff0c;大家好很开心又和大家见面了 ★ 在第一篇 楠姐技术漫画&#xff1a;图计算的那些事 发布之后&#xff0c;楠姐收到了很多建议、鼓励和支持&#xff0c;非常感谢大家的喜欢&#xff0c;所以楠姐尽自己所能马不停蹄开始第二篇的创作&#xff0c;虽迟但到~ ★…

高等数学笔记

|sinx|连续不可导 只要在x0处存在极限且极限等于f(x0)则函数在此处连续 如果某点可导则左右导数应该相等&#xff08;可导一定连续&#xff0c;连续不一定可导&#xff09; 双曲函数的由来 塞入dx 莱布尼茨公式 sin(nx)的k次导n^k*sin(nxkΠ/2) 注意符号&#xff01; 二阶导公…

实时操作系统Freertos开坑学习笔记:(五):任务调度和时间片调度

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、任务调度1.开启任务调度器函数2.启动第一个任务 二、任务切换的原理三、时间片调度1.基本概念2.看一个实际例程①我们设置滴答定时器中断时间为50ms&#x…

低代码平台:IVX 重新定义编程

目录 &#x1f36c;一、写在前面 &#x1f36c;二、低代码平台是什么 &#x1f36c;三、为什么程序员和技术管理者不太可能接受“低代码”平台&#xff1f; &#x1f36d;1、不安全&#xff08;锁定特性&#xff09; &#x1f36d;2、不信任 &#x1f36c;四、IVX低代码平台 &a…

Vue3数值动画(NumberAnimation)

效果如下图&#xff1a;在线预览 APIs 参数说明类型默认值必传from数值动画起始数值number0falseto数值目标值number1000falseduration数值动画持续时间&#xff0c;单位msnumber3000falseautoplay是否自动开始动画booleantruefalseprecision精度&#xff0c;保留小数点后几位…

vue响应式详解

1. 响应式的定义 我们都知道&#xff0c;vue是基于javascript的&#xff0c;那我们使用一段javascript代码来描述响应式 let a 1,b 1,c; c a b; console.log(c) // 输出 2 // 改变 a的值 a 3; // 重新给c赋值 即把 c a b; 再执行一遍c的值才能变为 4 // c a b; // …

map组件轨迹,定位,导航,定位点遮罩

小程序使用map组件实现轨迹&#xff0c;定位&#xff0c;导航&#xff0c;定位点遮罩 map组件常用属性说明&#xff0c; 看着还要自己研究写 我们立志成为cv工程师 直接上代码&#xff01;&#xff01;&#xff01; <template><map id"map" class"m…

天软高频因子日内及隔夜动量因子

天软因子序列课程再次启动&#xff0c;本周四&#xff08;9月7日&#xff09;下午4点相约腾讯会议&#xff0c;可直接扫描下方二维码&#xff0c;欢迎大家参会&#xff01; 本次会议主要内容有&#xff1a; 1.介绍日内及隔夜动量因子的构造逻辑&#xff0c;如何选择市 场代理变…