對S3C2440裸板程序設(shè)計(無操作系統(tǒng))的抽象
在利用控制器編寫裸板應(yīng)用程序時,編程人員只需要了解該控制器的初始化順序以及初始化的內(nèi)容而不需要了解初始化的具體細(xì)節(jié)就能完成應(yīng)用程序。顯然可以大大的提高工作效率,并且對于硬件的具體細(xì)節(jié)設(shè)置是在應(yīng)用程序中最容易出錯的地方,而利用控制器則可以大大的減少出錯的可能性。
ARM是功能更加強大的單片機,在學(xué)習(xí)裸機程序設(shè)計的過程中,發(fā)現(xiàn)ARM比一般的單片機集成了更多的外設(shè)(一般的單片機只集成了串口,還有四組IO端口),包含更多的GPIO,有更多的寄存器,通過寄存器的設(shè)置和啟用來控制相關(guān)引腳,從而控制相關(guān)設(shè)備。S3C2440內(nèi)部集成了硬件控制器,各種驅(qū)動協(xié)議用硬件控制器產(chǎn)生,我們只需配置對應(yīng)硬件控制器的寄存器即可產(chǎn)生相應(yīng)的驅(qū)動時序。 高端ARM學(xué)習(xí)以軟件編程為主(即理解為主),其資源豐富,很少需要需要擴展外設(shè),學(xué)習(xí)重點在于如何配置寄存器以及如何編寫應(yīng)用程序。
設(shè)置相應(yīng)的控制寄存器,讀寫相應(yīng)的數(shù)據(jù)寄存器就可以。學(xué)習(xí)裸板程序開發(fā)的重點是理解各種接口協(xié)議的原理,這樣就可以很好的理解控制器的初始化順序以及初始化的內(nèi)容。
下面以S3C2440的I2C控制器為例來講解。下面的程序是基于中斷模式,I2C協(xié)議的講解可以查看我以前的博客。I2C協(xié)議中規(guī)定:接收器接收到一個字節(jié)(地址或數(shù)據(jù))后,要發(fā)送一個ACK,發(fā)送器接收到ACK后可以接著發(fā)送數(shù)據(jù)或結(jié)束數(shù)據(jù)傳輸。接收器(這里我們是S3C2440的I2C控制器)收到ACK后會產(chǎn)生一個中斷,在中斷處理程序中可以繼續(xù)發(fā)送程序或者結(jié)束傳輸。理解了I2C協(xié)議的基本原理,編寫程序就水到渠成。
- //===================================================================
- //SMDK2440IICconfiguration
- //GPE15=IICSDA,GPE14=IICSCL
- //"Interruptmode"forIICblock
- //===================================================================
- //******************[Test_Iic]**************************************
- voidTest_Iic(void)
- {
- unsignedinti,j,save_E,save_PE;
- staticU8data[256];
- Uart_Printf("nIICTest(Interrupt)usingAT24C08n");
- save_E=rGPECON;//保存以前的值
- rGPECON|=0xa00000;//GPE15:IICSDA,GPE14:IICSCL
- pISR_IIC=(unsigned)IicInt;//設(shè)置中斷處理函數(shù)
- rINTMSK&=~(BIT_IIC);//打開IIC中斷
- //EnableACK,PrescalerIICCLK=PCLK/16,Enableinterrupt,TransmitclockvalueTxclock=IICCLK/16
- //IfPCLK50.7MHz,IICCLK=3.17MHz,TxClock=0.198MHz
- rIICCON=(1<<7)|(0<<6)|(1<<5)|(0xf);//第四位為1,SCL線被拉低,傳輸被中斷
- rIICADD=0x10;//2440slaveaddress=[7:1]
- rIICSTAT=0x10;//IICbusdataoutputenable(Rx/Tx)使能接收/發(fā)送功能
- rIICLC=(1<<2)|(1);//Filterenable,15clocksSDAoutputdelayaddedbyjunon
- Uart_Printf("WritetestdataintoAT24C08n");
- for(i=0;i<256;i++)
- Wr24C080(0xa0,(U8)i,i);
- for(i=0;i<256;i++)
- data[i]=0;
- Uart_Printf("ReadtestdatafromAT24C08n");
- for(i=0;i<256;i++)
- Rd24C080(0xa0,(U8)i,&(data[i]));
- //Linechanged0~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]****************************
- voidWr24C080(U32slvAddr,U32addr,U8data)
- {
- _iicMode=WRDATA;
- _iicPt=0;
- _iicData[0]=(U8)addr;
- _iicData[1]=data;
- _iicDataCount=2;
- rIICDS=slvAddr;//0xa0
- rIICSTAT=0xf0;//MasTx,Start主機發(fā)送器發(fā)出S信號
- //Clearingthependingbitisntneededbecausethependingbithasbeencleared.
- while(_iicDataCount!=-1);//等待數(shù)據(jù)數(shù)據(jù)發(fā)送完畢
- //開始一次新的傳輸,不過只發(fā)送設(shè)備地址,等待應(yīng)答,以證明上次傳輸完成。而下次Wr24C080的時候會重新開始,這次的傳輸并沒有寫入數(shù)據(jù)
- _iicMode=POLLACK;
- while(1)
- {
- rIICDS=slvAddr;
- _iicStatus=0x100;
- rIICSTAT=0xf0;//MasTx,Start
- rIICCON=0xaf;//ResumesIICoperation.
- while(_iicStatus==0x100);//等待數(shù)據(jù)數(shù)據(jù)發(fā)送完畢,狀態(tài)寄存器改變了就可以了
- if(!(_iicStatus&0x1))//接收到的最后一位為0(接收到ACK信號)
- break;//WhenACKisreceived判斷最后一位的狀態(tài)
- }
- rIICSTAT=0xd0;//StopMasTxcondition
- rIICCON=0xaf;//ResumesIICoperation.
- Delay(1);//Waituntilstopcondtionisineffect.
- //Writeiscompleted.
- }
- //**********************[Rd24C080]***********************************
- voidRd24C080(U32slvAddr,U32addr,U8*data)
- {
- _iicMode=SETRDADDR;
- _iicPt=0;
- _iicData[0]=(U8)addr;
- _iicDataCount=1;
- rIICDS=slvAddr;
- rIICSTAT=0xf0;//MasTx,Start
- //Clearingthependingbitisntneededbecausethependingbithasbeencleared.
- while(_iicDataCount!=-1);
- _iicMode=RDDATA;
- _iicPt=0;
- _iicDataCount=1;
- rIICDS=slvAddr;
- rIICSTAT=0xb0;//MasRx,Start
- rIICCON=0xaf;//ResumesIICoperation.
- while(_iicDataCount!=-1);
- *data=_iicData[1];
- }
- //-------------------------------------------------------------------------
- void__irqIicInt(void)
- {
- U32iicSt,i;
- rSRCPND=BIT_IIC;//Clearpendingbit
- rINTPND=BIT_IIC;
- iicSt=rIICSTAT;
- if(iicSt&0x8){}//Whenbusarbitrationisfailed.
- if(iicSt&0x4){}//WhenaslaveaddressismatchedwithIICADD
- if(iicSt&0x2){}//Whenaslaveaddressis0000000b
- if(iicSt&0x1){}//WhenACKisntreceived
- switch(_iicMode)
- {
- casePOLLACK:
- _iicStatus=iicSt;
- break;
- caseRDDATA:
- if((_iicDataCount--)==0)
- {
- _iicData[_iicPt++]=rIICDS;
- rIICSTAT=0x90;//StopMasRxcondition
- rIICCON=0xaf;//ResumesIICoperation.
- Delay(1);//Waituntilstopcondtionisineffect.
- //Toolongtime...
- //Thependingbitwillnotbesetafterissuingstopcondition.
- break;
- }
- _iicData[_iicPt++]=rIICDS;//Thelastdatahastobereadwithnoack.
- if((_iicDataCount)==0)
- rIICCON=0x2f;//ResumesIICoperationwithNOACK.
- else
- rIICCON=0xaf;//ResumesIICoperationwithACK
- break;
- caseWRDATA:
- if((_iicDataCount--)==0)
- {
- rIICSTAT=0xd0;//StopMasTxcondition
- rIICCON=0xaf;//ResumesIICoperation.
- Delay(1);//Waituntilstopcondtionisineffect.
- //Thependingbitwillnotbesetafterissuingstopcondition.
- break;
- }
- rIICDS=_iicData[_iicPt++];//_iicData[0]hasdummy.
- for(i=0;i<10;i++);//forsetuptimeuntilrisingedgeofIICSCL
- rIICCON=0xaf;//resumesIICoperation.
- break;
- caseSETRDADDR:
- //Uart_Printf("[S%d]",_iicDataCount);
- if((_iicDataCount--)==0)
- break;//IICoperationisstoppedbecauseofIICCON[4]
- rIICDS=_iicData[_iicPt++];
- for(i=0;i<10;i++);//ForsetuptimeuntilrisingedgeofIICSCL
- rIICCON=0xaf;//ResumesIICoperation.
- break;
- default:
- break;
- }
- }
評論