2440 MDK 裸机IIC程序

  最近花了几天的时间参考网上资料和板子自带的裸机程序,分离出了这个IIC程序.写这个代码参考了这个博友的博客

lastnight1034.我看了他的代码,基本是从板子自带程序翻译过来的,我的代码与之类似,修正 一些错误.

#include <S3C2440.H>
#define U32 unsigned int
#define U16 unsigned short
#define S32 int
#define S16 short int
#define U8  unsigned char

int j;
void Delay(int x);

//初始化函数
void init_iic()
{
      //设置GPE15->IICSDA 和 GPE14->IICSCL
    GPEUP  |= 0xc000;                  //Pull-up disable
    GPECON &= ~0xf0000000;
    GPECON |= 0xa0000000;              //GPE15:IICSDA , GPE14:IICSCL
    //使能ACK,预分频IICCLK=PCLK/16,使能中断,发送时钟Txclock=IICCLK/16
    IICCON =(1<<7)|(0<<6)|(1<<5)|(0xf);
    IICADD =0x10; //2440从地址=[7:1]
    IICSTAT=0x10; //IIC总线数据接收使能(Rx/Tx)
    //禁止IIC中断屏蔽寄存器,使其中断使能
//    INTMSK &= ~(BIT_IIC); 
    
}

//slave_addr为设备地址,通常为0xa0
//IIC_addr为0xa0页下的位地址
//IIC_data为需在IIC_addr上写的数据
void Write24C08_byte(U32 slave_addr,U32 IIC_addr,U8 data)
{
    unsigned int i,j;
    
    IICDS  = slave_addr;
    IICSTAT = 0xf0;                       //开始写
    /*注: bit[7:6]:11--master Tx mode
    bit[5]: 1--start signal
    bit[4]: 1--enable Rx/Tx
    */
    while(!(IICCON & 0x10));      //等待应答信号,该位为1,收到应答
    IICDS = IIC_addr;         //往移位寄存器送数据:数据地址
    
    /*注:根据datasheet,只有往IICDS里写新数据,SCL才会翻转,所以在每次
    中断后都应写个数据给rIICDS。
    */
    for(i=0;i<10;i++);   //短延迟,等待SCL拉高
    IICCON = 0xaf;   //重新赋值,清应答中断位  0xaf是什么值,为什么是这个值?
    while(!(IICCON & 0x10));        //等待应答
        
    IICDS  = data;  //往移位寄存器送数据:待写数据                 
    for(i=0;i<10;i++);   //短延迟,等待SCL拉高
    IICCON = 0xaf;   //重新赋值,清应答中断位
    while(!(IICCON & 0x10));  //等待应答
    
    /*注:从IIC_addr开始连续写byte_Count个字节数据:IIC_writedata[0]~ IIC_writedata[byte_Count]. */
    
    IICSTAT = 0xd0;                    //结束写
    IICCON  = 0xaf;                     //重新赋值,清应答中断位
    Delay(1);                               //延迟等待结束生效
    
    //上面写一个字节处理已经完成,但是最后一个应答后IICDS无新数据,造成          
    //SCL无法翻转,故下面再来个重复写设备地址操作,来等待最后一个数据发送结束
    for(;;) 
    {
        IICDS   = slave_addr;
        IICSTAT = 0xf0;         //开始写   
        IICCON  = 0xaf;
        while(!(IICCON& 0x10)) ;
        if(!(IICSTAT & 0x01))     //bit0:ACK is received
             break;
        }
    
    IICSTAT = 0xd0;               //结束写
    IICCON  = 0xaf;
    Delay(1);
}


//slave_addr为设备地址,通常为0xa0
//IIC_addr为0xa0页下的位地址
//databuffer[]为IIC_addr上的数据存放数据
void Read24C08_nbyte(U32 slave_addr,U32 IIC_addr,U8 byte_Count,U8 *databuffer)
{
    unsigned int i;
    U32 temp;
    IICDS   = slave_addr;  //把地址给移位寄存器
    IICSTAT = 0xf0;     //主发送模式,首先发送从设备地址
    while(!(IICCON & 0x10));  //等待从设备ACK

    IICDS   = IIC_addr;
    for(i=0;i<10;i++);
    IICCON  = 0xaf;  //准备接收特定地址的数据     10101111
    while(!(IICCON & 0x10)); 
     
    /*
    rIICSTAT = 0xb0;      // Master Rx,Start   //为何要进行再次赋值
    rIICCON  = 0xaf;      //Resumes IIC operation.
    Delay(1);
    //参考写
    */
    IICDS   = slave_addr;
    IICSTAT = 0xb0;      //bit[7:6]:10--master Rx mode
    IICCON  = 0xaf;
    while(!(IICCON & 0x10));
    temp = IICDS;       //第一个返回的是从设备地址+1
    //注:个人理解为这里需要把rIICDS里的数据取走,使得SCL能正常翻转,为下面的读取数据做准备
    for(j=0;j<byte_Count;j++)        
    {                 
        if(j==(byte_Count-1))                 
        {        
            IICCON = 0x2f; //最后一个字节,返回NOACK           101111    
        } 
        else
        {                                                       
            IICCON = 0xaf;    //非最后一个字节,返回ACK        10101111
        }                  
        while(!(IICCON & 0x10));
                          
        databuffer[j] = IICDS;         
    }  
    IICSTAT = 0x90;      //停止读
    IICCON  = 0xaf;
    Delay(1);

}
void Delay(int x) 
{
    int k,j;
    while(x)
    {
        for(k=0;k<=0x5;k++)
            for(j=0;j<=0xf;j++);
        x--;
    }
} 

博文为本人整理和修改,转载请表明出处.我本想采用中断 的方式实现,一直未成功.有实现的可以一起交流.

原文地址:https://www.cnblogs.com/dreamfactory/p/2924317.html