用户工具

站点工具


icore3_arm_hal_41
银杏科技有限公司旗下技术文档发布平台
技术支持电话0379-69926675-801
技术支持邮件Gingko@vip.163.com
版本 日期 作者 修改内容
V1.0 2020-04-21 gingko 初次建立






STM32CbeMX教程四十一——DSP_MATH实验

1. 新建工程:在主界面选择File–>New Project 或者直接点击ACCEE TO MCU SELECTOR  2. 出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置 在搜索栏的下面,提供的各种查找方式,可以选择芯片内核、型号等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32F407IGTx。  3. 配置RCC,使用外部时钟源  4. 配置调试引脚  5. 将LED对应的3个引脚(PI5,PI6,PI7)设置为GPIO_Output  6. 引脚模式配置  7. 设置串口  8设置定时器  9. 时钟源设置,选择外部高速时钟源,配置为最大主频  10. 工程文件的设置, 这里就是工程的各种配置 我们只用到有限几个,其他的默认即可 IDE我们使用的是 MDK5  11. 点击Code Generator,进行进一步配置

  • Copy all used libraries into the project folder
  • 将HAL库的所有.C和.H都复制到所建工程中
    • 优点:这样如果后续需要新增其他外设又可能不再用STM32CubeMX的时候便会很方便
    • 缺点:体积大,编译时间很长
  • Copy only the necessary library files
  • 只复制所需要的.C和.H(推荐)
    • 优点:体积相对小,编译时间短,并且工程可复制拷贝
    • 缺点:新增外设时需要重新用STM32CubeMX导入
  • Add necessary library files as reference in the toolchain project configuration file
  • 不复制文件,直接从软件包存放位置导入.C和.H
    • 优点:体积小,比较节约硬盘空间
    • 缺点:复制到其他电脑上或者软件包位置改变,就需要修改相对应的路径

自行选择方式即可

12. 然后点击GENERATE CODE 创建工程  创建成功,打开工程。





实验四十一:DSP_MATH实验

一、 实验目的与意义

  1. 了解STM32 DSP_MATH结构。
  2. 了解STM32 DSP_MATH特征。
  3. 掌握DSP_MATH使用方法。
  4. 掌握STM32 DSP_MATH库的配置方法
  5. 掌握Keil MDK集成开发环境使用方法。

二、 实验设备及平台

  1. iCore3 双核心板。点击购买
  2. JLINK(或相同功能)仿真器。点击购买
  3. Micro USB线缆。
  4. Keil MDK 开发平台。
  5. STM32CubeMX开发平台。
  6. 装有WIN XP(及更高版本)系统的计算机。

三、 实验原理

1、FPU简介

  • STM32F4xx属于Cortex M4F架构,带有32位的单精度硬件FPU(Float Point Unit),支持浮点指令集,相对比M0和M3架构,浮点运算性能高出数十倍甚至上百倍。CortexM4 FPU是ARM FPv4-SP单精度FPU一种实现形式。

2、DSP库的使用

  • STM32F4的Cortex-M4内核不仅内置硬件FPU单元,还支持DSP多种指令集,比如支持单周期乘加指令(MAC)、优化的单指令多数据指令(SIMD)等。因此Cortex-M4执行所有的DSP指令集都可以在单周期内完成,而Cortex-M3和M0需要多个指令和多个周期才能完成同样的功能。比如开方运算,M3和M0只能通过迭代法(标准数学函数库)计算,而M4F直接调用VSQRT指令完成。
  • (1)获取DSP库
    • ST官方提供了一整套的DSP库方便我们开发使用。在ST提供的标准库:stm32f4_dsp_stdperiph_lib.zip里面就有(该文件可以从ST官网上下载:http://www.st.com/web/en/catalog/tools/FM147/CL1794/SC961/SS1743/PF257901下载,文件名:STSW-STM32065)。下载解压缩之后,在目录STM32F4xx_DSP_StdPeriph_Lib_V1.4.0→Libraries→CMSIS→DSP_Lib下可以找到DSP库文件和测试实例。Sourse中是所有DSP库文件源代码,Examples文件夹下是一些测试实例。
  • (2)DSP库简介
    • ST提供了.lib格式的文件,方便使用这些库。这些.lib文件就是由Source文件夹下的源码编译生成的,如果想看某个函数的源码,可以在Source文件夹下面查找。.lib格式文件路径:STM32F4xx_DSP_StdPeriph_Lib_V1.4.0→Libraries→CMSIS→Lib→ARM,总共有8个.lib文件,和M4F相关的有两个:
      • arm_cortexM4bf_math.lib(浮点Cortex-M4大端模式)
      • arm_cortexM4lf_math.lib(浮点Cortex-M4小端模式)
  • STM32F4的内核CortexM4F采用小端模式,所以选择:arm_cortexM4lf_math.lib(浮点Cortex-M4小端模式)。

四、 实验程序

1. 硬件FPU功能的开启

  • 默认情况下,STM32F4xx的FPU是禁用的,可以通过设置协处理器控制寄存器(CPACR)来开启硬件FPU。在keil编程环境下,可以通过定义全局宏定义标识符_FPU_PRESENT和_FPU_USED都为1来开启硬件FPU。其中宏定义标识符_FPU_PRESENT用来确认处理是否带有FPU功能,标识符_FPU_USED用来确定是否开启FPU功能。实际上,因为STM32F4是带有FPU功能的,所以在stm32f4xx.h头文件中,默认定义_FPU_PRESENT为1。若要开启FPU还需要在头文件stm32f4xx.h中定义标示符_FPU_USED的值为1。即在刚才的宏定义下边添加一个宏定义。
#de-fi-ne __CM4_REV                     0x0001U  /*!< Core revision r0p1    */  
#de-fi-ne __MPU_PRESENT            1U       /*!< STM32F4XX provides an MPU     */  
#de-fi-ne __NVIC_PRIO_BITS         4U       /*!< STM32F4XX uses 4 Bits for the Priority Levels */  
#de-fi-ne __Vendor_SysTickConfig    0U       /*!< Set to 1 if different SysTick Config is used  */  
#de-fi-ne __FPU_PRESENT               1U       /*!< FPU present     */  
#define __FPU_USED                        1U  
  • 至此则完成硬件FPU的使能。在程序中如果遇到浮点运算就会使用硬件FPU相关指令,执行浮点运算,大大提升系统浮点运算速度。

2. DSP库编程环境搭建

  • 首先添加库文件。在工程目录下新建DSP_LIB文件夹用于存放库文件。然后把arm_cortexM4lf_math.lib和相关头文件(路径STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\ Libraries\CMSIS\Include 里的文件)拷贝到DSP_LIB文件夹中。
  • :ST官方提供了一整套的DSP库方便我们开发使用。在ST提供的标准库:stm32f4_dsp_stdperiph_lib.zip里面就有,该文件可以从ST官网上下载:http://www.st.com/web/en/catalog/tools/FM147/CL1794/SC961/SS1743/PF257901下载,文件名:STSW-STM32065。下载解压缩之后,在目录STM32F4xx_DSP_StdPeriph_Lib_V1.4.0→Libraries→CMSIS→DSP_Lib下可以找到DSP库文件和测试实例。Sourse中是所有DSP库文件源代码,Examples文件夹下是一些测试实例里的文件)。
  • 然后打开工程,新建DSP_LIB分组,并将arm_cortexM4lf_math.lib添加到工程里面。
  • 添加好文件之后,需要添加头文件包含路径,将第一步拷贝的Include文件夹和DSP_LIB文件夹,加入头文件包含路径。打开工程属性设置面板,然后点击”C/C++“选项卡,点击对号处,弹出include path设置面板。添加”..\DSP_LIB“和“..\DSP_LIB\Include“两个路径。

  • 最后,为了能够使用DSP库的所有功能,还需要添加以下几个全局宏定义
    • 1、ARM_MATH_CM4

  • 2、_CC_ARM
  • 3、ARM_MATH_MATRIX_CHECK
  • 4、ARM_MATH_ROUNDING
  • 添加方法是打开工程属性设置面板,然后点击”C/C++“选项卡,在“Preprocessor Symbols“下的”Define:”文本框中进行添加。两个宏之间用“,”隔开。

3. 主函数

  • 主函数中通过定时器计时,计算在普通模式下浮点数的计算所用时间与DSP模式下计算浮点数所用时间相对比,将结果打印在屏幕上,显而易见,DSP模式所花费的时间更少。
int main(void)  
{  
  /* USER CODE BEGIN 1 */  
    int i,j;  
    int res;  
    float time[2];  
    static int error_flag = 0;  
  /* USER CODE END 1 */  
  /* MCU Configuration--------------------------------------------------------*/  
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */  
  HAL_Init();  
  /* USER CODE BEGIN Init */  
  /* USER CODE END Init */ 
  /* Configure the system clock */  
  SystemClock_Config();  
  /* USER CODE BEGIN SysInit */ 
  /* USER CODE END SysInit */  
  /* Initialize all configured peripherals */  
  MX_GPIO_Init();  
  MX_TIM3_Init();  
  MX_UART4_Init();  
  /* USER CODE BEGIN 2 */  
  usart4.initialize(115200);  
  usart4.printf("\x0c"); 
  usart4.printf("\033[1;32;40m");     
  usart4.printf("Hello, I am iCore4!\r\n\r\n");  
  usart4.printf("DSP BasicMath TEST......\r\n");   
 /* Infinite loop */  
  /* USER CODE BEGIN WHILE */  
  while (1)  
  {  
    /* USER CODE END WHILE */   
    /* USER CODE BEGIN 3 */  
    timeout = 0;  
    __HAL_TIM_SET_COUNTER(&htim3,0);  
        for(j = 0;j < 10000;j++){  
            for(i = 0;i < MAX_BLOCKSIZE;i ++){  
                res = SinCos_Test(testInput_f32[i],0);  
                if(res != 0)error_flag ++;  
            }  
        }
        time[0] = __HAL_TIM_GET_COUTER(&htim3)+ timeout*5000;
        timeout = 0;  
        __HAL_TIM_SET_COUNTER(&htim3,0);  
        for(j = 0;j < 10000;j++){  
            for(i = 0;i < MAX_BLOCKSIZE;i ++){  
                res = SinCos_Test(testIput_f32[i],1);  
                if(res != 0)error_flag ++;  
            }  
        }  
        time[1] = __HAL_TIM_GET_COUTER(&htim3)+ timeout*5000;
        if(error_flag == 0){  
            usart4.printf("*NO DSP MATH LIB runtime:%0.1fms *USE DSP MATHLIB runtime:%0.1fms\r",time[0]/10,time[1]/10);  
            LED_GREEN_ON;  
            LED_RED_OFF;  
            LED_BLUE_OFF;  
        }  
        else{  
            usart4.printf("Error\r");             
            LED_GREEN_OFF;  
            LED_RED_ON;  
            LED_BLUE_OFF;  
        }  
  }  

4. 计算函数

int SinCos_Test(float testInput,unsigned char mode)  
{  
    float Sinx,Cosx;  
    float Result; 
    switch (mode){  
        case 0: //不适用DSP_MATH库
            Sinx = sinf(testInput);  
            Cosx = cosf(testInput);  
            Result = Sinx*Sinx + Cosx*Cosx;  
            Result = fabsf(Result-1.0f);  
            if(Result > DELTA)return -1;  
            break;  
 case 1://使用DSP_MATH库
            Sinx = arm_sin_f32(testInput);  
            Cosx = arm_cos_f32(testInput);  
            Result = Sinx*Sinx + Cosx*Cosx;  
            Result = fabsf(Result-1.0f);  
            if(Result > DELTA)return -1;       
            break;  
        default:  
            break;  
    }  
    return 0;  
}
}
time[0] = __HAL_TIM_GET_COUTER(&htim3)+ timeout*5000;
        timeout = 0;  
        __HAL_TIM_SET_COUNTER(&htim3,0);  
        for(j = 0;j < 10000;j++){  
            for(i = 0;i < MAX_BLOCKSIZE;i ++){  
                res = SinCos_Test(testIput_f32[i],1);  
                if(res != 0)error_flag ++;  
            }  
        }  
  time[1] = __HAL_TIM_GET_COUTER(&htim3)+ timeout*5000;
        if(error_flag == 0){  
            usart4.printf("*NO DSP MATH LIB runtime:%0.1fms *USE DSP MATHLIB runtime:%0.1fms\r",time[0] / 10, time[1] / 10);  
            LED_GREEN_ON;  
            LED_RED_OFF;  
            LED_BLUE_OFF;  
        }  
        else{  
            usart4.printf("Error\r");             
            LED_GREEN_OFF;  
            LED_RED_ON;  
            LED_BLUE_OFF;  
        }  
  }  
 

5. 启动定时器计数模式

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)  
{  
  if(tim_baseHandle->Instance==TIM3)  
  {  
    __HAL_RCC_TIM3_CLK_ENABLE();  
    HAL_NVIC_SetPriority(TIM3_IRQn, 1, 0);  
    HAL_NVIC_EnableIRQ(TIM3_IRQn);  
    HAL_TIM_Base_Start_IT(&htim3);//开启定时器中断计数模式
  }  
}

五、 实验步骤

  1. 把仿真器与iCore3的SWD调试口相连(直接相连或者通过转接器相连);
  2. 把iCore3通过Micro USB线与计算机相连,为iCore3供电;
  3. 打开Keil MDK 开发环境,并打开本实验工程;
  4. 烧写程序到iCore3上;
  5. 也可以进入Debug模式,单步运行或设置断点验证程序逻辑;
  6. 打开串口软件,显示运行结果。

六、 实验现象

  • 串口软件将会显示计算结果,LED将会表示状态。

icore3_arm_hal_41.txt · 最后更改: 2022/03/18 15:12 由 sean