5.3 CORDIC 使用说明

本章说明 N32H49x 标准外设库中 CORDIC 驱动的文件组成与 11 个公开函数,以及 3 个示例。CORDIC 是芯片内置的坐标旋转数字计算加速器,可用硬件完成三角函数、双曲函数、幅值与反正切等运算;数据位宽、缩放因子与输出限幅的取值请配合用户手册的“坐标旋转数字计算机(CORDIC)”章节阅读。

5.3.1 相关文件

相对路径 作用
firmware/n32h49x_std_periph_driver/inc/n32h49x_cordic.h 定义运算功能、数据位宽、缩放与限幅等配置项及寄存器掩码,声明 11 个公开函数
firmware/n32h49x_std_periph_driver/src/n32h49x_cordic.c 实现上述 11 个函数:初始化与结构体默认值、中断与 DMA 请求控制、数据寄存器地址获取与读写、状态标志读取与清除
projects/n32h49x_EVAL/examples/CORDIC/ CORDIC 示例根目录,含 CORDIC_Fixed_Sin_DMA、CORDIC_Fixed_Sin_IT、CORDIC_Float_Sin_IT 3 个示例
projects/n32h49x_EVAL/examples/CORDIC/CORDIC_Fixed_Sin_DMA/ 该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt
projects/n32h49x_EVAL/bsp/ 该示例引用的公共板级文件:串口日志函数

5.3.2 API 参考

搜索 API共 11 个函数

以下 11 个公开函数按 n32h49x_cordic.h 的声明顺序分为 4 组;每个条目给出功能摘要与 n32h49x_cordic.c 中该函数正上方的注释原文。

初始化与复位

CORDIC_DeInit、CORDIC_Init、CORDIC_StructInit

中断与 DMA 请求

CORDIC_InterruptCmd、CORDIC_DMAReadRequestCmd、CORDIC_DMAWriteRequestCmd

数据读写

CORDIC_GetRegisterAddr、CORDIC_WriteData、CORDIC_ReadData

状态与标志

CORDIC_GetFlagStatus、CORDIC_ClearStatusFlag

void CORDIC_DeInit(void)复位 CORDIC 外设。
源码注释
name    CORDIC_DeInit.
fun     DeInitializes the CORDIC peripheral.
param   none
return  none
void CORDIC_Init(CORDIC_InitType* CORDIC_InitParam)以 CORDIC_InitType 类型的 CORDIC_InitParam 初始化 CORDIC 模块。
源码注释
name    CORDIC_Init.
fun     Initialize the CORDIC module with CORDIC_InitParam of type CORDIC_InitType.
param   CORDIC_InitParam :
          - Pointer to the CORDIC_InitType structure which will be initialized.
return  none
void CORDIC_StructInit(CORDIC_InitType* CORDIC_InitParam)初始化用于 CORDIC 初始化的 CORDIC_InitType 结构体参数,通常在配置 CORDIC_InitType 参数之前调用。
源码注释
name    CORDIC_StructInit.
fun     Initializes the structure parameter of type CORDIC_InitType used to
        initialize CORDIC. This function is usually called before initializing
        a parameter of type CORDIC_InitType.
param   CORDIC_InitParam :
          - Pointer to the CORDIC_InitType structure which will be initialized.
return  none
void CORDIC_InterruptCmd(uint32_t Interrupt, FunctionalStatus Cmd)使能或关闭指定的 CORDIC 中断。
源码注释
name    CORDIC_InterruptCmd.
fun     Enables or disables the specified CORDIC interrupts.
param   Interrupt (The input parameters must be the following values):
          - CORDIC_INT
          - CORDIC_INT_INOVERFLOW
param   Cmd (The input parameters must be the following values):
          - ENABLE
          - DISABLE
return  none
void CORDIC_DMAReadRequestCmd(FunctionalStatus Cmd)使能或关闭 CORDIC 的 DMA 读请求。
源码注释
name    CORDIC_DMAReadRequestCmd.
fun     Enables or disables the CORDIC DMA read request.
param   Cmd (The input parameters must be the following values):
          - ENABLE
          - DISABLE
return  none
void CORDIC_DMAWriteRequestCmd(FunctionalStatus Cmd)使能或关闭 CORDIC 的 DMA 写请求。
源码注释
name    CORDIC_DMAWriteRequestCmd.
fun     Enables or disables the CORDIC DMA write request.
param   Cmd (The input parameters must be the following values):
          - ENABLE
          - DISABLE
return  none
uint32_t CORDIC_GetRegisterAddr(uint32_t Direction)获取用于 DMA 传输的 CORDIC 数据寄存器地址。
源码注释
name    CORDIC_GetRegisterAddr.
fun     Get the CORDIC data register address used for DMA transfer.
param   Direction (The input parameters must be the following values):
          - CORDIC_AS_DMA_SRCADDR
          - CORDIC_AS_DMA_DSTADDR
return  Address of data register.
void CORDIC_WriteData(uint32_t *pInData)写入用于 CORDIC 运算的 32 位输入数据。
源码注释
name    CORDIC_WriteData.
fun     Write 32-bit input data for the CORDIC processing.
param   pInData :
          - Points to the address of input data
return  none
void CORDIC_ReadData(uint32_t *pOutData)返回 CORDIC 运算的 32 位输出数据。
源码注释
name    CORDIC_ReadData.
fun     Return 32-bit output data of CORDIC processing.
param   pOutData :
          - Points to the address where the output data is stored
return  32-bit output data of CORDIC processing.
FlagStatus CORDIC_GetFlagStatus(uint32_t Flag)检查指定的 CORDIC 标志是否置位。
源码注释
name    CORDIC_GetFlagStatus.
fun     Checks whether the specified CORDIC flag is set or not.
param   Flag (The input parameters must be the following values):
          - CORDIC_FLAG_RRF
          - CORDIC_FLAG_INOVF
          - CORDIC_FLAG_DMAWENF
          - CORDIC_FLAG_DMARENF
          - CORDIC_FLAG_INTENF
return  SET or RESET
void CORDIC_ClearStatusFlag(uint32_t Flag)清除 CORDIC 的挂起标志。
源码注释
name    CORDIC_ClearStatusFlag.
fun     Clears the pending flag for the CORDIC.
param   Flag (The input parameters must be the following values):
          - CORDIC_FLAG_INOVF
          - CORDIC_FLAG_DMAWENF
          - CORDIC_FLAG_DMARENF
          - CORDIC_FLAG_INTENF
return  none
note    The RRF flag cannot be cleared by a call to this function;
        the RRF flag is cleared by hardware when reading the data
        register is complete.

5.3.3 Demo 示例说明

本节说明 CORDIC 的 3 个示例:CORDIC_Fixed_Sin_DMA 用 DMA 搬运定点正弦的输入与输出,CORDIC_Fixed_Sin_IT 用中断读取定点结果,CORDIC_Float_Sin_IT 用中断读取浮点结果。

5.3.3.1 CORDIC_Fixed_Sin_DMA 定点正弦 DMA 搬运

工程目录: projects/n32h49x_EVAL/examples/CORDIC/CORDIC_Fixed_Sin_DMA/

配置 CORDIC 与 DMA1 时钟→复位 CORDIC 并配置正弦运算参数→取得 CORDIC 读写寄存器地址→配置 DMA 读写通道并开启 DMA 请求→等待结果就绪标志后比对参考正弦值

项目 源码解读
功能 以定点 Q1.31 格式计算 64 点正弦;
CORDIC 配置为正弦函数、6 周期精度,并使能坐标与相位限幅;
DMA 读通道把 CORDIC_RDAT 结果搬到 aCalResult,DMA 写通道把 aInData 搬到 CORDIC_WDAT;
全部搬完后逐点与 aRefResult 比对。
源码组成 src/main.c:main、RCC_Configuration、NVIC_Configuration、DMA_ReadConfiguration、DMA_WriteConfiguration、CheckResidualError;
inc/n32h49x_it.h、src/n32h49x_it.c:中断向量与异常处理;
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 时钟:使能 CORDIC 与 DMA1 时钟,并调用 RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2);
CORDIC:CORDIC_FUNCTION_SINE、CORDIC_PRECISION_6CYCLES、CORDIC_CODIN_LIMIT_ENABLE、CORDIC_PHASE_LIMIT_ENABLE;
DMA 读通道:DMA1_CH1,映射 DMA_REMAP_CORDIC_RD;
DMA 写通道:DMA1_CH2,映射 DMA_REMAP_CORDIC_WR,两者均为 WORD 宽度、存储器地址自增、长度 64。
程序与数据路径 main 依次调用 RCC_Configuration、NVIC_Configuration、CORDIC_DeInit;
CORDIC_GetRegisterAddr 取回 CORDIC_RDAT、CORDIC_WDAT 地址,CORDIC_Init 配置正弦运算;
开 DMA 读请求后用 DMA_ReadConfiguration 把结果搬到 aCalResult,开 DMA 写请求后用 DMA_WriteConfiguration 把 aInData 搬到 CORDIC;
等待 CORDIC_FLAG_RRF 置位后逐点用 CheckResidualError 比对 aRefResult。
主要 API CORDIC_DeInit、CORDIC_GetRegisterAddr、CORDIC_Init、CORDIC_DMAReadRequestCmd、CORDIC_DMAWriteRequestCmd、CORDIC_GetFlagStatus
验证方法 编译下载运行后,串口打印 “CORDIC demo success!!!” 表示 64 点结果都在容差内;
若某点偏差超过 MAX_RESIDUAL_ERROR_18,打印 “Error[i]” 并停在 while(1)。
使用提示 使能 CORDIC 时必须把 HCLK 配置为 DIV2;
输入数据为 Q1.31 定点格式,数组从 0 递增到 2π;
该示例的 inc/ 目录只含中断头文件,没有独立的 main.h。
核心代码解读与移植

示例用两条 DMA 通道把 64 点 Q1.31 输入搬入 CORDIC、把结果搬出,最后逐点与参考正弦值比对。

数据路径: RCC_Configuration 使能 CORDIC 与 DMA1 时钟并设 HCLK 为 DIV2 → CORDIC_DeInit 复位 → CORDIC_GetRegisterAddr 取 CORDIC_RDAT、CORDIC_WDAT 地址 → CORDIC_Init 配置正弦运算 → DMA 读、写通道把 aInData 搬入 CORDIC、把结果搬入 aCalResult → 等待 CORDIC_FLAG_RRF 后逐点比对 aRefResult

1. 配置 CORDIC 与 DMA1 时钟。 RCC_Configuration 使能 CORDIC 与 DMA1 时钟,并把 HCLK 配置为 DIV2——使能 CORDIC 时这一分频是必需的。

src/main.csrc/main.c · RCC_Configuration
void RCC_Configuration()
{
    /* Enable DMA1 and CORDIC clock */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_CORDIC | RCC_AHB_PERIPHEN_DMA1, ENABLE);
    /* When enabling CORDIC, HCLK DIV2 must be configured */
    RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2);
}

移植到其它型号时只需保留 CORDIC 与所用 DMA 的时钟;RCC_PERIPH_HCLK_DIV2 不能省略。

2. 取得数据寄存器地址并配置正弦运算。 main 先用 CORDIC_GetRegisterAddr 取回读、写数据寄存器地址供 DMA 使用,再用结构体把 CORDIC 配置为正弦、6 周期精度并打开坐标与相位限幅。

src/main.csrc/main.c · main
    /* Get CORDIC read register (CORDIC_RDAT) address */
    rRegAddr = CORDIC_GetRegisterAddr(CORDIC_AS_DMA_SRCADDR);
    /* Get CORDIC write register (CORDIC_WDAT) address */
    wRegAddr = CORDIC_GetRegisterAddr(CORDIC_AS_DMA_DSTADDR);

    CORDIC_StructInit(&CORDIC_InitStructure);
    /* Select sine function */
    CORDIC_InitStructure.Function   = CORDIC_FUNCTION_SINE;
    /* Set max precision for Q1.31 sine */
    CORDIC_InitStructure.Precision  = CORDIC_PRECISION_6CYCLES;
    /* Enable Coordinate Limit */
    CORDIC_InitStructure.CodinLimit = CORDIC_CODIN_LIMIT_ENABLE;
    /* Enable Phase Limit */
    CORDIC_InitStructure.PhaseLimit = CORDIC_PHASE_LIMIT_ENABLE;
    /* Configure CORDIC */
    CORDIC_Init(&CORDIC_InitStructure);

换用其它运算功能或精度时改 Function 与 Precision 即可,读写寄存器地址由 Direction 参数区分。

3. 配置 DMA 读写通道并开启 DMA 请求。 DMA_ReadConfiguration 把外设地址设为 CORDIC_RDAT、存储器地址设为 aCalResult,并把该通道映射到 CORDIC 读请求;写侧由 DMA_WriteConfiguration 把 aInData 搬入 CORDIC_WDAT。

src/main.csrc/main.c · DMA_ReadConfiguration
    /* Reset DMA1 channel 1 */
    DMA_DeInit(DMA1_CH1);
    /* Initialize the DMA parameter structure */
    DMA_StructInit(&DMA_InitStructure);
    DMA_InitStructure.PeriphAddr     = SrcAddr;
    DMA_InitStructure.MemAddr        = (uint32_t)DstAddr;
    DMA_InitStructure.Direction      = DMA_DIR_PERIPH_SRC;
    DMA_InitStructure.BufSize        = DataLen;
    DMA_InitStructure.MemoryInc      = DMA_MEM_INC_ENABLE;
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_WORD;
    DMA_InitStructure.MemDataSize    = DMA_MEM_DATA_WIDTH_WORD;
    /* Initialize DMA1 channel 1 */
    DMA_Init(DMA1_CH1, &DMA_InitStructure);
    /* CORDIC read channel mapping */
    DMA_RequestRemap(DMA_REMAP_CORDIC_RD, DMA1_CH1, ENABLE);
    /* Enable DMA1 channel 1 transfer completion interrupt */
    DMA_ConfigInt(DMA1_CH1, DMA_INT_TXC, ENABLE);
    /* Enable DMA1 channel 1 */
    DMA_EnableChannel(DMA1_CH1, ENABLE);
src/main.csrc/main.c · main
    /* Configure DMA read channel */
    DMA_ReadConfiguration(rRegAddr, aCalResult, ARRAY_SIZE);
    /* Enable CORDIC DMA read request */
    CORDIC_DMAReadRequestCmd(ENABLE);

    /* Configure DMA write channel */
    DMA_WriteConfiguration(aInData, wRegAddr, ARRAY_SIZE);
    /* Enable CORDIC DMA write request */
    CORDIC_DMAWriteRequestCmd(ENABLE);

移植时两条通道的请求映射要与实际搬运方向一致;DMA 模式下不要再由 CPU 直接读写 CORDIC 数据寄存器。

4. 等待结果并比对参考值。 计算启动后 main 轮询 CORDIC_FLAG_RRF,就绪后逐点用 CheckResidualError 与参考正弦比较。

src/main.csrc/main.c · main
    while (CORDIC_GetFlagStatus(CORDIC_FLAG_RRF) == RESET)
    {
        /* Do nothing */
    }
    
    /* Compare CORDIC results to the reference values */
    for (i = 0; i < ARRAY_SIZE; i++)
    {
        /* Check the data results sequentially */
        if (CheckResidualError(aCalResult[i], aRefResult[i], MAX_RESIDUAL_ERROR_18) == 0U)
        {
            log_info("Error[%d]\n", i);
            while (1);
        }
    }

容差常量随精度选择调整:6 周期精度下正弦的残留误差约 2^-18。

对应源码: src/main.c

5.3.3.2 CORDIC_Fixed_Sin_IT 定点正弦中断读取

工程目录: projects/n32h49x_EVAL/examples/CORDIC/CORDIC_Fixed_Sin_IT/

配置 CORDIC 时钟→复位并配置正弦运算参数→使能 CORDIC 中断→逐点写入 Q1.31 输入数据→中断读回结果后比对参考正弦值

项目 源码解读
功能 以定点 Q1.31 格式计算 64 点正弦;
输入由主循环逐点写入 CORDIC_WDAT,每次结果就绪触发 Cordic_IRQn 中断;
Cordic_IRQ_IRQHandler 在中断里读回结果存入 aCalResult,主循环再逐点与 aRefResult 比对。
源码组成 src/main.c:main、RCC_Configuration、NVIC_Configuration、CheckResidualError、Cordic_IRQ_IRQHandler;
inc/n32h49x_it.h、src/n32h49x_it.c:中断向量与异常处理;
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 时钟:使能 CORDIC 时钟并调用 RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2);
CORDIC:CORDIC_FUNCTION_SINE、CORDIC_PRECISION_6CYCLES、CORDIC_CODIN_LIMIT_ENABLE、CORDIC_PHASE_LIMIT_ENABLE,并调用 CORDIC_InterruptCmd(CORDIC_INT, ENABLE);
NVIC:优先级组 0,使能 Cordic_IRQn。
程序与数据路径 main 依次调用 RCC_Configuration、NVIC_Configuration、CORDIC_DeInit、CORDIC_Init;
开中断后用 for 循环逐点调用 CORDIC_WriteData 写入 aInData;
每次运算完成,Cordic_IRQ_IRQHandler 检查 CORDIC_FLAG_RRF 并用 CORDIC_ReadData 读回 aCalResult;
主循环用 CheckResidualError 逐点比对 aRefResult。
主要 API CORDIC_DeInit、CORDIC_Init、CORDIC_InterruptCmd、CORDIC_WriteData、CORDIC_ReadData、CORDIC_GetFlagStatus
验证方法 编译下载运行后,串口打印 “CORDIC demo success!!!” 表示 64 点结果都在容差内;
若某点偏差超过 MAX_RESIDUAL_ERROR_18,打印 “Error[i]” 并停在 while(1)。
使用提示 使能 CORDIC 时必须把 HCLK 配置为 DIV2;
读取结果寄存器会插入总线等待直到计算完成,中断里直接调用 CORDIC_ReadData 即可;
读取数据寄存器后 CORDIC_FLAG_RRF 由硬件清除。
核心代码解读与移植

示例把 64 点 Q1.31 输入逐点写入 CORDIC,每次结果就绪由 Cordic_IRQn 中断读回,最后逐点与参考正弦值比对。

数据路径: RCC_Configuration 使能 CORDIC 时钟并设 HCLK 为 DIV2 → CORDIC_DeInit 复位 → CORDIC_Init 配置正弦运算 → CORDIC_InterruptCmd 开中断 → 主循环 CORDIC_WriteData 写入 aInData → Cordic_IRQ_IRQHandler 读 CORDIC_RDAT 到 aCalResult → 主循环比对 aRefResult

1. 配置 CORDIC 时钟。 RCC_Configuration 使能 CORDIC 时钟并把 HCLK 配置为 DIV2。

src/main.csrc/main.c · RCC_Configuration
void RCC_Configuration()
{
    /* Enable CORDIC clock */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_CORDIC, ENABLE);
    /* When enabling CORDIC, HCLK DIV2 must be configured */
    RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2);
}

使能 CORDIC 时 RCC_PERIPH_HCLK_DIV2 是必需的,移植时不能省略。

2. 配置正弦运算并使能中断。 main 把 CORDIC 配置为正弦、6 周期精度、坐标与相位限幅,并打开 CORDIC 中断。

src/main.csrc/main.c · main
    CORDIC_StructInit(&CORDIC_InitStructure);
    /* Select sine function */
    CORDIC_InitStructure.Function   = CORDIC_FUNCTION_SINE;
    /* Set max precision for Q1.31 sine */
    CORDIC_InitStructure.Precision  = CORDIC_PRECISION_6CYCLES;
    /* Enable Coordinate Limit */
    CORDIC_InitStructure.CodinLimit = CORDIC_CODIN_LIMIT_ENABLE;
    /* Enable Phase Limit */
    CORDIC_InitStructure.PhaseLimit = CORDIC_PHASE_LIMIT_ENABLE;
    /* Configure CORDIC */
    CORDIC_Init(&CORDIC_InitStructure);

    /* Enable CORDIC interrupt */
    CORDIC_InterruptCmd(CORDIC_INT, ENABLE);

中断方式适合边算边取结果,CPU 不必轮询完成标志。

3. 逐点写入输入数据。 开中断后 main 用循环把 aInData 的每个点写入数据寄存器,硬件随即开始计算。

src/main.csrc/main.c · main
    for (wArrayIndex = 0; wArrayIndex < ARRAY_SIZE; wArrayIndex++)
    {
        /* Write data to be calculated */
        CORDIC_WriteData((uint32_t *)&aInData[wArrayIndex]);
    }

输入按 Q1.31 定点沿 0 到 2π 均匀排列,写入顺序即结果读出的顺序。

4. 在中断中读回结果。 Cordic_IRQ_IRQHandler 检查 CORDIC_FLAG_RRF,就绪时读取数据寄存器并把结果存入 aCalResult,读操作同时由硬件清除该标志。

src/main.csrc/main.c · Cordic_IRQ_IRQHandler
void Cordic_IRQ_IRQHandler(void)
{
    if (CORDIC_GetFlagStatus(CORDIC_FLAG_RRF) != RESET)
    {
        /* Read calculation results */
        /* The RRF flag will be cleared after reading the data register */
        CORDIC_ReadData((uint32_t *)&aCalResult[rArrayIndex++]);
    }
}

移植到多通道或 DMA 混用时,注意不要在 DMA 读通道使能后再由 CPU 读 CORDIC_RDAT。

对应源码: src/main.c

5.3.3.3 CORDIC_Float_Sin_IT 浮点正弦中断读取

工程目录: projects/n32h49x_EVAL/examples/CORDIC/CORDIC_Float_Sin_IT/

配置 CORDIC 时钟→复位并配置浮点正弦运算参数→使能 CORDIC 中断→生成随机输入并逐点写入→中断读回浮点结果后比对参考值

项目 源码解读
功能 以浮点格式计算 64 点正弦;
rand 生成 -1.0~1.0 的输入,sinf 计算软件参考值;
CORDIC 配置为浮点输入输出,结果经中断读回后与参考值比对。
源码组成 src/main.c:main、RCC_Configuration、NVIC_Configuration、CheckResidualError、Cordic_IRQ_IRQHandler;
inc/n32h49x_it.h、src/n32h49x_it.c:中断向量与异常处理;
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 时钟:使能 CORDIC 时钟并调用 RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2);
CORDIC:CORDIC_FUNCTION_SINE、CORDIC_PRECISION_6CYCLES、CORDIC_INPUT_FLOAT、CORDIC_OUTPUT_FLOAT,并打开坐标与相位限幅;
NVIC:优先级组 0,使能 Cordic_IRQn。
程序与数据路径 main 依次初始化时钟、NVIC 与 CORDIC;
for 循环用 rand 生成 aInData 并用 sinf 算出 aRefResult;
再用 CORDIC_WriteData 逐点写入,Cordic_IRQ_IRQHandler 读回 aCalResult;
主循环用 CheckResidualError 比对。
主要 API CORDIC_DeInit、CORDIC_Init、CORDIC_InterruptCmd、CORDIC_WriteData、CORDIC_ReadData、CORDIC_GetFlagStatus
验证方法 串口打印 “CORDIC demo success!!!” 表示浮点结果都在容差内;
某点偏差超过 MAX_RESIDUAL_ERROR_18 时打印 “Error[i]” 并停在 while(1)。
使用提示 浮点输入范围需落在 -1.0~1.0;
sinf 的参考值按输入乘以 π 的正弦计算,量纲与 CORDIC 一致;
使能 CORDIC 时同样必须把 HCLK 配置为 DIV2。
核心代码解读与移植

示例用随机浮点输入驱动 CORDIC 计算正弦,结果经中断读回,并与 sinf 算出的参考值比对。

数据路径: RCC_Configuration 使能 CORDIC 时钟并设 HCLK 为 DIV2 → CORDIC_DeInit 复位 → CORDIC_Init 配置浮点正弦 → CORDIC_InterruptCmd 开中断 → 循环生成 aInData 与 aRefResult 并 CORDIC_WriteData 写入 → Cordic_IRQ_IRQHandler 读 CORDIC_RDAT 到 aCalResult → 主循环比对

1. 配置 CORDIC 时钟。 与定点示例相同,RCC_Configuration 使能 CORDIC 时钟并把 HCLK 配置为 DIV2。

src/main.csrc/main.c · RCC_Configuration
void RCC_Configuration(void)
{
    /* Enable CORDIC clock */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_CORDIC, ENABLE);
    /* When enabling CORDIC, HCLK DIV2 must be configured */
    RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2);
}

分频设置与定点示例一致,移植时照搬即可。

2. 配置浮点正弦运算并使能中断。 结构与定点示例相同,额外选择浮点输入与浮点输出。

src/main.csrc/main.c · main
    CORDIC_StructInit(&CORDIC_InitStructure);
    /* Select sine function */
    CORDIC_InitStructure.Function   = CORDIC_FUNCTION_SINE;
    /* Set max precision for Q1.31 sine */
    CORDIC_InitStructure.Precision  = CORDIC_PRECISION_6CYCLES;
    /* Select floating-point input */
    CORDIC_InitStructure.InSelect   = CORDIC_INPUT_FLOAT;
    /* Select floating-point output */
    CORDIC_InitStructure.OutSelect  = CORDIC_OUTPUT_FLOAT;
    /* Enable Coordinate Limit */
    CORDIC_InitStructure.CodinLimit = CORDIC_CODIN_LIMIT_ENABLE;
    /* Enable Phase Limit */
    CORDIC_InitStructure.PhaseLimit = CORDIC_PHASE_LIMIT_ENABLE;
    /* Configure CORDIC */
    CORDIC_Init(&CORDIC_InitStructure);

    /* Enable CORDIC interrupt */
    CORDIC_InterruptCmd(CORDIC_INT, ENABLE);

浮点模式下输入输出都按单精度浮点解析,不再做 Q1.31 定点换算。

3. 生成随机输入与参考值。 主循环用 rand 生成 -1.0~1.0 的输入,再用 sinf 算出软件参考值。

src/main.csrc/main.c · main
    for (i = 0; i < ARRAY_SIZE; i++)
    {
        /* Random generation of input data */
        aInData[i] = -1.0f + ((float)(rand() % 1999)) * 0.001f;

        /* Software calculation results */
        aRefResult[i] = sinf(aInData[i] * PI);
    }

生成范围与硬件相位输入范围一致,超出范围的点会被限幅而不参与正确性判定。

4. 写入输入并在中断中读回结果。 与定点示例相同,写侧逐点调用 CORDIC_WriteData,读侧在 Cordic_IRQ_IRQHandler 中读取数据寄存器。

src/main.csrc/main.c · Cordic_IRQ_IRQHandler
void Cordic_IRQ_IRQHandler(void)
{
    if (CORDIC_GetFlagStatus(CORDIC_FLAG_RRF) != RESET)
    {
        /* Read calculation results */
        /* The RRF flag will be cleared after reading the data register */
        CORDIC_ReadData((uint32_t *)&aCalResult[rArrayIndex++]);
    }
}

浮点结果读回后直接与 aRefResult 比较,容差同样由 MAX_RESIDUAL_ERROR_18 控制。

对应源码: src/main.c

5.3.4 注意与排障

场景 检查与建议 来源
结果读取与等待 计算一旦启动,读取结果寄存器都会插入总线等待直到计算完成,程序不必轮询完成标志。 用户手册
输出限幅 CODINLIMIT 把坐标输出限幅到 ±1,PHASELIMIT 把相位输出限幅到 ±π;
限幅会改变超出范围的结果。
用户手册
角度取值 相位输入 θ 的有效范围为 [-1, 1),即实际角度除以 π 后的值。 用户手册
输入范围与缩放 当 x、y 的绝对值超出允许范围时,必须按同一因子同时缩放 x 与 y 后再输入。 用户手册
16 位结果打包 INSIZE = 1 时 NUMWRITE 必须为 0;
OUTSIZE = 1 时 NUMREAD 必须为 0,只读一次结果寄存器即可。
用户手册
DMA 与 CPU 访问互斥 使能 DMA 读通道后不要再由 CPU 访问 CORDIC_RDAT;
使能 DMA 写通道后不要再由 CPU 访问 CORDIC_WDAT。
用户手册
缩放因子与 DMA DMA 传输过程中不能修改 SCALE 缩放因子。 用户手册
只用 DMA 重复运算 CORDIC 没有针对编程 CTRLSTS 的 DMA 请求,DMA 模式只适合重复执行同一功能与同一配置的运算。 用户手册
写配置寄存器 写入 CTRLSTS 会丢弃已存储但尚未计算的数据。 用户手册
缩放精度 缩放因子会引入截断误差,缩放位数越大精度损失越明显。 用户手册
国民技术开发套件文档中心

按芯片系列在线查阅国民技术 MCU 开发套件的芯片资料、SDK、驱动 API 与 Demo 示例说明。

© 2026 国民技术股份有限公司 版权所有粤ICP备11069485号本站使用不含 Cookie 的匿名访问统计