- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2023-07-31 geehy the first version
- */
- #ifndef APPLICATIONS_GEEHY_I2C_H_
- #define APPLICATIONS_GEEHY_I2C_H_
- #include <rtthread.h>
- #include "apm32f4xx_gpio.h"
- #include "apm32f4xx_i2c.h"
- #include "apm32f4xx_rcm.h"
- void I2C1_Init(void);
- void I2C_EE_BufferRead(I2C_T* i2c,uint8_t* pBuffer,uint8_t DeviceAddr, uint16_t ReadAddr, uint32_t NumByteToRead);
- void I2C_EE_BufferWrite(I2C_T* i2c,uint8_t* pBuffer,uint8_t DeviceAddr, uint16_t WriteAddr, uint32_t NumByteToWrite);
- void I2C_BufferWritePage(I2C_T* i2c,uint8_t DeviceAddr,uint16_t WriteAddr,uint8_t *pBuffer,uint32_t lenth);
- void EEprom_Test(void);
- #define SLAVE_ADDR 0X00A0 //AT24c256地址
- #endif /* APPLICATIONS_GEEHY_I2C_H_ */
- #include "Geehy_I2C.h"
- void I2C1_Init(void){
- GPIO_Config_T gpioConfigStruct;
- I2C_Config_T i2cConfigStruct;
- /** Enable I2C related Clock */
- RCM_EnableAHB1PeriphClockLPMode(RCM_AHB1_PERIPH_GPIOB);
- RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_I2C1);
- GPIO_ConfigPinAF(GPIOB,GPIO_PIN_SOURCE_6,GPIO_AF_I2C1);
- GPIO_ConfigPinAF(GPIOB,GPIO_PIN_SOURCE_7,GPIO_AF_I2C1);
- /** Free I2C_SCL and I2C_SDA */
- gpioConfigStruct.mode = GPIO_MODE_AF;
- gpioConfigStruct.otype = GPIO_OTYPE_OD;
- gpioConfigStruct.speed = GPIO_SPEED_50MHz;
- gpioConfigStruct.pin = GPIO_PIN_6;
- GPIO_Config(GPIOB, &gpioConfigStruct);
- gpioConfigStruct.mode = GPIO_MODE_AF;
- gpioConfigStruct.otype = GPIO_OTYPE_OD;
- gpioConfigStruct.speed = GPIO_SPEED_50MHz;
- gpioConfigStruct.pin = GPIO_PIN_7;
- GPIO_Config(GPIOB, &gpioConfigStruct);
- /** Config I2C1 */
- I2C_Reset(I2C1);
- i2cConfigStruct.mode = I2C_MODE_I2C;
- i2cConfigStruct.dutyCycle = I2C_DUTYCYCLE_2;
- i2cConfigStruct.ackAddress = I2C_ACK_ADDRESS_7BIT;
- i2cConfigStruct.ownAddress1 = 0X4f;
- i2cConfigStruct.ack = I2C_ACK_ENABLE;
- i2cConfigStruct.clockSpeed = 400000;
- I2C_Config(I2C1,&i2cConfigStruct);
- /** NVIC coniguration */
- // NVIC_EnableIRQRequest(I2C1_EV_IRQn,1,0);
- /** Enable the I2C1 Interrupt */
- // I2C_EnableInterrupt(I2C1,I2C_INT_EVT);
- /** Enable I2Cx */
- I2C_Enable(I2C1);
- // I2C_ClearIntFlag(I2C1,);
- }
- //void I2C_Start(I2C_T* i2c, uint8_t address, uint8_t direction){
- //}
- void I2C_EE_BufferRead(I2C_T* i2c,uint8_t* pBuffer,uint8_t DeviceAddr, uint16_t ReadAddr, uint32_t NumByteToRead){
- uint8_t trans[2];
- trans[0]=ReadAddr>>8;
- trans[1]=ReadAddr;
- while (I2C_ReadStatusFlag(i2c,I2C_FLAG_BUSBSY));
- //产生起始信号
- I2C_EnableGenerateStart(i2c);
- //检测并清除EV5
- while(!I2C_ReadEventStatus(i2c,I2C_EVENT_MASTER_MODE_SELECT));
- //发送从设备地址
- I2C_Tx7BitAddress(i2c,DeviceAddr,I2C_DIRECTION_TX);
- //检测并清除EV6
- while(!I2C_ReadEventStatus(i2c,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){}
- /*AT24C256-从设备内部地址是16bit-分两次写入*/
- I2C_TxData(i2c, trans[0]);
- //检测并清除EV8
- while(!I2C_ReadEventStatus(i2c,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
- I2C_TxData(i2c, trans[1]);
- //检测并清除EV8
- while(!I2C_ReadEventStatus(i2c,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
- //第二次Start信号
- I2C_EnableGenerateStart(i2c);
- //检测并清除EV5
- while(!I2C_ReadEventStatus(i2c,I2C_EVENT_MASTER_MODE_SELECT));
- //发送从设备地址
- I2C_Tx7BitAddress(i2c,DeviceAddr,I2C_DIRECTION_RX);
- //检测并清除EV6
- while(!I2C_ReadEventStatus(i2c,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){}
- while(NumByteToRead){
- //读到最后一个数据时,发送非应答信号,结束传输
- if(NumByteToRead==1){
- //disable ACK
- I2C_DisableAcknowledge(i2c);
- //发送STOP信号
- I2C_EnableGenerateStop(i2c);
- }
- while(I2C_ReadEventStatus(i2c,I2C_EVENT_MASTER_BYTE_RECEIVED)==0){}
- *pBuffer = I2C_RxData(i2c);
- pBuffer++;
- NumByteToRead--;
- }
- I2C_EnableAcknowledge(i2c);
- }
- void I2C_EE_BufferWrite(I2C_T* i2c,uint8_t* pBuffer,uint8_t DeviceAddr, uint16_t WriteAddr, uint32_t NumByteToWrite){
- uint8_t trans[2];
- trans[0]=WriteAddr>>8;
- trans[1]=WriteAddr;
- while (I2C_ReadStatusFlag(i2c,I2C_FLAG_BUSBSY));
- //产生起始信号
- I2C_EnableGenerateStart(i2c);
- //检测并清除EV5
- while(!I2C_ReadEventStatus(i2c,I2C_EVENT_MASTER_MODE_SELECT));
- //发送从设备地址
- I2C_Tx7BitAddress(i2c,DeviceAddr,I2C_DIRECTION_TX);
- //检测并清除EV6
- while(!I2C_ReadEventStatus(i2c,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){}
- /*AT24C256-从设备内部地址是16bit-分两次写入*/
- I2C_TxData(i2c, trans[0]);
- //检测并清除EV8
- while(!I2C_ReadEventStatus(i2c,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
- I2C_TxData(i2c, trans[1]);
- //检测并清除EV8
- while(!I2C_ReadEventStatus(i2c,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
- while(NumByteToWrite--){
- I2C_TxData(i2c,*pBuffer);
- pBuffer++;
- //检测并清除EV8
- while(!I2C_ReadEventStatus(i2c,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
- }
- I2C_EnableGenerateStop(i2c);
- }
- /*跨页写入数据*/
- void I2C_BufferWritePage(I2C_T* i2c,uint8_t DeviceAddr,uint16_t WriteAddr,uint8_t *pBuffer,uint32_t lenth)
- {
- uint32_t page_remain = 64-WriteAddr%64; //算出开始写入数据的某一页的剩余未写字节数
- if(page_remain>=lenth) //该页剩余的空间足够写入这些数据时
- {
- page_remain=lenth; //把写入长度赋值
- }
- while(1)
- {
- rt_thread_mdelay(7);/*写完一页需要加个7ms左右延时,否者I2C容易卡死*/
- I2C_EE_BufferWrite(i2c,pBuffer,DeviceAddr,WriteAddr,page_remain);
- if(page_remain==lenth) break; //判断是否写完,如果剩余的空间足够写入这些数据,就执行一次上面的函数,如果不够则进行下面的语句。
- WriteAddr+=page_remain; //如果不相等说明len比page_remain大,则地址偏移已经写入的长度
- pBuffer+=page_remain; //数据偏移
- lenth-=page_remain; //总长度减去已经写入的长度
- if(lenth<64) //判断剩余长度是否够写一整页,不够就赋值实际剩余长度,够就赋值64
- {
- page_remain=lenth;
- }
- else
- {
- page_remain=64;
- }
- }
- }
- void EEprom_Test(void){
- u8 i=0;
- uint8_t Wdata[255];
- u8 Rdata[255];
- /**eeprom*/
- for( i = 0; i < 255; i++){
- Wdata[i] = (i);
- }
- /*AT24C256 每页64字节 不可跨页操作,写入数据超过64字节需要做判断 -总共256K 分成512页*/
- I2C_BufferWritePage(I2C1,SLAVE_ADDR,0x0000,Wdata,255);/*跨页操作*/
- rt_thread_mdelay(7);
- I2C_EE_BufferRead(I2C1,Rdata,SLAVE_ADDR,0x0020,255);/*从 AT24C256 读数据没有跨页限制 */
- }