打印
[方案相关]

华大HC32F460 DCU实验

[复制链接]
1184|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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()函数进行初始化。
static void DCU1_ADD_Init(void)

{

      stc_dcu_init_t stcDcuInit;

      /* Enable peripheral clock */

      PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DCU1, Enable);

      /* Initialize DCU */

      MEM_ZERO_STRUCT(stcDcuInit);

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

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

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

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

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

}

2)DCU2初始化

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

static void DCU2_SUB_Init(void)

{

      stc_dcu_init_t stcDcuInit;

      /* Enable peripheral clock */

      PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DCU2, Enable);

      /* Initialize DCU */

      MEM_ZERO_STRUCT(stcDcuInit);

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

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

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

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

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

}

3)DCU3初始化

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

static void DCU3_Compare_Init(void)

{

      stc_dcu_init_t stcDcuInit;

      /* Enable peripheral clock */

      PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DCU3, Enable);

      /* Initialize DCU */

      MEM_ZERO_STRUCT(stcDcuInit);

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

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

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

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

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

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

}

4)LED初始化

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

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

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

static void DCU1_ADD(void)

{

       uint32_t i;

       en_result_t enTestResult = Ok;

       uint16_t au16Data0Val[4];

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

       uint16_t au16Data2Val[4];

       uint32_t u32CalTimes = sizeof(au16Data1Val)/2u;

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

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

       {

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

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

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

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

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

              {

                            enTestResult = Error;

                            break;

              }

              else

              {

              }

       }

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

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

       {

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

       }

       printf("\r\n");

       printf("au16Data1Val:");

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

       {

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

       }

       printf("\r\n");

       printf("au16Data2Val:");

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

       {

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

       }

       printf("\r\n");

       if (Ok == enTestResult)

       {

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

       }

       else

       {

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

       }

}

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

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

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

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

static void DCU2_SUB(void)

{

       uint32_t i;

       en_result_t enTestResult = Ok;

       uint16_t au16Data0Val[4];

       uint16_t au16Data2Val[4];

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

       uint32_t u32CalTimes = sizeof(au16Data1Val)/2u;

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

      

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

       {

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

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

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

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

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

              {

                            enTestResult = Error;

                            break;

              }

              else

              {

              }

       }

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

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

       {

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

       }

       printf("\r\n");

       printf("au16Data1Val:");

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

       {

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

       }

       printf("\r\n");

       printf("au16Data2Val:");

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

       {

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

       }

       printf("\r\n");

       if (Ok == enTestResult)

       {

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

       }

       else

       {

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

       }

}

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

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

static void DCU3_Compare(void)

{

       stc_dcu_init_t stcDcuInit;

       en_result_t enTestResult = Ok;

       en_flag_status_t enDcuFlag1 = Reset;

       en_flag_status_t enDcuFlag2 = Reset;

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

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

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

       uint32_t u32CalTimes = sizeof(au8Data1Val);

       uint32_t i;

       /* DATA0 = DATA1  &&  DATA0 = DATA2 */

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

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

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

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

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

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

       {

                     enTestResult = Error;

       }

       else

       {

       }

       DCU_ClearIrqFlag(M4_DCU3, DcuIntEq1);

       DCU_ClearIrqFlag(M4_DCU3, DcuIntEq2);

       /* DATA0 > DATA1  &&  DATA0 > DATA2 */

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

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

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

       enDcuFlag1 = DCU_GetIrqFlag(M4_DCU3, DcuIntGt1);

       enDcuFlag2 = DCU_GetIrqFlag(M4_DCU3, DcuIntGt2);

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

       {

                     enTestResult = Error;

       }

       else

       {

       }

       DCU_ClearIrqFlag(M4_DCU3, DcuIntGt1);

       DCU_ClearIrqFlag(M4_DCU3, DcuIntGt2);

       /* DATA0 < DATA1  &&  DATA0 < DATA2 */

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

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

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

       enDcuFlag1 = DCU_GetIrqFlag(M4_DCU3, DcuIntLs1);

       enDcuFlag2 = DCU_GetIrqFlag(M4_DCU3, DcuIntLs2);

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

       {

                     enTestResult = Error;

       }

       else

       {

       }

       DCU_ClearIrqFlag(M4_DCU3, DcuIntLs1);

       DCU_ClearIrqFlag(M4_DCU3, DcuIntLs2);

       /* DATA0 = DATA1  &&  DATA0 = DATA2 */

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

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

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

       enDcuFlag1 = DCU_GetIrqFlag(M4_DCU3, DcuIntEq1);

       enDcuFlag2 = DCU_GetIrqFlag(M4_DCU3, DcuIntEq2);

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

       {

                     enTestResult = Error;

       }

       else

       {

       }

       DCU_ClearIrqFlag(M4_DCU3, DcuIntEq1);

       DCU_ClearIrqFlag(M4_DCU3, DcuIntEq2);

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

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

       {

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

       }

       printf("\r\n");

       printf("au8Data1Val:");

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

       {

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

       }

       printf("\r\n");

       printf("au8Data2Val:");

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

       {

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

       }

       printf("\r\n");

       if (Ok == enTestResult)

       {

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

       }

       else

       {

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

       }

}     

    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 的数据处理模块,用于执行基本的数**算和比较操作。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

119

主题

854

帖子

1

粉丝