// File Name : IIC.c
// Function  : S3C2440 IIC-bus Master Tx/Rx mode Test Program
//             (Interrupt / Non Interrupt (Polling))
// Program   : Shin, On Pil (SOP)
// Date      : May 21, 2002
// Version   : 0.0
// History
//   0.0 : Programming start (March 11, 2002) -> SOP
//====================================================================

#include <string.h> 
//串口会用到
#include "2440addr.h"
//寄存器宏定义
#include "2440lib.h"
//要用到的函数,函数的声明
#include "def.h" 
//几个变量类型的宏定义
#include "IIC.h"


//volatile影响编译器编译的结果,指出volatile变量是随时可能
//发生变化的,与volatile变量有关的运算,不要进行编译优化
static U8 _iicData[IICBUFSIZE];  
//定义一个数组,里面有256个数据
static volatile int _iicDataCount;
//IIC数据计数
static volatile int _iicStatus;  
//IIC的状态
static volatile int _iicMode;   
//IIC的模式
static int _iicPt;   
//IIC的指针
//===================================================================
//       SMDK2440 IIC configuration
//  GPE15=IICSDA, GPE14=IICSCL
//  "Interrupt mode" for IIC block中断模式下的IIC操作
//===================================================================
//******************[ Test_Iic ]**************************************
void Test_Iic(void)

{

    unsigned int i,j,save_E,save_PE;

    static U8 data[256]; 
//定义一个256个8位数据的数组
    Uart_Printf("\nIIC Test(Interrupt) using AT24C02\n");
    save_E   = rGPECON;  
//保护现场
    save_PE  = rGPEUP;

    rGPEUP  |= 0xc000;     
//1100 0000 0000 0000禁止GPE14,GPE15上拉电阻
    rGPECON |= 0xa00000;      
//GPE15:IICSDA , GPE14:IICSCL (应该为0xa0000000)???
    pISR_IIC = (unsigned)IicInt; 
//函数赋给向量地址
    rINTMSK &= ~(BIT_IIC); 
//使能IIC中断
     
//Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
      // If PCLK 50.7MHz, IICCLK=PCLK/16=3.17MHz, Tx Clock(发送时钟)=IICCLK/16=0.198MHz
    rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);
    rIICADD  = 0x10;                   
//2440 slave address=[7:1]=0x10 从机地址
    rIICSTAT = 0x10;                   
//IIC bus data output enable(Rx/Tx) IIC数据输出使能
    rIICLC = (1<<2)|(1);      
//Filter enable, 5 clocks SDA output delay       added by junon(感觉没用)
   

    Uart_Printf("Write test data into AT24C02\n");
    for(i=0;i<256;i++)

    Wr24C080(0xa0,(U8)i,i); 
//从设备的地址为0xa0,从从设备的内部0地址开始到256地址结束,写入0~256
          

    for(i=0;i<256;i++)

        data[i] = 0;        
//data数组的元素全部初始化为0
    Uart_Printf("Read test data from AT24C02\n");

   

    for(i=0;i<256;i++)

        Rd24C080(0xa0,(U8)i,&(data[i]));
//读取从设备的中的数据存入data数组中
       
//Line changed 0 ~ f
    for(i=0;i<16;i++)

    {

        for(j=0;j<16;j++)

            Uart_Printf("%2x",data[i*16+j]); 
//打印刚才读出来的数据,即data数组里的值
        Uart_Printf("\n");                   
//每16字节换一行
    }

    rINTMSK |= BIT_IIC;   
//IIC操作结束,禁止IIC中断
    rGPEUP  = save_PE;    
//恢复现场
    rGPECON = save_E;

}


//*************************[ Wr24C080 ]****************************
//      函数名    从机地址   内部地址 写入的数据
//****************************************************************
void Wr24C080(U32 slvAddr,U32 addr,U8 data)

{


//过程就是:S(开始信号)---发送设备地址----设备内部地址----写入的数据
    _iicMode      = WRDATA;        
//设置为写数据模式

    _iicPt        = 0;          
//IIC指针指向0地址
    _iicData[0]   = (U8)addr;
//给Data数组的0元素赋值,内部地址
    _iicData[1]   = data;   
//给Data数组的1元素赋值,写入的数据
    _iicDataCount = 2;  
//数据计数初始值为2
   

    rIICDS   = slvAddr;                
//0xa0     把从机设备地址给IICDS
    rIICSTAT = 0xf0;                   
//MasTx,Start 设置为主发送模式,写IIC产生开始信号,使能RX/TX
     
//Clearing the pending bit isn't needed because the pending bit has been cleared.
    //开始IIC写,发送完从机设备地址后,产生中断,进入中断函数
    while(_iicDataCount!=-1
);//因为count是2,条件不成立然后等待!!第一次中断处理完后,count=1,然后再判断while中的条件不成立,继续等待,等到发送从机字设备的内部地址完后,产生中断有进入中断函数   


//以下的while语句是判断接没接收到ACK信号   

    _iicMode = POLLACK;
//等待ACK应答模式,有应答表示从设备已经收到
    while(1)

    {

        rIICDS     = slvAddr;          
//slvAddr=0xa0
        _iicStatus = 0x100;            
//IICSTAT clear??
        rIICSTAT   = 0xf0;             
//MasTx,Start,主发送模式,产生开始信号,使能串行输出,启动IIC
        rIICCON    = 0xaf;             
//Resumes IIC operation.
          

        while(_iicStatus==0x100);      
//Wait until IICSTAT change
          

        if(!(_iicStatus&0x1))       
//判断IICSTAT第0位是不是0,是0的话表示接收到ACK了
            break;                     
//When ACK is received
    }

     rIICSTAT=0xd0; 
           //产生停止信号,停止IIC
     rIICCON=0xaf;  
           //重新配置IICCON.
     Delay(1);                
//等待直到IICSTAT的停止信号有效
      
//Write is completed.

}

       


//**********************[ Rd24C080 ] ***********************************
//读随机地址的数据读函数
//过程:S---发送设备地址---设备内部地址---发送设备地址---读取数据---NOACK---中止
void Rd24C080(U32 slvAddr,U32 addr,U8 *data)

{

    _iicMode      = SETRDADDR; 
//设置读地址
    _iicPt        = 0;

    _iicData[0]   = (U8)addr;

    _iicDataCount = 1;  
    rIICDS   = slvAddr;                 
//slvAddr=0xa0首先写入从设备地址 
    rIICSTAT = 0xf0;                   
//MasTx,Start开始启动信号  

     
//Clearing the pending bit isn't needed because the pending bit has been cleared.
    while(_iicDataCount!=-1);
//因为count是1,条件不成立然后等待!!第一次中断处理完后,count=0,然后再判断while中的条件不成立,继续等待,等到发送从机字设备的内部地址完后,产生中断有进入中断函数,执行完中断函数后,此时count=-1了所以就退出此while循环
    _iicMode      = RDDATA; 
//读数据模式 

    _iicPt        = 0;

    _iicDataCount = 1;       
//读一个数据(地址)
   

    rIICDS        = slvAddr;            
//slvAddr=0xa0,又发送一次从机设备地址
    rIICSTAT      = 0xb0;              
//1011,10~MasRx,1~Start,1~RxTx enable主接收模式
    rIICCON       = 0xaf;              
//Resumes IIC operation.  

    while(_iicDataCount!=-1);    
//等待,发送完设备地址后,产生中断进入中断函数执行第二次中断处理后,count=-1了,条件不成立退出while,继续下面的语句
    *data = _iicData[1]; 
//把从IICDS中接收到的数据送给指针data,
}


//-------------------------------------------------------------------------
void __irq IicInt(void)         
//IIC中断初始化函数 

{

    U32 iicSt,i;

   

    rSRCPND = BIT_IIC;         
//Clear pending bit以便下次产生中断可以执行
    rINTPND = BIT_IIC;         
//Clear pending bit以便下次产生中断可以执行
    iicSt   = rIICSTAT;        
//把IICSTAT状态寄存器的值赋给iicSt
   

    if(iicSt & 0x8){}          
//When bus arbitration is failed.当总线仲裁失败时,执行空操作
    if(iicSt & 0x4){}          
//When a slave address is matched with.当接收到的从地址和IICADD中地址匹配时,执行空操作
    if(iicSt & 0x2){}          
//When a slave address is 0000000b.接收到从地址为
0000000b
    if(iicSt & 0x1){}          
//When ACK isn't received未收到ACK应答信号执行空操作
    switch(_iicMode)            
//根据模式的不同执行不同的操作
    {

       case POLLACK:  
//ACK模式
           _iicStatus = iicSt;
//让_iicStatus就等于IICSTAT的值
           break;
       case RDDATA: 
//读数据模式
           if((_iicDataCount--)==0)
//count初始为1,不执行if代码段。完后count=0。第二次中断过来,条件成立就执行if内部代码
           {

               _iicData[_iicPt++] = rIICDS;    
//重新把IICDS中的值读取出来到_iicData[1]
           

               rIICSTAT = 0x90;                
//Stop MasRx condition 1001 0000 产生停止信号
               rIICCON  = 0xaf;                
//Resumes IIC operation.恢复IIC操作
               Delay(1);                       
//Wait until stop condtion is in effect.
                                                //Too long time... 等待直到停止信号起效
                                               
//The pending bit will not be set after issuing stop condition.

               break;                          
//跳回到读函数中   
           }   

            
//未读完最后一个字节不能产生ACK。读取IICDS中的数据
           _iicData[_iicPt++] = rIICDS;        
//The last data has to be read with no ack.
           if((_iicDataCount)==0)

               rIICCON = 0x2f;                  
//因为条件成立所以执行rIICCON=0x2f;主机产生NOACK,释放IIC操作
           else

               rIICCON = 0xaf;                
//产生ACK,释放IIC操作
               break;
        case WRDATA: 
//写数据模式
            if((_iicDataCount--)==0)          
//判断自减后是否为0.(2自减后为1,不为0)
            {

                rIICSTAT = 0xd0;               
//Stop MasTx condition产生停止信号
                rIICCON  = 0xaf;               
//Resumes IIC operation.恢复IIC的操作
                Delay(1);                      
//Wait until stop condtion is in effect.等待直到停止信号起效
                      
//The pending
bit will not be set after issuing stop condition.
                break;   

            }

           
//自减后不为0,则执行下面的语句
            rIICDS = _iicData[_iicPt++];       
//_iicPt++是先判断,后自加,所以此条语句是rIICDS = _iicData[0],因为写函数中_iicData[0]=addr,
                                               
//即往从设备的addr地址发送数据
            for(i=0;i<10;i++);                 
//在IICSCL上升沿之前有一个建立时间
             

            rIICCON = 0xaf;                    
//恢复IIC的操作
            break;

           


//SETRDADDR模式下的中断:
/*第一次中断处理后:count=0,_iicData[0]=IICDS中的值(又一次发送从设备地址引起的)*/
/*第二次中断处理后:count=-1,_iicPt=1(接收IICDS的值完毕后产生的中断*/
        case SETRDADDR:                    
//设置读地址            


//          Uart_Printf("[ S%d ]",_iicDataCount); 
            if((_iicDataCount--)==0)
//判断自减后是否为0
                break;                         
//IIC operation is stopped because of IICCON[4]   
            rIICDS = _iicData[_iicPt++];

            for(i=0;i<10;i++);                 
//For setup time until rising edge of IICSCL
            rIICCON = 0xaf;                    
//Resumes IIC operation.
            break;

 
//SETRDADDR模式下的中断:
 /*第一次中断后:count=0,iicPt=1(发送从设备地址引起的)*/
 /*第二次中断后:count=-1,iicPt=1因为if内部代码是直接跳回读函数,没继续执行if外面的代码,所以iicPt=1(发送从设备内部地址引起的)
        default:

            break;     

    }

}
 
 
 
//       SMDK2440 IIC configuration
//  GPE15=IICSDA, GPE14=IICSCL
//  "Non-Interrupt" mode for IIC block
//===================================================================

//*********************[ Test_Iic2 ]*********************************
void Test_Iic2(void)

{

    unsigned int i,j,save_E,save_PE;

    static U8 data[256];

   

    Uart_Printf("[ IIC Test(Polling) using KS24C080 ]\n");
    save_E   = rGPECON;

    save_PE  = rGPEUP;
    rGPEUP  |= 0xc000;                 
//Pull-up disable
    rGPECON |= 0xa00000;               
//GPE15:IICSDA , GPE14:IICSCL(应改为0xa0000000)  
     
//Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
    rIICCON  = (1<<7) | (0<<6) | (1<<5) | (0xf);
    rIICADD  = 0x10;                   
//2440 slave address = [7:1]
    rIICSTAT = 0x10;                   
//IIC bus data output enable(Rx/Tx)
 //rIICLC = (1<<2)|(3);  // Filter enable, 15 clocks SDA output delay     added by junon

   

    Uart_Printf("Write test data into KS24C080\n");
    for(i=0;i<256;i++)

        _Wr24C080(0xa0,(U8)i,255-i);

    for(i=0;i<256;i++)

        data[i] = 0;
    Uart_Printf("Read test data from KS24C080\n");

    for(i=0;i<256;i++)

        _Rd24C080(0xa0,(U8)i,&(data[i]));
    for(i=0;i<16;i++)

    {

        for(j=0;j<16;j++)

            Uart_Printf("%2x ",data[i*16+j]);

        Uart_Printf("\n");

    }

   

    rGPEUP  = save_PE;

    rGPECON = save_E;

}
//**************[ _Wr24C080 ]*****************************************
void _Wr24C080(U32 slvAddr,U32 addr,U8 data)

{

    _iicMode      = WRDATA;  
//设置为写数据模式
    _iicPt        = 0;       
//IIC指针指向0地址
    _iicData[0]   = (U8)addr;
//给Data数组的0元素赋值,内部地址
    _iicData[1]   = data;    
//给Data数组的1元素赋值,写入的数据
    _iicDataCount = 2;       
//数据计数初始值为2
   

    rIICDS        = slvAddr;
//0xa0     把从机设备地址给IICDS
     
//Master Tx mode, Start(Write), IIC-bus data output enable设置为主发送模式,写IIC产生开始信号,使能RX/TX
     
//Bus arbitration sucessful, Address as slave status flag Cleared,
     
//Address zero status flag cleared, Last received bit is 0
    rIICSTAT      = 0xf0;     

     
//Clearing the pending bit isn't needed because the pending bit has been cleared.
    while(_iicDataCount!=-1)

       Run_IicPoll();
    _iicMode = POLLACK;
    while(1)

    {

        rIICDS     = slvAddr;

        _iicStatus = 0x100;            
//To check if _iicStatus is changed
        rIICSTAT   = 0xf0;             
//Master Tx, Start, Output Enable, Sucessful, Cleared, Cleared, 0
        rIICCON    = 0xaf;             
//Resumes IIC operation.
        while(_iicStatus==0x100) 

            Run_IicPoll();

             

        if(!(_iicStatus & 0x1))

            break;                     
//When ACK is received
    }

    rIICSTAT = 0xd0;                   
//Master Tx condition, Stop(Write), Output Enable
    rIICCON  = 0xaf;                   
//Resumes IIC operation.
    Delay(1);                          
//Wait until stop condtion is in effect.

      //Write is completed.

}

       


//************************[ _Rd24C080 ]********************************
void _Rd24C080(U32 slvAddr,U32 addr,U8 *data)

{

    _iicMode      = SETRDADDR;

    _iicPt        = 0;

    _iicData[0]   = (U8)addr;

    _iicDataCount = 1;
    rIICDS   = slvAddr;

    rIICSTAT = 0xf0;                   
//MasTx,Start 
     
//Clearing the pending bit isn't needed because the pending bit has been cleared.
    while(_iicDataCount!=-1)

        Run_IicPoll();
    _iicMode      = RDDATA;

    _iicPt        = 0;

    _iicDataCount = 1;

   

    rIICDS   = slvAddr;

    rIICSTAT = 0xb0;                   
//Master Rx,Start
    rIICCON  = 0xaf;                   
//Resumes IIC operation.  

    while(_iicDataCount!=-1)

        Run_IicPoll();
    *data = _iicData[1];

}
//**********************[ Run_IicPoll ]*********************************
//该函数的作用就是判断一个字节是否发送或者接收完毕,因为已经说明了,只要传
输完毕,就会产生中断,使 IIC 控制寄存器的 bit4 置 1。该函数判断该位,如果
为1,说明传输完毕,可以进行下面的字节传输,如果是 0,则继续等待,直到它变
为1。如果变为1,就调用IicPoll 函数。
 //********************************************************************//

void Run_IicPoll(void)

{

    if(rIICCON & 0x10)                 
       IicPoll();

}      

   


//**********************[IicPoll ]**************************************
//该函数的主体是一个 switch  语句,用来判断现在进行的是什么操作,并进行
相应的读写操作。这个函数主要反映了 I2C 的时序
//***********************************************************************//
void IicPoll(void)

{

    U32 iicSt,i;

   

    iicSt = rIICSTAT;

    if(iicSt & 0x8){}                  
//When bus arbitration is failed.
    if(iicSt & 0x4){}                  
//When a slave address is matched with IICADD
    if(iicSt & 0x2){}                  
//When a slave address is 0000000b
    if(iicSt & 0x1){}                  
//When ACK isn't received
    switch(_iicMode)

    {

        case POLLACK:

            _iicStatus = iicSt;

            break;
        case RDDATA:

            if((_iicDataCount--)==0)

            {

                _iicData[_iicPt++] = rIICDS;

           

                rIICSTAT = 0x90;               
//Stop MasRx condition
                rIICCON  = 0xaf;               
//Resumes IIC operation.

                Delay(1);                      
//Wait until stop condtion is in effect.
                                               
//Too long time...
                                               
//The pending bit will not be set after issuing stop condition.
                break;   

            }     

            _iicData[_iicPt++] = rIICDS;

                       
//The last data has to be read with no ack.
            if((_iicDataCount)==0)

                rIICCON = 0x2f;                
//Resumes IIC operation with NOACK. 

            else

                rIICCON = 0xaf;                
//Resumes IIC operation with ACK
            break;
        case WRDATA:

            if((_iicDataCount--)==0)

            {

                rIICSTAT = 0xd0;               
//stop MasTx condition
                rIICCON  = 0xaf;               
//resumes IIC operation

                Delay(1);                      
//wait until stop condtion is in effect.
                      
//The pending bit will not be set after issuing stop condition.
                break;   

            }

            rIICDS = _iicData[_iicPt++];       
//_iicData[0] has dummy.
            for(i=0;i<10;i++);                 
//for setup time until rising edge of IICSCL
            rIICCON = 0xaf;                    
//resumes IIC operation.
            break;
        case SETRDADDR:


//          Uart_Printf("[S%d]",_iicDataCount);
            if((_iicDataCount--)==0)

            {

                break;                 
//IIC operation is stopped because of IICCON[4]   

            }

            rIICDS = _iicData[_iicPt++];

            for(i=0;i<10;i++);         
//for setup time until rising edge of IICSCL
            rIICCON = 0xaf;            
//resumes IIC operation.
            break;
        default:

            break;     

    }

}

mini2440裸机之I2C的更多相关文章

  1. mini2440裸机音乐播放器(非常久曾经的笔记)

    [这是好久曾经写的.有点乱,没时间整理.当做记录用的.] 图片粘贴失效.没上传图,想要的直接下载文档吧. 项目目的:通过IIS,触摸屏,LCD模块实现音乐播放器功能(button上一首.下一首.播放. ...

  2. mini2440裸机试炼之——DMA直接存取 实现Uart(串口)通信

    这个仅仅能作为自己初步了解MDA的开门篇 实现功能: 将字符串数据通过DMA0通道传递给UTXH0,然后在终端 显示.传输数据完后.DMA0产生中断,beep声, LED亮. DMA基本知识 计算机系 ...

  3. mini2440裸机试炼之—RTC闹钟中断,节拍中断

    版权声明:博客地址:http://blog.csdn.net/muyang_ren.源代码能够在我的github上找看看 https://blog.csdn.net/muyang_ren/articl ...

  4. mini2440裸机试炼之——看门狗中断和复位操作

    看门狗的工作原理: 设本系统程序完整执行一周期的时间是Tp,看门狗的定时周期为Ti,Ti>Tp,在程序正常执行时,定时器就不会溢出,若因为干扰等原因使系统不能在Tp时刻改动定时器的记数值,定时器 ...

  5. mini2440 裸机程序,下载到nand 里面,复制到 sdram 中不运行

    按照韦东山的视频中 sdram的裸机代码,写了一份,通过 minitools 下载到 0x30000000,然后烧录到 nand中,接过不能正常运行. 尝试过多种方法后,只有一种解决方法,就是不要用 ...

  6. mini2440 裸机程序下载到 sdram 不能运行。

    今天在 写了个简单的 led 的汇编程序,下载到 mini2440 的 nand flash 里面可以正常运行,但是下载到 sdram 里面不能运行. 后来发现有几个注意点, 要在 sdram 中运行 ...

  7. mini2440裸机之MMU(二)(mmu.c) (转)

    分类: 嵌入式 http://blog.chinaunix.net/uid-26435987-id-3082166.html(转) /********************************* ...

  8. 八、mini2440裸机程序之UART(2)UART0与PC串口通信【转】

    转自:http://blog.csdn.net/shengnan_wu/article/details/8309417 版权声明:本文为博主原创文章,未经博主允许不得转载. 1.相关原理图 2.相关寄 ...

  9. 八、mini2440裸机程序之UART(1)简单介绍【转】

    转自:http://blog.csdn.net/shengnan_wu/article/details/8298869 一.概述          S3C2440通用异步接收和发送(UART)提供了三 ...

随机推荐

  1. 什么是MEAN全堆栈javascript开发框架

    什么是MEAN全堆栈javascript开发框架 使用JavaScript能够完整迅速做出Web应用程序,目前一套工具包括MongoDB.ExpressJS,AngularJS和Node.js越来越受 ...

  2. 《java系统性能优化》--2.高速缓存

    上一节.简介了怎样发现性能瓶颈.从这节開始.我会和大家分享我在项目中做的一些性能调优工作.这个系列没有什么顺序可言,认为什么重要.就说说什么. 这节.我们聊缓存. 最開始接触缓存这个词,是学习硬件知识 ...

  3. android项目总体界面架构(可直接复用)

    文章解读.效果图.源代码下载链接 http://blog.csdn.net/gao_chun/article/details/37903673

  4. Installshield脚本拷贝文件常见问题汇总

    原文:Installshield脚本拷贝文件常见问题汇总 很多朋友经常来问:为什么我用CopyFile/XCopyFile函数拷贝文件无效?引起这种情况的原因有很多,今天略微总结了一下,欢迎各位朋友跟 ...

  5. C# 标签(条码)

    C# 标签(条码) 上一篇说到条码的打印,主要是通过读取模板定义文件(XML文件),然后结合从数据库中读取的动态数据结合而产生条码.下面主要说一下如何设计这个条码模板.设计过程也很简单,只需要简单的拖 ...

  6. js 实现复制粘贴文本过滤(保留文字和图片)

    实现复制粘贴文本过滤(保留文字和图片) demo如下: <head> <meta http-equiv="Content-Type" content=" ...

  7. 【【分享】深入浅出WPF全系列教程及源码 】

    因为原书作者的一再要求,在此声明,本书中的部分内容引用了原书名为<深入浅出WPF>的部分内容,假设博文不能满足你现有的学习须要,能够购买正版图书! 本人10月份提出离职,可是交接非常慢,预 ...

  8. 编写SQL的辅助工具

    原文:编写SQL的辅助工具 今天在同事的帮助下,下载了一个工具:ApexSQL edit,可能是我孤陋寡闻,不知道还有这样的好工具,它可以在我键入SQL时,帮助我提示表的名称和列名称.还可以帮助我格式 ...

  9. codeblock 设置背景颜色

    今天觉得codeblock看着刺眼,想了想,能不能跟vs利用dark背景一样可以设置一个舒服的背景.于是就开始各种点击,各种摸索了. 1. 背景和各种颜色设置 不妨先说下vs中的设置是:工具(Tool ...

  10. AngularJS学习笔记filter

    filter是对数据进行过滤操作,比如按某个字段搜索.格式化数据等等,是一个非常有用的接口.下面就简单介绍下它的用法. AngularJS自带的filter接口,|是filter的分隔符,参数用:分隔 ...