shaoshunda 发表于 2008-7-29 11:00:42

LPC2148 GPIO模拟I2C(源码)

#include <LPC214X.H>
#include "delay.h"

#define USE_FAST_IO

#define GPIO0M                0x00000001
#define GPIO1M                0x00000002

#define SetPortBit(port,bit)   port=port|(1<<bit)
#define ClrPortBit(port,bit)   port=port&(~(1<<bit))
#define GetPortBit(port,bit)   port&(1<<bit)

#define NACK 0
#define SACK1

#define IO_GND (unsigned int)(1<<19)//0x00080000
#define IO_SDA (unsigned int)(1<<21)//0x00200000
#define IO_SCL (unsigned int)(1<<23)//0x00800000

unsigned char f_I2C_Error=0;
//unsigned char GetBit(unsigned char DDRport,unsigned char bit)

#define                LSB(a)                                        ((unsigned char)a)
#define                MSB(a)                                        ((unsigned char)(a>>8))
//============================================================
void IicBusDelay( void )
{
//delay_us(5);
}
void ClrSCL(void)
{
        //P1.19P1.21 P1.23
#ifdef USE_FAST_IO
        FIO1DIR=FIO1DIR|(IO_SCL)|(IO_SDA)|(IO_GND);
        FIO1MASK = ~(IO_SCL);
        FIO1PIN = 0x00000000;
#else
        IO1DIR=IO1DIR|(IO_SCL)|(IO_SDA)|(IO_GND);
        IO1CLR = IO_SCL;
#endif
        IicBusDelay();
}
void ClrSDA(void)
{
        //P1.19P1.21 P1.23
#ifdef USE_FAST_IO
        FIO1DIR=FIO1DIR|(IO_SCL)|(IO_SDA)|(IO_GND);
        FIO1MASK = ~(IO_SDA);
        FIO1PIN = 0x00000000;
#else
        IO1DIR=IO1DIR|(IO_SCL)|(IO_SDA)|(IO_GND);
        IO1CLR = IO_SDA;
#endif
        IicBusDelay();
}
unsigned char GetSDA(void)
{
        unsigned int val;
        //P1.19P1.21 P1.23
#ifdef USE_FAST_IO
        FIO1DIR=FIO1DIR&(~(IO_SDA));
        FIO1DIR=FIO1DIR|(IO_SCL)|(IO_GND);
        FIO1MASK = ~(IO_SDA);
        delay_us(1);
        val=FIO1PIN;
#else
        IO1DIR=IO1DIR&(~(IO_SDA));
        IO1DIR=IO1DIR|(IO_SCL)|(IO_GND);
        delay_us(1);
        val=IO1PIN;
#endif
        val=val & IO_SDA;
        if(val)
        return 1;
        else
        return 0;
}
unsigned char GetSCL(void)
{
        unsigned int val;
        //P1.19P1.21 P1.23
#ifdef USE_FAST_IO
        FIO1DIR=FIO1DIR&(~(IO_SCL));
        FIO1DIR=FIO1DIR|(IO_SDA)|(IO_GND);
        FIO1MASK = ~(IO_SCL);
        delay_us(1);
        val=FIO1PIN;
#else
        IO1DIR=IO1DIR&(~(IO_SCL));
        IO1DIR=IO1DIR|(IO_SDA)|(IO_GND);
        delay_us(1);
        val=IO1PIN;
#endif
        val=val & IO_SCL;
        if(val)
        return 1;
        else
        return 0;
}
void SetSCL(void)
{
        unsigned char chr1;
#ifdef USE_FAST_IO
        FIO1DIR=FIO1DIR|(IO_SCL)|(IO_SDA)|(IO_GND);
        FIO1MASK = ~(IO_SCL);
        FIO1PIN = IO_SCL;
#else
        IO1DIR=IO1DIR|(IO_SCL)|(IO_SDA)|(IO_GND);
        IO1SET = IO_SCL;
#endif
    if( GetSCL() == 1 ) return ;
        for(chr1=0; chr1<255; chr1++)                        // 为避免数据传送时受IIC总线上大电容(100-1000P)的影响,以及适应某些反应速度慢的IC在做出反应前拉低SCL的做法
                if( GetSCL() == 1 ) break ;
}

void SetSDA(void)
{
        unsigned char chr1;
#ifdef USE_FAST_IO
        FIO1DIR=FIO1DIR|(IO_SCL)|(IO_SDA)|(IO_GND);
        FIO1MASK = ~(IO_SDA);
        FIO1PIN = IO_SDA;
#else
        IO1DIR=IO1DIR|(IO_SCL)|(IO_SDA)|(IO_GND);
        IO1SET = IO_SDA;
#endif
    if( GetSDA() == 1 ) return ;
        for(chr1=0; chr1<255; chr1++)                        // 为避免数据传送时受IIC总线上大电容(100-1000P)的影响,以及适应某些反应速度慢的IC在做出反应前拉低SCL的做法
                if( GetSDA() == 1 ) break ;
}

void ACK(unsigned char ack)
{
if(!ack)//非应答
    SetSDA();            
else    //应答
    ClrSDA();
IicBusDelay();
SetSCL();
IicBusDelay();
ClrSCL();                     
IicBusDelay();
}
void I2CInit(void)
{
        f_I2C_Error=0;
        PINSEL2=PINSEL2&0xfffffff7;//P1.25 -16 用作GPIO 管脚
        PINSEL2=PINSEL2|0x00000004;//P1.31 - 26 用作一个调试端口
        //P1.19P1.21 P1.23
#ifdef USE_FAST_IO
        SCS |= GPIO1M;        /* set GPIOx to use Fast I/O */
        FIO1DIR=FIO1DIR|(IO_SCL)|(IO_SDA)|(IO_GND);
        FIO1MASK = ~(IO_GND);
        FIO1PIN = 0x00000000;
#else
        IO1DIR=IO1DIR|(IO_SCL)|(IO_SDA)|(IO_GND);
        IO1CLR = IO_GND;
#endif
}

void IicStart(void)
{
        f_I2C_Error=0;
    IicBusDelay();
SetSDA();      
    IicBusDelay();
SetSCL();
    IicBusDelay();
        if( GetSDA()==0)
        {
                f_I2C_Error = 1 ;
                return ;
        }
        if( GetSCL()==0 )
        {
                f_I2C_Error = 1 ;
                return ;
        }
ClrSDA();         
    IicBusDelay();
ClrSCL();         
    IicBusDelay();
}

void IicStop( void )
{
IicBusDelay();
ClrSDA();   
IicBusDelay();
SetSCL();
IicBusDelay();
SetSDA();   
IicBusDelay();
}

void IicSendByte(unsigned char chr)
{
unsigned char i;

for(i=0;i<8;i++)
{
    if(chr&0x80)
      SetSDA();   
    else
      ClrSDA();               
    SetSCL();      
    IicBusDelay();      
    ClrSCL();
    chr<<=1;
    IicBusDelay();
}
IicBusDelay();

SetSDA();               
IicBusDelay();
SetSCL();
IicBusDelay();
if(GetSDA())
    f_I2C_Error=1;   //失败
else
    f_I2C_Error=0;      
ClrSCL();
IicBusDelay();
}

unsigned char IicReceiveByte(unsigned char ack)
{
unsigned char i,rval;

rval=0;
SetSDA();
for(i=0;i<8;i++)
{
    IicBusDelay();         
    ClrSCL();                  
    IicBusDelay();
    SetSCL();               
    IicBusDelay();
    rval<<=1;
    if(GetSDA())
      rval++;
}
ClrSCL();   
IicBusDelay();
ACK(ack);
return(rval);
}

shaoshunda 发表于 2008-7-29 11:02:32

* *备注:所有函数在12m频率以上都比较准确,注意头文件里Fclk的设置                                          
****************************************************************/

#include "delay.h"

/**********************************************************************
**函数名称:delay_s()
**函数功能:秒级延时,注意设置delay.h中的Fclk
**函数入口:t
**函数出口:无
***********************************************************************/
void delay_s(unsigned long int t)
    {
    unsigned long int i;
    unsigned long int j;
    j=Fclk*t;
    for(i = 0; i < j; i++);
    }

/**********************************************************************
**函数名称:delay_ms()
**函数功能:毫秒级延时,注意设置delay.h中的Fclk
**函数入口:t
**函数出口:无
***********************************************************************/                          
void delay_ms(unsigned long int t)
    {
    unsigned long int i;
    unsigned long int j;
    j=Fclk/1000*t;
    for(i = 0; i < j; i++);
    }

/**********************************************************************
**函数名称:delay_us()
**函数功能:微秒级延时,注意设置delay.h中的Fclk
**函数入口:t
**函数出口:无
***********************************************************************/
void delay_us(unsigned long int t)
    {
    unsigned long int i;
    unsigned long int j;
    j=Fclk/1000000*t;
    for(i = 0; i < j; i++);
    }

shaoshunda 发表于 2008-7-29 11:04:29

#ifndef __delay_H
#define __delay_H
#defineFclk    60000000
//**********************函数声明***************************
void delay_s (unsigned long int t);
void delay_ms(unsigned long int t);
void delay_us(unsigned long int t);
//*********************************************************
#endif

shaoshunda 发表于 2008-7-29 11:06:12

好用的就顶一下

YourARM 发表于 2008-8-22 12:26:42

我认为函数的返回不应该放到全局变量中。以启动条件为例:
void IicStart(void)
{
      f_I2C_Error=0;
    IicBusDelay();
SetSDA();      
    IicBusDelay();
SetSCL();
    IicBusDelay();
      if( GetSDA()==0)
      {
                f_I2C_Error = 1 ;
                return ;
      }
      if( GetSCL()==0 )
      {
                f_I2C_Error = 1 ;
                return ;
      }
ClrSDA();         
    IicBusDelay();
ClrSCL();         
    IicBusDelay();
}

可改为:
unsigned char IicStart(void)
{
    IicBusDelay();
    SetSDA();      
    IicBusDelay();
    SetSCL();
    IicBusDelay();

    if( GetSDA()==0)
    {
      return 1;
    }

    if( GetSCL()==0 )
    {
      return 1;
    }

    ClrSDA();         
    IicBusDelay();
    ClrSCL();         
    IicBusDelay();

    return 0;
}

agengood 发表于 2009-10-8 12:36:43

mark

windcavalier 发表于 2009-10-25 01:27:52

mark

kivensky 发表于 2009-10-25 11:07:26

开发工具用的是什么?

zhaojun_xf 发表于 2010-6-28 10:23:10

不错,学习一下!!!!!!!!!!!!!

anigon 发表于 2010-7-29 08:58:35

mark
页: [1]
查看完整版本: LPC2148 GPIO模拟I2C(源码)