文章标题

    xiaoxiao2021-03-25  124

    STM32_IIC 24C02

    第一步引脚配置 ,IIC配置

    #include "24C02.h" #include "stm32f10x.h" #define I2C_Speed 800000 #define I2C1_SLAVE_ADDRESS7 0xA0 #define I2C_PageSize 8 #define EEPROM_ADDRESS 0xA0 void I2C_Configuration(void) { I2C_InitTypeDef I2C_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);//I2C时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO, ENABLE);//GPIO时钟使能 // PB6,7 SCL and SDA */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//复用开漏 GPIO_Init(GPIOB, &GPIO_InitStructure); I2C_DeInit(I2C1); //初始化IIC I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //设置为IIC模式 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //I2C工作于快速模式 I2C_InitStructure.I2C_OwnAddress1 =I2C1_SLAVE_ADDRESS7;;//设置第一个设备的地址 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//使能应答 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //应答7位地址 I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;//时钟设置为40K I2C_Cmd(I2C1, ENABLE); //使能I2C1 I2C_Init(I2C1, &I2C_InitStructure);//以上参数初始化结构体 }

    第二部 IIC的通讯 /************************************************ ** 函数名: I2C_EE_ByteWrite ** 功能描述: 一个字节写入EEPROM ** 输入参数: pBuffer 要写入数据数组的指针 WriteAddr 24C02 中要写入数据的首地址 *************************************************/ void I2C_EE_ByteWrite(uint8_t* pBuffer,uint8_t WriteAddr) { /产生I2Cx传输 START 条件/ I2C_GenerateSTART(I2C1, ENABLE); //设置主机模式 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); /I2C设备 发送方向/ I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter); //等待选着过程完成 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /* 发送数据到EEPROM内部地址 I2C_SendData(I2C1, WriteAddr); //等待字节完成 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* //通过外设 发送地址·*/ I2C_SendData(I2C1, *pBuffer); //等待字节发送完成 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    /产生I2Cx STOP条件/ I2C_GenerateSTOP(I2C1, ENABLE); } IIC中断说明 I2C所有函数说明

    I2C_CheckEvent 事件所有值如下

    /********************************************************** ** 函数名: II2C_EE_BufferRead ** 功能描述:将EEPROM的数据读入指针缓冲组中 ** 输入参数: pBuffer 指向要读出数据的数组指针 ReadAddr:24c02 要读出数据的首地址 NumByteToRead:读出的字节数 ** 输出参数:无 ***********************************************************/ void I2C_EE_BufferRead(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead) { I2C_EE_WaitEepromStandbyState();//等待EEPROM等待命令 while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); /*产生起始条件 */ I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //向指定的从I2C设备传送地址字 选择发送方向 I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_Cmd(I2C1, ENABLE); //EEPROM数据起始地址 I2C_SendData(I2C1, ReadAddr); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /*再次发送起始条件*/ I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); /*向指定I2c设备传送地址字 选择接受方向*/ I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); /*直到读取完成*/ while(NumByteToRead) { if(NumByteToRead == 1) { /*失能 I2C应答功能*/ I2C_AcknowledgeConfig(I2C1, DISABLE); /*产生停止条件*/ I2C_GenerateSTOP(I2C1, ENABLE); } //检查是否接受到数据 if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) { /*读取通过I2CX 最近接收的数据 */ *pBuffer = I2C_ReceiveData(I2C1); pBuffer++; NumByteToRead--; } } //使能指定 I2C的应答功能 I2C_AcknowledgeConfig(I2C1, ENABLE); }

    I2C在读取完 最后一个字节 发送NACk 释放总线

    /********************************************************** ** 函数名:I2C_EE_WaitEepromStandbyState ** 功能描述:等待EEPROM为待命状态 ** 输入参数:无 ** 输出参数:无 ***********************************************************/ void I2C_EE_WaitEepromStandbyState(void) { __IO uint16_t SR1_Tmp = 0; do { /*产生起始条件*/ I2C_GenerateSTART(I2C1, ENABLE); /*读取指定I2C寄存器 I2C_SR1 并返回值*/ SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1); /*向指定的从I2C设备传送地址字,选择发送方向*/ I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter); }while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002));//直到地址发送结束 //清除I2X应答错误标志位 I2C_ClearFlag(I2C1, I2C_FLAG_AF); /*产生停止条件*/ I2C_GenerateSTOP(I2C1, ENABLE); }

    I2C_SR1寄存器的第二位

    I2C_Direction

    /********************************************************** ** 函数名: I2C_EE_BufferWrite ** 功能描述: 可跨页在任意地址开始写数据 ** 输入参数: pBuffer: 指向写入数据的指针 WriteAddr:24C02要写入数据的首地址 NumByteToWrite:写入的字节数 ** 输出参数:无 ***********************************************************/ void I2C_EE_BufferWrite(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite) { uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0; Addr = WriteAddr % I2C_PageSize;//写入地址是每一页的第几位 count = I2C_PageSize - Addr;//要写入数据的个数 NumOfPage = NumByteToWrite / I2C_PageSize;//要写入的页数 NumOfSingle = NumByteToWrite % I2C_PageSize;//不足一页的个数 //I2C_EE_WaitEepromStandbyState();//等待EEPROM为待命状态 /*如果写入地址是也开始的 */ if(Addr == 0) { /*如果数据小于一页*/ if(NumOfPage == 0) { I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写少于一页的数据 I2C_EE_WaitEepromStandbyState(); //德昂带EEPROM待命的状态 } /*如果数据大于一页 */ else { while(NumOfPage--)//要写入的页数 { I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize); //写一页的数据 I2C_EE_WaitEepromStandbyState(); //等待EEPROM WriteAddr += I2C_PageSize; //地址加8 pBuffer += I2C_PageSize;//数据加8 } if(NumOfSingle!=0) //剩余数据小于一页 { I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写小于一页的数据 I2C_EE_WaitEepromStandbyState(); // } } } /*如果不是页 开始的 */ else { /* 如果小于一页 */ if(NumOfPage== 0) { I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle); //写小于一页的数据 I2C_EE_WaitEepromStandbyState(); } /* 如果大于等于一页*/ else { NumByteToWrite -= count; NumOfPage = NumByteToWrite / I2C_PageSize;//重新计算写入页数 NumOfSingle = NumByteToWrite % I2C_PageSize;//计算不足一页的个数 if(count != 0) { I2C_EE_PageWrite(pBuffer, WriteAddr, count); //将开始的空间写满 I2C_EE_WaitEepromStandbyState(); WriteAddr += count; pBuffer += count; } while(NumOfPage--) //要写的页数 { I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize); I2C_EE_WaitEepromStandbyState(); WriteAddr += I2C_PageSize; pBuffer += I2C_PageSize; } if(NumOfSingle != 0)//剩余数据小于一页 { I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写小于一页的数据 I2C_EE_WaitEepromStandbyState(); // } } } } /********************************************************** ** 函数名: I2C_EE_PageWrite ** 功能描述: 写小于一页的数据EEPROM ** 输入参数: pBuffer 指向要写入数据数组的指针 WriteAddr: 24C02要写入数据的首地址 NumByteToWrite:要写入字节数 ** 输入参数: 无 ***********************************************************/ void I2C_EE_PageWrite(uint8_t* pBuffer, uint8_t WriteAddr, uint8_t NumByteToWrite) { /*等待总线空闲*/ while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); /*产生I2X START条件*/ I2C_GenerateSTART(I2C1, ENABLE); //设置主机模式 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); /*向指定I2C设备发送地址 选择发送方向*/ I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter); //等待完成 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /*通过 外设I2C 发送地址 */ I2C_SendData(I2C1, WriteAddr); //等待完成 while(! I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /*知道写完数据*/ while(NumByteToWrite--) { /* 发送当前字节数据*/ I2C_SendData(I2C1, *pBuffer); /* 指针指向下一个要写的数据 */ pBuffer++; //等待字节写完 while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); } /* 停止条件*/ I2C_GenerateSTOP(I2C1, ENABLE); }

    main 主函数

    int main(void) { u8 my_buf[20]; SystemInit(); //系统初始化 Usart_Configuration();//窗口初始化 I2C_Configuration();//I2C初始化 delay_ms(10); //在地址10 写入指定长度数据 I2C_EE_BufferWrite("系统初始化时钟配置",10,18); I2C_EE_BufferRead(my_buf,10,18); //读取地址10处的数据 printf(my_buf);//用串口打印读取到的数据 while(1); }

    最后附上源代码 仅供参考和学习

    转载请注明原文地址: https://ju.6miu.com/read-5621.html

    最新回复(0)