2301_81068482 2025-01-12 22:22 采纳率: 92.9%
浏览 10
已结题

遇到的代码书写问题解释

img

img


在找开源的时候 遇到了这样写的代码
问了一些软件对代码的解释 但是不是特别明白 不知道能不能具体讲讲为什么这样写 这样写有什么好处

  • 写回答

5条回答 默认 最新

  • 檀越@新空间 2025-01-12 22:25
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    这段代码涉及到了STM32微控制器中的DMA(直接内存访问)和CCM RAM(紧密耦合内存)的使用。让我们逐一解析并解答你的问题。

    1. 关于DMA的变量放置位置

    问题描述:

    //使用DMA的变量时候不能将其放在CCM RAM中!!
    uint16_t ADC1Result[4];
    uint16_t ADC2Result[2];
    __attribute__((section("ccmram"))) ADC_Data_t Vcap,Vin,Vout,Iin,Iout,Icap;
    

    解释:

    • DMA(Direct Memory Access) 是一种硬件机制,允许外设与内存之间直接传输数据,而不需要CPU介入。
    • CCM RAM(紧密耦合内存) 是一种快速访问的内存区域,通常用于存储需要高速读取的数据。

    为什么不能将DMA变量放在CCM RAM中?

    • DMA操作通常需要较高的带宽和较低的延迟。如果DMA使用的变量被放置在CCM RAM中,虽然访问速度快,但可能会导致其他重要任务(如中断处理)的性能下降,因为CCM RAM的容量有限且是共享资源。
    • 另外,某些STM32型号可能不支持DMA从CCM RAM读取数据,这会导致运行时错误。

    好处:

    • 如果变量放置在普通的SRAM中,可以确保DMA操作不受CCM RAM容量限制的影响,并且不会影响其他高优先级的任务。

    2. 函数声明和实现

    问题描述:

    _attribute_((section("ccmram"))) void Get_ADC(ADC_Data_t *ADC)
    {
        ADC->now_value = ADC->conversion.proportion * (ADC->ADC_value) + ADC->conversion.offset;
        ADC->ave_value = LowPass(ADC->now_value, ADC->ave_value, ADC->lowpass_a);
    }
    
    _attribute_((section("ccmram"))) void Resolve_ADC(void)
    {
        Get_ADC(&Vout);
        Get_ADC(&Vcap);
        Get_ADC(&Iin);
        Get_ADC(&Iout);
        Get_ADC(&Icap);
    
    #if DELETE_VIN
        // SAMPLE Vin.ADC value Vout.ADC value;
        // Vin.ave value Vout.ave_value;
        // Vin.now_value Vout.now_value;
    #else
        Get_ADC(&Vin);
    #endif
    }
    

    解释:

    • __attribute__((section("ccmram"))) 属性将函数或变量放置在CCM RAM中。
    • Get_ADC 函数计算ADC值并更新平均值。
    • Resolve_ADC 函数调用 Get_ADC 来处理多个ADC数据。

    为什么使用 __attribute__((section("ccmram")))

    • 将函数放在CCM RAM中可以提高执行速度,尤其是在需要频繁调用该函数的情况下。

    修改后的代码

    为了更清晰地展示,我们可以对代码进行一些改进:

    // 定义ADC数据结构体
    typedef struct {
        uint16_t ADC_value;
        float conversion_proportion;
        float conversion_offset;
        float lowpass_a;
        uint16_t now_value;
        uint16_t ave_value;
    } ADC_Data_t;
    
    // 定义低通滤波器函数
    float LowPass(uint16_t new_value, float old_value, float alpha) {
        return alpha * new_value + (1 - alpha) * old_value;
    }
    
    // 使用DMA的变量
    uint16_t ADC1Result[4];
    uint16_t ADC2Result[2];
    
    // 放置在CCM RAM中的变量
    __attribute__((section("ccmram"))) ADC_Data_t Vcap, Vin, Vout, Iin, Iout, Icap;
    
    // 获取ADC数值
    void Get_ADC(ADC_Data_t *ADC) {
        ADC->now_value = ADC->conversion_proportion * (ADC->ADC_value) + ADC->conversion_offset;
        ADC->ave_value = LowPass(ADC->now_value, ADC->ave_value, ADC->lowpass_a);
    }
    
    // 解算ADC数值
    void Resolve_ADC(void) {
        Get_ADC(&Vout);
        Get_ADC(&Vcap);
        Get_ADC(&Iin);
        Get_ADC(&Iout);
        Get_ADC(&Icap);
    
    #if DELETE_VIN
        // 样例代码,注释掉
    #else
        Get_ADC(&Vin);
    #endif
    }
    

    总结

    • 将DMA使用的变量放在普通SRAM中,避免CCM RAM的容量限制和潜在的性能问题。
    • 将需要高性能的函数放在CCM RAM中,以提高执行速度。
    • 确保代码的可读性和可维护性,通过适当的注释和结构化代码。
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 1月21日
  • 已采纳回答 1月13日
  • 创建了问题 1月12日