上回我们说到了MG32F02A的IIC从机的使用。
这次来讲一下我们MG32F02A特别好用的东西:硬件CRC校验
CRC校验大家都知道,在欧洲的电器中必须使用CRC校验,而CRC校验的运算量很大,需要比较多的时间,而我们硬件逻辑处理器就有处理的能力,并且带有DMA功能,那就好呀,拿来直接用。
以下是携带了DMA功能的CRC校验功能代码:
- #include "MG32x02z_DRV.H"
- #include
- typedef uint8_t u8;
- typedef uint16_t u16;
- typedef uint32_t u32;
- typedef uint64_t u64;
- #define URTX URT0
- #define GPL_InputDataEndian_LITTLE GPL_CR0_BEND_EN_disable_w
- #define GPL_InputDataEndian_BIG GPL_CR0_BEND_EN_mask_w
- #define IS_GPL_InputDataEndian_MODE(MODE) (((MODE) == GPL_InputDataEndian_LITTLE) ||
- ((MODE) == GPL_InputDataEndian_BIG))
- #define GPL_InputDataInverse_DISABLE GPL_CR0_IN_INV_disable_w
- #define GPL_InputDataInverse_ENABLE GPL_CR0_IN_INV_mask_w
- #define IS_GPL_InputDataInverse_MODE(MODE) (((MODE) == GPL_InputDataInverse_ENABLE) ||
- ((MODE) == GPL_InputDataInverse_DISABLE))
- #define GPL_InputDataReverse_NONE GPL_CR0_BREV_MDS_disable_w
- #define GPL_InputDataReverse_BYTE GPL_CR0_BREV_MDS_8bit_w
- #define GPL_InputDataReverse_HALFWORD GPL_CR0_BREV_MDS_16bit_w
- #define GPL_InputDataReverse_WORD GPL_CR0_BREV_MDS_32bit_w
- #define IS_GPL_InputDataReverse_MODE(MODE) (((MODE) == GPL_InputDataReverse_NONE) ||
- ((MODE) == GPL_InputDataReverse_BYTE) ||
- ((MODE) == GPL_InputDataReverse_HALFWORD) ||
- ((MODE) == GPL_InputDataReverse_WORD))
- #define GPL_OutputDataReverse_NONE GPL_CR1_CRC_BREV_disable_w
- #define GPL_OutputDataReverse_BYTE GPL_CR1_CRC_BREV_8bit_w
- #define GPL_OutputDataReverse_HALFWORD GPL_CR1_CRC_BREV_16bit_w
- #define GPL_OutputDataReverse_WORD GPL_CR1_CRC_BREV_32bit_w
- #define IS_GPL_OutputDataReverse_MODE(MODE) (((MODE) == GPL_OutputDataReverse_NONE) ||
- ((MODE) == GPL_OutputDataReverse_BYTE) ||
- ((MODE) == GPL_OutputDataReverse_HALFWORD) ||
- ((MODE) == GPL_OutputDataReverse_WORD))
- #define GPL_CRC_Polynomial_0x1021 GPL_CR1_CRC_MDS_ccitt16_w
- #define GPL_CRC_Polynomial_0x07 GPL_CR1_CRC_MDS_crc8_w
- #define GPL_CRC_Polynomial_0x8005 GPL_CR1_CRC_MDS_crc16_w
- #define GPL_CRC_Polynomial_0x4C11DB7 GPL_CR1_CRC_MDS_crc32_w
- #define IS_GPL_CRC_Polynomial_MODE(MODE) (((MODE) == GPL_CRC_Polynomial_0x1021) ||
- ((MODE) == GPL_CRC_Polynomial_0x07) ||
- ((MODE) == GPL_CRC_Polynomial_0x8005) ||
- ((MODE) == GPL_CRC_Polynomial_0x4C11DB7))
- #define GPL_CRC_InputDataWidth_8bit GPL_CR1_CRC_DSIZE_8bit_w
- #define GPL_CRC_InputDataWidth_16bi GPL_CR1_CRC_DSIZE_16bit_w
- #define GPL_CRC_InputDataWidth_32bit GPL_CR1_CRC_DSIZE_32bit_w
- #define IS_GPL_CRC_InputDataWidth_MODE(MODE) (((MODE) == GPL_CRC_InputDataWidth_8bit) ||
- ((MODE) == GPL_CRC_InputDataWidth_16bi) ||
- ((MODE) == GPL_CRC_InputDataWidth_32bit))
- #define CRC_8 0
- #define CRC_8_ITU 1
- #define CRC_8_ROHC 2
- #define CRC16_BUYPASS 3
- #define CRC16_ARC 4
- #define CRC16_MAXIM 5
- #define CRC16_DDS110 6
- #define CRC16_CMS 7
- #define CRC16_USB 8
- #define CRC16_MODBUS 9
- #define CRC16_XMODEM 10
- #define CRC16_GSM 11
- #define CRC16_KERMIT 12
- #define CRC16_AUG_CCITT 13
- #define CRC16_TMS37157 14
- #define CRC16_RIELLO 15
- #define CRC16_A 16
- #define CRC16_CCITT_FALSE 17
- #define CRC16_GENIBUS 18
- #define CRC16_MCRF4XX 19
- #define CRC16_X25 20
- #define CRC32_POSIX 21
- #define CRC32_MPEG2 22
- #define CRC32 23
- #define CRC32_BZIP2 24
- #define CRC32_JAMCRC 25
- typedef struct{
- uint32_t InputDataInverse;
- uint32_t InputDataEndian;
- uint32_t InputDataReverse;
- uint32_t CRC_Polynomial;
- uint32_t CRC_InputDataWidth;
- uint32_t OutputDataReverse;
- uint32_t CRC_InitialValue;
- uint32_t CRC_Type;
- }GPL_CRC_InitTypedef;
- void GPL_CRC_Config(GPL_CRC_InitTypedef * GPL_CRC)
- {
- GPL->CR1.W = 0;
- GPL->CR0.W = 0;
- GPL->DIN.W = 0;
- GPL->CR0.W = GPL_CRC->InputDataInverse |
- GPL_CRC->InputDataEndian |
- GPL_CRC->InputDataReverse;
- GPL->CRCINIT.W = GPL_CRC->CRC_InitialValue;
- GPL->CR1.W = GPL_CRC->CRC_Polynomial |
- GPL_CRC->CRC_InputDataWidth |
- GPL_CRC->OutputDataReverse;
- GPL->CR1.B[0] |= GPL_CR1_CRC_EN_mask_b0;
- }
- uint8_t DataPattern[] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};//
- void CSC_Init (void)
- {
- CSC_PLL_TyprDef CSC_PLL_CFG;
- UnProtectModuleReg(MEMprotect); // Setting flash wait state
- MEM_SetFlashWaitState(MEM_FWAIT_ONE); // 50MHz> Sysclk >=25MHz
- ProtectModuleReg(MEMprotect);
- UnProtectModuleReg(CSCprotect);
- CSC_CK_APB_Divider_Select(APB_DIV_1); // Modify CK_APB divider APB=CK_MAIN/1
- CSC_CK_AHB_Divider_Select(AHB_DIV_1); // Modify CK_AHB divider AHB=APB/1
- /* CK_HS selection */
- CSC_IHRCO_Select(IHRCO_12MHz); // IHRCO Sel 12MHz
- CSC_IHRCO_Cmd(ENABLE);
- while(CSC_GetSingleFlagStatus(CSC_IHRCOF) == DRV_Normal);
- CSC_ClearFlag(CSC_IHRCOF);
- CSC_CK_HS_Select(HS_CK_IHRCO); // CK_HS select IHRCO
- /* PLL */
- /**********************************************************/
- CSC_PLL_CFG.InputDivider=PLLI_DIV_2; // 12M/2=6M
- CSC_PLL_CFG.Multiplication=PLLIx16; // 6M*16=96M
- CSC_PLL_CFG.OutputDivider=PLLO_DIV_2; // PLLO=96M/2=48M
- CSC_PLL_Config(&CSC_PLL_CFG);
- CSC_PLL_Cmd(ENABLE);
- while(CSC_GetSingleFlagStatus(CSC_PLLF) == DRV_Normal);
- CSC_ClearFlag(CSC_PLLF);
- /**********************************************************/
- /* CK_MAIN */
- CSC_CK_MAIN_Select(MAIN_CK_HS);
- /* Configure ICKO function */
- /* Configure peripheral clock */
- CSC_PeriphProcessClockSource_Config(CSC_I2C0_CKS, CK_APB);
- CSC_PeriphProcessClockSource_Config(CSC_UART0_CKS, CK_APB);
- CSC_PeriphOnModeClock_Config(CSC_ON_GPL,ENABLE);
- CSC_PeriphOnModeClock_Config(CSC_ON_UART0,ENABLE);
- CSC_PeriphOnModeClock_Config(CSC_ON_DMA,ENABLE);
- CSC_PeriphOnModeClock_Config(CSC_ON_PortB,ENABLE);
- CSC_PeriphOnModeClock_Config(CSC_ON_PortE,ENABLE);
- ProtectModuleReg(CSCprotect);
- }
- void Sample_URT0_Init(void)
- {
- URT_BRG_TypeDef URT_BRG;
- URT_Data_TypeDef DataDef;
- PIN_InitTypeDef PINX_InitStruct;
- //==Set CSC init
- //MG32x02z_CSC_Init.h(Configuration Wizard)
- //Select CK_HS source = CK_IHRCO
- //Select IHRCO = 11.0592M
- //Select CK_MAIN Source = CK_HS
- //Configure PLL->Select APB Prescaler = CK_MAIN/1
- //Configure Peripheral On Mode Clock->Port B/URT0 = Enable
- //Configure Peripheral On Mode Clock->URT0->Select URT0_PR Source = CK_APB(11.0592)
- //==Set GPIO init
- //MG32x02z_GPIO_Init.h(Configuration Wizard)->Use GPIOB->Pin8/9
- //GPIO port initial is 0xFFFF
- //Pin8 mode is PPO/Pin9 mode is ODO
- //Pin8/9 pull-up resister Enable
- //Pin8/9 function URT0_TX/RX
- PINX_InitStruct.PINX_Mode = PINX_Mode_PushPull_O; // Pin select Push Pull mode
- PINX_InitStruct.PINX_PUResistant = PINX_PUResistant_Enable; // Enable pull up resistor
- PINX_InitStruct.PINX_Speed = PINX_Speed_Low;
- PINX_InitStruct.PINX_OUTDrive = PINX_OUTDrive_Level0; // Pin output driver full strength.
- PINX_InitStruct.PINX_FilterDivider = PINX_FilterDivider_Bypass; // Pin input deglitch filter clock divider bypass
- PINX_InitStruct.PINX_Inverse = PINX_Inverse_Disable; // Pin input data not inverse
- PINX_InitStruct.PINX_Alternate_Function = 3; // Pin AFS = URT0_TX
- GPIO_PinMode_Config(PINB(8),&PINX_InitStruct); // TXD at PB8
- PINX_InitStruct.PINX_Mode = PINX_Mode_OpenDrain_O; // Pin select Open Drain mode
- PINX_InitStruct.PINX_Alternate_Function = 3; // Pin AFS = URT0_RX
- GPIO_PinMode_Config(PINB(9),&PINX_InitStruct); // RXD at PB9
- //=====Set Clock=====//
- //---Set BaudRate---//
- URT_BRG.URT_InteranlClockSource = URT_BDClock_PROC;
- URT_BRG.URT_BaudRateMode = URT_BDMode_Separated;
- URT_BRG.URT_PrescalerCounterReload = 0; //Set PSR
- URT_BRG.URT_BaudRateCounterReload = 3; //Set RLR
- URT_BaudRateGenerator_Config(URTX, &URT_BRG); //BR115200 = f(CK_URTx)/(PSR+1)/(RLR+1)/(OS_NUM+1)
- URT_BaudRateGenerator_Cmd(URTX, ENABLE); //Enable BaudRateGenerator
- //---TX/RX Clock---//
- URT_TXClockSource_Select(URTX, URT_TXClock_Internal); //URT_TX use BaudRateGenerator
- URT_RXClockSource_Select(URTX, URT_RXClock_Internal); //URT_RX use BaudRateGenerator
- URT_TXOverSamplingSampleNumber_Select(URTX, 25); //Set TX OS_NUM
- URT_RXOverSamplingSampleNumber_Select(URTX, 25); //Set RX OS_NUM
- URT_RXOverSamplingMode_Select(URTX, URT_RXSMP_3TIME);
- URT_TX_Cmd(URTX, ENABLE); //Enable TX
- URT_RX_Cmd(URTX, ENABLE); //Enable RX
- //=====Set Mode=====//
- //---Set Data character config---//
- DataDef.URT_TX_DataLength = URT_DataLength_8;
- DataDef.URT_RX_DataLength = URT_DataLength_8;
- DataDef.URT_TX_DataOrder = URT_DataTyped_LSB;
- DataDef.URT_RX_DataOrder = URT_DataTyped_LSB;
- DataDef.URT_TX_Parity = URT_Parity_No;
- DataDef.URT_RX_Parity = URT_Parity_No;
- DataDef.URT_TX_StopBits = URT_StopBits_1_0;
- DataDef.URT_RX_StopBits = URT_StopBits_1_0;
- DataDef.URT_TX_DataInverse = DISABLE;
- DataDef.URT_RX_DataInverse = DISABLE;
- URT_DataCharacter_Config(URTX, &DataDef);
- //---Set Mode Select---//
- URT_Mode_Select(URTX, URT_URT_mode);
- //---Set DataLine Select---//
- URT_DataLine_Select(URTX, URT_DataLine_2);
- //=====Set Error Control=====//
- // to do...
- //=====Set Bus Status Detect Control=====//
- // to do...
- //=====Set Data Control=====//
- URT_RXShadowBufferThreshold_Select(URTX, URT_RXTH_1BYTE);
- URT_IdlehandleMode_Select(URTX, URT_IDLEMode_No);
- URT_TXGaudTime_Select(URTX, 0);
- //=====Enable URT Interrupt=====//
- URT_IT_Cmd(URTX, URT_IT_RX, ENABLE);
- URT_ITEA_Cmd(URTX, ENABLE);
- NVIC_EnableIRQ(URT0_IRQn);
- //=====Enable URT=====//
- URT_Cmd(URTX, ENABLE);
- //==See MG32x02z_URT0_IRQ.c when interrupt in
- }
- int fputc(int ch,FILE *f)
- {
- URT_SetTXData(URTX,1,ch);
- while(URT_GetITSingleFlagStatus(URTX,URT_IT_TC)==DRV_UnHappened);
- URT_ClearITFlag(URTX,URT_IT_TC);
- return ch;
- }
- void UartSendByte(int ch)
- {
- URT_SetTXData(URTX,1,ch);
- while(URT_GetITSingleFlagStatus(URTX,URT_IT_TC)==DRV_UnHappened);
- URT_ClearITFlag(URTX,URT_IT_TC);
- }
- void DMA_Init(void)
- {
- DMA_BaseInitTypeDef DMATestPattern;
- // ------------------------------------------------------------------------
- // 1.Enable DMA
- DMA_Cmd(ENABLE);
- // ------------------------------------------------------------------------
- // 2.Enable Channel0
- DMA_Channel_Cmd(DMAChannel0, ENABLE);
- // ------------------------------------------------------------------------
- DMA_BaseInitStructure_Init(&DMATestPattern);
- // 3.initial & modify parameter
- // DMA channel select
- DMATestPattern.DMAChx = DMAChannel0;
- // channel x source/destination auto increase address
- DMATestPattern.SrcSINCSel = ENABLE;
- DMATestPattern.DestDINCSel = DISABLE;
- // DMA source peripheral config
- DMATestPattern.SrcSymSel = DMA_MEM_Read;
- // DMA destination peripheral config
- DMATestPattern.DestSymSel = DMA_GPL_Write;
- // DMA Burst size config
- DMATestPattern.BurstDataSize = DMA_BurstSize_1Byte;
- // DMA transfer data count initial number
- DMATestPattern.DMATransferNUM = 9;
- // source/destination config
- DMATestPattern.DMASourceAddr = &DataPattern;
- // DMATestPattern.DMADestinationAddr = &GPL->DIN;
- DMA_Channel_Cmd(DMAChannel0, ENABLE);
- DMA_Base_Init(&DMATestPattern);
- }
- void GPL_CRC_Check(void)
- {
- GPL_CRC_InitTypedef lGPL_CRC;
- lGPL_CRC.CRC_Type = CRC32_POSIX; //Select type of CRC you want.
- switch(lGPL_CRC.CRC_Type)
- {
- case CRC_8:// width=8 poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4 residue=0x00 name="CRC-8"
- lGPL_CRC.InputDataInverse = GPL_InputDataInverse_DISABLE;
- lGPL_CRC.InputDataEndian = GPL_InputDataEndian_LITTLE;
- lGPL_CRC.InputDataReverse = GPL_InputDataReverse_NONE;
- lGPL_CRC.CRC_InitialValue = 0UL;
- lGPL_CRC.CRC_InputDataWidth = GPL_CRC_InputDataWidth_8bit;
- lGPL_CRC.CRC_Polynomial = GPL_CRC_Polynomial_0x07;
- lGPL_CRC.OutputDataReverse = GPL_OutputDataReverse_NONE;
- GPL_CRC_Config(&lGPL_CRC);
- /* lCount = 0;
- do{
- GPL->DIN.B[0] = DataPattern[lCount];
- }while(++ lCount < 9);
- */
- GPL_DMAN_Cmd(ENABLE);
- while (DMA_GetSingleFlagStatus(DMA, DMA_FLAG_CH0_TCF) == DRV_UnHappened);
- DMA_ClearFlag(DMA, DMA_FLAG_CH0_TCF);
- if(GPL->DOUT.B[0] != 0xF4)
- printf("Error CRC8 0x07 not equal is 0xF4, Now is 0x%2X Fail.nr", GPL->DOUT.B[0]);
- else
- printf("Error CRC8 0x07 Check OKnr");
- break;
- case CRC_8_ITU:// width=8 poly=0x07 init=0x00 refin=false refout=false xorout=0x55 check=0xa1 residue=0xac name="CRC-8/ITU"
- lGPL_CRC.InputDataInverse = GPL_InputDataInverse_DISABLE;
- lGPL_CRC.InputDataEndian = GPL_InputDataEndian_LITTLE;
- lGPL_CRC.InputDataReverse = GPL_InputDataReverse_NONE;
- lGPL_CRC.CRC_InitialValue = 0UL;
- lGPL_CRC.CRC_InputDataWidth = GPL_CRC_InputDataWidth_8bit;
- lGPL_CRC.CRC_Polynomial = GPL_CRC_Polynomial_0x07;
- lGPL_CRC.OutputDataReverse = GPL_OutputDataReverse_NONE;
- GPL_CRC_Config(&lGPL_CRC);
- /* lCount = 0;
- do{
- GPL->DIN.B[0] = DataPattern[lCount];
- }while(++ lCount < 9);
- */
- GPL_DMAN_Cmd(ENABLE);
- while (DMA_GetSingleFlagStatus(DMA, DMA_FLAG_CH0_TCF) == DRV_UnHappened);
- DMA_ClearFlag(DMA, DMA_FLAG_CH0_TCF);
- if((GPL->DOUT.B[0] ^ 0x55) != 0xA1)
- printf("Error CRC8 0x07 ITU not equal is 0xA1, Now is 0x%2X Fail.nr", (GPL->DOUT.B[0] ^ 0x55));
- else
- printf("Error CRC8 0x07 ITU Check OKnr");
- break;
- case CRC32_JAMCRC:// width=32 poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0x00000000 check=0x340bc6d9 residue=0x00000000 name="JAMCRC"
- lGPL_CRC.InputDataInverse = GPL_InputDataInverse_DISABLE;
- lGPL_CRC.InputDataEndian = GPL_InputDataEndian_LITTLE;
- lGPL_CRC.CRC_InputDataWidth = GPL_CRC_InputDataWidth_8bit;
- lGPL_CRC.CRC_Polynomial = GPL_CRC_Polynomial_0x4C11DB7;
- lGPL_CRC.CRC_InitialValue = 0xFFFFFFFFUL;
- lGPL_CRC.InputDataReverse = GPL_InputDataReverse_BYTE;
- lGPL_CRC.OutputDataReverse = GPL_OutputDataReverse_WORD;
- GPL_CRC_Config(&lGPL_CRC);
- /* lCount = 0;
- do{
- GPL->DIN.B[0] = DataPattern[lCount];
- }while(++ lCount < 9);
- */
- GPL_DMAN_Cmd(ENABLE);
- while (DMA_GetSingleFlagStatus(DMA, DMA_FLAG_CH0_TCF) == DRV_UnHappened);
- DMA_ClearFlag(DMA, DMA_FLAG_CH0_TCF);
- if((GPL->DOUT.W ^ 0x00000000) != 0x340BC6D9UL)
- printf("Error CRC32 0x04c11db7 JAMCRC not equal 0x340BC6D9, Now is 0x%8X Fail.nr", (GPL->DOUT.W ^ 0x00000000));
- else
- printf("Error CRC32 0x04c11db7 JAMCRC Check OKnr");
- break;
- }
- }
- int main()
- {
- PIN_InitTypeDef PINX_InitStruct;
- CSC_Init();
- PINX_InitStruct.PINX_Mode = PINX_Mode_PushPull_O; // Pin select digital input mode
- PINX_InitStruct.PINX_PUResistant = PINX_PUResistant_Enable; // Enable pull up resistor
- PINX_InitStruct.PINX_Speed = PINX_Speed_Low;
- PINX_InitStruct.PINX_OUTDrive = PINX_OUTDrive_Level0; // Pin output driver full strength.
- PINX_InitStruct.PINX_FilterDivider = PINX_FilterDivider_Bypass;// Pin input deglitch filter clock divider bypass
- PINX_InitStruct.PINX_Inverse = PINX_Inverse_Disable; // Pin input data not inverse
- PINX_InitStruct.PINX_Alternate_Function = 0; // Pin AFS = 0
- GPIO_PinMode_Config(PINE(15),&PINX_InitStruct); // D6 setup at PE15
- Sample_URT0_Init();
- printf("hellon");
- DMA_Init();
- DMA_ClearFlag(DMA, DMA_FLAG_CH0_TCF);
- DMA_StartRequest(DMAChannel0);
- GPL_CRC_Check();
- while(1);
- }
受帖子篇幅影响,我只贴出了几种CRC校验方案。
另外,我发现CRC的DMA驱动代码有误,需要进行以下修改才能使用DMA:
- void GPL_DMA_Cmd(FunctionalState State)
- {
- if(State == ENABLE)
- GPL->CR0.W |= GPL_DMA_ENABLE;// GPL->CR0.B[0] |= GPL_DMA_MASK;
- else
- GPL->CR0.W &= (~GPL_DMA_ENABLE);
- }
然后GPL_DMA_ENABLE的定义应该是GPL_CR0_DMA_EN_mask_w 而不是GPL_CR0_DMA_EN_mask_b3
|