移植iic--24c02和fdc2214

IIC

一、用於連接CPU和外圍電路的總線,一般有兩根信號線,一根是雙向的數據線SDA,另一根是時鐘線SCL。I2C總線上允許連接多個微處理器以及各種外圍設備,爲了進行通訊,每個接到I2C總線的設備都有一個唯一的地址。

二、信號。IIC在每次傳輸完一字節後需要應答信號。

  1. 在進行通信時,主控要告訴外設開始和結束,分別對應開始和結束信號。
  2. IIC在每次傳輸完一字節後需要應答信號。
  3. 在驅動大部分外設時,傳輸一個字節數據需要SCL==1。此時SDA上的數據認爲是可信的。這也就是說如果對於信號沒有特殊的要求,這部分不需要改寫。這裏直接用的正點原子的,就是初始化和配置端口需要自己改。
    #include "myiic.h"
    #include "delay.h"
    //////////////////////////////////////////////////////////////////////////////////	 
    //本程序只供學習使用,未經作者許可,不得用於其它任何用途
    //ALIENTEK STM32F407開發板
    //IIC 驅動代碼	   
    //正點原子@ALIENTEK
    //技術論壇:www.openedv.com
    //創建日期:2014/5/6
    //版本:V1.0
    //版權所有,盜版必究。
    //Copyright(C) 廣州市星翼電子科技有限公司 2014-2024
    //All rights reserved									  
    ////////////////////////////////////////////////////////////////////////////////// 	
    
    //初始化IIC
    void IIC_Init(void)
    {			
      GPIO_InitTypeDef  GPIO_InitStructure;
    
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB時鐘
    
      //GPIOB8,B9初始化設置
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通輸出模式
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推輓輸出
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
      GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
    	IIC_SCL=1;
    	IIC_SDA=1;
    }
    //產生IIC起始信號
    void IIC_Start(void)
    {
    	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_SCL=0;
    	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
     	delay_us(4);
    	IIC_SCL=1; 
    	IIC_SDA=1;//發送I2C總線結束信號
    	delay_us(4);							   	
    }
    //等待應答信號到來
    //返回值: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();
    	IIC_SDA=0;
    	delay_us(2);
    	IIC_SCL=1;
    	delay_us(2);
    	IIC_SCL=0;
    }
    //不產生ACK應答		    
    void IIC_NAck(void)
    {
    	IIC_SCL=0;
    	SDA_OUT();
    	IIC_SDA=1;
    	delay_us(2);
    	IIC_SCL=1;
    	delay_us(2);
    	IIC_SCL=0;
    }					 				     
    //IIC發送一個字節
    //返回從機有無應答
    //1,有應答
    //0,無應答			  
    void IIC_Send_Byte(u8 txd)
    {                        
        u8 t;   
    	SDA_OUT(); 	    
        IIC_SCL=0;//拉低時鐘開始數據傳輸
        for(t=0;t<8;t++)
        {              
            IIC_SDA=(txd&0x80)>>7;
            txd<<=1; 	  
    		delay_us(2);   //對TEA5767這三個延時都是必須的
    		IIC_SCL=1;
    		delay_us(2); 
    		IIC_SCL=0;	
    		delay_us(2);
        }	 
    } 	    
    //讀1個字節,ack=1時,發送ACK,ack=0,發送nACK   
    u8 IIC_Read_Byte(unsigned char ack)
    {
    	unsigned char i,receive=0;
    	SDA_IN();//SDA設置爲輸入
        for(i=0;i<8;i++ )
    	{
            IIC_SCL=0; 
            delay_us(2);
    		IIC_SCL=1;
            receive<<=1;
            if(READ_SDA)receive++;   
    		delay_us(1); 
        }					 
        if (!ack)
            IIC_NAck();//發送nACK
        else
            IIC_Ack(); //發送ACK   
        return receive;
    }

     

三、我們有了驅動的信號,就可以做讀或者寫數據了。這是我們就要看好數據手冊了。主要是他需要的地址信息(每個外設唯一)和信號指令(讀或者寫)。

  1. 先來看24c02的首地址,A2/1/0都是地址位。                                                                                                                           當24c02的三個A管腳都置零時,如果寫數據則首地址位是1010 0000,如果讀數據也就是1010 0001。
  2. 在看fdc2214的首地址。他是這麼說的“當ADDR pin設置爲低時,FDC I2C地址爲0x2A;當ADDR pin設置爲高時,FDC I2C地址爲0x2B”。
  3. 然後我們看他們給我們讀取或寫入數據的規則。拿24c02讀數據來說:                                    他說我們需要先寫一個起始條件,然後器件地址接應答,在進入讀模式讀取8位數據,最後停止。
    //在AT24CXX指定地址讀出一個數據
    //ReadAddr:開始讀數的地址  
    //返回值  :讀到的數據
    u8 AT24CXX_ReadOneByte(u16 ReadAddr)
    {				  
    	u8 temp=0;		  	    																 
        IIC_Start();  
    	if(EE_TYPE>AT24C16)
    	{
    		IIC_Send_Byte(0XA0);	   //發送寫命令
    		IIC_Wait_Ack();
    		IIC_Send_Byte(ReadAddr>>8);//發送高地址	    
    	}else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //發送器件地址0XA0,寫數據 	   
    	IIC_Wait_Ack(); 
        IIC_Send_Byte(ReadAddr%256);   //發送低地址
    	IIC_Wait_Ack();	    
    	IIC_Start();  	 	   
    	IIC_Send_Byte(0XA1);           //進入接收模式			   
    	IIC_Wait_Ack();	 
        temp=IIC_Read_Byte(0);		   
        IIC_Stop();//產生一個停止條件	    
    	return temp;
    }

     

  4. 在看fdc2214                                                                         我們需要寫入器件地址和寄存器地址,在進行數據讀取,最後無應答和停止信號,只不過這個寄存器是16位的。我們需要讀兩次。其實和上面24c02的代碼是很像的。
    u16 FDC_Read(u8 reg)    //核心代碼    //不需修改
    {
    	u16 res;
       FDC_IIC_Start(); 
    	FDC_IIC_Send_Byte((FDC2214_ADDR<<1)|0);//發送器件地址+寫命令	
    	FDC_IIC_Wait_Ack();		//等待應答 
        FDC_IIC_Send_Byte(reg);	//寫寄存器地址
        FDC_IIC_Wait_Ack();		//等待應答
        FDC_IIC_Start();
    	FDC_IIC_Send_Byte((FDC2214_ADDR<<1)|1);//發送器件地址+讀命令	
        FDC_IIC_Wait_Ack();		//等待應答 
    	res=FDC_IIC_Read_Byte(1)<<8;//讀取數據,發送ACK
    	  
    	res|=FDC_IIC_Read_Byte(0);//讀取數據,發送nACK
        FDC_IIC_Stop();			//產生一個停止條件
    	return res;		
    }

    結束了。

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章