对S3C2440裸板程序设计(无操作系统)的抽象

本文介绍了在S3C2440裸板上使用I2C控制器的方法,通过具体的代码示例展示了如何配置控制器寄存器以实现数据的读写操作。文章详细解释了I2C协议的工作原理及其在硬件控制器上的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对S3C2440裸板程序设计(无操作系统)的抽象

在嵌入式领域中,几乎所有的设备控制和各种协议控制都在同一个嵌入式CPU当中,非常有利于对CPU Core和设备进行抽象。如果能对CPU Core和设备的各种控制进行抽象,人们在移植OS或者开发驱动程序时就没有必要对CPU进行非常深入的了解,不必要了解某个寄存器的某个位是控制什么的,也没有必要了解怎样初始化某个控制寄存器等等。
在利用控制器编写裸板应用程序时,编程人员只需要了解该控制器的初始化顺序以及初始化的内容而不需要了解初始化的具体细节就能完成应用程序。显然可以大大的提高工作效率,并且对于硬件的具体细节设置是在应用程序中最容易出错的地方,而利用控制器则可以大大的减少出错的可能性。
ARM是功能更加强大的单片机,在学习裸机程序设计的过程中,发现ARM比一般的单片机集成了更多的外设(一般的单片机只集成了串口,还有四组IO端口),包含更多的GPIO,有更多的寄存器,通过寄存器的设置和启用来控制相关引脚,从而控制相关设备。S3C2440内部集成了硬件控制器,各种驱动协议用硬件控制器产生,我们只需配置对应硬件控制器的寄存器即可产生相应的驱动时序。 高端ARM学习以软件编程为主(即理解为主),其资源丰富,很少需要需要扩展外设,学习重点在于如何配置寄存器以及如何编写应用程序。

设置相应的控制寄存器,读写相应的数据寄存器就可以。学习裸板程序开发的重点是理解各种接口协议的原理,这样就可以很好的理解控制器的初始化顺序以及初始化的内容。

下面以S3C2440的I2C控制器为例来讲解。下面的程序是基于中断模式,I2C协议的讲解可以查看我以前的博客。I2C协议中规定:接收器接收到一个字节(地址或数据)后,要发送一个ACK,发送器接收到ACK后可以接着发送数据或结束数据传输。接收器(这里我们是S3C2440的I2C控制器)收到ACK后会产生一个中断,在中断处理程序中可以继续发送程序或者结束传输。理解了I2C协议的基本原理,编写程序就水到渠成。

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

//******************[ Test_Iic ]**************************************
void Test_Iic(void)
{
    unsigned int i,j,save_E,save_PE;
    static U8 data[256];

    Uart_Printf("\nIIC Test(Interrupt) using AT24C08\n");

    save_E   = rGPECON;                 //保存以前的值
    rGPECON |= 0xa00000;                //GPE15:IICSDA , GPE14:IICSCL 

    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 = 3.17MHz, Tx Clock = 0.198MHz
    rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);//第四位为1,SCL线被拉低,传输被中断

    rIICADD  = 0x10;                    //2440 slave address = [7:1]
    rIICSTAT = 0x10;                    //IIC bus data output enable(Rx/Tx)使能接收/发送功能
    rIICLC = (1<<2)|(1);  		     // Filter enable, 15 clocks SDA output delay       added by junon
    
    Uart_Printf("Write test data into AT24C08\n");

    for(i=0;i<256;i++)
        Wr24C080(0xa0,(U8)i,i);
           
    for(i=0;i<256;i++)
        data[i] = 0;

    Uart_Printf("Read test data from AT24C08\n");
    
    for(i=0;i<256;i++)
        Rd24C080(0xa0,(U8)i,&(data[i])); 

        //Line changed 0 ~ f
    for(i=0;i<16;i++)
    {
        for(j=0;j<16;j++)
            Uart_Printf("%2x ",data[i*16+j]);
        Uart_Printf("\n");
    }
    rINTMSK |= BIT_IIC;    
    rGPECON = save_E;
}


//*************************[ Wr24C080 ]****************************
void Wr24C080(U32 slvAddr,U32 addr,U8 data)
{
    _iicMode      = WRDATA;
    _iicPt        = 0;
    _iicData[0]   = (U8)addr;
    _iicData[1]   = data;
    _iicDataCount = 2;
    
    rIICDS   = slvAddr;                 //0xa0
    rIICSTAT = 0xf0;                    //MasTx,Start主机发送器 发出S信号
      //Clearing the pending bit isn't needed because the pending bit has been cleared.
    
    while(_iicDataCount!=-1);//等待数据数据发送完毕




//开始一次新的传输,不过只发送设备地址,等待应答,以证明上次传输完成。而下次Wr24C080的时候会重新开始,这次的传输并没有写入数据
    _iicMode = POLLACK;

    while(1)
    {
        rIICDS     = slvAddr;
        _iicStatus = 0x100;
        rIICSTAT   = 0xf0;              //MasTx,Start
        rIICCON    = 0xaf;              //Resumes IIC operation. 
           
        while(_iicStatus==0x100)    ;//等待数据数据发送完毕,状态寄存器改变了就可以了
           
        if(!(_iicStatus&0x1))     //接收到的最后一位为0 (接收到ACK信号)
            break;           //When ACK is received  判断最后一位的状态
    }
    rIICSTAT = 0xd0;                    //Stop MasTx condition 
    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);

    _iicMode      = RDDATA;
    _iicPt        = 0;
    _iicDataCount = 1;
    
    rIICDS        = slvAddr;
    rIICSTAT      = 0xb0;               //MasRx,Start
    rIICCON       = 0xaf;               //Resumes IIC operation.   
    while(_iicDataCount!=-1);

    *data = _iicData[1];
}


//-------------------------------------------------------------------------
void __irq IicInt(void)
{
    U32 iicSt,i;
    
    rSRCPND = BIT_IIC;          //Clear pending bit
    rINTPND = BIT_IIC;
    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;      
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值