目录

06.02_DSP-开方

测试步骤

使用硬件dsp进行除法计算

实测数据

aDSP_Sqrt(a)err
0 (0x00000000)00
1 (0x00000001)10
10 (0x0000000a)30
100 (0x00000064)100
1000 (0x000003e8)310
10000 (0x00002710)1000
32767 (0x00007fff)1810
65535 (0x0000ffff)2550
65536 (0x00010000)2560
65536 (0x00010000)2560
131072 (0x00020000)3620
262144 (0x00040000)5120
524288 (0x00080000)7240
1048576 (0x00100000)10240
2097152 (0x00200000)14480
4194304 (0x00400000)20480
8388608 (0x00800000)28960
16777216 (0x01000000)40960
33554432 (0x02000000)57920
67108864 (0x04000000)81920
134217728 (0x08000000)115850
268435456 (0x10000000)163840
536870912 (0x20000000)231700
1073741824 (0x40000000)327680
2147483648 (0x80000000)463400
1 (0x00000001)10
3 (0x00000003)10
7 (0x00000007)20
15 (0x0000000f)30
31 (0x0000001f)50
63 (0x0000003f)70
127 (0x0000007f)110
255 (0x000000ff)150
511 (0x000001ff)220
1023 (0x000003ff)310
2047 (0x000007ff)450
4095 (0x00000fff)630
8191 (0x00001fff)900
16383 (0x00003fff)1270
32767 (0x00007fff)1810
65535 (0x0000ffff)2550
8191 (0x00001fff)900
16383 (0x00003fff)1270
32767 (0x00007fff)1810
65535 (0x0000ffff)2550
131071 (0x0001ffff)3620
262143 (0x0003ffff)5110
524287 (0x0007ffff)7240
1048575 (0x000fffff)10230
2097151 (0x001fffff)14480
4194303 (0x003fffff)20470
8388607 (0x007fffff)28960
16777215 (0x00ffffff)40950
33554431 (0x01ffffff)57920
67108863 (0x03ffffff)81910
134217727 (0x07ffffff)115850
268435455 (0x0fffffff)163830
536870911 (0x1fffffff)231700
1073741823 (0x3fffffff)327670
2147483647 (0x7fffffff)463400
4294967295 (0xffffffff)655350

time = 107

参考代码

06.02_DSP_Sqrt.c

/**
 * @brief DSP-开方
 * @details 使用硬件dsp进行除法计算
 */
#include "lks32mc09x_dsp.h"
#include "lks32mc09x_timer.h"
volatile int a = 10000;
volatile int y;
volatile int time;
void Timer0_Init(void);
/**
 * @brief 主函数,用于测试HSI时钟输出及GPIO翻转
 */
int main(void)
{
    DSP_Init();
    Timer0_Init();

    while (1)
    {
        TIMER_StatisticsStart(TIMER0);
        y = DSP_Sqrt(a);
        time = TIMER_StatisticsStop(TIMER0);
    }
}
/**
 * @brief 配置定时器0,用来统计除法执行时间
 */
void Timer0_Init(void)
{
    TIMER_TimerInitTypeDef TIMER_InitStruct;
    TIMER_StructInit(&TIMER_InitStruct);

    TIMER_InitStruct.EN = 1;
    TIMER_InitStruct.TH = 0xffff;

    TIMER_Init(TIMER0, &TIMER_InitStruct);
    TIMER_Enable(TIMER0);
}
#include "math.h"

使用到的库函数

库函数部分代码

#define REG_RESET(reg,mask) reg &= ~(mask)
#define REG_SET(reg,mask) reg |= (mask)
#define REG_WRITE(reg,mask) reg = (mask)
#define SYS0 ((SYS_TypeDef *)(SYS_BASE))
#define SYS_MODULE_DSP0 BIT17
#define SYS_MODULE_TIMER0 BIT4
#define SYS_MODULE_TIMER1 BIT5
#define SYS_MODULE_TIMER2 BIT6
#define TIMER0 ((TIMER_TypeDef *)TIMER0_BASE)
#define TIMER1 ((TIMER_TypeDef *)TIMER1_BASE)
#define TIMER2 ((TIMER_TypeDef *)TIMER2_BASE)
/**
 * @brief Timer初始化结构体
 */
typedef struct TIMER_TimerInitTypeDef {
    uint8_t EN;
    uint32_t CAP1_CLR_EN;
    uint32_t CAP0_CLR_EN;
    uint32_t ONE_TRIG;
    uint32_t CENTER;
    uint32_t DIR;
    uint32_t ClockDiv;
    uint32_t ETON;
    uint32_t GATE_EN;
    uint32_t RL_EN;
    uint32_t XCLK_EN;
    uint32_t SRC1;
    uint32_t CH1Output;
    uint32_t CH1_WorkMode;
    uint32_t CH1_FE_CAP_EN;
    uint32_t CH1_RE_CAP_EN;
    uint32_t SRC0;
    uint32_t CH0Output;
    uint32_t CH0_WorkMode;
    uint32_t CH0_FE_CAP_EN;
    uint32_t CH0_RE_CAP_EN;
    uint32_t TH;
    uint32_t CNT;
    uint32_t CHN0;
    uint32_t CHN1;
    uint32_t EVT;
    uint32_t FLT;
    uint32_t IE;
    uint32_t CMP0_TRIGGER_MODE;
    uint32_t CMP1_TRIGGER_MODE;
    uint32_t SHADOW;
    uint32_t CH1_DEFAULT;
    uint32_t CH0_DEFAULT;
    uint32_t HALT_PRT;
    uint32_t FAIL_SEL;
    uint32_t FAIL_POL;
    uint32_t FAIL_EN;
    uint32_t MOE;
};
/**
 * @brief Timer初始化
 * @param TIMERx Timer实例指针
 * @param TIMER_InitStruct Timer初始化结构体指针
 */
void TIMER_Init(TIMER_TypeDef *TIMERx, TIMER_TimerInitTypeDef *TIMER_InitStruct)
{
    uint32_t th = TIMER_InitStruct->TH;
    TIMER_Enable(TIMERx);
    if (TIMERx != TIMER2) // 只有timer2是32位定时器
    {
        if (th > 0xffff)
        {
            th = 0xffff;
        }
        else
        {
            __NOP();
        }
    }
    else
    {
        __NOP();
    }
    // 配置Timer寄存器
    TIMERx->CFG2 = (TIMER_InitStruct->EN << 15) |
                   (TIMER_InitStruct->ONE_TRIG << 9) |
                   (TIMER_InitStruct->CENTER << 8) |
                   (TIMER_InitStruct->DIR << 6) |
                   (TIMER_InitStruct->ClockDiv << 4) |
                   (TIMER_InitStruct->ETON << 3) |
                   (TIMER_InitStruct->GATE_EN << 2) |
                   (TIMER_InitStruct->RL_EN << 1) |
                   TIMER_InitStruct->XCLK_EN;

    TIMERx->CFG0 = (TIMER_InitStruct->CMP0_TRIGGER_MODE << 9) |
                   (TIMER_InitStruct->CAP0_CLR_EN << 8) |
                   (TIMER_InitStruct->SRC0 << 4) |
                   (TIMER_InitStruct->CH0Output << 3) |
                   (TIMER_InitStruct->CH0_WorkMode << 2) |
                   (TIMER_InitStruct->CH0_FE_CAP_EN << 1) |
                   (TIMER_InitStruct->CH0_RE_CAP_EN << 0);

    TIMERx->CFG1 = (TIMER_InitStruct->CMP1_TRIGGER_MODE << 9) |
                   (TIMER_InitStruct->CAP1_CLR_EN << 8) |
                   (TIMER_InitStruct->SRC1 << 4) |
                   (TIMER_InitStruct->CH1Output << 3) |
                   (TIMER_InitStruct->CH1_WorkMode << 2) |
                   (TIMER_InitStruct->CH1_FE_CAP_EN << 1) |
                   (TIMER_InitStruct->CH1_RE_CAP_EN << 0);

    TIMERx->CHN0 = TIMER_InitStruct->CHN0;
    TIMERx->CHN1 = TIMER_InitStruct->CHN1;
    TIMERx->TH   = th;
    TIMERx->CNT  = TIMER_InitStruct->CNT;
    TIMERx->EVT  = TIMER_InitStruct->EVT;
    TIMERx->FLT  = TIMER_InitStruct->FLT;
    TIMERx->IE   = TIMER_InitStruct->IE;

    TIMERx->IO = (TIMER_InitStruct->HALT_PRT << 7) |
                 (TIMER_InitStruct->CH0_DEFAULT << 8) |
                 (TIMER_InitStruct->CH1_DEFAULT << 9) |
                 (TIMER_InitStruct->MOE << 6) |
                 (TIMER_InitStruct->FAIL_SEL << 2) |
                 (TIMER_InitStruct->FAIL_POL << 1) |
                 (TIMER_InitStruct->FAIL_EN << 0);

    // 影子寄存器配置
    TIMERx->CFG2 |= (TIMER_InitStruct->SHADOW << 10);
}
/**
 * @brief Timer结构体初始化
 * @param TIMER_InitStruct Timer初始化结构体指针
 */
void TIMER_StructInit(TIMER_TimerInitTypeDef *TIMER_InitStruct)
{
    for (int i = 0; i < sizeof(TIMER_TimerInitTypeDef) / sizeof(uint32_t); i++)
    {
        ((uint32_t *)TIMER_InitStruct)[i] = 0;
    }
}
/**
 * @brief 使能Timer
 * @param TIMERx Timer实例指针
 */
void TIMER_Enable(TIMER_TypeDef *TIMERx)
{
    if (TIMERx == TIMER0)
    {
        SYS_ModuleClockCmd(SYS_MODULE_TIMER0, ENABLE);
    }
    else if (TIMERx == TIMER1)
    {
        SYS_ModuleClockCmd(SYS_MODULE_TIMER1, ENABLE);
    }
    else if (TIMERx == TIMER2)
    {
        SYS_ModuleClockCmd(SYS_MODULE_TIMER2, ENABLE);
    }
    else
    {
        __NOP();
    }
}
/**
 * @brief 初始化DSP模块
 *
 * 该函数用于初始化DSP模块,使其处于可用状态。
 */
void DSP_Init(void)
{
    SYS_ModuleClockCmd(SYS_MODULE_DSP0, ENABLE);
    SYS_SoftResetModule(SYS_MODULE_DSP0);
}
/**
 * @brief 数字模块时钟使能
 * @param nModule 模块编号
 * @param state 使能或禁用状态
 */
void SYS_ModuleClockCmd(uint32_t nModule, uint8_t state)
{
    REG_WRITE(SYS0->PROTECT, 0x7a83);
    if (state)
    {
        REG_SET(SYS0->CLK_FEN, nModule);
    }
    else
    {
        REG_RESET(SYS0->CLK_FEN, nModule);
    }
    REG_WRITE(SYS0->PROTECT, 0);
}
/**
 * @brief 计算平方根
 *
 * @param val 输入值
 * @return 平方根值
 */
uint16_t DSP_Sqrt(uint32_t val)
{
    DSP0_RAD = val;
    return DSP0_SQRT;
}
/**
 * @brief 软复位模块
 * @param nModule 模块编号
 */
void SYS_SoftResetModule(uint32_t nModule)
{
    REG_WRITE(SYS0->PROTECT, 0x7a83);
    REG_SET(SYS0->SFT_RST, nModule);
    REG_RESET(SYS0->SFT_RST, nModule); // 触发复位后需清除复位位
    REG_WRITE(SYS0->PROTECT, 0);
}