#include "includes.h" #include "trace.h" #include "AT24C128.h" #include "stdio.h" //#include "sys.h" #include "delay.h" //#include "sys.h" /* AT24C128C organized as 256 pages of 64-bytes each AT24C512C, organized as 512 pages of 128 bytes each 不同的的EEPROM对应的页大小不一样,注意修改 */ #define PAGE_SIZE 64 OS_SEM i2c_sem; void I2C_init(void) { // OS_ERR err; GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);//使能GPIOB时钟 //解除写保护 GPIO_InitStructure.GPIO_Pin = IIC_WP_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;//2MHz GPIO_Init(IIC_WP_PORT, &GPIO_InitStructure); //解除写保护 // GPIO_ResetBits(IIC_WP_PORT,IIC_WP_PIN); //打开写保护 GPIO_SetBits(IIC_WP_PORT,IIC_WP_PIN); //IIC时钟信号位 GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_PIN); GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);//初始化 //IIC数据信号位 GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//OD GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz GPIO_SetBits(IIC_SDA_PORT,IIC_SDA_PIN); GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);//初始化 // OSSemCreate(&i2c_sem, "i2c_sem", 1, &err); } u8 iic_cmd_delay=0; /***********************iic**************************/ void delay_nop(void) { unsigned int i; for(i=0;i<50;i++) __nop(); } //产生IIC起始信号 void IIC_Start(void) { /*while(iic_cmd_delay < E_DELAY) // 距上一个命令时间太短 { R_WDT_Restart(); }*/ SDA_OUT();//sda线输出 IIC_SDA = 1; IIC_SCL = 1; delay_us(4); IIC_SDA = 0;//START:when CLK is high,DATA change form high to low delay_us(4); IIC_SCL = 0;//钳住I2C总线,准备发送或接收数据 } //产生IIC停止信号 void IIC_Stop(void) { SDA_OUT();//sda线输出 IIC_SDA = 0; IIC_SCL = 0; delay_us(4); IIC_SCL = 1; IIC_SDA = 1;//发送I2C总线结束信号 delay_us(4); iic_cmd_delay=0; } //等待应答信号到来 //返回值: // 1,接收应答失败 // 0,接收应答成功 u8 IIC_Wait_Ack(void) { u8 ucErrTime=0; SDA_IN(); //SDA设置为输入 IIC_SDA=1;delay_us(1); IIC_SCL=1;delay_us(1); while(READ_SDA) { ucErrTime++; if(ucErrTime>250) { IIC_Stop(); return 1; } } IIC_SCL=0;//时钟输出0 return 0; } //产生ACK应答 void IIC_Ack(void) { IIC_SCL = 0; SDA_OUT();//sda线输出 IIC_SDA = 0; delay_us(4); IIC_SCL = 1; delay_us(2); IIC_SCL = 0; } //不产生ACK应答 void IIC_NAck(void) { IIC_SCL = 0; SDA_OUT();//sda线输出 IIC_SDA = 1; delay_us(4); IIC_SCL = 1; delay_us(2); IIC_SCL = 0; } //IIC发送一个字节 //返回从机有无应答 //1,有应答 //0,无应答 void IIC_Send_Byte(u8 txd) { u8 t; IIC_SCL=0;//拉低时钟开始数据传输 SDA_OUT(); for(t=0;t<8;t++) { IIC_SDA=(txd&0x80)>>7; // SDA_OUT(); // if((txd&0x80)>>7) // IIC_SDA=1; // else // IIC_SDA=0; txd<<=1; delay_us(4); //对TEA5767这三个延时都是必须的 IIC_SCL=1; delay_us(2); IIC_SCL=0; delay_us(2); } } //读1个字节,ack=1时,发送ACK,ack=0,发送nACK u8 IIC_Read_Byte(u8 ack) { u8 i,receive=0; SDA_IN();//SDA设置为输入 for(i=0;i<8;i++ ) { IIC_SCL=0; delay_us(4); IIC_SCL=1; receive<<=1; if(READ_SDA)receive++; delay_us(1); } if (!ack) IIC_NAck();//发送nACK else IIC_Ack(); //发送ACK return receive; } /***********************以上为IIC驱动**************************/ /***********************iic**************************/ //在AT24CXX指定地址读出一个数据 //ReadAddr:开始读数的地址 //返回值 :读到的数据 u8 AT24CXX_ReadOneByte(u32 ReadAddr) { u8 temp; u8 addrH,addrL; addrH=ReadAddr>>8; addrL=ReadAddr&0xff; IIC_Start(); IIC_Send_Byte(0xa0); IIC_Wait_Ack(); IIC_Send_Byte(addrH); //发送高地址 IIC_Wait_Ack(); IIC_Send_Byte(addrL); //发送低地址 IIC_Wait_Ack(); IIC_Start(); IIC_Send_Byte(0xa1); //进入接收模式 IIC_Wait_Ack(); temp= IIC_Read_Byte(0); IIC_Stop();//产生一个停止条件 delay_us(4); return temp; } //在AT24CXX指定地址写入一个数据 //WriteAddr :写入数据的目的地址 //DataToWrite:要写入的数据 void AT24CXX_WriteOneByte(u32 WriteAddr,u8 DataToWrite) { u8 addrH,addrL; addrH=WriteAddr>>8; addrL=WriteAddr&0xff; IIC_Start(); IIC_Send_Byte(0xa0); IIC_Wait_Ack(); IIC_Send_Byte(addrH); //发送高地址 IIC_Wait_Ack(); IIC_Send_Byte(addrL); //发送低地址 IIC_Wait_Ack(); IIC_Send_Byte(DataToWrite); //发送字节 IIC_Wait_Ack(); IIC_Stop();//产生一个停止条件 delay_ms(10);//两次写操作,必须加间隔,否则写不进去 } //在AT24CXX里面的指定地址开始读出指定个数的数据 //ReadAddr :开始读出的地址 对24c02为0~255 //pBuffer :数据数组首地址 //NumToRead:要读出数据的个数 void AT24CXX_Read(u32 ReadAddr,u8 *pBuffer,u16 NumToRead) { u8 addrH,addrL; u16 lentmp,lentow,lens; u8 tmp; OS_ERR err; CPU_SR_ALLOC(); if(NumToRead==0) return; OS_CRITICAL_ENTER(); OSSemPend(&i2c_sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err); I2C_init(); delay_ms(100);//两次写操作,必须加间隔,否则写不进去 IWDG_ReloadCounter(); lentmp=NumToRead; while(lentmp) { tmp=ReadAddr%PAGE_SIZE; tmp=PAGE_SIZE-tmp; if(tmp>=lentmp)//当页剩余空间大于要写入的长度 { lentow=lentmp; } else { lentow=tmp;//写入长度只能是剩余空间长度 } lentmp=lentmp-lentow;//计算要在下一页写入的长度 lens=lentow; addrH=ReadAddr>>8; addrL=ReadAddr&0xff; IIC_Start(); IIC_Send_Byte(0xa0);//写 IIC_Wait_Ack(); IIC_Send_Byte(addrH); //发送高地址 IIC_Wait_Ack(); IIC_Send_Byte(addrL); //发送低地址 IIC_Wait_Ack(); delay_us(4); IIC_Start(); IIC_Send_Byte(0xa1); //读 //进入接收模式 IIC_Wait_Ack(); while(lentow) { *pBuffer=IIC_Read_Byte(1); pBuffer++; //ReadAddr++; lentow--; } IIC_Read_Byte(0); IIC_Stop();//产生一个停止条件 delay_us(4); //printf("at24 read %d %d\r\n", ReadAddr, lens); ReadAddr=ReadAddr+lens;//下一页的地址 } GPIO_SetBits(IIC_WP_PORT,IIC_WP_PIN); OSSemPost(&i2c_sem, OS_OPT_POST_ALL, &err); OS_CRITICAL_EXIT(); } //在AT24CXX里面的指定地址开始写入指定个数的数据 //WriteAddr :开始写入的地址 对24c02为0~255 //pBuffer :数据数组首地址 //NumToWrite:要写入数据的个数 // 每128bytes为一个page,写操作不能跨页 void AT24CXX_Write(u32 WriteAddr,u8 *pBuffer,u16 NumToWrite) { u8 addrH,addrL; u16 lentmp,lentow,lens; u8 tmp; OS_ERR err; CPU_SR_ALLOC(); if(NumToWrite==0) return; OS_CRITICAL_ENTER(); OSSemPend(&i2c_sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err); I2C_init(); IIC_WRITE_PROTECT_OFF(); delay_ms(10);//两次写操作,必须加间隔,否则写不进去 IWDG_ReloadCounter(); lentmp=NumToWrite; while(lentmp) { tmp=WriteAddr%PAGE_SIZE; tmp=PAGE_SIZE-tmp; if(tmp>=lentmp)//当页剩余空间大于要写入的长度 { lentow=lentmp; } else { lentow=tmp;//写入长度只能是剩余空间长度 } lentmp=lentmp-lentow;//计算要在下一页写入的长度 lens=lentow; addrH=WriteAddr>>8; addrL=WriteAddr&0xff; IIC_Start(); IIC_Send_Byte(0xa0); IIC_Wait_Ack(); IIC_Send_Byte(addrH); //发送高地址 IIC_Wait_Ack(); IIC_Send_Byte(addrL); //发送低地址 IIC_Wait_Ack(); while(lentow--) { IIC_Send_Byte(*pBuffer); IIC_Wait_Ack(); pBuffer++; } IIC_Stop();//产生一个停止条件 delay_ms(10); //printf("at24 write %d %d %d, %d\r\n", WriteAddr, lens, addrH, addrL); WriteAddr=WriteAddr+lens;//下一页的地址 } delay_ms(10);//两次写操作,必须加间隔,否则写不进去 IIC_WRITE_PROTECT_ON(); OSSemPost(&i2c_sem, OS_OPT_POST_ALL, &err); OS_CRITICAL_EXIT(); } void AT24CXX_clr(u32 WriteAddr,u32 NumToWrite) { u8 addrH,addrL; u16 lentmp,lentow,lens; u8 tmp; lentmp=NumToWrite; while(lentmp) { tmp=WriteAddr%PAGE_SIZE; tmp=PAGE_SIZE-tmp; if(tmp>=lentmp) { lentow=lentmp; } else { lentow=tmp; } lentmp=lentmp-lentow; lens=lentow; addrH=WriteAddr>>8; addrL=WriteAddr&0xff; IIC_Start(); IIC_Send_Byte(0xa0); IIC_Wait_Ack(); IIC_Send_Byte(addrH); //发送高地址 IIC_Wait_Ack(); IIC_Send_Byte(addrL); //发送低地址 IIC_Wait_Ack(); while(lentow--) { IIC_Send_Byte(0xff); IIC_Wait_Ack(); } IIC_Stop();//产生一个停止条件 delay_ms(10); WriteAddr=WriteAddr+lens; } delay_ms(10); } //----------------------EEPROM---------------------------// //--------------------------------------------------------EEPROM DATA /*********************************************END OF FILE**********************/ #define I2C_DATA_LEN 256 u8 I2c_Buf_Write[I2C_DATA_LEN], I2c_Buf_Read[I2C_DATA_LEN]; /** * @brief I2C(AT24C02)读写测试 * @param 无 * @retval 正常返回 1 ,不正常返回 0 */ uint8_t I2C_Test(void) { u16 i; I2C_init(); EEPROM_INFO("\r\nI2C(AT24C128)字节读写测试\r\n"); memset(I2c_Buf_Write, 0, I2C_DATA_LEN); memset(I2c_Buf_Read, 0, I2C_DATA_LEN); for ( i=0; i< I2C_DATA_LEN; i++ ) //填充缓冲 { I2c_Buf_Write[i] = i; AT24CXX_WriteOneByte(i, i); I2c_Buf_Read[i] = AT24CXX_ReadOneByte(i); } data_dump("I2C Write", I2c_Buf_Write, I2C_DATA_LEN); data_dump("I2C Read", I2c_Buf_Read, I2C_DATA_LEN); EEPROM_INFO("\r\nI2C(AT24C128)连续地址读写测试\r\n"); memset(I2c_Buf_Write, 0, I2C_DATA_LEN); memset(I2c_Buf_Read, 0, I2C_DATA_LEN); for ( i=0; i< I2C_DATA_LEN; i++ ) //填充缓冲 { I2c_Buf_Write[i] = i+100; } AT24CXX_clr(I2C_DATA_LEN, I2C_DATA_LEN); AT24CXX_Read(I2C_DATA_LEN, I2c_Buf_Read, I2C_DATA_LEN); data_dump("I2C Read", I2c_Buf_Read, I2C_DATA_LEN); AT24CXX_Write(I2C_DATA_LEN, I2c_Buf_Write, I2C_DATA_LEN); AT24CXX_Read(I2C_DATA_LEN, I2c_Buf_Read, I2C_DATA_LEN); data_dump("I2C Write", I2c_Buf_Write, I2C_DATA_LEN); data_dump("I2C Read", I2c_Buf_Read, I2C_DATA_LEN); EEPROM_INFO("\r\nI2C(AT24C128)读写测试成功\r\n"); return 1; } void Tmp75_read(u8 *pBuffer) { u16 lentow;//lentmp,,lens; lentow = 2; IIC_Start(); IIC_Send_Byte(0x90);//写 IIC_Wait_Ack(); IIC_Send_Byte(0x00); //发送寄存器地址 IIC_Wait_Ack(); delay_us(4); IIC_Start(); IIC_Send_Byte(0x91); //读 //进入接收模式 IIC_Wait_Ack(); while(lentow) { *pBuffer=IIC_Read_Byte(1); pBuffer++; //ReadAddr++; lentow--; } IIC_Stop();//产生一个停止条件 } float Temp_test(void) { float temp_data,tmp; u8 Temp_buf[4]; I2C_init(); Tmp75_read(Temp_buf); //data_dump("temp Read", Temp_buf, 2); tmp = (float)(Temp_buf[1]>>4); tmp /= 16.0; temp_data = (float)Temp_buf[0] + tmp; // printf("\ntmp: "); // printf("%.4f ℃\n",temp_data); return temp_data; }