【STM32】检测SD卡是否插入
- 开发环境
- 原理图
- 确定引脚的高低电平
- 中断方式检测插入
- 配置引脚
- 打开引脚的中断
- 编写代码
- 显示SD卡信息
- 引脚中断回调函数
- 实现的效果
开发环境
软件:STM32CubeIDE1.14.1
硬件:立创天空星STM32F407VE;SD卡
原理图
要确认TF卡槽的9脚SD_DECT (自行确认具体的引脚)是否连接了
比如下图的就连上了PD3
下面的这个就没有连接,无法检测。
确定引脚的高低电平
SD插入后引脚为低电平,没插入为高电平。如果不知道怎么检测,有如下方法
把PD3(检测引脚)设为输入模式,然后不断检测引脚的电平。插拔几次,看串口输出的电平即可确认。
知道SD卡检测引脚的电平后,就可以检测SD卡的状态了 。
GPIO_PinState SD_insert/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){SD_insert = HAL_GPIO_ReadPin(SD_DECT_GPIO_Port, SD_DECT_Pin);printf("sd:%d\n", SD_insert);HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);HAL_Delay(1000);
中断方式检测插入
如果喜欢,可以轮询检测引脚的状态,也即上面提到的检测电平的方法,不过这样效率太低,可以改用中断的方式。
配置引脚
配置引脚为外部中断,选择上升下降沿触发外部中断,这样插入和拔出都能检测
打开引脚的中断
注意这个中断优先级应该比SDIO的中断要高,不然拔出了还在进行SDIO操作,导致错误 。
编写代码
显示SD卡信息
先写一个能显示SD卡信息的函数,在插入时显示卡的信息。
void SD_Getinfo(void)
{printf("SD_Getinfo\n");HAL_SD_CardStateTypeDef state = HAL_SD_GetCardState(&hsd);HAL_SD_CardCIDTypeDef SD_CardCID;if (state == HAL_SD_CARD_TRANSFER){HAL_SD_GetCardCID(&hsd, &SD_CardCID);printf("\nInitialize SD card sucessfully!\n");printf("SD card information\n");printf("CardType :%ld\n", hsd.SdCard.CardType);printf("CardVersion :%ld\n", hsd.SdCard.CardVersion);printf("Class :%ld\n", hsd.SdCard.Class);printf("RelCardAdd :%ld\n", hsd.SdCard.RelCardAdd);printf("BlockNbr :%ld\n", hsd.SdCard.BlockNbr);printf("BlockSize :%ld\n", hsd.SdCard.BlockSize);printf("LogBlockNbr :%ld\n", hsd.SdCard.LogBlockNbr);printf("LogBlockSize :%ld\n", hsd.SdCard.LogBlockSize);printf("ManufacturerID :%d\n", SD_CardCID.ManufacturerID);}else{printf("SD card initialize failed.\n");}
}
引脚中断回调函数
开启中断后,需要编写GPIO中断回调函数。插入时调用 MX_SDIO_Init(); 初始化SDIO,然后显示SD卡的信息。
拔出时复位SDIO HAL_SD_DeInit(&hsd); 再显示会提示没有初始化。
由于插拔过程电平是不稳定的,类似按键的抖动,因此需要消抖。
这里为了简单,直接用HAL延时。实际应用自行查找更好的消抖方法
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{HAL_Delay(30);if (GPIO_Pin == SD_DECT_Pin){/* in = 0 */if (GPIO_PIN_RESET == HAL_GPIO_ReadPin(SD_DECT_GPIO_Port, SD_DECT_Pin)){printf("SD in\n");MX_SDIO_SD_Init();printf("SD init\n");SD_Getinfo();}/* out = 1 */else{printf("SD out\n");HAL_SD_DeInit(&hsd);printf("SD deinit\n");SD_Getinfo();}}
}
实现的效果
如果对你有帮助,点个赞吧 ^ ^!