[方案相关] 华大HC32F460 DCU实验

[复制链接]
2759|5
 楼主| LEDyyds 发表于 2024-2-26 21:09 | 显示全部楼层 |阅读模式
  数据计算单元(Data Computing Unit)是一个不借助于CPU的简单处理数据的模块。每个DCU单元具有3个数据寄存器(DATA0、DATA1、DATA2),能够进行2个数据的加减和比较大小,以及窗口比较功能。本产品搭载4个DCU单元,每个单元均可独立完成自身功能。

        DCU加法模式计算DATA0和DATA1的和,其中DATA0作为被加数,DATA1作为加数。每次写DATA1寄存器进行一次(DATA0+DATA1)/2的运算,DATA0+DATA1的结果存入DATA0,而(DATA0+DATA1)/2的结果存入DATA2。当DATA0+DATA1结果超过0xFF(8bit模式)或0xFFFF(16bit模式)或0xFFFF_FFFF(32bit模式)时产生标志位并产生中断。

        DCU减法模式计算DATA0和DATA1的差,其中DATA0作为被减数,DATA1作为减数。每次写DATA1寄存器进行一次(DATA0-DATA1)/2的运算,DATA0-DATA1的结果存入DATA0,而(DATA0-DATA1)/2的结果存入DATA2。当DATA0-DATA1结果小于0x0(8bit,16bit,32bit模式)时产生标志位并产生中断。

        DCU比较模式比较DATA0和DATA1以及DATA0和DATA2的大小,可选择当DATA0大于DATA1,DATA0小于DATA1,DATA0等于DATA1时以及当DATA0大于DATA2,DATA0小于DATA2,DATA0等于DATA2时产生标志位并产生中断。比较模式下可以选择数据开始比较的条件,写DATA0后比较或写任何数据寄存器后比较。
将工程模板复制到实验目录下,将工程名改为DCU。

       勾选FWLibCfg.h配置中的CLK_EN、EFM_EN、GPIO_EN、PWC_EN、SRAM_EN、UTILITY_EN、DCU_EN选项

【第二步:初始化编程】

  1)DCU1初始化

在main.c文件中创建DCU1_ADD_Init()函数进行初始化。
  1. static void DCU1_ADD_Init(void)

  2. {

  3.       stc_dcu_init_t stcDcuInit;

  4.       /* Enable peripheral clock */

  5.       PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DCU1, Enable);

  6.       /* Initialize DCU */

  7.       MEM_ZERO_STRUCT(stcDcuInit);

  8.       stcDcuInit.u32IntSel = 0ul;//无中断

  9.       stcDcuInit.enIntWinMode = DcuIntInvalid;//没有窗口中断

  10.       stcDcuInit.enDataSize = DcuDataBit16;//16位数据

  11.       stcDcuInit.enOperation = DcuOpAdd;//加法模式

  12. DCU_Init(M4_DCU1, &stcDcuInit);//DCU初始化函数  

  13. }

2)DCU2初始化

在main.c文件中创建DCU2_SUB_Init()函数进行初始化。

  1. static void DCU2_SUB_Init(void)

  2. {

  3.       stc_dcu_init_t stcDcuInit;

  4.       /* Enable peripheral clock */

  5.       PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DCU2, Enable);

  6.       /* Initialize DCU */

  7.       MEM_ZERO_STRUCT(stcDcuInit);

  8.       stcDcuInit.u32IntSel = 0ul;//无中断

  9.       stcDcuInit.enIntWinMode = DcuIntInvalid;//没有窗口中断

  10.       stcDcuInit.enDataSize = DcuDataBit16;//16位数据

  11.       stcDcuInit.enOperation = DcuOpSub;//减法模式

  12.       DCU_Init(M4_DCU2, &stcDcuInit);//DCU初始化函数      

  13. }

3)DCU3初始化

在main.c文件中创建DCU3_Compare_Init()函数进行初始化。

  1. static void DCU3_Compare_Init(void)

  2. {

  3.       stc_dcu_init_t stcDcuInit;

  4.       /* Enable peripheral clock */

  5.       PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DCU3, Enable);

  6.       /* Initialize DCU */

  7.       MEM_ZERO_STRUCT(stcDcuInit);

  8.       stcDcuInit.u32IntSel = 0ul;//无中断

  9.       stcDcuInit.enIntWinMode = DcuIntInvalid;//没有窗口中断

  10.       stcDcuInit.enDataSize = DcuDataBit8;//8位数据

  11.       stcDcuInit.enOperation = DcuOpCompare;//比较功能

  12.       stcDcuInit.enCmpTriggerMode = DcuCmpTrigbyData0;//写入DATA0后比较

  13.       DCU_Init(M4_DCU3, &stcDcuInit);//DCU初始化函数      

  14. }

4)LED初始化

将LED的头文件和源文件添加到工程文件中,根据原理图初始化LED1、LED2、LED3,LED初始化函数请放在HardwareInt()函数中。

【第三步:DCU1加**能实现】

在man.c文件中创建DCU1_ADD()函数并声明。

  1. static void DCU1_ADD(void)

  2. {

  3.        uint32_t i;

  4.        en_result_t enTestResult = Ok;

  5.        uint16_t au16Data0Val[4];

  6.        uint16_t au16Data1Val[4] = {0, 10, 500, 1000};

  7.        uint16_t au16Data2Val[4];

  8.        uint32_t u32CalTimes = sizeof(au16Data1Val)/2u;

  9.        DCU_WriteDataHalfWord(M4_DCU1, DcuRegisterData0, 0u);//写入Data0数据

  10.        for (i = 0u; i < u32CalTimes; i++)

  11.        {

  12.               DCU_WriteDataHalfWord(M4_DCU1, DcuRegisterData1, au16Data1Val[i]);

  13.               au16Data0Val[i] = DCU_ReadDataHalfWord(M4_DCU1, DcuRegisterData0);

  14.               au16Data2Val[i] = DCU_ReadDataHalfWord(M4_DCU1, DcuRegisterData2);

  15.               /* Compare DCU regisger DATA0 && DATA2 value: DATA0 value == 2 * DATA2 value */

  16.               if (au16Data0Val[i] != (2u * au16Data2Val[i]))

  17.               {

  18.                             enTestResult = Error;

  19.                             break;

  20.               }

  21.               else

  22.               {

  23.               }

  24.        }

  25.        printf("DCU1_ADD\r\nau16Data0Val:");

  26.        for(i = 0u; i < u32CalTimes; i++)

  27.        {

  28.               printf("%4d\t",au16Data0Val[i]);

  29.        }

  30.        printf("\r\n");

  31.        printf("au16Data1Val:");

  32.        for(i = 0u; i < u32CalTimes; i++)

  33.        {

  34.               printf("%4d\t",au16Data1Val[i]);

  35.        }

  36.        printf("\r\n");

  37.        printf("au16Data2Val:");

  38.        for(i = 0u; i < u32CalTimes; i++)

  39.        {

  40.               printf("%4d\t",au16Data2Val[i]);

  41.        }

  42.        printf("\r\n");

  43.        if (Ok == enTestResult)

  44.        {

  45.               LedOn(LED1);  /* Test pass && meet the expected */

  46.        }

  47.        else

  48.        {

  49.               LedOff(LED1);  /* Test fail && don't meet the expected */

  50.        }

  51. }

  52. 使用DCU写函数写入数据0给DATA0寄存器作初始值,通过for语句,使用DCU写函数把au16Data1Val数组写入到DATA1寄存器中,au16Data0Val和au16Data2Val数组获取计算出的DATA0和DATA2的值,if语句判断DATA2的值是否为DATA0的一半,总共for语句循环4次。

  53. 计算出的结果不符合我们的预期,LED1熄灭,反之LED点亮,最后打印出3个数组的值。

  54. 【第四步:DCU2减**能实现】

  55. 在man.c文件中创建DCU2_SUB()函数并声明,DCU2的减法思想与加法思想是相同的,这里就不赘述了。计算的结果预期一致LED2点亮,不一致则LED2熄灭,打印最后三个数组值。

  56. static void DCU2_SUB(void)

  57. {

  58.        uint32_t i;

  59.        en_result_t enTestResult = Ok;

  60.        uint16_t au16Data0Val[4];

  61.        uint16_t au16Data2Val[4];

  62.        uint16_t au16Data1Val[4] = {0, 10, 500, 1000};

  63.        uint32_t u32CalTimes = sizeof(au16Data1Val)/2u;

  64.        DCU_WriteDataHalfWord(M4_DCU2, DcuRegisterData0, 2000u);//写入Data0数据

  65.       

  66.        for (i = 0u; i < u32CalTimes; i++)

  67.        {

  68.               DCU_WriteDataHalfWord(M4_DCU2, DcuRegisterData1, au16Data1Val[i]);

  69.               au16Data0Val[i] = DCU_ReadDataHalfWord(M4_DCU2, DcuRegisterData0);

  70.               au16Data2Val[i] = DCU_ReadDataHalfWord(M4_DCU2, DcuRegisterData2);

  71.               /* Compare DCU regisger DATA0 && DATA2 value: DATA0 value == 2 * DATA2 value */

  72.               if (au16Data0Val[i] != (2u * au16Data2Val[i]))

  73.               {

  74.                             enTestResult = Error;

  75.                             break;

  76.               }

  77.               else

  78.               {

  79.               }

  80.        }

  81.        printf("DCU2_SUB\r\nau16Data0Val:");

  82.        for(i = 0u; i < u32CalTimes; i++)

  83.        {

  84.               printf("%4d\t",au16Data0Val[i]);

  85.        }

  86.        printf("\r\n");

  87.        printf("au16Data1Val:");

  88.        for(i = 0u; i < u32CalTimes; i++)

  89.        {

  90.               printf("%4d\t",au16Data1Val[i]);

  91.        }

  92.        printf("\r\n");

  93.        printf("au16Data2Val:");

  94.        for(i = 0u; i < u32CalTimes; i++)

  95.        {

  96.               printf("%4d\t",au16Data2Val[i]);

  97.        }

  98.        printf("\r\n");

  99.        if (Ok == enTestResult)

  100.        {

  101.               LedOn(LED2);  /* Test pass && meet the expected */

  102.        }

  103.        else

  104.        {

  105.               LedOff(LED2);  /* Test fail && don't meet the expected */

  106.        }

  107. }

【第五步:DCU3比较功能实现】

在man.c文件中创建DCU2_Compare()函数并声明。

  1. static void DCU3_Compare(void)

  2. {

  3.        stc_dcu_init_t stcDcuInit;

  4.        en_result_t enTestResult = Ok;

  5.        en_flag_status_t enDcuFlag1 = Reset;

  6.        en_flag_status_t enDcuFlag2 = Reset;

  7.        uint8_t au8Data0Val[4] = {00, 22, 44, 88};

  8.        uint8_t au8Data1Val[4] = {00, 11, 55, 88};

  9.        uint8_t au8Data2Val[4] = {00, 11, 55, 88};

  10.        uint32_t u32CalTimes = sizeof(au8Data1Val);

  11.        uint32_t i;

  12.        /* DATA0 = DATA1  &&  DATA0 = DATA2 */

  13.        DCU_WriteDataByte(M4_DCU3, DcuRegisterData1, au8Data1Val[0]);

  14.        DCU_WriteDataByte(M4_DCU3, DcuRegisterData2, au8Data2Val[0]);

  15.        DCU_WriteDataByte(M4_DCU3, DcuRegisterData0, au8Data0Val[0]);

  16.        enDcuFlag1 = DCU_GetIrqFlag(M4_DCU3, DcuIntEq1);//DATA0 = DATA1

  17.        enDcuFlag2 = DCU_GetIrqFlag(M4_DCU3, DcuIntEq2);//DATA0 = DATA2

  18.        if ((Set != enDcuFlag1) || (Set != enDcuFlag2))

  19.        {

  20.                      enTestResult = Error;

  21.        }

  22.        else

  23.        {

  24.        }

  25.        DCU_ClearIrqFlag(M4_DCU3, DcuIntEq1);

  26.        DCU_ClearIrqFlag(M4_DCU3, DcuIntEq2);

  27.        /* DATA0 > DATA1  &&  DATA0 > DATA2 */

  28.        DCU_WriteDataByte(M4_DCU3, DcuRegisterData1, au8Data1Val[1]);

  29.        DCU_WriteDataByte(M4_DCU3, DcuRegisterData2, au8Data2Val[1]);

  30.        DCU_WriteDataByte(M4_DCU3, DcuRegisterData0, au8Data0Val[1]);

  31.        enDcuFlag1 = DCU_GetIrqFlag(M4_DCU3, DcuIntGt1);

  32.        enDcuFlag2 = DCU_GetIrqFlag(M4_DCU3, DcuIntGt2);

  33.        if ((Set != enDcuFlag1) || (Set != enDcuFlag2))

  34.        {

  35.                      enTestResult = Error;

  36.        }

  37.        else

  38.        {

  39.        }

  40.        DCU_ClearIrqFlag(M4_DCU3, DcuIntGt1);

  41.        DCU_ClearIrqFlag(M4_DCU3, DcuIntGt2);

  42.        /* DATA0 < DATA1  &&  DATA0 < DATA2 */

  43.        DCU_WriteDataByte(M4_DCU3, DcuRegisterData1, au8Data1Val[2]);

  44.        DCU_WriteDataByte(M4_DCU3, DcuRegisterData2, au8Data2Val[2]);

  45.        DCU_WriteDataByte(M4_DCU3, DcuRegisterData0, au8Data0Val[2]);

  46.        enDcuFlag1 = DCU_GetIrqFlag(M4_DCU3, DcuIntLs1);

  47.        enDcuFlag2 = DCU_GetIrqFlag(M4_DCU3, DcuIntLs2);

  48.        if ((Set != enDcuFlag1) || (Set != enDcuFlag2))

  49.        {

  50.                      enTestResult = Error;

  51.        }

  52.        else

  53.        {

  54.        }

  55.        DCU_ClearIrqFlag(M4_DCU3, DcuIntLs1);

  56.        DCU_ClearIrqFlag(M4_DCU3, DcuIntLs2);

  57.        /* DATA0 = DATA1  &&  DATA0 = DATA2 */

  58.        DCU_WriteDataByte(M4_DCU3, DcuRegisterData1, au8Data1Val[3]);

  59.        DCU_WriteDataByte(M4_DCU3, DcuRegisterData2, au8Data2Val[3]);

  60.        DCU_WriteDataByte(M4_DCU3, DcuRegisterData0, au8Data0Val[3]);

  61.        enDcuFlag1 = DCU_GetIrqFlag(M4_DCU3, DcuIntEq1);

  62.        enDcuFlag2 = DCU_GetIrqFlag(M4_DCU3, DcuIntEq2);

  63.        if ((Set != enDcuFlag1) || (Set != enDcuFlag2))

  64.        {

  65.                      enTestResult = Error;

  66.        }

  67.        else

  68.        {

  69.        }

  70.        DCU_ClearIrqFlag(M4_DCU3, DcuIntEq1);

  71.        DCU_ClearIrqFlag(M4_DCU3, DcuIntEq2);

  72.        printf("DCU3_Compare\r\nau8Data0Val:");

  73.        for(i = 0u; i < u32CalTimes; i++)

  74.        {

  75.               printf("%4d\t",au8Data0Val[i]);

  76.        }

  77.        printf("\r\n");

  78.        printf("au8Data1Val:");

  79.        for(i = 0u; i < u32CalTimes; i++)

  80.        {

  81.               printf("%4d\t",au8Data1Val[i]);

  82.        }

  83.        printf("\r\n");

  84.        printf("au8Data2Val:");

  85.        for(i = 0u; i < u32CalTimes; i++)

  86.        {

  87.               printf("%4d\t",au8Data2Val[i]);

  88.        }

  89.        printf("\r\n");

  90.        if (Ok == enTestResult)

  91.        {

  92.               LedOn(LED3);  /* Test pass && meet the expected */

  93.        }

  94.        else

  95.        {

  96.               LedOff(LED3);  /* Test fail && don't meet the expected */

  97.        }

  98. }     

    DATA0作为比较源,3个数组传入DCU的3个数据寄存器中,通过获取DCU标志位函数,判断比较结果是否为预期一致,代码中一共比较了4次,预期一致LED3点亮,不一致则LED3熄灭。


七毛钱 发表于 2024-2-27 09:48 | 显示全部楼层
这个实验是不是有22个小实验
范德萨发额 发表于 2024-2-28 14:39 | 显示全部楼层
预期一致LED3点亮,不一致则LED3熄灭
lvuu 发表于 2024-8-27 00:25 | 显示全部楼层
数据计算单元 (DCU) 是一种独立于 CPU 的数据处理模块,用于执行基本的数**算和比较操作。
范德萨大师傅 发表于 2024-12-31 13:02 | 显示全部楼层
如何在 DCU 模块上进行加法、减法和比较操作
Amazingxixixi 发表于 2024-12-31 14:01 | 显示全部楼层
学习一下,第一次听说DCU
您需要登录后才可以回帖 登录 | 注册

本版积分规则

122

主题

867

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部