<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > STM32 I2C AT24C02驅(qū)動(dòng)

          STM32 I2C AT24C02驅(qū)動(dòng)

          作者: 時(shí)間:2016-11-25 來(lái)源:網(wǎng)絡(luò) 收藏
          如果搞過(guò)51的I2C的同志,再來(lái)看看STM32的I2C驅(qū)動(dòng),一定有相見(jiàn)恨晚的感覺(jué)。STM32自帶I2C硬件模塊,再配合ST的官方庫(kù)函數(shù),I2C在STM32這里可以玩得如火的地步。這里的這個(gè)I2C驅(qū)動(dòng)算是很完整了的,可以直接拿來(lái)用到項(xiàng)目開(kāi)發(fā)中去。好,不廢話,上圖:

          工程結(jié)構(gòu)圖:

          本文引用地址:http://www.ex-cimer.com/article/201611/321301.htm

          1、main.c

          #include"stm32f10x.h"
          #include"usart1.h"
          #include"led.h"
          #include"i2c_at24c02.h"
          #include



          struct Contact{
          u8 Name[15]; //姓名
          u8 Phone[11];//電話
          u8 BirthDay[10];//生日
          }WgchnlnContact[3],NewContact;
          struct Contact WgchnlnContact[3]={
          {
          "wgchnln",
          "18682101373",
          "1987-02-19",
          },
          {
          "hezepan",
          "18528473728",
          "1987-10-28",
          },
          {
          "lixiaowei",
          "13527492729",
          "1988-12-02",
          }};


          #ifdef Test

          void I2C_Test(void)
          {
          u16 i;
          u8 I2c_Buf[256];

          printf("寫入的數(shù)據(jù)");

          //填充緩沖
          for(i=0;i<=255;i++)
          {
          I2c_Buf[i]=i;
          printf("0x%x ",I2c_Buf[i]);
          if(i == 9)
          {
          printf("");
          }
          }
          printf("");

          I2C_AT24Cx_Writes(0,I2c_Buf,256);//將I2C_Buf中順序遞增的數(shù)據(jù)寫入EERPOM中


          //清緩沖
          for(i=0;i<=255;i++)
          {
          I2c_Buf[i]=0;
          }

          printf("讀出的數(shù)據(jù)");
          I2C_AT24Cx_Reads(0,I2c_Buf,256);//將EEPROM讀出數(shù)據(jù)順序保持到I2C_Buf中

          //將I2C_Buf中的數(shù)據(jù)通過(guò)串口打印
          for(i=0;i<256;i++)
          {
          if(I2c_Buf[i]!=i)
          {
          printf("錯(cuò)誤:I2C EEPROM寫入與讀出的數(shù)據(jù)不一致");
          while(1);
          }
          printf("0x%X ", I2c_Buf[i]);
          if(i == 9)
          {
          printf("");
          }
          }
          }
          #endif

          int main(void)
          {
          u8 ReadBuffer[36];
          u8 i=0;
          u8 j=0;
          USART_Config(); //串口1初始化
          printf("這是一個(gè)I2C-EEPROM-AT24C02演示實(shí)驗(yàn)");

          //Led_Init(); //LED初始化

          I2C_AT24Cx_Init(); //I2C初始化

          #ifdef Test
          I2C_Test();
          #endif


          printf("寫入聯(lián)系人");
          for(j=0;j<3;j++)
          {
          I2C_AT24Cx_Writes(0+j*36,WgchnlnContact[j].Name,15);
          I2C_AT24Cx_Writes(15+j*36,WgchnlnContact[j].Phone,11);
          I2C_AT24Cx_Writes(26+j*36,WgchnlnContact[j].BirthDay,10);
          }
          j=0;

          printf("讀出聯(lián)系人");
          for(j=0;j<3;j++)
          {
          I2C_AT24Cx_Reads(j*36,ReadBuffer,36);

          for(i=0;i<15;i++)
          {
          NewContact.Name[i]=ReadBuffer[i];
          }
          i=0;
          printf("姓名:%s",NewContact.Name);

          for(i=0;i<11;i++)
          {
          NewContact.Phone[i]=ReadBuffer[i+15];
          }
          i=0;
          printf("電話:%s",NewContact.Phone);//為什么打印第二個(gè)聯(lián)系人的號(hào)碼電話會(huì)把第一個(gè)聯(lián)系人的生日一同打印出來(lái)

          for(i=0;i<10;i++)
          {
          NewContact.BirthDay[i]=ReadBuffer[i+26];
          }
          i=0;
          printf("生日:%s",NewContact.BirthDay);

          }
          while(1);
          }

          2、今天的主角:i2c_at24c02.c

          #include"stm32f10x.h"
          #include"i2c_at24c02.h"


          #define AT24Cx_Address 0xa0 //I2C芯片地址 EEPROM
          #define AT24Cx_PageSize 8 //芯片內(nèi)部一頁(yè)容量


          static void I2C_ATC24x_GPIO_Config(void)
          {
          GPIO_InitTypeDef GPIO_InitStructure;

          RCC_APB2PeriphClockCmd(I2C_SCL_GPIO_RCC,ENABLE); //沒(méi)有外部中斷,沒(méi)有重映射,所以不需要開(kāi)啟復(fù)用功能


          GPIO_InitStructure.GPIO_Pin =I2C_SCL_Pin|I2C_SDA_Pin;
          GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_OD; //設(shè)置管腳為復(fù)用功能開(kāi)漏輸出 SDA是輸入輸出引腳

          GPIO_Init(I2C_SCL_GPIO, &GPIO_InitStructure);
          }



          static void I2C_Config(void)
          {
          I2C_InitTypeDef I2C_InitStructure;


          RCC_APB1PeriphClockCmd(I2C_RCC,ENABLE);


          I2C_DeInit(I2C);

          I2C_InitStructure.I2C_ClockSpeed =100000; //100KHz I2C時(shí)鐘頻率
          I2C_InitStructure.I2C_Mode =I2C_Mode_I2C; //I2C模式
          I2C_InitStructure.I2C_DutyCycle =I2C_DutyCycle_2; //時(shí)鐘占空比
          I2C_InitStructure.I2C_OwnAddress1 =0x30; //主機(jī)地址 可以任意的
          I2C_InitStructure.I2C_Ack =I2C_Ack_Enable; //開(kāi)啟ACK應(yīng)答響應(yīng)
          I2C_InitStructure.I2C_AcknowledgedAddress =I2C_AcknowledgedAddress_7bit;//7位地址模式 非10為地址模式


          I2C_Init(I2C,&I2C_InitStructure);


          I2C_Cmd(I2C,ENABLE);


          I2C_AcknowledgeConfig(I2C,ENABLE);
          }



          void I2C_AT24Cx_Init(void)
          {
          I2C_ATC24x_GPIO_Config();

          I2C_Config();
          }


          void I2C_AT24Cx_Reads(u8 Address,u8 *ReadBuffer,u16 ReadNumber)
          {
          if(ReadNumber==0) //沒(méi)有需要讀取的數(shù)據(jù)
          return;


          while(I2C_GetFlagStatus(I2C,I2C_FLAG_BUSY));


          I2C_AcknowledgeConfig(I2C, ENABLE);


          I2C_GenerateSTART(I2C,ENABLE);
          while(!I2C_CheckEvent(I2C,I2C_EVENT_MASTER_MODE_SELECT)); //檢查是不是主模式與起始位已經(jīng)發(fā)送 備注:這樣做的目的就是為了清空該事件


          I2C_Send7bitAddress(I2C,AT24Cx_Address, I2C_Direction_Transmitter);
          while (!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//檢查數(shù)據(jù)是不是已經(jīng)發(fā)送地址完成


          I2C_SendData(I2C, Address);
          while (!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //檢查數(shù)據(jù)是不是已經(jīng)發(fā)送完成

          //需要讀取數(shù)據(jù),這個(gè)時(shí)候需要變換數(shù)據(jù)傳輸方向,就要主機(jī)重新發(fā)送起始位
          I2C_GenerateSTART(I2C, ENABLE);
          while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_MODE_SELECT));


          I2C_Send7bitAddress(I2C,AT24Cx_Address, I2C_Direction_Receiver); //再一次發(fā)送EEPROM地址
          while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));


          while(ReadNumber)
          {

          if(ReadNumber==1)
          {
          I2C_AcknowledgeConfig(I2C, DISABLE);//關(guān)閉應(yīng)答
          I2C_GenerateSTOP(I2C,ENABLE);//使能停止功能
          }

          while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)); //檢查是不是接受到了數(shù)據(jù)
          *ReadBuffer=I2C_ReceiveData(I2C);
          ReadBuffer++;
          ReadNumber--;
          }
          I2C_AcknowledgeConfig(I2C, ENABLE);//允許應(yīng)答模式
          }



          static void I2C_AT24Cx_WaitForComplete(void)
          {
          vu16 SR1_Tmp;
          do
          {

          I2C_GenerateSTART(I2C1, ENABLE); //一旦發(fā)送起始位,主機(jī)等待讀取SR1,然后發(fā)送地址

          SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1); //也是為了清除該事件

          I2C_Send7bitAddress(I2C1,AT24Cx_Address, I2C_Direction_Transmitter);
          }while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002)); //直到地址發(fā)送完成


          I2C_ClearFlag(I2C, I2C_FLAG_AF); //前面如果出現(xiàn)過(guò)忙碌 就會(huì)出現(xiàn)應(yīng)答錯(cuò)誤現(xiàn)象

          I2C_GenerateSTOP(I2C, ENABLE);
          }



          void I2C_AT24Cx_WriteByte(u8 Address,u8 WriteData)
          {

          I2C_GenerateSTART(I2C, ENABLE);
          while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_MODE_SELECT));


          I2C_Send7bitAddress(I2C,AT24Cx_Address, I2C_Direction_Transmitter);
          while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //實(shí)際就是等待收到EEPROM的ACK應(yīng)答信號(hào)(收到ACK后,硬件會(huì)做相應(yīng)的置位)


          I2C_SendData(I2C, Address);
          while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));


          I2C_SendData(I2C, WriteData);
          while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));


          I2C_GenerateSTOP(I2C, ENABLE); //這里的設(shè)置停止為與接收時(shí)不同 這里是寫入最后一個(gè)數(shù)據(jù)之后設(shè)置停止位

          I2C_AT24Cx_WaitForComplete();
          }



          void I2C_AT24Cx_WritePage(u8 Address,u8 *WriteData,u16 WriteNumber)
          {
          while(I2C_GetFlagStatus(I2C, I2C_FLAG_BUSY));


          I2C_GenerateSTART(I2C, ENABLE);
          while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_MODE_SELECT));


          I2C_Send7bitAddress(I2C,AT24Cx_Address, I2C_Direction_Transmitter);
          while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));


          I2C_SendData(I2C,Address);
          while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

          while(WriteNumber--)
          {
          I2C_SendData(I2C,*WriteData);
          WriteData++;
          while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
          }


          I2C_GenerateSTOP(I2C, ENABLE);
          }



          void I2C_AT24Cx_Writes(u8 Address,u8 *WriteData,u16 WriteNumber)
          {
          u8 Temp;


          Temp=Address%AT24Cx_PageSize;
          if(Temp)//存在頁(yè)不對(duì)齊的現(xiàn)象
          {
          Temp=AT24Cx_PageSize-Temp;//求出頁(yè)不對(duì)齊的數(shù)量
          I2C_AT24Cx_WritePage(Address,WriteData,Temp);
          Address+=Temp;
          WriteData+=Temp;
          WriteNumber-=Temp;
          I2C_AT24Cx_WaitForComplete();
          }

          while(WriteNumber)
          {

          if(WriteNumber>=AT24Cx_PageSize)
          {
          I2C_AT24Cx_WritePage(Address,WriteData,AT24Cx_PageSize);
          Address+=AT24Cx_PageSize;
          WriteData+=AT24Cx_PageSize;
          WriteNumber-=AT24Cx_PageSize;
          I2C_AT24Cx_WaitForComplete();
          }

          else
          {
          I2C_AT24Cx_WritePage(Address,WriteData,WriteNumber);
          WriteNumber=0;
          I2C_AT24Cx_WaitForComplete();
          }
          }
          }

          i2c_at24c02.h


          #ifndef _I2C_AT24C02_H
          #define _I2C_AT24C02_H

          #include"stm32f10x.h"


          #define I2C I2C1
          #define I2C_RCC RCC_APB1Periph_I2C1

          #define I2C_SCL_GPIO_RCC RCC_APB2Periph_GPIOB
          #define I2C_SCL_GPIO GPIOB
          #define I2C_SCL_Pin GPIO_Pin_6

          #define I2C_SDA_GPIO_RCC RCC_APB2Periph_GPIOB
          #define I2C_SDA_GPIO GPIOB
          #define I2C_SDA_Pin GPIO_Pin_7

          void I2C_AT24Cx_Init(void); //I2C外設(shè)與AT24C02初始化

          void I2C_AT24Cx_Reads(u8 Address,u8 *ReadBuffer,u16 ReadNumber); //從AT24C02中讀取數(shù)據(jù) EEPROM

          void I2C_AT24Cx_WriteByte(u8 Address,u8 WriteData); //寫入一字節(jié)數(shù)據(jù)

          void I2C_AT24Cx_WritePage(u8 Address,u8 *WriteData,u16 WriteNumber); //寫入一頁(yè)之內(nèi)數(shù)據(jù)

          void I2C_AT24Cx_Writes(u8 Address,u8 *WriteData,u16 WriteNumber); //寫入任意數(shù)量的數(shù)據(jù) 流程:寫入也不對(duì)齊部分--寫入整頁(yè)部分(假如需要)--寫入最后不足一頁(yè)的
          #endif

          剩下的串口驅(qū)動(dòng)與LED驅(qū)動(dòng)分別見(jiàn):《STM32 串口例程之查詢收發(fā)》、《STM32 基于庫(kù)函數(shù)控制按鍵 蜂鳴器 LED顯示》完全一樣的。這里就不在重復(fù)上代碼了。

          以上,結(jié)束。



          關(guān)鍵詞: STM32I2CAT24C02驅(qū)

          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();