<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> STM32 >> 瀏覽文章

        STM32學習之GPIO與SYSTICK使用+軟件仿真

        作者:huqin   來源:本站原創   點擊數:  更新時間:2014年05月05日   【字體:

        小弟也是剛剛學習STM32,有什么不懂的還望大師們指點。

        以下程序是利用SYSTICK作為延時程序使GPIOA_Pin0產生1S的電壓變化。初學,也就會這些了,拿出來與大家分享一下。

        #include"stm32f10x_conf.h"
        void delay_ms(u32 ms);   聲明延時函數
        void GPIO_Config(void);   聲明GPIO配置函數
        int main(void)   主程序
        {
           SystemInit();    初始化系統時鐘默認72MHZ
           RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);    使能GPIOA時鐘
           GPIO_Config();    調用GPIO配置函數
           while(1)
         {
             GPIO_SetBits(GPIOA,GPIO_Pin_0); GPIOA的 Pin0腳置1(高電平)
            delay_ms(1000);  延時1000ms=1s
            GPIO_ResetBits(GPIOA,GPIO_Pin_0);GPIOA的 Pin0腳置0(低電平)
            delay_ms(1000);  延時1000ms=1s

         }
         


        }
        void GPIO_Config(void)  配置GPIOA函數
        {
            GPIO_InitTypeDef GPIO_InitStruct;
            GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
            GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
            GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;
            GPIO_Init(GPIOA,&GPIO_InitStruct);
         
        }

        void delay_ms(u32  ms) 延時函數,重點!
        {
                int temp;
                SysTick->CTRL=0x01;
                SysTick->LOAD=9000*ms;
                SysTick->VAL=0x00;
         do
         {
         temp=SysTick->CTRL;
         }
          while((temp&0x01)&&(!(temp&(1<<16))));
         
        }

        下面我把延時函數系統講一下:

        延時函數主要用到的是systick,也叫滴答系統時鐘。我只知道systick其中的一個功能就是可以做定時器用而且非常精準,其他的許多功能還在研究。

        systick的4個寄存器,CTRL-控制寄存器,LOAD-重裝載寄存器,VAL-當前值寄存器,CALIB-校準寄存器。

        SYSTICK_CTRL 寄存器中只有0,1,2,16這四位是有效的。

        第 0 位:ENABLE,Systick 使能位 (0:關閉 Systick 功能;1:開啟 Systick功能)
        第 1 位:TICKINT,Systick 中斷使能位 (0:關閉 Systick 中斷;1:開啟Systick 中斷)
        第 2 位:CLKSOURCE,Systick 時鐘源選擇 (0:使用 HCLK/8 作為 Systick時鐘;1:使用 HCLK 作為 Systick 時鐘)
        第 16 位:COUNTFLAG,有些人這樣說的: SysTick 已經數到了 0,則該位為 1。如果讀取該位,該位將自動清零(我不太理解這句話,我的疑問是SYSTICK數到了0是不是說VAL寄存器從重裝載值遞減到了0,第二個就是SYSTICK數到0之后這個位是保持1還是返回到0,讀取該位自動清0是什么時候讀取。)這個先埋個疑問一會說說我的理解。

        SYSTICK_LOAD 重裝載寄存器,不用多說,假如你讓systick_val寄存器從100遞減到0,這個寄存器里面裝的就是100,只不過用二進制表示,但是這個寄存器雖然是32位的,但只有24位有效,其最高的八位保留,它能裝入最大值為0xFFFFFF(0xFFFFFF==0x00FFFFFF,C語言中二者的值是一樣的,如0x01==0x0001==0x00000001)。

        SYSTICK_CAL  當前值寄存器,書上說讀取它時返回當前寄存器的值,對他進行寫操作則清0,同時也對上面所說SYSTICK_CTRL中 第16位清0。我理解是這樣的,這個寄存器里面的值是不斷變化的,一個指令周期完成一次自減,至于如何自減我們無須討論太多,只需知道若選擇1KHZ的頻 率,則它在1秒的時間里可以變化1000次,每變化一次便可自減一次,換句話說,我們將1000裝入它時開始計時,逐步遞減999,998......到 它減到0計時結束剛好耗時1秒。

        SYSTICK_CALIB  校準寄存器,這個還沒研究透(都說一般用不到,但最終還得弄明白它),sorry!

        那么SYSTICK 的工作流程到底是怎樣實現定時的呢,下面以定時1ms為例。

        1s=1000ms=1000000us,首先 

        配置SysTick->CTRL=0x01;對照上面便知,先使能SYSTICK,關閉了中斷,選擇HCLK/8位工作頻率,狀態標志位清零;然后SysTick->LOAD=9000*ms;設置重裝載寄存器的值,我們的系統時鐘是72MHZ,上面我們選擇的8分頻也就是9MHZ,也就是說1ms變化9000次,然后SysTick->VAL=0x00;清 零當前寄存器值,前面我們說了,VAL寄存器是不斷自減的,并且只要它為0(無論是被寫入0還是自減到0)就自動裝入LOAD寄存器中的值再一次開始遞 減,這樣循環往復,那么VAL為0時的第二個動作是將CTAL寄存器的16位狀態位置1,而我們就是通過讀取CTAL寄存器的16位狀態位才能知道是否到 了1ms,這里也說一下上面埋下的疑問,這個狀態位其實像一個監視器一樣監視著VAL寄存器,只要VAL為0,它立刻置1,并且一直保持,直到對它讀取時 它才又一次被清0。

        緊接著判斷1ms是否達到,do{...}while(...)語句,主要判斷CTRL寄存器中的16位是否為1,temp=SysTick->CTRL;將CTRL中的值傳遞給變量temp,注意while中的是重點, while((temp&0x01)&&(!(temp&(1<<16))));說 實話我看到這個語句真的不知道什么意思,C語言學的還不算透徹,這里面其實不只是判斷CTRL中的標志位,還判斷了systick是否失能,如果 systick失能則在此處為0繼續執行程序不再進行判斷。先整體看看這個語句的結構,語句1&&語句2,這個“&&” 表示邏輯與操作和按位與“&”相似,是有順序執行的,先判斷語句1,如果是真則判斷語句2,語句2為真則結果為真(1),語句2為假則結果為假 (0);若語句1為假,則不再對語句2進行判斷,直接輸出為假(0)。那么如上,語句1(temp&0x01)是判斷systick是使能還是失 能,若使能則語句1為真繼續判斷語句2,若失能則語句1為假,則整個語句為假程序向下執行,不再循環。既然語句1為真則繼續判斷語句2(!(temp&(1<<16)),它才是真正判斷CTRL標志位的,這個應該很好理解,如果CTRL標志位為1,則語句2為假(0),則整個語句為假(0),向下執行程序(systick正好產生了1ms的時間間隔)。

         

        這么點程序,其實要說的可真不少,ARM真的太深奧了。以上這種方式是對寄存器直接操作,也可用stm32 提供的SYSTICK函數,不過我感覺想弄懂它是怎么工作的還是要學習它相關的寄存器。函數庫只是為了方便開發,在開發大程序是有一定的優勢。好了最后看一下我的軟仿圖吧:

         


        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮