// 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. 多线程学习之一独木桥模式Single Threaded Execution Pattern

    Single Threaded Execution Pattern[独木桥模式] 一:single threaded execution pattern的参与者--->SharedResourc ...

  2. 关于s2sh框架关于hibernate懒加载问题的说明和解决方案

    首先我们来看下面这个图,解释了一个web程序的一次请求流程! 懒加载异常的说明: 懒加载就是我们在查询一个对象时,它所有的属性是否要被查出来! 如果懒加载开启的话,session在service层就被 ...

  3. sql注入工具sqlmap使用参数说明

    Options(选项):--version 显示程序的版本号并退出-h, --help 显示此帮助消息并退出-v VERBOSE 详细级别:0-6(默认为1)Target(目标):以下至少需要设置其中 ...

  4. 一个简单的创建dom的函数

    var  regName = /^(div|a|p|ul|li|input|select|document|body|iframe)$/;function createDom(name, obj) { ...

  5. 项目笔记---CSharp图片处理

    原文:项目笔记---CSharp图片处理 项目笔记---CSharp图片处理 最近由于项目上需要对图片进行二值化处理,就学习了相关的图片处理上的知识,从开始的二值化的意义到动态阀值检测二值化等等,并用 ...

  6. weblogic启动报错--com.octetstring.vde.backend.BackendRoot

    错误现象: 使用bea用户启动weblogic时报错,错误信息如下: <2014-7-29 下午07时47分23秒 CST> <Notice> <Log Manageme ...

  7. 2.2 LINQ中使用from子句指定数据源

    数据源是LINQ查询中必不可少的元素,数据源是实现泛型接口IEnumerable<T>或IQueryable<T>的类对象. 可以将IEnumerable<T>简单 ...

  8. Redis3

    Redis到底该如何利用 上两篇受益匪浅,秉着趁热打铁,不挖到最深不罢休的精神,我决定追加这篇.上一篇里最后我有提到实现分级缓存管理应该是个可行的方案,因此今天特别实践了一下.不过缓存分级之后也发现了 ...

  9. leetcode[85] Maximal Rectangle

    给定一个只含0和1的数组,求含1的最大矩形面积. Given a 2D binary matrix filled with 0's and 1's, find the largest rectangl ...

  10. 开辟html5和css3学习随笔(2015-3-2)

    1.移动端超出指定行数隐藏并显示省略号 <!DOCTYPE html> <html> <head> <meta http-equiv="Conten ...