welcom ! Handel home

2014年6月17日 星期二

ST32 M3 basic source code 註釋說明 範例


flash 晶片內部記憶體flash操作函數
我的理解——對晶片內部flash進行操作的函數,包括讀取,狀態,擦除,寫入等等,可以允許程式去操作flash上的資料。
基礎應用1FLASH時序延遲幾個週期,等待匯流排同步操作。推薦按照單片機系統運行頻率,
024MHz時,取Latency=0
2448MHz時,取Latency=1
48~72MHz時,取Latency=2

所有程式中必須的
用法:FLASH_SetLatency(FLASH_Latency_2);
位置:RCC初始化子函數裡面,時鐘起振之後。

基礎應用2,開啟FLASH預讀緩衝功能,加速FLASH的讀取。所有程式中必須的
用法:FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
位置:RCC初始化子函數裡面,時鐘起振之後。

3         lib:調試所有外設初始化的函數。
我的理解——不理解,也不需要理解。只要知道所有外設在調試的時候,EWRAM需要從這個函數裡面獲得調試所需資訊的位址或者指標之類的資訊。
基礎應用1,只有一個函數debug。所有程式中必須的。
用法:        
#ifdef DEBUG
        debug();
#endif
       位置:main函數開頭,聲明變數之後。

4         nvic:系統中斷管理。
我的理解——管理系統內部的中斷,負責打開和關閉中斷。
基礎應用1,中斷的初始化函數,包括設置中斷向量表位置,和開啟所需的中斷兩部分。所有程式中必須的。
用法:       
 void NVIC_Configuration(void)
{
   NVIC_InitTypeDef NVIC_InitStructure;                   //中斷管理恢復默認參數
   #ifdef   VECT_TAB_RAM   //如果C/C++ Compiler\Preprocessor\Defined symbols中的定義了VECT_TAB_RAM(見程式庫更改內容的表格)
       NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //則在RAM調試
   #else                                                                   //如果沒有定義VECT_TAB_RAM
       NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);//則在Flash裡調試
   #endif                                                                   //結束判斷語句

   //以下為中斷的開啟過程,不是所有程式必須的。
   //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
   //設置NVIC優先順序分組,方式。
   //注:一共16個優先順序,分為搶佔式和回應式。兩種優先順序所占的數量由此代碼確定,NVIC_PriorityGroup_x可以是01234,分別代表搶佔優先順序有124816個和回應優先順序有168421個。規定兩種優先順序的數量後,所有的中斷級別必須在其中選擇,搶佔級別高的會打斷其他中斷優先執行,而回應級別高的會在其他中斷執行完優先執行。

   //NVIC_InitStructure.NVIC_IRQChannel = 中斷通道名; //開中斷,中斷名稱見函式程式庫
   //NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //搶佔優先順序
   //NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;         //回應優先順序
   //NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //啟動此通道的中斷
  //NVIC_Init(&NVIC_InitStructure);                                     //中斷初始化
}

5         rcc:單片機時鐘管理。
我的理解——管理外部、內部和外設的時鐘,設置、打開和關閉這些時鐘。
基礎應用1:時鐘的初始化函數過程——
用法:
void RCC_Configuration(void)                                //時鐘初始化函數
{
   ErrorStatus HSEStartUpStatus;                                     //等待時鐘的穩定
   RCC_DeInit();                                                                //時鐘管理重置
   RCC_HSEConfig(RCC_HSE_ON);                                  //打開外部晶振
   HSEStartUpStatus = RCC_WaitForHSEStartUp();          //等待外部晶振就緒
   if (HSEStartUpStatus == SUCCESS)
   {
       FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//flash讀取緩衝,加速
       FLASH_SetLatency(FLASH_Latency_2);                      //flash操作的延時
       RCC_HCLKConfig(RCC_SYSCLK_Div1);                       //AHB使用系統時鐘
       RCC_PCLK2Config(RCC_HCLK_Div2);                          //APB2(高速)為HCLK的一半
       RCC_PCLK1Config(RCC_HCLK_Div2);                          //APB1(低速)為HCLK的一半
//注:AHB主要負責外部記憶體時鐘。PB2負責ADI/O,高級TIM,串口1APB1負責DAUSBSPII2CCAN,串口2345,普通TIM
      RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //PLLCLK = 8MHz * 9 = 72 MH
      RCC_PLLCmd(ENABLE);                                              //啟動PLL
      while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){}     //等待PLL啟動
      RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //PLL設置為系統時鐘源
      while (RCC_GetSYSCLKSource() != 0x08){}     //等待系統時鐘源的啟動
   }
   //RCC_AHBPeriphClockCmd(ABP2設備1 | ABP2設備2 |, ENABLE); //啟動AHP設備
   //RCC_APB2PeriphClockCmd(ABP2設備1 | ABP2設備2 |, ENABLE);//啟動ABP2設備
   //RCC_APB1PeriphClockCmd(ABP2設備1 | ABP2設備2 |, ENABLE); //啟動ABP1設備
}

6        exti:外部設備中斷函數

我的理解——外部設備通過引腳給出的硬體中斷,也可以產生軟體插斷,19個上升、下降或都觸發。EXTI0EXTI15連接到管腳,EXTI16連接到PVDVDD監視),EXTI17連接到RTC(鬧鐘),EXTI18連接到USB(喚醒)。
基礎應用1,設定外部中斷初始化函數。按需求,不是必須代碼。
用法: void EXTI_Configuration(void)
{
   EXTI_InitTypeDef EXTI_InitStructure;                               //外部設備中斷恢復默認參數
   EXTI_InitStructure.EXTI_Line = 通道1|通道2; //設定所需產生外部中斷的通道,一共19個。
   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;     //產生中斷
   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //上升下降沿都觸發
   EXTI_InitStructure.EXTI_LineCmd = ENABLE;             //啟動中斷的接收
   EXTI_Init(&EXTI_InitStructure);             //外部設備中斷啟動
}

7        dma:通過匯流排而越過CPU讀取外設資料

我的理解——通過DMA應用可以加速單片機外設、記憶體之間的資料傳輸,並在傳輸期間不影響CPU進行其他事情。這對於入門開發基本功能來說沒有太大必要,這個內容先行跳過。

8        systic:系統計時器
我的理解——可以輸出和利用系統時鐘的計數、狀態。
基礎應用1,精確計時的延時子函數。推薦使用的代碼。
用法:
static vu32 TimingDelay;                                                                               //全域變數聲明
void SysTick_Config(void)                                                                            //systick初始化函數
{
SysTick_CounterCmd(SysTick_Counter_Disable);                                  //停止系統計時器
SysTick_ITConfig(DISABLE); //停止systick中斷
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //systick使用HCLK作為時鐘源,頻率值除以8
SysTick_SetReload(9000);                                                                       //重置時間1毫秒(以72MHz為基礎計算)
SysTick_ITConfig(ENABLE);                                                                   //開啟systic中斷
}

void Delay (u32 nTime)                                                                                   //延遲一毫秒的函數
{
SysTick_CounterCmd(SysTick_Counter_Enable);                      //systic開始計時
   TimingDelay = nTime;                      //計時長度賦值給遞減變數
while(TimingDelay != 0); //檢測是否計時完成
SysTick_CounterCmd(SysTick_Counter_Disable);                                       //關閉計數器
SysTick_CounterCmd(SysTick_Counter_Clear);                      //清除計數值
}

void TimingDelay_Decrement(void) //遞減變數函數,函數名由stm32f10x_it.c中的中斷回應函式定義好了。
{
if (TimingDelay != 0x00) //檢測計數變數是否達到0
{ TimingDelay--; //計數變數遞減
}
}

注:建議熟練後使用,所涉及知識和設備太多,新手出錯的可能性比較大。新手可用簡化的延時函數代替:

void Delay(vu32 nCount)                                                                               //簡單延時函數
{
   for(; nCount != 0; nCount--);                                                                          //迴圈變數遞減計數
}

當延時較長,又不需要精確計時的時候可以使用嵌套迴圈:

void Delay(vu32 nCount)                      //簡單的長時間延時函數
{int i; //聲明內部遞減變數
   for(; nCount != 0; nCount--)                                                             //遞減變數計數
{for (i=0; i<0xffff i="" nbsp="" span="">內部迴圈遞減變數計數
}

9        gpioI/O設置函數

我的理解——所有輸入輸出管腳模式設置,可以是上下拉、浮空、開漏、類比、推挽模式,頻率特性為2M10M50M。也可以向該管腳直接寫入資料和讀取資料。

基礎應用1gpio初始化函數。所有程式必須。

用法:void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;                      //GPIO狀態恢復預設參數
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_標號 | GPIO_Pin_標號 ; //管腳位置定義,標號可以是NONEALL015
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;//輸出速度2MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //類比輸入模式
GPIO_Init(GPIOC, &GPIO_InitStructure); //CGPIO初始化
//注:以上四行代碼為一組,每組GPIO屬性必須相同,預設的GPIO參數為:ALL2MHzFLATING。如果其中任意一行與前一組相應設置相同,那麼那一行可以省略,由此推論如果前面已經將此行參數設定為默認參數(包括使用GPIO_InitTypeDef GPIO_InitStructure代碼),本組應用也是默認參數的話,那麼也可以省略。以下重複這個過程直到所有應用的管腳全部被定義完畢。
……
}

基礎應用2,向管腳寫入01

用法:GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x01);    //寫入1
基礎應用3,從管腳讀入01
用法:GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6)
                                                                                                          
 讓它跑起來,基本硬體功能的建立

0 實驗之前的準備

a) 接通串口轉接器

b) 下載IO與串口的原廠程式,編譯通過保證調試所需硬體正常。

1 flashlibnvicrccGPIO,基礎程式庫編寫

a) 這幾個庫函數中有一些函數是關於晶片的初始化的,每個程式中必用。為保障程式品質,初學階段要求嚴格遵守官方習慣。注意,官方程式庫常式中有個platform_config.h檔,是專門用來指定同類外設中第幾號外設被使用,就是說在main.c裡面所有外設序號用x代替,比如USARTx,程式會到這個頭檔中去查找到底是用那些外設,初學的時候參考常式別被這個所迷惑住。

b) 全部必用代碼取自庫函數所帶常式,並增加逐句注釋。

c) 習慣順序——Libdebug),RCC(包括Flash優化),NVICGPIO

d) 必用模組初始化函數的定義:

void RCC_Configuration(void); //定義時鐘初始化函數
void GPIO_Configuration(void); //定義管腳初始化函數
void NVIC_Configuration(void); //定義中斷管理初始化函數
void Delay(vu32 nCount); //定義延遲函數

e) Main中的初始化函式呼叫:
RCC_Configuration(); //時鐘初始化函式呼叫
NVIC_Configuration(); //中斷初始化函式呼叫
GPIO_Configuration(); //管腳初始化函式呼叫

f) Lib注意事項:
屬於LibDebug函數的調用,應該放在main函數最開始,不要改變其位置。

g) RCC注意事項:
Flash優化處理可以不做,但是兩句也不難也不用改參數……
根據需要開啟設備時鐘可以節省電能
時鐘頻率需要根據實際情況設置參數

h) NVIC注意事項
注意理解佔先優先順序和響應優先順序的分組的概念

i) GPIO注意事項
注意以後的過程中收集不同管腳應用對應的頻率和模式的設置。
作為高低電平的I/O,所需設置:RCC初始化裡面打開RCC_APB2
PeriphClockCmd(RCC_APB2Periph_GPIOA);GPIO裡面管腳設定:IO輸出(50MHzOut_PP);IO輸入(50MHzIPU);

j) GPIO應用
GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_RESET);//重置
GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x01);//寫入1
GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x00);//寫入0
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6) ;//讀入IO

k) 簡單Delay函數
void Delay(vu32 nCount)//簡單延時函數
{for(; nCount != 0; nCount--);}

實驗步驟:
RCC初始化函數裡添加:RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB , ENABLE);
不用其他中斷,NVIC初始化函數不用改

GPIO初始化代碼:

//IO輸入,GPIOB21011腳輸出
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 ;//管腳號
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //輸出速度
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //輸入輸出模式
    GPIO_Init(GPIOB, &GPIO_InitStructure);              //初始化

簡單的延遲函數:

void Delay(vu32 nCount)                   //簡單延時函數
{ for (; nCount != 0; nCount--);}           //迴圈計數延時

完成之後再在main.cwhile裡面寫一段:
GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x01);//寫入1
Delay0xffff;
GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x00);//寫入0
Delay0xffff;

就可以看到連接在PB2腳上的LED閃爍了,單片機就跑起來了。


沒有留言: