历史上的今天
返回首页

历史上的今天

今天是:2025年04月02日(星期三)

正在发生

2019年04月02日 | stm32F103模拟I2C读写24c02

2019-04-02 来源:eefocus

/*********文件名:i2c_ee.h**********/


/* Define to prevent recursive inclusion ------------------------------------ */

#ifndef __I2C_EE_H

#define __I2C_EE_H


/* Includes ------------------------------------------------------------------*/

#include "stm32f10x.h"


/* Exported macro ------------------------------------------------------------*/

#define ADDR_24CXX        0xA0


#define SCLH         GPIOB->BSRR = GPIO_Pin_6

#define SCLL         GPIOB->BRR  = GPIO_Pin_6 

   

#define SDAH         GPIOB->BSRR = GPIO_Pin_7

#define SDAL         GPIOB->BRR  = GPIO_Pin_7


#define SCLread      GPIOB->IDR  & GPIO_Pin_6

#define SDAread      GPIOB->IDR  & GPIO_Pin_7


 


/* Exported functions ------------------------------------------------------- */

void I2C_EE_Init(void);

uint8_t I2C_EE_BufferWrite(uint8_t *psrc_data,uint8_t adr,uint8_t nbyte);

uint8_t I2C_EE_BufferRead(uint8_t *pdin_data,uint8_t adr,uint8_t nbyte);



#endif /* __I2C_EE_H */


//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////


/*********文件名:i2c_ee.c**********/


#include "i2c_ee.h"


enum ENUM_TWI_REPLY

{

TWI_NACK=0

,TWI_ACK=1

};


enum ENUM_TWI_BUS_STATE

{

TWI_READY=0

,TWI_BUS_BUSY=1

,TWI_BUS_ERROR=2

};



void I2C_EE_Init(void)

{

  GPIO_InitTypeDef  GPIO_InitStructure; 

  

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

  

  // Configure I2C1 pins: 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_Out_OD;  

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  

}



void TWI_delay(void)

   uint8_t i=10; //i=10延时1.5us//这里可以优化速度 ,经测试最低到5还能写入

   while(i--); 

   

}

/**************************************************************************

延时

ms:延时的毫秒数

CYCLECOUNTER / 72000000 

***************************************************************************/

void DelayMs(uint16_t ms)

{

 uint16_t iq0;

        uint16_t iq1;

 for(iq0 = ms; iq0 > 0; iq0--)

 {

  for(iq1 = 11998; iq1 > 0; iq1--); // ( (6*iq1+9)*iq0+15 ) / 72000000 

  

 }

}


uint8_t TWI_Start(void)

{

 SDAH;

 SCLH;

 TWI_delay();

 if(!SDAread)return TWI_BUS_BUSY; //SDA线为低电平则总线忙,退出

 SDAL;

 TWI_delay();

 if(SDAread) return TWI_BUS_ERROR; //SDA线为高电平则总线出错,退出

 SCLL;

 TWI_delay();

 return TWI_READY;

}


/*void TWI_Stop(void)

{

 SCLL;

 TWI_delay();

 SDAL;

 TWI_delay();

 SCLH;

 TWI_delay();

 SDAH;

 TWI_delay();

}*/

void TWI_Stop(void)

{

 SDAL;

 SCLL;

 TWI_delay();

 SCLH;

 TWI_delay();

 SDAH;

 TWI_delay();

}


void TWI_Ack(void)

 SCLL;

 TWI_delay();

 SDAL;

 TWI_delay();

 SCLH;

 TWI_delay();

 SCLL;

 TWI_delay();

}


void TWI_NoAck(void)

 SCLL;

 TWI_delay();

 SDAH;

 TWI_delay();

 SCLH;

 TWI_delay();

 SCLL;

 TWI_delay();

}


uint8_t TWI_WaitAck(void)   //返回为:=1有ACK,=0无ACK

{

 SCLL;

 TWI_delay();

 SDAH;   

 TWI_delay();

 SCLH;

 TWI_delay();

 if(SDAread)

 {

          SCLL;

          return 0;

 }

 SCLL;

 return 1;

}


void TWI_SendByte(uint8_t SendByte) //数据从高位到低位//

{

    uint8_t i=8;

    while(i--)

    {

        SCLL;

        TWI_delay();

        if(SendByte&0x80)

          SDAH;  

        else 

        SDAL;   

        SendByte<<=1;

        TWI_delay();

        SCLH;

        TWI_delay();

    }

    SCLL;

}



uint8_t TWI_ReceiveByte(void)  //数据从高位到低位//

    uint8_t i=8;

    uint8_t ReceiveByte=0;


    SDAH;    

    while(i--)

    {

      ReceiveByte <<= 1;      

      SCLL;

      TWI_delay();

      SCLH;

      TWI_delay(); 

      if(SDAread)

      {

        ReceiveByte |= 0x01;

      }

    }

    SCLL;

    return ReceiveByte;

}


//返回:3写入成功;0写器件地址出错,1总线忙,2出错

//写入1字节数据           SendByte:待写入数据    WriteAddress:待写入地址 

uint8_t TWI_WriteByte(uint8_t SendByte, uint8_t WriteAddress)

{  

    uint8_t i;

 uint16_t j;

 i = TWI_Start();

    if(i)

   return i;

     

    TWI_SendByte( ADDR_24CXX & 0xFE);//写器件地址  写入:地址最低位是0,读取:地址最低位是1

    

 if(!TWI_WaitAck())

 {

   TWI_Stop(); 

   return 0;

 }

 

    TWI_SendByte(WriteAddress);   //设置起始地址      

    TWI_WaitAck(); 

    TWI_SendByte(SendByte);           //写数据

    TWI_WaitAck();   

    TWI_Stop(); 

 //注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)

    DelayMs(12); //写入延时 12ms  写周期大于10ms即可

    return 3;

}


 


 


//返回:0写器件地址出错,1总线忙,2出错,

//读出1字节数据

//ReadAddress:待读出地址 

uint8_t TWI_ReadByte( uint8_t ReadAddress)

{  

    uint8_t i,temp;

    i = TWI_Start();

    if(i)

   return i;

     

    TWI_SendByte((ADDR_24CXX & 0xFE));//写器件地址,先执行一次伪写操作 

    if(!TWI_WaitAck())

 {

   TWI_Stop(); 

   return 0;

 }


    TWI_SendByte(ReadAddress);   //设置起始地址      

    TWI_WaitAck();

    TWI_Start();

    TWI_SendByte((ADDR_24CXX & 0xFE)|0x01);    //读器件地址    写入:地址最低位是0,读取:地址最低位是1

    TWI_WaitAck();

   

    //*pDat = TWI_ReceiveByte();

    temp = TWI_ReceiveByte();

    

    TWI_NoAck();

     

    TWI_Stop();

    return temp;//返回的如果是0,1,2则与错误代码相同了,再考虑一下

}


/***************************************************************************

向24c256中写多个字节

psrc_data:指向要写入数据数组的指针

adr:24c256中要写入数据的首地址

nbyte:写入的字节数

返回值:  0:执行完毕;1:执行出现错误

形参中:C02只有一个地址adr;C256中有高位地址hadr和低位地址ladr

***************************************************************************/

uint8_t I2C_EE_BufferWrite(uint8_t *psrc_data,uint8_t adr,uint8_t nbyte)

{

   uint8_t i;

  

 for(;nbyte!=0;nbyte--)

 {

  i = TWI_Start();

        if(i)

     return i;

         

        TWI_SendByte( ADDR_24CXX & 0xFE);//写器件地址 

    

     if(!TWI_WaitAck())

     {

       TWI_Stop(); 

       return 0;

     }

 

        TWI_SendByte(adr);   //设置起始地址      

        TWI_WaitAck(); 

        TWI_SendByte(*psrc_data);           //写数据

        TWI_WaitAck();   

        psrc_data++;    //指向待写数据的指针加1

  adr++;    //对24C08的操作地址加1 

        TWI_Stop(); 

  //注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)

        DelayMs(12); //写入延时 12ms  写周期大于10ms即可

        

 }

 return 0;

}



/***************************************************************************

从24c02读多个字节

pdin_data:指向要保存读出数据的数组的指针

adr:24c02中要读出数据的首地址

nbyte:读出的字节数

返回值:  0:执行完毕;1:执行出现错误

***************************************************************************/

uint8_t I2C_EE_BufferRead(uint8_t *pdin_data,uint8_t adr,uint8_t nbyte)

{

 uint8_t i;

    i = TWI_Start();

    if(i)

   return i;

     

    TWI_SendByte((ADDR_24CXX & 0xFE));//写器件地址,先执行一次伪写操作 

    if(!TWI_WaitAck())

 {

   TWI_Stop(); 

   return 0;

 }


 TWI_SendByte(adr);   //设置起始地址      

    TWI_WaitAck();

    TWI_Start();

    TWI_SendByte((ADDR_24CXX & 0xFE)|0x01);    //读器件地址    写入:地址最低位是0,读取:地址最低位是1

    TWI_WaitAck();


 while(nbyte!=1)                 //读入前(nbyte-1)个字节

 {

  *pdin_data = TWI_ReceiveByte(); //循环从24C02中读数据,存入pdin_data所指的存储器中

  TWI_Ack();   //IIC应答

  pdin_data++;  //指向存储读入数据的存储器指针加1

  nbyte--;  //剩余要读入的字节减1

 };


 *pdin_data = TWI_ReceiveByte();  //读入最后一个字节

 TWI_NoAck();      //IIC无应答操作

     

    TWI_Stop();   

 

 return 0;

}


/*

void TWI_24CXX_Write(uint8_t* pDat, uint8_t nAddr, uint8_t nLen)

{

  uint16_t i;

  for(i=0;i

  {

    TWI_WriteByte(*(pDat+i), nAddr+i);

    

   

  }

}


void TWI_24CXX_Read(uint8_t* pDat, uint8_t nAddr, uint8_t nLen)

{

    uint16_t i;

    for(i=0; i

      *(pDat+i) = TWI_ReadByte(nAddr+i);

}

*/


推荐阅读

史海拾趣

Autotrol公司的发展小趣事

Autotrol公司成立于1964年,最初是一家领先的可定制小功率齿轮马达生产商。在初创时期,公司面临着激烈的市场竞争和技术挑战。然而,Autotrol凭借其卓越的技术实力和创新能力,成功开发出一系列具有竞争力的齿轮马达产品,逐渐在市场中脱颖而出。公司不断完善产品线,推出了永久磁铁同步电动机、滞后电动机和直流齿轮马达等,这些产品以其高效、稳定的性能赢得了客户的信赖。

Cypress(赛普拉斯)公司的发展小趣事

随着公司业务的不断发展,Cypress开始在全球范围内拓展市场。公司不仅在加州硅谷设立了最早的设计中心,还在美国的其他州以及英格兰、爱尔兰、菲律宾等地设立了设计工厂。此外,Cypress还在菲律宾和印尼设立了组装、检测工厂,形成了全球化的生产网络。这些举措不仅提高了公司的生产效率和产品质量,也进一步巩固了Cypress在全球电子芯片市场的地位。

Dielectric Laboratories公司的发展小趣事

随着电子行业的不断发展,市场对电子元件的需求也在不断变化。为了适应这一变化,DLI不断调整产品战略,推出了更多符合市场需求的新产品。例如,针对商业和工业领域的需求,DLI研发了具有高性能、高可靠性特点的MLCC产品,并成功打开了市场。此外,公司还不断加大研发投入,探索新的技术领域,以保持其在行业中的领先地位。

AAC [American Accurate Components]公司的发展小趣事

近年来,AAC公司一直致力于技术创新和产品研发。在声学、光学、触感、传感器及半导体等领域,AAC积累了近三十年的技术经验。这些技术积累使得AAC能够不断推出具有创新性和竞争力的新产品。例如,AAC在某次创新峰会上发布了超宽频音质的Opera高低音分频方案、旗舰级体验大众化的声学触觉一体化Combo方案以及安卓触感“天花板级”的仿生振感马达等三大技术新品。这些新品的发布不仅彰显了AAC在电声元器件领域的技术实力,也为智能手机等消费电子行业注入了新的活力。

这五个故事只是AAC公司发展历程中的一部分,但它们足以展现AAC在电子行业中的不断进取和创新精神。从一个合资企业起步,到如今成为全球著名的电声元器件制造商之一,AAC凭借敏锐的市场洞察、坚定的发展决心以及持续的技术创新,在电子行业书写了自己的传奇篇章。

请注意,以上内容仅是基于参考文章的事实性描述,并未涉及对AAC公司的任何评价或判断。同时,由于我无法获取AAC公司的实时信息,因此以上内容可能与AAC公司的最新发展情况有所出入。如需了解更多关于AAC公司的最新信息,建议查阅相关新闻或访问AAC公司官方网站。

General Cable公司的发展小趣事
根据应用需求,将YN5103的数据和控制引脚连接到相应的输入或输出设备。例如,数据引脚可能连接到微控制器或其他数据源,控制引脚可能用于接收外部控制信号。
BULGIN公司的发展小趣事

BULGIN公司的历史可以追溯到1923年,当时A.F.Bulgin先生和他的同伴在英国创立了A.F.Bulgin有限公司。公司专注于无线电电子零件的制造与生产,凭借产品的优质口碑,BULGIN的品牌逐渐广为人知。随着订单的不断增加,公司迅速成长,并在二战前已经拥有了当时最先进的现代化大规模生产线。

问答坊 | AI 解惑

高频电路EMI优化

我来传个深入讲解EMI优化的文章,谢谢大家交流…

查看全部问答>

IC封装技术和图解

基本上各种封装都有了~!!…

查看全部问答>

用电阻做功率模拟

请教各位,我现在测一块散热板的散热效率,打算用铜壳线绕电阻做一个30W的发热源,电阻型号有以下几款 220Ω/5W;500Ω/8W;输入电压在60V左右,请问应该怎样排列电阻效果才好?谢谢!…

查看全部问答>

今天参加mcu day赠送的一款开发板

参加TI mcu Day时,送的开发板,据说可以当做jtag仿真器使用,双重功能!!!…

查看全部问答>

hmc5883的程序有人做过么?我的程序哪里出问题了?本人菜鸟,见笑了。

调了好几个小时了,就是不知道问题在哪里,请高手们指点。 测量先不说,就是怎么读寄存器都没弄清。 看了中文的pdf了,但是还是没搞懂,先看看我的程序吧。 程序部分(已近将无关部分删除): uchar code table[]=\"0123456789\"; //////////// ...…

查看全部问答>

有谁会用CCS5.1开发MSP430?初学者。求指导~

本人初学MSP430,对CCS5.1 软件不是很熟悉,哪位可以指导一下?或者有软件教程也好~~…

查看全部问答>

有谁用了ADS8332,求程序!

最近用到团购买回来的ADS8332,但是调试了两天没成功,求助各位!谢谢!…

查看全部问答>

NXP 的 FAE 怎么样啊?

请问坛里的大侠,最近接到一家代理的NXP FAE 的职位,不知道这行有前途不?…

查看全部问答>

谁用单片机驱动过PS2的数字小键盘?

我在网上买了一块PS2的数字小键盘,就是传统台式机键盘最右边的数字键部分。 学习了一下PS2及扫描编码相关内容,看懂了程序,但是,由于小键盘只有部分按键,有的键还是不能读取。 0—9数字键是可以输入的,小键盘的enter也能读取,但+、-、*、/ ...…

查看全部问答>

如何用2节3V的钮扣电池提供正负3.3V的电源?

各位大侠,现工作中遇到问题,要用2节3V的钮扣电池提供正负3.3V的电源,求解答…

查看全部问答>