本程序利用STM32F4的硬件IIC实现对AT24C02的任何操作!! /** ****************************************************************************** * @file bsp.c * @author wangfei * @date 13-April-2012 * @e-mail wfmjj@hotmail.com * @brief Initialize peripherals. *****************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx.h" #include "bsp.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /** * @brief This function handles NMI exception. * @param None * @retval None */ void Bsp_Init(void) { Bsp_GPIO_Config(); Bsp_IIC_Config(); Bsp_USART3_Config(); } /** * @brief This function config gpio. * @param None * @retval None */ void Bsp_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; //定义结构体 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE); //打开外设GPIOE的时钟--LED RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //turn on gpioc clock RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //打开GPIOB口的时钟I2C_CLK--PB6 //LED端口配置 GPIO_InitStructure.GPIO_Pin=(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3); //led口配置 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL; GPIO_Init(GPIOE, &GPIO_InitStructure); //USART3端口配置 GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_USART3); //Connect USART3 pins to AF7 GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_USART3); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOC, &GPIO_InitStructure); //IIC端口设置 IIC_CLK和IIC_SDA引脚均要设置为复用开漏不带上拉输出 GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_I2C1); //开启PB6的复用功能连接至I2C1 GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_I2C1); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6 | GPIO_Pin_7; //选择PB6和PB7引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //开启PB6和PB7的复用功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //PB6和PB7设置为开漏输出 GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_NOPULL; //PB6和PB7口不带上拉电阻 GPIO_Init(GPIOB, &GPIO_InitStructure); } /** * @brief This function config iic. * @param None * @retval None */ void Bsp_IIC_Config(void) { I2C_InitTypeDef I2C_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE); //打开IIC外设时钟 I2C_DeInit(I2C1); //将外设IIC的各个寄存器恢复到复位以后的值 I2C_InitStructure.I2C_ClockSpeed=100000; //标准模式 时钟频率为100KHZ I2C_InitStructure.I2C_Mode=I2C_Mode_I2C; //选中I2C模式 I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1=0X00; //当I2C出于从模式时,自身的地址 I2C_InitStructure.I2C_Ack=I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit; I2C_Init(I2C1, &I2C_InitStructure); I2C_AcknowledgeConfig(I2C1,ENABLE); //在接收到一个字节后返回一个应答ACK I2C_Cmd(I2C1,ENABLE); //开启外设IIC模块 } /** * @brief This function config usart3. * @param None * @retval None */ void Bsp_USART3_Config(void) { USART_InitTypeDef USART_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //turn on usart3 clock USART_InitStructure.USART_BaudRate =115200 ; //波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART3, &USART_InitStructure); //USART_ITConfig(USART3,USART_IT_RXNE,ENABLE); USART_Cmd(USART3,ENABLE); USART_ClearFlag(USART3, USART_FLAG_TC); //清除发送完成标志位 } /** ****************************************************************************** * @file at24c02.c * @author wangfei * @date 13-April-2012 * @e-mail wfmjj@hotmail.com * @brief write or read eeprom *****************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx.h" #include "at24c02.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /** * @brief This function write one byte to at24c02. * @param None * @retval None */ void IIC_Write_AT24C02_OneByte(uint8_t addr,uint8_t data) { uint16_t flag; //判断BUSY是否为1,BUSY=1总线处于忙状态 while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)); //如果BUSY=1则等待一直等到BUSY=0 //主机产生起始条件 I2C_GenerateSTART(I2C1,ENABLE); //判断SB是否为1,SB=1起始条件已经发送 即判断EV5 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)==ERROR); //当产生了起始条件,设备就进入了主模式 //发送eepROM的地址0XA0 I2C_Send7bitAddress(I2C1,0XA0,I2C_Direction_Transmitter); //软件读取SR1寄存器后,写数据寄存器的操作将清除SB位 //判断ADDR是否为1,ADDR=1地址发送结束 即判断EV6 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR); flag=I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位 //发送AT24C02的内部地址:即数据要写入的地址 I2C_SendData(I2C1,addr); //判断TXE是否为1,TXE=1移位寄存器不为空,数据寄存器为空 即判断EV8 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING)==ERROR); //发送数据到要写入的地址 I2C_SendData(I2C1,data); //对数据寄存器的写操作将清除TXE位 //判断TXE和BTF是否为1,TXE=1,BTF=1请求设置停止位 即判断EV8_2 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)==ERROR); //关闭通讯,产生停止条件 I2C_GenerateSTOP(I2C1,ENABLE); //产生停止条件时,硬件自动清除TXE和BTF位 } /** * @brief This function waite for eeprom standby state. * @param none * @retval None */ /*AT24C02在接收完数据后,启动内部周期写入数据的时间内不会对主机的请求做出应答的特性,因此此 函数循环发送起始信号,若检测到AT24C02的应答,则说明AT24C02已完成上一步的数据写入,进入稳定状态 可以进行下一次的操作,因此这个函数在数据写入完成后必须调用此函数,判断AT24C02是否进入稳定状态*/ void IIC_Waite_AT24C02_Standby(void) { uint16_t SR1_Flag; I2C1->SR1&=0X0000; //清除I2C1_SR1寄存器 do { I2C_GenerateSTART(I2C1,ENABLE); //产生起始条件 SR1_Flag=I2C1->SR1; //软件读取SR1寄存器后,写数据寄存器的操作将清除SB位 I2C_Send7bitAddress(I2C1,0XA0,I2C_Direction_Transmitter); //发送7位AT24C02的地址 }while((I2C1->SR1&0X0002)==0X00); //当ADDR=1时,跳出此循环表明AT24C02写入数据已完成 I2C_ClearFlag(I2C1,I2C_FLAG_AF); //清除应答失败位 I2C_GenerateSTOP(I2C1,ENABLE); //发送停止信号 } /* * 函数名:IIC_AT24C02_PageWrite * 描述 :在EEPROM的一个写循环中可以写多个字节,但一次写入的字节数 * 不能超过EEPROM页的大小。AT24C02每页有8个字节。 * 输入 :-pBuffer 缓冲区指针 * -WriteAddr 接收数据的EEPROM的地址 * -NumByte 要写入EEPROM的字节数 * 输出 :无 * 返回 :无 * 调用 :外部调用 */ void IIC_AT24C02_PageWrite(uint8_t *pBuffer,uint8_t WriteAddr,uint8_t NumByte) { uint16_t state; //判断BUSY是否为1,BUSY=1总线处于忙状态 while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)); //如果BUSY=1则等待一直等到BUSY=0 //主机产生起始条件 I2C_GenerateSTART(I2C1,ENABLE); //判断SB是否为1,SB=1起始条件已经发送 即判断EV5 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)==ERROR); //当产生了起始条件,设备就进入了主模式 //发送eepROM的地址0XA0 I2C_Send7bitAddress(I2C1,0XA0,I2C_Direction_Transmitter); //软件读取SR1寄存器后,写数据寄存器的操作将清除SB位 //判断ADDR是否为1,ADDR=1地址发送结束 即判断EV6 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR); state=I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位 //发送AT24C02的内部地址:即数据要写入的地址 I2C_SendData(I2C1,WriteAddr); //判断TXE是否为1,TXE=1移位寄存器不为空,数据寄存器为空 即判断EV8 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING)==ERROR); for(;NumByte>0;NumByte--) { //发送数据到要写入的地址 I2C_SendData(I2C1,*pBuffer); //对数据寄存器的写操作将清除TXE位 //缓冲区指针加1指向下一个要写入的数据 pBuffer++; //判断TXE和BTF是否为1,TXE=1,BTF=1请求设置停止位 即判断EV8_2 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)==ERROR); } //关闭通讯,产生停止条件 I2C_GenerateSTOP(I2C1,ENABLE); //产生停止条件时,硬件自动清除TXE和BTF位 } /** * @brief This function read one byte from slect address. * @param none * @retval None */ /*选择性读取允许主器件对AT24C02寄存器的任意字节读操作,具体步骤如下: 1--主器件发送起始信号,从器件地址,和他想读取的字节数据的地址执行一个伪写操作 2--AT24C02应答之后,主器件从新发送起始信号和从器件地址,此时R/W位置1。 3--AT24C02响应并发送应答信号,然后输出一个所要求的8位字节数据。 4--主器件不发送应答信号,但产生一个停止信号。*/ uint8_t IIC_Read_AT24C02_OneByte(uint8_t address) { uint16_t temp,flag; //判断BUSY是否为1,BUSY=1总线处于忙状态 while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)); //如果BUSY=1则等待一直等到BUSY=0 //主机产生起始条件 I2C_GenerateSTART(I2C1,ENABLE); //判断SB是否为1,SB=1起始条件已经发送 即判断EV5 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)==ERROR); //当产生了起始条件,设备就进入了主模式 //发送eepROM的地址0XA0 I2C_Send7bitAddress(I2C1,0XA0,I2C_Direction_Transmitter); //软件读取SR1寄存器后,写数据寄存器的操作将清除SB位 //判断ADDR是否为1,ADDR=1地址发送结束 即判断EV6 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR); flag=I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位 //发送想要读取字节的地址 I2C_SendData(I2C1,address); //判断TXE是否为1,TXE=1移位寄存器不为空,数据寄存器为空 即判断EV8 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING)==ERROR); //主机重新发送起始信号 I2C_GenerateSTART(I2C1,ENABLE); //判断SB是否为1,SB=1起始条件已经发送 即判断EV5 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)==ERROR); //当产生了起始条件,设备就进入了主模式 //主机重新发送AT24C02的地址,这是R/W位置1 I2C_Send7bitAddress(I2C1,0XA0,I2C_Direction_Receiver); //判断ADDR是否为1,ADDR=1地址发送结束 即判断EV6 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)==ERROR); flag=I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位 I2C_AcknowledgeConfig(I2C1,DISABLE); I2C_GenerateSTOP(I2C1,ENABLE); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)==ERROR); temp=I2C_ReceiveData(I2C1); I2C_AcknowledgeConfig(I2C1, ENABLE); //打开应答信号使其回到初始状态 return temp; } /* * 函数名:IIC_AT24C02_PageRead * 描述 :从EEPROM里面读取一块数据。 * 输入 :-pBuffer 存放从EEPROM读取的数据的缓冲区指针。 * -ReadAddr 接收数据的EEPROM的地址。 * -NumByte 要从EEPROM读取的字节数。 * 输出 :无 * 返回 :无 * 调用 :外部调用 */ void IIC_AT24C02_PageRead(uint8_t *pBuffer,uint8_t ReadAddr,uint8_t NumByte) { uint16_t flag1,flag2; //判断BUSY是否为1,BUSY=1总线处于忙状态 while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)); //如果BUSY=1则等待一直等到BUSY=0 //主机产生起始条件 I2C_GenerateSTART(I2C1,ENABLE); //判断SB是否为1,SB=1起始条件已经发送 即判断EV5 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)==ERROR); //当产生了起始条件,设备就进入了主模式 //发送eepROM的地址0XA0 I2C_Send7bitAddress(I2C1,0XA0,I2C_Direction_Transmitter); //软件读取SR1寄存器后,写数据寄存器的操作将清除SB位 //判断ADDR是否为1,ADDR=1地址发送结束 即判断EV6 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR); flag1=I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位 //发送想要读取字节的地址 I2C_SendData(I2C1,ReadAddr); //判断TXE是否为1,TXE=1移位寄存器不为空,数据寄存器为空 即判断EV8 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING)==ERROR); //主机重新发送起始信号 I2C_GenerateSTART(I2C1,ENABLE); //判断SB是否为1,SB=1起始条件已经发送 即判断EV5 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)==ERROR); //当产生了起始条件,设备就进入了主模式 //主机重新发送AT24C02的地址,这是R/W位置1 I2C_Send7bitAddress(I2C1,0XA0,I2C_Direction_Receiver); //判断ADDR是否为1,ADDR=1地址发送结束 即判断EV6 while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)==ERROR); flag2=I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位 //接收AT24C02发送的数据 while(NumByte) { if(NumByte==1) //等于1时数据已经发送完成 { //主机不再发送响应信号 I2C_AcknowledgeConfig(I2C1,DISABLE); //主机产生停止信号 I2C_GenerateSTOP(I2C1,ENABLE); } //检查RXNE是否为1,即判断EV7 if(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)==SUCCESS) { /* Read a byte from the EEPROM */ *pBuffer = I2C_ReceiveData(I2C1); //软件读取数据寄存器的值,讲清除RXNE位 /* Point to the next location where the byte read will be saved */ pBuffer++; /* Decrement the read bytes counter */ NumByte--; } } I2C_AcknowledgeConfig(I2C1, ENABLE); //打开应答信号使其回到初始状态 } /* * 函数名:IIC_AT24C02_BufferWrite * 描述 :将缓冲区中的数据写到I2C EEPROM中 * 输入 :-pBuffer 缓冲区指针 * -WriteAddr 接收数据的EEPROM的地址 * -NumByteToWrite 要写入EEPROM的字节数 * 输出 :无 * 返回 :无 */ void IIC_AT24C02_BufferWrite(uint8_t *pBuffer,uint8_t WriteAddr,uint8_t NumByteToWrite ) { uint8_t NumofPage=0; //要写入的数据块按页操作所需的次数(AT24C02页写,可一次写入8个字节数据) uint8_t NumofSignal=0; //要写入的数据块按页写操作完成后剩余的字节数 uint8_t addr=0; //要写入数据块的首地址是否为8的倍数 uint8_t count=0; // addr=WriteAddr%I2C_PageSize; //判断要写入的数据块首地址是否为8的倍数,addr=0则为8的整数倍 //如果要写入的数据的起始地址不是8的倍数,则addr不为0.算出与8的差值。 //写入数据的起始地址+这个差值=下一个为8的倍数的地址 count=8-addr; NumofPage=NumByteToWrite/I2C_PageSize; //计算写入的数据块按页写需要进行页操作的次数 NumofSignal=NumByteToWrite%I2C_PageSize; //页操作剩余的字节数 /* 如果要写入数据块的首地址为8的倍数,即addr=0只需操作几次页写函数即可 */ if(addr==0) //首先判断起始地址是否为8的整数倍,在判断要写的数据长度是否大于8个字节 { //如果写入的数据块长度小于8个字节 if(NumofPage==0) { IIC_AT24C02_PageWrite(pBuffer,WriteAddr,NumofSignal); IIC_Waite_AT24C02_Standby(); } else //要写入的数据块长度大于8个字节,即按页操作 { while(NumofPage--) { IIC_AT24C02_PageWrite(pBuffer,WriteAddr,8); //进行页操作一次可以连续写入8个字节数据 IIC_Waite_AT24C02_Standby(); WriteAddr+=8; //写入数据的地址加8 pBuffer+=8; //将要写入的数据的指针加8 } if(NumofSignal!=0) //按页操作完成之后的数据不够8个字节的 { IIC_AT24C02_PageWrite(pBuffer,WriteAddr,NumofSignal); //将剩余的字节数写入到对应的地址中 IIC_Waite_AT24C02_Standby(); } } } else //如果写入数据的起始地址不为8的倍数,即addr!=0. { //如果写入的数据块长度小于8个字节 if(NumofPage==0) { IIC_AT24C02_PageWrite(pBuffer,WriteAddr,NumofSignal); IIC_Waite_AT24C02_Standby(); } else //要写入的数据块长度大于8个字节,即按页操作 { //首先要先写入count个数据,即算出写完counter个字节数据后NumByteToWrite的新值 NumByteToWrite-=count; NumofPage=NumByteToWrite/I2C_PageSize; //计算写入的数据块按页写需要进行页操作的次数 NumofSignal=NumByteToWrite%I2C_PageSize; //页操作剩余的字节数 if(count!=0) { IIC_AT24C02_PageWrite(pBuffer,WriteAddr,count); IIC_Waite_AT24C02_Standby(); WriteAddr+=count; pBuffer+=count; } while(NumofPage--) { IIC_AT24C02_PageWrite(pBuffer,WriteAddr,8); //进行页操作一次可以连续写入8个字节数据 IIC_Waite_AT24C02_Standby(); WriteAddr+=8; //写入数据的地址加8 pBuffer+=8; //将要写入的数据的指针加8 } if(NumofSignal!=0) //按页操作完成之后的数据不够8个字节的 { IIC_AT24C02_PageWrite(pBuffer,WriteAddr,NumofSignal); //将剩余的字节数写入到对应的地址中 IIC_Waite_AT24C02_Standby(); } } } } /** ****************************************************************************** * @file app.c * @author wangfei * @date 13-April-2012 * @e-mail wfmjj@hotmail.com * @brief Initialize peripherals. *****************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx.h" #include "app.h" #include "bsp.h" #include "at24c02.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ uint8_t PageWrite[8]={1,2,3,4,5,6,7,8}; uint8_t PageRead[8]; uint8_t SequenceWrite[15]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; uint8_t SequenceRead[15]; /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /** * @brief This function handles NMI exception. * @param None * @retval None */ int main(void) { uint8_t I2C_Data,i,m; uint8_t *p,*q,*r,*s; uint8_t ReadSum=0,WriteSum=0; p=PageWrite; q=PageRead; r=SequenceWrite; s=SequenceRead; GPIO_ResetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3)); //可以通过观察LED的状态判断写入和读取的数值相等不 Bsp_Init(); //单字节的读与写 IIC_Write_AT24C02_OneByte(200,0x78); IIC_Waite_AT24C02_Standby(); I2C_Data=IIC_Read_AT24C02_OneByte(200); if(I2C_Data==0x78) { GPIO_SetBits(GPIOE,(GPIO_Pin_0)); } //页写和连续读取 IIC_AT24C02_PageWrite(p,2,8); IIC_Waite_AT24C02_Standby(); IIC_AT24C02_PageRead(q,2,8); if(PageRead[1]==2) { GPIO_SetBits(GPIOE,(GPIO_Pin_1)); } //连续写与读 IIC_AT24C02_BufferWrite(r,15,15); IIC_Waite_AT24C02_Standby(); IIC_AT24C02_PageRead(s,15,15); WriteSum=SequenceWrite_Checksum(); ReadSum=SequenceRead_Checksum(); if(WriteSum==ReadSum) { GPIO_SetBits(GPIOE,(GPIO_Pin_2)); } while(1) { USART_SendData(USART3,I2C_Data); while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET); Delay(10000000); for(i=0;i |
STM32F407 定时器触发DMA 求助大神
【MCU实战经验】基于STM32F407的音频播放器设计
盘古UE-STM32F407工控板原理图
【STM32F429心得\疑问】+STM32F4之FSMC和FMC
STM32F429读取IO口传输的数据速率
STM32F407ZGT6 手摸芯片背部重启
STM32F4 SPI 动作时,软件片选信号被拉高,IO口程序逻辑失控
STM32F401RE NUCLEO求助,串口一直不能进中断
读取STM32F407内部温度传感器值错误
STM32F429多路内部ADC独立采集的办法