新聞中心

        EEPW首頁 > 嵌入式系統 > 牛人業話 > SAM4E單片機之旅——1、LED閃爍之空循環

        SAM4E單片機之旅——1、LED閃爍之空循環

        作者: 時間:2017-01-10 來源:網絡 收藏

          最近因為導師要寫一本關于SAME4單片機的書籍,而我也作為一個嵌入式的初學者看了這本書。現在也讓我寫寫幾個小的程序,做做示例。既然寫了文檔之類的,就發到博客上來吧。

        本文引用地址:http://www.104case.com/article/201701/342708.htm

          目前關于這芯片能參考的書籍大概就只有英文手冊了。用的板子是16E。IDE用的是Atmel Studio。既然是學習單片機,就沒有使用asf框架,而是直接采用訪問寄存器的方法了。

          第一個程序就是控制板子上一個燈的閃爍了。

          一、電路

            

        wps_clip_image-6498

         

          通過查看電路圖,可以發現有一個藍色的燈連接在PA0引腳上。我們可以通過改變PA0輸出的電平實現燈的閃爍。

          二、寄存器的訪問和CMSIS

          對單片機的操作需要通過對相關寄存器的訪問來實現。比如,為調節PA0引腳上的電平,首先我們需要允許PIOA控制PA0引腳。通過查看寄存器說明可知,這只要向相應的PIO使能寄存器(PIO_PER)寫入0x01就可以了。同時,也可以查到PIOA的PIO_PER被映射到地址0x400E0E00上了。所以通過如下代碼就可以達到目的:

          /* 假設 unsigned int長度為32位 */

          unsigned int* PIOA_PER_p = (unsigned int*)0x400E0E00u;

          (*PIOA_PER_p) = 0x01;

          這樣做非常繁瑣,而且我們也不能保證unsigned int總是32位長。 而且當我們換一塊開發板的時候,外設的寄存器地址可能會不同,導致移植起來十分困難。

          所以CMSIS出現了。

          ARM® Cortex™ 微控制器軟件接口標準 (CMSIS) 是 Cortex-M 處理器系列的與供應商無關的硬件抽象層。CMSIS 可實現與處理器和外設之間的一致且簡單的軟件接口,從而簡化軟件的重用,縮短微控制器開發人員新手的學習過程,并縮短新設備的上市時間。

          軟件的創建是嵌入式產品行業的一個主要成本因素。通過跨所有 Cortex-M 芯片供應商產品將軟件接口標準化(尤其是在創建新項目或將現有軟件遷移到新設備時),可以大大降低成本。

          《CMSIS到底是什么》介紹了大概介紹了CMSIS。在這里,我們可以使用它提供的微控制器專用頭文件(我們這使用的就是sam.h了),這里提供里外設寄存器的定義,中斷號碼等:

          #include

          PIOA->PIO_PER = (uint32_t)0x01;

          我們在以后的程序代碼中也將使用CMSIS。

          三、實現思路

          PIO的引腳是復用的,但在這里我們直接使用PIO控制器控制引腳的電平就可以了。可以通過向PIO_SODR、PIO_CODR寫入特定的值來直接控制引腳的電平。

          然后,通過讓程序執行一個次數較長的空循環就可以實現延時功能。

          四、代碼

          實現較為簡單,直接看代碼就可以了(需要運行Debug模式下產生的代碼):

          #include

          int main(void)

          {

          /* PIO控制器直接控制PA0引腳 */

          PIOA->PIO_PER = (uint32_t)0x01;

          /* PA0輸出使能 */

          PIOA->PIO_OER = (uint32_t)0x01;

          /* PA0輸出寫使能 */

          PIOA->PIO_OWER = (uint32_t)0x01;

          while (1) {

          /* 設置PA0引腳為高電平,燈滅 */

          PIOA->PIO_SODR = (uint32_t)0x01;

          /* 延遲 */

          for (int i=0; i<1024*1024*2; ++i)

          ;

          /* 設置PA0引腳為高電平,燈亮 */

          PIOA->PIO_CODR = (uint32_t)0x01;

          for (int i=0; i<1024*1024*2; ++i)

          ;

          }

          return 0;

          }

          五、編譯器優化的副作用

          上面的示例代碼中,通過空循環實現延遲的語句出現了兩次。很自然的會想到要將這些語句提出成一個函數,甚至可以使用一個參數來大致控制延遲時間的長短:

          void Delay(int num)

          {

          for (int i = 0; i < 1024 * 1024 * num; ++i );

          }

          然后試著通過這個函數來進行延遲。很遺憾,再運行程序時我們發現LED會一直亮著,而不會閃爍。即使是在Debug模式下,編譯器也把這個函數調用給優化掉。類似的情況也會出現不少,這給我們對程序的調試造成一定的不便。 原因是Atmel Studio默認的Debug配置中,使用了O1級別的優化,可以在項目屬性中關閉它。

          我們試著使用宏來實現這個“函數”:

          #define Delay(num) 

          do{ 

          for (int i = 0; i < 1024 * 1024 * (num); ++i ); 

          }while(0)

          再運行一下,很好,LED又開始閃爍了。

          程序發布的時候,我們一般會使用Release模式生成代碼。Atmel Studio使用的gcc編譯器果然“不負眾望”,把這個空循環語句直接優化掉了。

          我們可以使用如下語句阻止編譯器的優化:

          for (int i = 0; i < 1024 * 1024 * num; ++i )

          asm ("");

          或者使用volatile關鍵字:

          for (volatile int i = 0; i < 1024 * 1024 * num; ++i ) ;

         



        關鍵詞: SAM4E LED

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 上饶县| 东阿县| 仲巴县| 清镇市| 濮阳县| 易门县| 龙岩市| 九寨沟县| 西华县| 浦北县| 石阡县| 富锦市| 五原县| 新巴尔虎左旗| 昌黎县| 治多县| 平泉县| 留坝县| 巴塘县| 华蓥市| 梁山县| 大名县| 德钦县| 项城市| 哈巴河县| 榆林市| 昌图县| 水富县| 榆社县| 武汉市| 阿克陶县| 新乡市| 九龙坡区| 视频| 泰宁县| 武夷山市| 营山县| 尼木县| 名山县| 璧山县| 文昌市|