新发基金的好处和坏处是什么?新基金的封闭期一般是多久?
新发基金的好处和坏处是什么?新发基金的优点:1、认购费率低:一般
2023/07/06
导语“我们在前面章节中使用了SDIO接口对SD卡进行读写操作,使用的轮询模式,这种模式效率低下,F103有SDIO接口的DMA模式,DMA模式在不需要CPU操作的情况下,自动的将数据进行读取和写入。”
(资料图片仅供参考)
同第八章。
SDIO配置为4位的总线模式。
在DMA的配置中,SDIO的DMA通道只有一个,所以读和写之间需要进行方向改变。地址增长选择内存,这是因为我们把SDIO外设的数据发送到内存中,或从内存中读入数据。
在NVIC中断配置中,设置SDIO的中断优先级比DMA的优先级高。
玩成上述配置后,进行代码生成。
在stm32F103 中SDIO的DMA只有一个通道,因此读写是公用的,需要在读写之前进行方向配置,不能简单的调用HALSDReadBlocksDMA()库函数来完成读,不能简单的调用HALSDWriteBlocksDMA()来完成写操作。我们编写DIOReadBlocksDMA()、SDIOWriteBlocksDMA()来使用DMA模式。
(1)sdio.h
/* USER CODE BEGIN Private defines */extern DMA_HandleTypeDef hdma_sdio;/* USER CODE END Private defines *//* USER CODE BEGIN Prototypes */ HAL_StatusTypeDef SDIO_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); HAL_StatusTypeDef SDIO_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); /* USER CODE END Prototypes */在sdio.c中/* USER CODE BEGIN 1 */ HAL_StatusTypeDef SDIO_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) { HAL_StatusTypeDef Return_Status; HAL_SD_CardStateTypeDef SD_Card_Status; do { SD_Card_Status = HAL_SD_GetCardState(hsd); }while(SD_Card_Status != HAL_SD_CARD_TRANSFER ); /* SDIO DMA DeInit */ /* SDIO DeInit */ HAL_DMA_DeInit(&hdma_sdio); /* 改变DMA的方向,重新初始化 */ hdma_sdio.Instance = DMA2_Channel4; hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE; hdma_sdio.Init.MemInc = DMA_MINC_ENABLE; hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; hdma_sdio.Init.Mode = DMA_NORMAL; hdma_sdio.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_sdio) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA( hsd,hdmarx,hdma_sdio); Return_Status = HAL_SD_ReadBlocks_DMA( hsd,pData, BlockAdd, NumberOfBlocks); return Return_Status; } HAL_StatusTypeDef SDIO_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) { HAL_StatusTypeDef Return_Status; HAL_SD_CardStateTypeDef SD_Card_Status; do { SD_Card_Status = HAL_SD_GetCardState(hsd); }while(SD_Card_Status != HAL_SD_CARD_TRANSFER ); /* SDIO DMA DeInit */ /* SDIO DeInit */ HAL_DMA_DeInit(&hdma_sdio); /* 改变DMA的方向,重新初始化 */ hdma_sdio.Instance = DMA2_Channel4; hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE; hdma_sdio.Init.MemInc = DMA_MINC_ENABLE; hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; hdma_sdio.Init.Mode = DMA_NORMAL; hdma_sdio.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_sdio) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(hsd,hdmatx,hdma_sdio); Return_Status = HAL_SD_WriteBlocks_DMA(hsd,pData, BlockAdd, NumberOfBlocks); return Return_Status; }
在min.c中
/*SD 操作*/typedef enum {FAILED= 0, PASSED = !FAILED} TestStatus;/* 私有宏定义 ----------------------------------------------------------------*/#define BLOCK_SIZE 512 // SD卡块大小 #define NUMBER_OF_BLOCKS 8 // 测试块数量(小于15)#define WRITE_READ_ADDRESS 0x00002000 // 测试读写地址#define SDMMC hsd/* 私有变量 ------------------------------------------------------------------*/__align(4) uint32_t Buffer_Block_Tx[BLOCK_SIZE*NUMBER_OF_BLOCKS]; // 写数据缓存__align(4) uint32_t Buffer_Block_Rx[BLOCK_SIZE*NUMBER_OF_BLOCKS]; // 读数据缓存HAL_StatusTypeDef sd_status; // HAL库函数操作SD卡函数返回值:操作结果TestStatus test_status; // 数据测试结果void SD_EraseTest_DMA();void SD_Write_Read_Test_DMA();HAL_StatusTypeDef Return_Status;HAL_SD_CardStateTypeDef SD_Card_Status;HAL_DMA_StateTypeDef DMA_Status;
在mian函数中:
//申明测试函数 SD_EraseTest_DMA(); SD_Write_Read_Test_DMA();
在main.c
/*************************************/TestStatus eBuffercmp(uint32_t* pBuffer, uint32_t BufferLength){ while (BufferLength--) { /* SD卡擦除后的可能值为0xff或0 */ if ((*pBuffer != 0xFFFFFFFF) && (*pBuffer != 0)) { return FAILED; } pBuffer++; } return PASSED;}void SD_EraseTest_DMA(void){ /* 第1个参数为SD卡句柄,第2个参数为擦除起始地址,第3个参数为擦除结束地址 */ sd_status=HAL_SD_Erase(&SDMMC,WRITE_READ_ADDRESS,WRITE_READ_ADDRESS+NUMBER_OF_BLOCKS*4); printf("《SD》""erase status:%drn",sd_status); HAL_Delay(500); if (sd_status == HAL_OK) { /* 读取刚刚擦除的区域 */ sd_status = SDIO_ReadBlocks_DMA(&SDMMC,(uint8_t *)Buffer_Block_Rx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS); printf("《SD》""erase read status:%drn",sd_status); /* 把擦除区域读出来对比 */ test_status = eBuffercmp(Buffer_Block_Rx,BLOCK_SIZE*NUMBER_OF_BLOCKS); if(test_status == PASSED) printf("《SD》""除测试成功!rn" ); else printf("《SD》""擦除不成功,数据出错!rn" ); } else { printf("《SD》""擦除测试失败!部分SD不支持擦除,只要读写测试通过即可rn" ); }}void Fill_Buffer(uint32_t *pBuffer, uint32_t BufferLength, uint32_t Offset){ uint32_t index = 0; /* 填充数据 */ for (index = 0; index < BufferLength; index++ ) { pBuffer[index] = index + Offset; }}TestStatus Buffercmp(uint32_t* pBuffer1, uint32_t* pBuffer2, uint32_t BufferLength){ while (BufferLength--) { if(BufferLength%50==0) { printf("buf:0x%08X - 0x%08Xrn",*pBuffer1,*pBuffer2); } if (*pBuffer1 != *pBuffer2) { return FAILED; } pBuffer1++; pBuffer2++; } return PASSED;}void SD_Write_Read_Test_DMA(void){ printf(" Warning: this programmay erase all the TFcard data. rn"); printf("rn Initialize SD card successfully!rnrn"); printf(" SD card information! rn"); printf(" CardCapacity : %llu rn",((unsigned long long)SDMMC.SdCard.BlockSize*hsd.SdCard.BlockNbr)); printf(" CardBlockSize : %d rn",SDMMC.SdCard.BlockSize); printf(" RCA : %d rn",SDMMC.SdCard.RelCardAdd); printf(" CardType : %d rn",SDMMC.SdCard.CardType); int i,j = 0; /* 填充数据到写缓存 */ Fill_Buffer(Buffer_Block_Tx,BLOCK_SIZE*NUMBER_OF_BLOCKS, 0x6666); /* 往SD卡写入数据 */ sd_status = SDIO_WriteBlocks_DMA(&SDMMC,(uint8_t *)Buffer_Block_Tx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS); printf("《SD》""write status:%drn",sd_status); HAL_Delay(600); /* 从SD卡读取数据 */ sd_status = SDIO_ReadBlocks_DMA(&SDMMC,(uint8_t *)Buffer_Block_Rx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS); printf("《SD》""read status:%drn",sd_status); /* 比较数据 */ test_status = Buffercmp(Buffer_Block_Tx, Buffer_Block_Rx, BLOCK_SIZE*NUMBER_OF_BLOCKS/4); //比较 if(test_status == PASSED) { printf("《SD》""》读写测试成功!rn" ); for(i=0;i
可以看到能够正确的使用DMA进行SD卡的读写操作。
我们在上一节中使用DMA的使用读写过程中要改变DMA的方向,在每个读写函数中进行,可以单独实现:
在sdio.h
HAL_StatusTypeDef SD_DMAConfigRX(SD_HandleTypeDef *hsd);HAL_StatusTypeDef SD_DMAConfigTX(SD_HandleTypeDef *hsd);HAL_StatusTypeDef SDIO_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks);HAL_StatusTypeDef SDIO_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks);
在sdio.c 中
HAL_StatusTypeDef SDIO_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks){ HAL_StatusTypeDef Return_Status; HAL_SD_CardStateTypeDef SD_Card_Status; do { SD_Card_Status = HAL_SD_GetCardState(hsd); }while(SD_Card_Status != HAL_SD_CARD_TRANSFER ); if (SD_DMAConfigRX(hsd) != HAL_OK) { return HAL_ERROR; } else { Return_Status = HAL_SD_ReadBlocks_DMA( hsd,pData, BlockAdd, NumberOfBlocks); return Return_Status; }}HAL_StatusTypeDef SDIO_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks){ HAL_StatusTypeDef Return_Status; HAL_SD_CardStateTypeDef SD_Card_Status; do { SD_Card_Status = HAL_SD_GetCardState(hsd); }while(SD_Card_Status != HAL_SD_CARD_TRANSFER ); if (SD_DMAConfigTX(hsd) != HAL_OK) { return HAL_ERROR; } else { Return_Status = HAL_SD_WriteBlocks_DMA(hsd,pData, BlockAdd, NumberOfBlocks); return Return_Status; }}HAL_StatusTypeDef SD_DMAConfigRX(SD_HandleTypeDef *hsd){ HAL_StatusTypeDef status = HAL_ERROR; hdma_sdio.Instance = DMA2_Channel4; hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE; hdma_sdio.Init.MemInc = DMA_MINC_ENABLE; hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; hdma_sdio.Init.Mode = DMA_NORMAL; hdma_sdio.Init.Priority = DMA_PRIORITY_LOW; __HAL_LINKDMA( hsd,hdmarx,hdma_sdio); HAL_DMA_Abort(&hdma_sdio); HAL_DMA_DeInit(&hdma_sdio); status = HAL_DMA_Init(&hdma_sdio); return status;}HAL_StatusTypeDef SD_DMAConfigTX(SD_HandleTypeDef *hsd){ HAL_StatusTypeDef status = HAL_ERROR; hdma_sdio.Instance = DMA2_Channel4; hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE; hdma_sdio.Init.MemInc = DMA_MINC_ENABLE; hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; hdma_sdio.Init.Mode = DMA_NORMAL; hdma_sdio.Init.Priority = DMA_PRIORITY_LOW; __HAL_LINKDMA( hsd,hdmarx,hdma_sdio); HAL_DMA_Abort(&hdma_sdio); HAL_DMA_DeInit(&hdma_sdio); status = HAL_DMA_Init(&hdma_sdio); return status;}
标签: