15 玩转STM32之IIC通信(芯片硬件篇)(下)

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 15 玩转STM32之IIC通信(芯片硬件篇)

9-I2C控制器接收一个字节的数据函数

/**
  * @brief  Returns the most recent received data by the I2Cx peripheral.
  * @param  I2Cx: where x can be 1, 2 or 3 to select the I2C peripheral.
  * @retval The value of the received data.
  */
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx)
10-I2C控制器获取最新的通信事件涵数
/**
  * @brief  Returns the last I2Cx Event.
  * @param  I2Cx: where x can be 1, 2 or 3 to select the I2C peripheral.
  *    
  * @note   For detailed description of Events, please refer to section I2C_Events
  *         in stm32f4xx_i2c.h file.
  *   
  * @retval The last event
  */
uint32_t I2C_GetLastEvent(I2C_TypeDef* I2Cx)
以上就是这些部分,具体的其他部分请查看相关.c以及.h文件和数据手册。
15.3 应用
#include "bsp_i2c_ee.h"
#include "bsp_usart.h"
uint16_t EEPROM_ADDRESS;
static __IO uint32_t  I2CTimeout = I2CT_LONG_TIMEOUT;  
static uint32_t I2C_TIMEOUT_UserCallback(uint8_t errorCode);
/**
  * @brief  I2C 工作模式配置
  * @param  无
  * @retval 无
  */
void I2C_Config(void)
{
I2C_InitTypeDef             I2C_InitStructure;
           GPIO_InitTypeDef  GPIO_InitStructure;
           /*-------------------第1步--------------------*/ 
           /*时钟使能*/
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); //I2C2时钟使能
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE); //GPIO时钟使能
           /*-------------------第2步--------------------*/          
           /*GPIO引脚复用*/
  GPIO_PinAFConfig(GPIOH, GPIO_PinSource4, GPIO_AF_I2C2); //将PH4复用给I2C2
  GPIO_PinAFConfig(GPIOH, GPIO_PinSource5, GPIO_AF_I2C2); //将PH5复用给I2C2
  /*初始化GPIO */  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用模式
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;//开漏输出模式
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;//使能上拉
  GPIO_Init(GPIOH, &GPIO_InitStructure);// 初始化PH4:SCL
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_Init(GPIOH, &GPIO_InitStructure);// 初始化PH5:SDA
           /*-------------------第3步--------------------*/
           /* I2C 配置 */
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;           //I2C模式 */
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;           // SCL 时钟线的占空比
  I2C_InitStructure.I2C_OwnAddress1 =I2C_OWN_ADDRESS7; // 从机时,自身器件地址
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;           // 使能ACK相应
   //7bit的寻址模式
           I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_InitStructure.I2C_ClockSpeed = 400000;                // 通信速率<=400K
  I2C_Init(I2C2, &I2C_InitStructure);                            // I2C2 初始化
           /*-------------------第4步--------------------*/
           I2C_Cmd(I2C2, ENABLE);                                  // 使能 I2C2
           /*-------------------第5步--------------------*/
           I2C_AcknowledgeConfig(I2C2, ENABLE);  //使能IIC ACK功能
           EEPROM_ADDRESS = 0xA0;//EEPROM器件地址
}
/**
  * @brief   将缓冲区中的数据写到I2C EEPROM中
  * @param  
  *                      @arg pBuffer:缓冲区指针
  *                      @arg WriteAddr:写地址
  *     @arg NumByteToWrite:写的字节数
  * @retval  无
  */
void I2C_Buffer_Write(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)
{
  u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
  Addr = WriteAddr % I2C_PageSize;
  count = I2C_PageSize - Addr;
  NumOfPage =  NumByteToWrite / I2C_PageSize;
  NumOfSingle = NumByteToWrite % I2C_PageSize;
  /* If WriteAddr is I2C_PageSize aligned  */
  if(Addr == 0)
  {
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage == 0)
    {
      I2C_Page_Write(pBuffer, WriteAddr, NumOfSingle);
      I2C_WaitEepromStandbyState();
    }
    /* If NumByteToWrite > I2C_PageSize */
    else 
    {
      while(NumOfPage--)
      {
        I2C_Page_Write(pBuffer, WriteAddr, I2C_PageSize);
        I2C_WaitEepromStandbyState();
        WriteAddr +=  I2C_PageSize;
        pBuffer += I2C_PageSize;
      }
      if(NumOfSingle!=0)
      {
        I2C_Page_Write(pBuffer, WriteAddr, NumOfSingle);
        I2C_WaitEepromStandbyState();
      }
    }
  }
  /* If WriteAddr is not I2C_PageSize aligned  */
  else
  {
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage== 0)
    {
      I2C_Page_Write(pBuffer, WriteAddr, NumOfSingle);
      I2C_WaitEepromStandbyState();
    }
    /* If NumByteToWrite > I2C_PageSize */
    else
    {
      NumByteToWrite -= count;
      NumOfPage =  NumByteToWrite / I2C_PageSize;
      NumOfSingle = NumByteToWrite % I2C_PageSize;          
      if(count != 0)
      { 
        I2C_Page_Write(pBuffer, WriteAddr, count);
        I2C_WaitEepromStandbyState();
        WriteAddr += count;
        pBuffer += count;
      }
      while(NumOfPage--)
      {
        I2C_Page_Write(pBuffer, WriteAddr, I2C_PageSize);
        I2C_WaitEepromStandbyState();
        WriteAddr +=  I2C_PageSize;
        pBuffer += I2C_PageSize; 
      }
      if(NumOfSingle != 0)
      {
        I2C_Page_Write(pBuffer, WriteAddr, NumOfSingle);
        I2C_WaitEepromStandbyState();
      }
    }
  } 
}
/**
  * @brief   写一个字节到I2C EEPROM中
  * @param  
  *                      @arg pBuffer:缓冲区指针
  *                      @arg WriteAddr:写地址
  * @retval  无
  */
uint32_t I2C_Byte_Write(u8* pBuffer, u8 WriteAddr)
{
  /* Send STRAT condition   启动操作*/
  I2C_GenerateSTART(I2C2, ENABLE);
  I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* Test on EV5 and clear it 检测总线是否忙*/
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(0);
  }   
  /* Send EEPROM address for write 发送器件地址 写操作 */
  I2C_Send7bitAddress(I2C2, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* Test on EV6 and clear it   等待ACK*/
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(1);
  }   
  /* Send the EEPROM's internal address to write to  发送器件内写地址 */
  I2C_SendData(I2C2, WriteAddr);
  I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* Test on EV8 and clear it   等待ACK*/
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) 
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(2);
  }
  /* Send the byte to be written   写数据*/
  I2C_SendData(I2C2, *pBuffer);
  I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* Test on EV8 and clear it 等待ACK*/
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(3);
  }
  /* Send STOP condition 停止操作*/
  I2C_GenerateSTOP(I2C2, ENABLE);
  return 1;
}
/**
  * @brief   在EEPROM的一个写循环中可以写多个字节,但一次写入的字节数
  *          不能超过EEPROM页的大小,AT24C02每页有8个字节
  * @param  
  *                      @arg pBuffer:缓冲区指针
  *                      @arg WriteAddr:写地址
  *     @arg NumByteToWrite:写的字节数
  * @retval  无
  */
uint32_t I2C_Page_Write(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite)
{
  I2CTimeout = I2CT_LONG_TIMEOUT;
  while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY))  //检测IIC控制器是否忙 确认没有总线上没有通信
   {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(4);
  }
  /* Send START condition 启动操作*/
  I2C_GenerateSTART(I2C2, ENABLE);
  I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* Test on EV5 ((uint32_t)0x00030001)    and clear it   确认以下信息: BUSY-总线正在进行通信, MSL-主/从模式, and SB-起始位已经发送*/
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(5);
  }
  /* Send EEPROM address for write 写器件地址 写操作*/
  I2C_Send7bitAddress(I2C2, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* Test on EV6 ((uint32_t)0x00070082) and clear it 等待ACK                      确认以下信息:  TRA-发送器/接收器, BUSY-总线正在进行通信, MSL-主/从模式,  TXE-数据寄存器为空, ADDR-地址已发送(主模式)*/
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(6);
  }
  /* Send the EEPROM's internal address to write to 发送器件内写地址*/   
  I2C_SendData(I2C2, WriteAddr); 
  I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* Test on EV8 and clear it 等待ACK    ((uint32_t)0x00070084)   确认以下信息: TRA-发送器/接收器, BUSY-总线正在进行通信, MSL-主/从模式, TXE-数据寄存器为空 and BTF-字节传输完成 */
  while(! I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(7);
  }
  /* While there is data to be written */
  while(NumByteToWrite--) 
  {
    /* Send the current byte 写数据*/
    I2C_SendData(I2C2, *pBuffer);
    /* Point to the next byte to be written */
    pBuffer++;
    I2CTimeout = I2CT_FLAG_TIMEOUT;
    /* Test on EV8 and clear it 等待ACK                         ((uint32_t)0x00070084)   确认以下信息: TRA-发送器/接收器, BUSY-总线正在进行通信, MSL-主/从模式, TXE-数据寄存器为空 and BTF-字节传输完成*/
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
    {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(8);
    }
  }
  /* Send STOP condition 停止操作*/
  I2C_GenerateSTOP(I2C2, ENABLE);
  return 1;
}
/**
  * @brief   从EEPROM里面读取一块数据
  * @param  
  *                      @arg pBuffer:存放从EEPROM读取的数据的缓冲区指针
  *                      @arg WriteAddr:接收数据的EEPROM的地址
  *     @arg NumByteToWrite:要从EEPROM读取的字节数
  * @retval  无
  */
uint32_t I2C_Buffer_Read(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)
{ 
    I2CTimeout = I2CT_LONG_TIMEOUT;
  //*((u8 *)0x4001080c) |=0x80;
    while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY))    //检测IIC控制器是否忙
    {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(9);
    }
  /* Send START condition 启动操作*/
  I2C_GenerateSTART(I2C2, ENABLE);
  //*((u8 *)0x4001080c) &=~0x80;
  I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* Test on EV5 ((uint32_t)0x00030001)    and clear it   确认以下信息: BUSY-总线正在进行通信, MSL-主/从模式, and SB-起始位已经发送*/
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(10);
   }
  /* Send EEPROM address for write  写器件地址 写操作*/
  I2C_Send7bitAddress(I2C2, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* Test on EV6 ((uint32_t)0x00070082) and clear it 等待ACK                      确认以下信息:  TRA-发送器, BUSY-总线正在进行通信, MSL-主/从模式,  TXE-数据寄存器为空, ADDR-地址已发送(主模式)*/
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
    {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(11);
   }
//  /* Clear EV6 by setting again the PE bit 清除事件6   实际测试去掉也没有出错*/
//  I2C_Cmd(I2C2, ENABLE);
  /* Send the EEPROM's internal address to write to 发送器件内读地址*/
  I2C_SendData(I2C2, ReadAddr); 
     I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* Test on EV8 and clear it 等待ACK    ((uint32_t)0x00070084)   确认以下信息: TRA-发送器, BUSY-总线正在进行通信, MSL-主/从模式, TXE-数据寄存器为空 and BTF-字节传输完成 */
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
    {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(12);
   }
  /* Send STRAT condition a second time 重亲启动操作*/ 
  I2C_GenerateSTART(I2C2, ENABLE);
     I2CTimeout = I2CT_FLAG_TIMEOUT;
   /* Test on EV5 ((uint32_t)0x00030001)    and clear it   确认以下信息: BUSY-总线正在进行通信, MSL-主/从模式, and SB-起始位已经发送*/
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
    {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(13);
   }
  /* Send EEPROM address for read 发送器件地址+1  读操作*/
  I2C_Send7bitAddress(I2C2, EEPROM_ADDRESS, I2C_Direction_Receiver);
     I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* Test on EV6 ((uint32_t)0x00030002) and clear it 等待ACK                      确认以下信息:  TRA-接收器, BUSY-总线正在进行通信, MSL-主/从模式,  TXE-数据寄存器为空, ADDR-地址已发送(主模式)*/
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
    {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(14);
   }
  /* While there is data to be read */
  while(NumByteToRead) 
  {                     
                      I2CTimeout = I2CT_LONG_TIMEOUT;
                      if(NumByteToRead == 1)//最后一个数据的话
    {
      /* Disable Acknowledgement 禁止ACK 结束数据接收*/
      I2C_AcknowledgeConfig(I2C2, DISABLE);
      /* Send STOP Condition 停止操作*/
      I2C_GenerateSTOP(I2C2, ENABLE);
    }
                      else
                                 /* Enable Acknowledgement to be ready for another reception 使能ACK  重复数据接收*/
                                 I2C_AcknowledgeConfig(I2C2, ENABLE);                     
                      while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED)==0)  //等待数据接收结束  ((uint32_t)0x00030040)   BUSY-总线正在进行通信, MSL-主/从模式, and RXNE-数据寄存器非空 flags
                      {
                                 if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(3);
                      }           
                      {
                        /* Read a byte from the device 读取数据*/
      *pBuffer = I2C_ReceiveData(I2C2);
      /* Point to the next location where the byte read will be saved */
      pBuffer++;
      /* Decrement the read bytes counter */
      NumByteToRead--;
                      }          
  }
  return 1;
}
/**
  * @brief  Wait for EEPROM Standby state
  * @param  无
  * @retval 无
  */
void I2C_WaitEepromStandbyState(void)     
{
  vu16 SR1_Tmp = 0;
  do
  {
    /* Send START condition */
    I2C_GenerateSTART(I2C2, ENABLE);
    /* Read I2C2 SR1 register */
    SR1_Tmp = I2C_ReadRegister(I2C2, I2C_Register_SR1);
    /* Send EEPROM address for write */
    I2C_Send7bitAddress(I2C2, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  }while(!(I2C_ReadRegister(I2C2, I2C_Register_SR1) & 0x0002));
  /* Clear AF flag */
  I2C_ClearFlag(I2C2, I2C_FLAG_AF);
  /* STOP condition */   
  I2C_GenerateSTOP(I2C2, ENABLE);
}
/**
  * @brief  Basic management of the timeout situation.
  * @param  errorCode:错误代码,可以用来定位是哪个环节出错.
  * @retval 返回0,表示IIC读取失败.
  */
static  uint32_t I2C_TIMEOUT_UserCallback(uint8_t errorCode)
{
  /* Block communication and all processes */
  return 0;
}
/*********************************************END OF FILE**********************/
#ifndef __I2C_EE_H
#define           __I2C_EE_H
#include "stm32f4xx.h"
/* AT24C01/02每页有8个字节 */
//#define I2C_PageSize           8
/* AT24C04/08A/16A每页有16个字节 */
#define I2C_PageSize           16                                
/* STM32 I2C 快速模式 */
#define I2C_Speed              400000
/* 这个地址只要与STM32外挂的I2C器件地址不一样即可 */
#define I2C_OWN_ADDRESS7      0X0A  
/*I2C接口*/
#define EEPROM_I2C                          I2C2
#define EEPROM_I2C_CLK                      RCC_APB1Periph_I2C2
#define EEPROM_I2C_CLK_INIT                                                                                          RCC_APB1PeriphClockCmd
#define EEPROM_I2C_SCL_PIN                  GPIO_Pin_4                
#define EEPROM_I2C_SCL_GPIO_PORT            GPIOH                      
#define EEPROM_I2C_SCL_GPIO_CLK             RCC_AHB1Periph_GPIOH
#define EEPROM_I2C_SCL_SOURCE               GPIO_PinSource4
#define EEPROM_I2C_SCL_AF                   GPIO_AF_I2C2
#define EEPROM_I2C_SDA_PIN                  GPIO_Pin_5                 
#define EEPROM_I2C_SDA_GPIO_PORT            GPIOH                      
#define EEPROM_I2C_SDA_GPIO_CLK             RCC_AHB1Periph_GPIOH
#define EEPROM_I2C_SDA_SOURCE               GPIO_PinSource5
#define EEPROM_I2C_SDA_AF                   GPIO_AF_I2C2
/*等待超时时间*/
#define I2CT_FLAG_TIMEOUT         ((uint32_t)0x1000)
#define I2CT_LONG_TIMEOUT         ((uint32_t)(10 * I2CT_FLAG_TIMEOUT))
/*
* AT24C02      2kb   = 256 B ,    1个块  32 页, 8 字节/页,Block0          
* AT24C04      4kb   = 512 B ,    2个块2*32 页,16 字节/页,Block0~1
* AT24C08      8kb   =  1K B ,    4个块4*32 页,16 字节/页,Block0~3
* AT24C16      16kb  =  2K B ,    8个块8*32 页,16 字节/页,Block0~7
*
* Device Address
* 1 0 1 0 A2 A1 A0 R/W
* 1 0 1 0 0  0  0  0 = 0XA0
* 1 0 1 0 0  0  0  1 = 0XA1
*/
/* EEPROM Addresses defines */                                                                                                                                                                                                                           
#define EEPROM_Block0_ADDRESS 0xA0  /* 块0 AT24C02 AT24C04  AT24C08  AT24C16*/
#define EEPROM_Block1_ADDRESS 0xA2  /*块1  AT24C04  AT24C08  AT24C16*/
#define EEPROM_Block2_ADDRESS 0xA4  /*块2  AT24C08  AT24C16*/
#define EEPROM_Block3_ADDRESS 0xA6  /*块3  AT24C08 AT24C16*/
#define EEPROM_Block4_ADDRESS 0xA8  /* 块4 AT24C16*/
#define EEPROM_Block5_ADDRESS 0xAA  /*块5  AT24C16*/
#define EEPROM_Block6_ADDRESS 0xAC  /*块6  AT24C16*/
#define EEPROM_Block7_ADDRESS 0xAE  /*块7  AT24C16*/
void I2C_Config(void);
void I2C_Buffer_Write(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite);
uint32_t I2C_Byte_Write(u8* pBuffer, u8 WriteAddr);
uint32_t I2C_Page_Write(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite);
uint32_t I2C_Buffer_Read(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead);
void I2C_WaitEepromStandbyState(void);
#endif /* __I2C_EE_H */
相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
2月前
STM32--SPI通信与W25Q64(2)
STM32--SPI通信与W25Q64(2)
|
2月前
|
存储 传感器 芯片
STM32--SPI通信与W25Q64(1)
STM32--SPI通信与W25Q64(1)
|
2月前
|
存储 传感器
【STM32基础 CubeMX】uart串口通信
【STM32基础 CubeMX】uart串口通信
205 0
|
9月前
|
芯片
STM32速成笔记(五)—串口通信
本文介绍了串口通信的概念,用途以及一些相关概念。介绍了如何进行printf重定向,如何根据接收到的特定信息,执行特定操作。此外,本文以通过上位机发送特殊指令控制LED亮灭的小项目,给出了详细的配置方法和程序设计。
144 0
STM32速成笔记(五)—串口通信
|
12月前
|
定位技术
激光雷达A1M8与STM32通信
激光雷达A1M8与STM32通信
140 0
|
19天前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
63 2
|
2月前
|
传感器
|
19天前
|
IDE 开发工具
使用STM32F103标准库实现自定义键盘
通过本文,我们学习了如何使用STM32F103标准库实现一个简单的自定义键盘。我们首先初始化了GPIO引脚,然后实现了一个扫描函数来检测按键状态。这个项目不仅能够帮助我们理解STM32的GPIO配置和按键扫描原理,还可以作为进一步学习中断处理和低功耗设计的基础。希望本文对你有所帮助,祝你在嵌入式开发的道路上不断进步!
65 4
|
19天前
|
存储 数据采集 数据安全/隐私保护
使用STM32F103读取TF卡并模拟U盘:使用标准库实现
通过以上步骤,你可以实现用STM32F103将TF卡内容变成U盘进行读取。这种功能在数据采集、便携式存储设备等应用中非常有用。如果你有更多的需求,可以进一步扩展此项目,例如添加文件管理功能、加密存储等。希望这篇博客能帮到你,如果有任何问题,欢迎在评论区留言讨论!
19 1