• 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--;
        }
    } 

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

  • 相关阅读:
    Scalaz(15)- Monad:依赖注入-Reader besides Cake
    Scalaz(14)- Monad:函数组合-Kleisli to Reader
    Scalaz(13)- Monad:Writer
    Scalaz(12)- Monad:再述述flatMap,顺便了解MonadPlus
    Scalaz(11)- Monad:你存在的意义
    Scalaz(10)- Monad:就是一种函数式编程模式-a design pattern
    Scalaz(9)- typeclass:checking instance abiding the laws
    Scalaz(8)- typeclass:Monoid and Foldable
    Scalaz(7)- typeclass:Applicative-idomatic function application
    Scalaz(6)- typeclass:Functor-just map
  • 原文地址:https://www.cnblogs.com/dreamfactory/p/2924317.html
Copyright © 2020-2023  润新知