首页 > 其他分享 >STM32使用SDIO模式和DMA实现SD卡的读写及擦除操作

STM32使用SDIO模式和DMA实现SD卡的读写及擦除操作

时间:2023-11-21 13:32:37浏览次数:36  
标签:DMA SDIO STM32 CmdInitStructure errorstatus InitStructure SD

对于STM32操作SD卡来说,最重要的就算初始化、写操作、读操作、擦除这几个操作了。
对于初始化部分上一篇文章已经分析,本篇就主要分析写、读、擦除操作。
本篇函数来自于STM32提供的例程。参考野火的程序进行了解释,与野火函数有些不同。
这几种函数完成之后,就是开始实现对SD卡进行操作了。

SD卡擦除函数

SD卡擦除函数比较简单,只用到CMD32、CMD33、CMD38指令。

STM32使用SDIO模式和DMA实现SD卡的读写及擦除操作_数据传输

最后需要确保SD卡擦除完成才能退出SD_Erase函数。通过IsCardProgramming函数实现。

/**
 * @brief 控制 SD 卡擦除指定的数据区域
 * @param startaddr: 擦除的开始地址
 * @param endaddr: 擦除的结束地址
 * @retval SD_Error: SD 返回的错误代码
 */
SD_Error SD_Erase(uint32_t startaddr, uint32_t endaddr)
{
  SD_Error errorstatus = SD_OK;
  uint32_t delay = 0;
  __IO uint32_t maxdelay = 0;
  uint8_t cardstate = 0;

  /*!< 检查SD卡是否支持擦除操作 */
  if (((CSD_Tab[1] >> 20) & SD_CCCC_ERASE) == 0)
  {
    errorstatus = SD_REQUEST_NOT_APPLICABLE;
    return(errorstatus);
  }

  maxdelay = 120000 / ((SDIO->CLKCR & 0xFF) + 2);    //延时,根据时钟分频设计来计算

  if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED)    //卡上锁
  {
    errorstatus = SD_LOCK_UNLOCK_FAILED;
    return(errorstatus);
  }

  /* SDHC卡,地址参数为块地址,每块512字节,SDSC卡地址为字节地址 */
  if (CardType == SDIO_HIGH_CAPACITY_SD_CARD) 
  {
    startaddr /= 512;
    endaddr /= 512;
  }
  
  /*!<  ERASE_GROUP_START (CMD32) and SD_CMD_SD_ERASE_GRP_END(CMD33) */
  if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || 
      (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || 
      (SDIO_HIGH_CAPACITY_SD_CARD == CardType))
  {
    /*!< Send CMD32 SD_ERASE_GRP_START with startaddr  */
    SDIO_CmdInitStructure.SDIO_Argument = startaddr;
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_ERASE_GRP_START;
    SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(&SDIO_CmdInitStructure);
    errorstatus = CmdResp1Error(SD_CMD_SD_ERASE_GRP_START);
    if (errorstatus != SD_OK)
    {
      return(errorstatus);
    }

    /*!< Send CMD33 SD_ERASE_GRP_END with endaddr  */
    SDIO_CmdInitStructure.SDIO_Argument = endaddr;
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_ERASE_GRP_END;
    SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(&SDIO_CmdInitStructure);
    errorstatus = CmdResp1Error(SD_CMD_SD_ERASE_GRP_END);
    if (errorstatus != SD_OK)
    {
      return(errorstatus);
    }
  }

  /*!< Send CMD38 ERASE */
  SDIO_CmdInitStructure.SDIO_Argument = 0;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ERASE;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);
  errorstatus = CmdResp1Error(SD_CMD_ERASE);
  if (errorstatus != SD_OK)
  {
    return(errorstatus);
  }

  for (delay = 0; delay < maxdelay; delay++){}
  /*!< 等待SD卡的内部时序操作完成 */
  errorstatus = IsCardProgramming(&cardstate);

  while ((errorstatus == SD_OK) && 
         ((SD_CARD_PROGRAMMING == cardstate) || (SD_CARD_RECEIVING == cardstate)))
          //SD卡编程 || SD卡接收
  {
    errorstatus = IsCardProgramming(&cardstate);    //检测SD卡是否在读写操作
  }
  return(errorstatus);
}

数据写入操作(单块写入、DMA传输方式)

STM32使用SDIO模式和DMA实现SD卡的读写及擦除操作_错误代码_02

因为分析DMA传输模式,故有关轮询的函数删掉了。

数据写入函数

/**
 * @brief 向 sd 卡写入一个 BLOCK 的数据(512 字节)
 * @note 本函数使用后需要调用如下两个函数来等待数据传输完成
 * - SD_WaitWriteOperation(): 确认 DMA 已把数据传输到 SDIO 接口
 * - SD_GetStatus(): 确认 SD 卡内部已经把数据写入完毕
 * @param writebuff: 指向要写入的数据
 * @param WriteAddr: 要把数据写入到 sd 卡的地址
 * @param BlockSize: 块大小,sdhc 卡为 512 字节
 * @retval SD_Error: 返回的 sd 错误代码
 */
SD_Error SD_WriteBlock(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize)
{
  SD_Error errorstatus = SD_OK;

  TransferError = SD_OK;
  TransferEnd = 0;
  StopCondition = 0;
  
  SDIO->DCTRL = 0x0;

  if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  {
    BlockSize = 512;
    WriteAddr /= 512;
  }
  
//+++++++++++++++++++++++++++++++++++野火添加的函数++++++++++++++++++++++++++++++++++++
  /*-------------- add , 没有这一段容易卡死在DMA检测中 -------------------*/
  /* Set Block Size for Card,cmd16,
   * 若是sdsc卡,可以用来设置块大小,
   * 若是sdhc卡,块大小为512字节,不受cmd16影响 
   */
  /*!< Send CMD 16 */
  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;   
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);
  errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);
  if (SD_OK != errorstatus)
  {
    return(errorstatus);
  }
//+++++++++++++++++++++++++++++++++++野火添加的函数++++++++++++++++++++++++++++++++++++

  /*!< Send CMD24 WRITE_SINGLE_BLOCK */
  SDIO_CmdInitStructure.SDIO_Argument = WriteAddr;    //写入地址
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_SINGLE_BLOCK;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);
  errorstatus = CmdResp1Error(SD_CMD_WRITE_SINGLE_BLOCK);
  if (errorstatus != SD_OK)
  {
    return(errorstatus);
  }
  /*!< 配置SDIO的写数据寄存器 */
  SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
  SDIO_DataInitStructure.SDIO_DataLength = BlockSize;
  SDIO_DataInitStructure.SDIO_DataBlockSize = (uint32_t) 9 << 4;    //可用此参数代替SDIO_DataBlockSize_512b
  SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;    //写数据
  SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
  SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;    //开启数据通道状态机
  SDIO_DataConfig(&SDIO_DataInitStructure);

  SDIO_ITConfig(SDIO_IT_DATAEND, ENABLE);    //数据传输结束中断
  SD_LowLevel_DMA_TxConfig((uint32_t *)writebuff, BlockSize);    //配置DMA
  SDIO_DMACmd(ENABLE);    //使能SDIO的DMA请求

  return(errorstatus);
}

首先,设置SDIO->DCTRL清零,清除之前的传输设置。

发送CMD16指定块的大小。对于标准卡,要写入 BlockSize 长度字节的块;对于 SDHC 卡,写入固定为 512 字节的块。

发送CMD24通知 SD 卡要进行数据写入操作,并指定待写入数据的目标地址。

通过结构体配置数据传输的超时、块数量、块大小、传输方向等参数。

调用 SDIO_ITConfig 函数使能 SDIO 数据结束传输结束中断,传输结束时,会跳转到 SDIO 的 中断服务函数运行。

调用前面讲解的 SD_LowLevel_DMA_TxConfig 函数,配置使能 SDIO 数据向 SD 卡的数据传输的 DMA 请求。为使 SDIO 发送 DMA 请求,需要调用 SDIO_DMACmd 函数使能。

SDIO 外设会自动生成 DMA 发送请求,将指定数据使用 DMA 传输写入到 SD 卡内。

写入DMA配置

/*
 * 函数名:SD_DMA_RxConfig
 * 描述  :为SDIO发送数据配置DMA2的通道4的请求
 * 输入  :BufferDST:装载了数据的变量指针
 *  	   BufferSize:	缓冲区大小
 * 输出  :无
 */
void SD_LowLevel_DMA_TxConfig(uint32_t *BufferSRC, uint32_t BufferSize)
{

  DMA_InitTypeDef DMA_InitStructure;

  DMA_ClearFlag(DMA2_FLAG_TC4 | DMA2_FLAG_TE4 | DMA2_FLAG_HT4 | DMA2_FLAG_GL4);

  /*!< DMA2 Channel4 disable */
  DMA_Cmd(DMA2_Channel4, DISABLE);

  /*!< DMA2 Channel4 Config */
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SDIO_FIFO_ADDRESS;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)BufferSRC;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//外设为写入目标
  DMA_InitStructure.DMA_BufferSize = BufferSize / 4;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;	//外设地址不自增
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA2_Channel4, &DMA_InitStructure);

  /*!< DMA2 Channel4 enable */
  DMA_Cmd(DMA2_Channel4, ENABLE);  
}

写入操作等待函数

/**
 * @brief 本函数会一直等待到 DMA 传输结束
 * 在 SDIO_WriteBlock() 和 SDIO_WriteMultiBlocks() 函数后必须被调用以确保DMA 数据传输完成
 * @param None.
 * @retval SD_Error: 返回的 sd 错误代码.
 */
SD_Error SD_WaitWriteOperation(void)
{
  SD_Error errorstatus = SD_OK;
  //等待 DMA 是否传输结束
  while ((SD_DMAEndOfTransferStatus() == RESET) 
        && (TransferEnd == 0) && (TransferError == SD_OK))
  {}

  if (TransferError != SD_OK)
  {
    return(TransferError);
  }

  /*!< 清除标志 */
  SDIO_ClearFlag(SDIO_STATIC_FLAGS);

  return(errorstatus);
}

调用库函数 SD_DMAEndOfTransferStatus 一直检测 DMA 的传输完成标志,当 DMA 传输 结束时,该函数会返回 SET 值。另外,while 循环中的判断条件使用的 TransferEnd 和 TransferError是全局变量,它们会在 SDIO 的中断服务函数根据传输情况被设置,传输结束后,根据TransferError 的值来确认是否正确传输,若不正确则直接返回错误代码。SD_WaitWriteOperation 函数最后是清 除相关标志位并返回错误。由于这个函数里的 while 循环的存在,它会确保 DMA 的传输结束。

数据读取操作(单块读取、DMA传输方式)

STM32使用SDIO模式和DMA实现SD卡的读写及擦除操作_数据传输_03

数据读取函数

/**
 * @brief 向 sd 卡写入一个 BLOCK 的数据(512 字节)
 * @note 本函数使用后需要调用如下两个函数来等待数据传输完成
 * - SD_WaitWriteOperation(): 确认 DMA 已把数据传输到 SDIO 接口
 * - SD_GetStatus(): 确认 SD 卡内部已经把数据写入完毕
 * @param writebuff: 指向要写入的数据
 * @param WriteAddr: 要把数据写入到 sd 卡的地址
 * @param BlockSize: 块大小,sdhc 卡为 512 字节
 * @retval SD_Error: 返回的 sd 错误代码
 */

SD_Error SD_ReadBlock(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize)
{
  SD_Error errorstatus = SD_OK;

  TransferError = SD_OK;
  TransferEnd = 0;    //传输结束标志位,在中断服务中置1
  StopCondition = 0;
  
  SDIO->DCTRL = 0x0;
  
  if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  {
    BlockSize = 512;
    ReadAddr /= 512;
  }
  //+++++++++++++++++++++++++++++++++++野火添加的函数++++++++++++++++++++++++++++++++++++
  /*-------------- add , 没有这一段容易卡死在DMA检测中 -------------------*/
  /* Set Block Size for Card,cmd16,
   * 若是sdsc卡,可以用来设置块大小,
   * 若是sdhc卡,块大小为512字节,不受cmd16影响 
   */
  /*!< Send CMD 16 */
  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;   
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);
  errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);
  if (SD_OK != errorstatus)
  {
    return(errorstatus);
  }
  //+++++++++++++++++++++++++++++++++++野火添加的函数++++++++++++++++++++++++++++++++++++
  
  SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
  SDIO_DataInitStructure.SDIO_DataLength = BlockSize;
  SDIO_DataInitStructure.SDIO_DataBlockSize = (uint32_t) 9 << 4;
  SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO;    //数据传输方向
  SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
  SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
  SDIO_DataConfig(&SDIO_DataInitStructure);

  /*!< Send CMD17 READ_SINGLE_BLOCK */
  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)ReadAddr;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_READ_SINGLE_BLOCK;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);
  errorstatus = CmdResp1Error(SD_CMD_READ_SINGLE_BLOCK);
  if (errorstatus != SD_OK)
  {
    return(errorstatus);
  }

  SDIO_ITConfig(SDIO_IT_DATAEND, ENABLE);    //启用或禁用SDIO中断,第一个为指定禁用值
  SDIO_DMACmd(ENABLE);    //启用或禁用SDIO DMA请求。 
  SD_LowLevel_DMA_RxConfig((uint32_t *)readbuff, BlockSize);

  return(errorstatus);
}

数据读操作和写操作类似!

首先,设置SDIO->DCTRL清零,清除之前的传输设置。

发送CMD16指定块的大小。对于标准卡,要写入 BlockSize 长度字节的块;对于 SDHC 卡,写入固定为 512 字节的块。

通过结构体配置数据传输的超时、块数量、块大小、传输方向等参数。

发送CMD17,SD卡在接收到命令后就会通过数据线把书记传输到SDIO的数据FIFO中。

调用 SDIO_ITConfig 函数使能 SDIO 数据结束传输结束中断,传输结束时,会跳转到 SDIO 的 中断服务函数运行。

调用前面讲解的 SD_LowLevel_DMA_RxConfig 函数,配置使能 SDIO 从 SD 卡读取数据的 DMA 请求。为使 SDIO 发送 DMA 请求,需要调用 SDIO_DMACmd 函数使能。

SD 卡发出的数据将会传输到 STM32 的 SDIO 外设,而 SDIO 外设激发 DMA 请求,把 数据搬运到内存中。

读取DMA配置

/*
  * 函数名:SD_DMA_RxConfig
  * 描述  :为SDIO接收数据配置DMA2的通道4的请求
  * 输入  :BufferDST:用于装载数据的变量指针
  *	      : BufferSize:	缓冲区大小
  * 输出  :无
  */
void SD_LowLevel_DMA_RxConfig( uint32_t *BufferDST, uint32_t BufferSize )
{
    DMA_InitTypeDef DMA_InitStructure;
 
    DMA_ClearFlag(DMA2_FLAG_TC4 | DMA2_FLAG_TE4 | DMA2_FLAG_HT4 | DMA2_FLAG_GL4);//清除DMA标志位
 
    /*!< DMA2 Channel4 disable */
    DMA_Cmd(DMA2_Channel4, DISABLE);    //SDIO为第四通道
 
    /*!< DMA2 Channel4 Config */
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SDIO_FIFO_ADDRESS;    //外设地址,fifo
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)BufferDST;    //目标地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;    //外设为源地址
    DMA_InitStructure.DMA_BufferSize = BufferSize / 4;    //除以4,把字转成字节单位
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;    //使能外设地址不自增
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    //使能存储目标地址自增
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;    //外设数据大小为字,32位
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;    //外设数据大小为字,32位
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;    //不循环,循环模式主要用在adc上
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;    //通道优先级高
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;    //非 存储器至存储器模式
    DMA_Init(DMA2_Channel4, &DMA_InitStructure);
 
    /*!< DMA2 Channel4 enable */
    DMA_Cmd(DMA2_Channel4, ENABLE);
}

读取操作等待函数

/**
 * @brief 本函数会一直等待到 DMA 传输结束
 * SDIO_ReadMultiBlocks() 函数后必须被调用以确保 DMA 数据传输完成
 * @param None.
 * @retval SD_Error: 返回的 sd 错误代码.
 */
SD_Error SD_WaitWriteOperation(void)
{
  SD_Error errorstatus = SD_OK;
    
  //等待 DMA 传输结束
  while ((SD_DMAEndOfTransferStatus() == RESET) 
        && (TransferEnd == 0) && (TransferError == SD_OK))
  {}

  if (TransferError != SD_OK)
  {
    return(TransferError);
  }

  /*!< Clear all the static flags */
  SDIO_ClearFlag(SDIO_STATIC_FLAGS);

  return(errorstatus);
}

其中,写入读取操作分为单块和多块,但是相差不大,故本篇文章仅仅分析了单块读取操作!

SDIO的中断服务操作

中断服务操作在 stm32f10x_it.c 文件中。需要注意!!!!!

在进行数据传输操作时都会使能相关标志中断,用于跟踪传输进程和错误检测。

中断服务接口

 stm32f10x_it.c 文件中需要设置:(其实设置到sdio用户自定文件中也可!)

void SDIO_IRQHandler(void) 
{		
    /* Process All SDIO Interrupt Sources */									
 	SD_ProcessIRQSrc();
}

中断服务函数

SD_Error SD_ProcessIRQSrc(void)
{
  if (StopCondition == 1)    //发送读、写命令时设置为1
  {
    SDIO->ARG = 0x0;    //命令参数寄存器
    SDIO->CMD = 0x44C;    //命令寄存器 0100-0100-1100
                          /*    CPSMEN[10]    WAITRESP[7:6]  CMDINDEX[5:0]
                           *    0100          01             001100
                           *    开启命令状态机  短响应         命令索引:CMD12
                           */
    TransferError = CmdResp1Error(SD_CMD_STOP_TRANSMISSION);
  }
  else
  {
    TransferError = SD_OK;
  }
  SDIO_ClearITPendingBit(SDIO_IT_DATAEND);    //清除中断
  SDIO_ITConfig(SDIO_IT_DATAEND, DISABLE);    //关闭SDIO中断使能
  TransferEnd = 1;
  return(TransferError);
}

函数首先判断 StopCondition !多块读写中被置为1,单块读写中是置为0 。SD卡要求多块读写命令有 CMD12 结束,SD卡收到 CMD12 时才停止多块的传输!发送命令直接采用向寄存器写入命令和参数的方式。此外,根据传输情况设置全局变量 TransferError、TransferEnd 。

至此,大部分的STM32 的 SDIO 功能就基本上看到了。可根据此执行一些简单的读写操作了。

标签:DMA,SDIO,STM32,CmdInitStructure,errorstatus,InitStructure,SD
From: https://blog.51cto.com/u_15784394/8500677

相关文章

  • STM32快速上手踩坑记录(keil5+CubeMX安装+实现SPI通信)
    硬件:ST-LINKv2+STM32F103C8T6+Kingst逻辑分析仪TM32F103C8T6引脚图STM32F103C8T6引脚图及引脚功能说明_stm32f103c8t6引脚图及功能_eewj的博客-CSDN博客安装keil5官网下载:KeilProductDownloads点击MDK-Arm下载即可,目前最新版本是5.38,公司信息什么的随便填一下,下载之后......
  • 2023版 STM32实战3 按键外部中断(电路与代码都讲解)
    常规电路(带上拉电阻)阻值可选3.3/4.7/5.1/10单位K  偷懒电路利用GPIO内部的上拉模式 代码(直接拷贝使用)这是一个外部中断控制变量a增加减少的demo为了新手方便我直接都写在了main.c文件 #include"stm32f10x.h"u8keyflag=0;u8a=0;voidKEY_Init(void){......
  • podman容器无法从外部连接
    启动容器时添加--nethost参数即可podmanrun-d-p80:80--rm--network=host--namenginxnginx如果有防火墙可以尝试放行端口#放行ufwallow80#关闭ufwdeny80......
  • STM32固件库开发流程
    1.新建工程模板文件夹名字设为fwlib-Template另外新建4个文件夹,Project是工程文件,libraries存放固件库,user存放自己写的代码,Doc存放说明,最后是清除编译文件的代码。2.新建工程将工程保存在前面新建的Project文件夹中再选择所用的芯片型号3.添加组文件夹其中CMSIS如下:......
  • 基于mdev实现adb热插拔(@STM32MP157D+fusb302)
    关键词:fusb302、uevent、mdev、adbd等等。1fusb302关于USB插拔检测,以及增加uevent事件fsusb302支持USBPowerDelivery协议(USBPowerDelivery),支持识别各种USB设备和对应的状态。fusb302支持DRP(DualRolePower)、DFP(DownstreamFacingPort)、UFP(UpstreamFacingPort)......
  • STM32407ZE一些引脚的位置
    TFTLCD引脚RTOSCLK1234567891011121314151617F12D4D14D0E7E9E11E13E15D9GND3.3VGND5VF11MO空B0G14D5G15D15D1E8E10E12E14D8D10B153.3......
  • Docker开始收费了,开始转学podman【第一篇podman容器的安装和基本操作】
    podman什么是Podman?Podman是无守护程序容器引擎,用于在Linux系统上开发,管理和运行OCI容器。容器可以以root用户或无根模式运行。简而言之:`aliasdocker=podman`。Podman(PodManager)是一个功能齐全的容器引擎,它是一个简单的无守护工具。Podman提供了一个类似Docker-CLI的命令......
  • (STM32)TIM输出比较
    TIM输出比较(OC):主要功能输出PWM波形,PWM波形是驱动电机的必要条件,所以信息TIM输出比较就等于学习PWMCNT:计数器,计数自增,CCR:捕获比较寄存器,程序员给定的一个值当CNT,大于、小于、大于CCR时,输出就会置0,置1,置0....,一个不断跳变的pwm的波形每个高级定时器和通用定时器都拥......
  • 基于stm32H730的解决方案开发之SD卡的读写调试
    一概述在嵌入式小系统领域,SD卡存储是一个非常重要的功能。可从难度上,它又是非常难的。因为它涉及到两个大的功能点,一个是文件系统,这个难度非一般。另外一个是sd卡的底层驱动。涉及到的接口多,所以也是一个难度高的地方。两个混合在一起,非常容易出问题。笔者在这块花费了很多时......
  • 2023版 STM32实战1 LED灯驱动(电路与代码都讲解)
    电路图常规画法(带限流电阻计算公式)设LED电流为20mA(统一单位为0.02A)电压为3.3V限流电阻=(电源电压-负载正向工作电压)/工作电流限流电阻=(5V-3.3V)/0.02mA=1.7/V0.02A=85R省事画法(直接用IO输出)代码(直接拷贝使用)找对引脚!!!这是一个LED闪烁的demo为了新手方便我直接都写在了main.c......