本帖最后由 myxiaonia 于 2015-3-12 00:51 编辑
dma实在太强大,stm32f1的crc计算,使用dma传输,在72m主频下,1k次竟然在0.2us内完成。。。。。。。。。。作为对比的软件传递方法,用时128us,这个差距,简直爆出翔了
不敢私藏代码,愿把测试代码奉上,希望对大家有用(计时是用的mdk调试模式时寄存器窗口中的时间值)
- #define CRC_START(src, len) CRC->CR = CRC_CR_RESET;
- {DMA_Channel_TypeDef *ps = DMA2_Channel1;
- while(ps->CCR & DMA_CCR1_EN);
- ps->CMAR = (uint32_t)src;
- ps->CNDTR = len;
- ps->CCR |= DMA_CCR1_EN; }
- void CRC_DMA_Configuration(void)
- {
- RCC->AHBENR |= 0
- | RCC_AHBENR_CRCEN
- | RCC_AHBENR_DMA2EN
- ;
- DMA2_Channel1->CPAR = (uint32_t)&CRC->DR;
- DMA2_Channel1->CCR = 0
- | DMA_CCR1_MEM2MEM //M2M模式传送
- | DMA_CCR1_PLVH //优先级最高
- | DMA_CCR1_MSIZE32 //外设位宽32位
- | DMA_CCR1_PSIZE32 //缓冲区位宽32位
- | DMA_CCR1_MINC //缓冲区地址自增
- // | DMA_CCR1_PINC //外设地址不变
- // | DMA_CCR1_CIRC //非循环模式
- | DMA_CCR1_DIR //存储器到外设
- | DMA_CCR1_TEIE //传输错误中断
- // | DMA_SxCR_HTIE
- | DMA_CCR_TCIE //开启传输完成中断
- // | DMA_SxCR_EN //DMA流使能
- ;
- }
- void DMA2_Channel1_IRQHandler(void)
- {
- DMA_Channel_TypeDef *pch = DMA2_Channel1;
- DMA_TypeDef *pdma = DMA2;
-
- pch->CCR &=~DMA_CCR1_EN;
- pdma->IFCR = DMA_IFCR_CGIF1;
- }
- uint32_t clc_crc(const uint32_t *ptr,uint32_t length)
- {
- CRC->CR=CRC_CR_RESET;
- for( ; length; --length)
- CRC->DR = *ptr++;
- return CRC->DR;
- }
- int main(void)
- {
- NVIC_SetPriority(DMA2_Channel1_IRQn,NVIC_EncodePriority(3,6,0));
- NVIC_EnableIRQ(DMA2_Channel1_IRQn);
- CRC_DMA_Configuration();
- while(1)
- {
- clc_crc((uint32_t *)0x2000c000,1024);
- CRC_START((void *)0x2000c000,1024);
- }
- }
复制代码
楼主后来有用过redroof上面的方法再测次时间么,是否还是0.2us?
0.2us肯定是不对的,至于问题在哪里没找到,有例程可以试试
不错,我也试了下,速度是常规方法的2倍左右
不过奇怪的是,只能用DMA1, 换成DMA2就卡死。mcu是stm32f072。
-----------------------糊涂了,stm32f072没有DMA2...
- unsigned long CRC32_Calc(unsigned long initial, const void* msg, int size)
- {
- static DMA_InitTypeDef DMA_InitStructure;
- static int first_run = 1;
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
- DMA_DeInit(DMA1_Channel1);
- initial = ((initial >> 1) & 0x55555555) | ((initial & 0x55555555) << 1);
- initial = ((initial >> 2) & 0x33333333) | ((initial & 0x33333333) << 2);
- initial = ((initial >> 4) & 0x0f0f0f0f) | ((initial & 0x0f0f0f0f) << 4);
- initial = ((initial >> 8) & 0x00ff00ff) | ((initial & 0x00ff00ff) << 8);
- initial = (initial >> 16) | (initial << 16); // st提供了源操作数按位反转,却没有提供初值也按位反转的功能。。。
- CRC_SetInitRegister(initial);
- CRC_ResetDR();
- if(first_run) {
- DMA_StructInit(&DMA_InitStructure);
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
- DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
- DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
- DMA_InitStructure.DMA_PeripheralBaseAddr = (unsigned long)CRC_BASE;
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
- }
- DMA_InitStructure.DMA_MemoryBaseAddr = (unsigned long)(msg);
- DMA_InitStructure.DMA_BufferSize = size;
- DMA_Init(DMA1_Channel1, &DMA_InitStructure);
- DMA_Cmd(DMA1_Channel1, ENABLE);
- ( { while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);});
- first_run = 0;
- return CRC_GetCRC();
- }
复制代码一周热门 更多>