STM8的C語言編程1-14講完整版.doc_第1頁
STM8的C語言編程1-14講完整版.doc_第2頁
STM8的C語言編程1-14講完整版.doc_第3頁
STM8的C語言編程1-14講完整版.doc_第4頁
STM8的C語言編程1-14講完整版.doc_第5頁
已閱讀5頁,還剩26頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

STM8S的C語言編程(1)- 基本程序與啟動代碼現(xiàn)在幾乎所有的單片機都能用C語言編程了,采用C語言編程確實能帶來很多好處,至少可讀性比匯編語言強多了。在STM8的開發(fā)環(huán)境中,可以通過新建一個工程,自動地建立起一個C語言的框架,生成后開發(fā)環(huán)境會自動生成2個C語言的程序,一個是main.c,另一個是stm8_interrupt_vector.c。main.c中就是一個空的main()函數(shù),如下所示:/* MAIN.C file* * Copyright (c) 2002-2005 STMicroelectronics*/main() while (1);而在stm8_interrupt_vector.c中,就是聲明了對應該芯片的中斷向量,如下所示:/* BASIC INTERRUPT VECTOR TABLE FOR STM8 devices* Copyright (c) 2007 STMicroelectronics*/typedef void far (*interrupt_handler_t)(void);struct interrupt_vector unsigned char interrupt_instruction; interrupt_handler_t interrupt_handler;far interrupt void NonHandledInterrupt (void) /* in order to detect unexpected events during development, it is recommended to set a breakpoint on the following instruction */ return;extern void _stext(); /* startup routine */struct interrupt_vector const _vectab = 0x82, (interrupt_handler_t)_stext, /* reset */ 0x82, NonHandledInterrupt, /* trap */ 0x82, NonHandledInterrupt, /* irq0 */ 0x82, NonHandledInterrupt, /* irq1 */ 0x82, NonHandledInterrupt, /* irq2 */ 0x82, NonHandledInterrupt, /* irq3 */ 0x82, NonHandledInterrupt, /* irq4 */ 0x82, NonHandledInterrupt, /* irq5 */ 0x82, NonHandledInterrupt, /* irq6 */ 0x82, NonHandledInterrupt, /* irq7 */ 0x82, NonHandledInterrupt, /* irq8 */ 0x82, NonHandledInterrupt, /* irq9 */ 0x82, NonHandledInterrupt, /* irq10 */ 0x82, NonHandledInterrupt, /* irq11 */ 0x82, NonHandledInterrupt, /* irq12 */ 0x82, NonHandledInterrupt, /* irq13 */ 0x82, NonHandledInterrupt, /* irq14 */ 0x82, NonHandledInterrupt, /* irq15 */ 0x82, NonHandledInterrupt, /* irq16 */ 0x82, NonHandledInterrupt, /* irq17 */ 0x82, NonHandledInterrupt, /* irq18 */ 0x82, NonHandledInterrupt, /* irq19 */ 0x82, NonHandledInterrupt, /* irq20 */ 0x82, NonHandledInterrupt, /* irq21 */ 0x82, NonHandledInterrupt, /* irq22 */ 0x82, NonHandledInterrupt, /* irq23 */ 0x82, NonHandledInterrupt, /* irq24 */ 0x82, NonHandledInterrupt, /* irq25 */ 0x82, NonHandledInterrupt, /* irq26 */ 0x82, NonHandledInterrupt, /* irq27 */ 0x82, NonHandledInterrupt, /* irq28 */ 0x82, NonHandledInterrupt, /* irq29 */;在stm8_interrupt_vector.c中,除了定義了中斷向量表外,還定義了空的中斷服務程序,用于那些不用的中斷。當然在自動建立時,所有的中斷服務都是空的,因此,除了第1個復位的向量外,其它都指向那個空的中斷服務函數(shù)。生成框架后,就可以用Build菜單下的Rebuild All對項目進行編譯和連接,生成所需的目標文件,然后就可以加載到STM8的芯片中,這里由于main()函數(shù)是一個空函數(shù),因此沒有任何實際的功能。不過我們可以把這個框架對應的匯編代碼反出來,看看C語言生成的代碼,這樣可以更深入地了解C語言編程的特點。生成的代碼包括4個部分,如圖1、圖2、圖3、圖4所示。 圖1 圖2 圖3 圖4 圖1顯示的是從內(nèi)存地址8000H開始的中斷向量表,中斷向量表中的第1行82008083H為復位后單片機運行的第1跳指令的地址。從表中可以看出,單片機復位后,將從8083H開始運行。其它行的中斷向量都指向同一個位置的中斷服務程序80D0H。 圖2顯示的是3個字節(jié),前2個字節(jié)8083H為復位后的第1條指令的地址,第3個字節(jié)是一個常量0,后面的啟動代碼要用到。 圖3顯示的是啟動代碼,啟動代碼中除了初始化堆棧指針外,就是初始化RAM單元。由于目前是一個空的框架,因此在初始化完堆棧指針(設置成0FFFH)后,由于8082H單元的內(nèi)容為0,因此程序就跳到了80B1H,此處是一個循環(huán),將RAM單元從0到5初始化成0。然后由于寄存器X設置成0100H,就直接通過CALL main進入C的main()函數(shù)。 圖4顯示的是main()函數(shù)和中斷服務函數(shù),main()函數(shù)對應的代碼就是一個無限的循環(huán),而中斷服務函數(shù)就一條指令,即中斷返回指令。 通過分析,可以看出用C語言編程時,比匯編語言編程時,就是多出了一段啟動代碼。 2010-7-30STM8的C語言編程(2) 變量空間的分配 STM8的C語言編程(2) 變量空間的分配采用C這樣的高級語言,其實可以不用關(guān)心變量在存儲器空間中是如何具體分配的。但如果了解如何分配,對編程還是有好處的,尤其是在調(diào)試時。例如下面的程序定義了全局變量數(shù)組buffer和一個局部變量i,在RAM中如何分配的呢?/* MAIN.C file* * Copyright (c) 2002-2005 STMicroelectronics*/unsigned char buffer10; / 定義全局變量main() unsigned char i; / 定義局部變量 for(i=0;i10;i+) bufferi = 0x55; 我們可以通過DEBUG中的反匯編窗口,看到如下的對應代碼:從這段代碼中可以看到,全局變量buffer被分配到空間從地址0000H到0009H。而局部變量i則在堆??臻g中分配,通過PUSH A指令,將堆棧指針減1,騰出一個字節(jié)的空間,而SP+1指向的空間就是分配給局部變量使用的空間。由此可以得出初步的結(jié)論,對于全局變量,內(nèi)存分配是從低地址0000H開始向上分配的。而局部變量則是在堆??臻g中分配。另外從上一篇文章中,可以知道堆棧指針初始化時為0FFFH。而根據(jù)PUSH指令的定義,當壓棧后堆棧指針減1。因此堆棧是從上往下使用的。因此根據(jù)內(nèi)存分配和堆棧使用規(guī)則,我們在程序設計時,不能定義過多的變量,免得沒有空間給堆棧使用。換句話說,當定義變量時,一定要考慮到堆棧空間,尤其是那些復雜的系統(tǒng),程序調(diào)用層數(shù)多,這樣就會占用大量的堆棧空間。總之,在單片機的程序設計時,由于RAM空間非常有限,要充分考慮到全局變量、局部變量、程序調(diào)用層數(shù)和中斷服務調(diào)用對空間的占用。STM8的C語言編程(3) GPIO輸出 STM8的C語言編程(3) GPIO輸出與前些日子寫的用匯編語言進行的實驗一樣,從今天開始,要在ST的三合一開發(fā)板上,用C語言編寫程序,進行一系列的實驗。首先當然從最簡單的LED指示燈閃爍的實驗開始。開發(fā)板上的LED1接在STM8的PD3上,因此要將PD3設置成輸出模式,為了提高高電平時的輸出電流,要將其設置成推挽輸出方式。這主要通過設置對應的DDR/CR1/CR2寄存器實現(xiàn)。利用ST的開發(fā)工具,先生成一個C語言程序的框架,然后修改其中的main.c,修改后的代碼如下。編譯通過后,下載到開發(fā)板,運行程序,可以看到LED1在閃爍,且閃爍的頻率為5HZ。/* MAIN.C file* * Copyright (c) 2002-2005 STMicroelectronics*/#include STM8S207C_S.h/ 函數(shù)功能:延時函數(shù)/ 輸入?yún)?shù):ms - 要延時的毫秒數(shù),這里假設CPU的主頻為2MHZ/ 輸出參數(shù):無/ 返 回 值:無/ 備 注:無void DelayMS(unsigned int ms) unsigned char i; while(ms != 0) for(i=0;i250;i+) for(i=0;i75;i+) ms-; / 函數(shù)功能:主函數(shù)/ 初始化GPIO端口PD3,驅(qū)動PD3為高電平和低電平/ 輸入?yún)?shù):ms - 要延時的毫秒數(shù),這里假設CPU的主頻為2MHZ/ 輸出參數(shù):無/ 返 回 值:無/ 備 注:無main() PD_DDR = 0x08; PD_CR1 = 0x08; / 將PD3設置成推挽輸出 PD_CR2 = 0x00; while(1) PD_ODR = PD_ODR | 0x08; / 將PD3的輸出設置成1 DelayMS(100); / 延時100MS PD_ODR = PD_ODR & 0xF7; / 將PD3的輸出設置成0 DelayMS(100); / 延時100MS 需要注意的是,當生成完框架后,為了能方便使用STM8的寄存器名字,必須包括STM8S207C_S.h,最好將該文件拷貝到C:Program FilesSTMicroelectronicsst_toolsetinclude目錄下,拷貝到工程目錄下?;蛘邔⒃撀窂教顚懙皆摴こ痰腟ettings中的C Compiler選項Preprocessor的Additional include中,這樣編譯時才會找到該文件。STM8的C語言編程(4) GPIO輸出和輸入 STM8的C語言編程(3) GPIO輸出和輸入今天要進行的實驗,是利用GPIO進行輸入和輸出。在ST的三合一開發(fā)板上,按鍵接在GPIO的PD7上,LED接在GPIO的PD3上,因此我們要將GPIO的PD7初始化成輸入,PD3初始化成輸出。關(guān)于GPIO的引腳設置,主要是要初始化方向寄存器DDR,控制寄存器1(CR1)和控制寄存器2(CR2),寄存器的每一位對應GPIO的每一個引腳。具體的設置功能定義如下:DDR CR1 CR2 引腳設置0 0 0 懸浮輸入0 0 1 上拉輸入0 1 0 中斷懸浮輸入0 1 1 中斷上拉輸入1 0 0 開漏輸出1 1 0 推挽輸出1 X 1 輸出(最快速度為10MHZ)另外,輸出引腳對應的寄存器為ODR,輸入引腳對應的寄存器為IDR。下面的程序是檢測按鍵的狀態(tài),當按鍵按下時,點亮LED,當按鍵抬起時,熄滅LED。同樣也是利用ST的開發(fā)工具,先生成一個C語言程序的框架,然后修改其中的main.c,修改后的代碼如下。編譯通過后,下載到開發(fā)板,運行程序,按下按鍵,LED就點亮,抬起按鍵,LED就熄滅了。另外,要注意,將STM8S207C_S.h拷貝到當前項目的目錄下。/ 程序描述:檢測開發(fā)板上的按鍵,若按下,則點亮LED,若抬起,則熄滅LED/ 按鍵接在MCU的GPIO的PD7上/ LED接在MCU的GPIO的PD3上#include STM8S207C_S.hmain() PD_DDR = 0x08; PD_CR1 = 0x08; / 將PD3設置成推挽輸出 PD_CR2 = 0x00; while(1) / 進入無限循環(huán) if(PD_IDR & 0x80) = 0x80) / 讀入PD7的引腳信號 PD_ODR = PD_ODR & 0xF7; / 如果PD7為1,則將PD3的輸出設置成0,熄滅LED else PD_ODR = PD_ODR | 0x08; / 否則,將PD3的輸出設置成1,點亮LED STM8的C語言編程(5)8位定時器應用之一 STM8的C語言編程(5)8位定時器應用之一在STM8單片機中,有多種定時器資源,既有8位的定時器,也有普通的16位定時器,還有高級的定時器。今天的實驗是用最簡單的8位定時器TIM4來進行延時,然后驅(qū)動LED閃爍。為了簡單起見,這里是通過程序查詢定時器是否產(chǎn)生更新事件,來判斷定時器的延時是否結(jié)束。同樣還是利用ST的開發(fā)工具,生成一個C程序的框架,然后修改其中的main.c,修改后的代碼如下。編譯通過后,下載到開發(fā)板,運行程序,可以看到LED在閃爍,或者用示波器可以在LED引腳上看到方波。在這里要特別提醒的是,從ST給的手冊上看,這個定時器中的計數(shù)器是一個加1計數(shù)器,但本人在實驗過程中感覺不太對,經(jīng)過反復的實驗,我認為應該是一個減1計數(shù)器(也許是我拿的手冊不對,或許是理解上有誤)。例如,當給定時器中的自動裝載寄存器裝入255時,產(chǎn)生的方波頻率最小,就象下面代碼中計算的那樣,產(chǎn)生的方波頻率為30HZ左右。若初始化時給自動裝載寄存器裝入1,則產(chǎn)生的方波頻率最大,大約為3.9K左右。也就是說實際的分頻數(shù)為ARR寄存器的值+1。/ 程序描述:通過初始化定時器4,進行延時,驅(qū)動LED閃爍/ LED接在MCU的GPIO的PD3上#include STM8S207C_S.hmain() / 首先初始化GPIO PD_DDR = 0x08; PD_CR1 = 0x08; / 將PD3設置成推挽輸出 PD_CR2 = 0x00; / 然后初始化定時器4 TIM4_IER = 0x00; / 禁止中斷 TIM4_EGR = 0x01; / 允許產(chǎn)生更新事件 TIM4_PSCR = 0x07; / 計數(shù)器時鐘=主時鐘/128=2MHZ/128 / 相當于計數(shù)器周期為64uS TIM4_ARR = 255; / 設定重裝載時的寄存器值,255是最大值 TIM4_CNTR = 255; / 設定計數(shù)器的初值 / 定時周期=(ARR+1)*64=16320uS TIM4_CR1 = 0x01; / b0 = 1,允許計數(shù)器工作 / b1 = 0,允許更新 / 設置控制器,啟動定時器 while(1) / 進入無限循環(huán) while(TIM4_SR1 & 0x81) = 0x00); / 等待更新標志 TIM4_SR1 = 0x00; / 清除更新標志 PD_ODR = PD_ODR 0x08; / LED驅(qū)動信號取反 / LED閃爍頻率=2MHZ/128/255/2=30.63 STM8與匯編語言(9)EEPROM應用EEPROM是單片機應用系統(tǒng)中經(jīng)常會用到的存儲器,它主要用來保存一些掉電后需要保持不變的數(shù)據(jù)。在以前的單片機系統(tǒng)中,通常都是在單片機外面再擴充一個EEPROM芯片,這種方法除了增加成本外,也降低了可靠性?,F(xiàn)在,很多單片機的公司都推出了集成有小容量EEPROM的單片機,這樣就方便了使用,降低了成本,提高了可靠性。STM8單片機芯片內(nèi)部也集成有EEPROM,容量從640字節(jié)到2K字節(jié)。最為特色的是,在STM8單片機中,對EEPROM的訪問就象常規(guī)的RAM一樣,非常方便。EEPROM的地址空間與內(nèi)存是統(tǒng)一編址的,地址從004000H開始,大小根據(jù)不同的芯片型號而定。下面的實驗程序,就是先給EEPROM中的第一個單元004000H寫入55H,然后再讀到全局變量ch中。同樣還是利用ST的開發(fā)工具,生成一個C語言程序的框架,然后修改其中的main.c,修改后的代碼如下。/ 程序描述:對芯片內(nèi)部的EEPROM存儲單元進行實驗#include STM8S207C_S.hunsigned char ch; main() unsigned char *p; p = (unsigned char *)0x4000; / 指針p指向芯片內(nèi)部的EEPROM第一個單元 / 對數(shù)據(jù)EEPROM進行解鎖 do FLASH_DUKR = 0xae; / 寫入第一個密鑰 FLASH_DUKR = 0x56; / 寫入第二個密鑰 while(FLASH_IAPSR & 0x08) = 0); / 若解鎖未成功,則重新再來 *p = 0xaa; / 寫入第一個字節(jié) while(FLASH_IAPSR & 0x04) = 0); / 等待寫操作成功 ch = *p; / 將寫入的內(nèi)容讀到變量ch中 while(1) ; 這里要注意的是,2個密鑰的順序,與STM8的用戶手冊上是相反的,如果按照手冊上的順序,就會停留在dowhile循環(huán)中。具體原因,也不是很清楚,也可能是我拿到的手冊(中文和英文的都一樣)太舊了,或者是理解有誤。 另外,上面的實驗程序中,ch不能為局部變量,否則的話,在調(diào)試環(huán)境中跟蹤ch變量時,顯示的結(jié)果就不對,通過反匯編,我覺得是編譯有問題,當定義成局部變量時,ch = *p的匯編代碼如下:main.c:23 ch = *p; / 將寫入的內(nèi)容讀到變量ch中 0x80f0 0x7B01 LD A,(0x01,SP) LD A,(0x01,SP) 0x80f2 0x97 LD XL,A LD XL,A 0x80f3 0x1E02 LDW X,(0x02,SP) LDW X,(0x02,SP) 0x80f5 0xF6 LD A,(X) LD A,(X) 0x80f6 0x97 LD XL,A LD XL,A如果將ch定義成全局變量,則匯編代碼為:main.c:22 ch = *p; / 將寫入的內(nèi)容讀到變量ch中 0x80ef 0x1E01 LDW X,(0x01,SP) LDW X,(0x01,SP) 0x80f1 0xF6 LD A,(X) LD A,(X) 0x80f2 0xB700 LD 0x00,A LD 0x00,A 這一段代碼的分析僅供參考,本人使用的開發(fā)環(huán)境為STVD4.1.0,編譯器版本號為:COSMIC的CxSTM84.2.4。STM8的C語言編程(10) 修改CPU的時鐘在有些單片機的應用系統(tǒng)中,并不需要CPU運行在多高的頻率。在低頻率下運行,芯片的功耗會大大下降。STM8單片機在運行過程中,可以隨時修改CPU運行時鐘頻率,非常方便。實現(xiàn)這一功能,主要涉及到時鐘分頻寄存器(CLK_CKDIVR)。時鐘分頻寄存器是一個8位的寄存器,高3位保留,位4和位3用于定義高速內(nèi)部時鐘的預分頻,而位2到位0則用于CPU時鐘的分頻。這5位的詳細定義如下:位4 位3 高速內(nèi)部時鐘的分頻系數(shù)0 0 10 1 21 0 41 1 8位2 位1 位0 CPU時鐘的分頻系數(shù)0 0 0 10 0 1 20 1 0 40 1 1 81 0 0 161 0 1 321 1 0 641 1 1 128假設我們使用內(nèi)部的高速RC振蕩器,其頻率為16MHZ,當位4為0,位3為1時,則內(nèi)部高速時鐘的分頻系數(shù)為2,因此輸出的主時鐘為8MHZ。當位2為0,位1為1,位0為0時,CPU時鐘的分頻系數(shù)為4,即CPU時鐘=主時鐘/4=2MHZ。下面的實驗程序首先將CPU的運行時鐘設置在8MHZ,然后快速閃爍LED指示燈。接著,通過修改主時鐘的分頻系數(shù)和CPU時鐘的分頻系數(shù),將CPU時鐘頻率設置在500KHZ,然后再慢速閃爍LED指示燈。通過觀察LED指示燈的閃爍頻率,可以看到,同樣的循環(huán)代碼,由于CPU時鐘頻率的改變,閃爍頻率和時間長短都發(fā)生了變化。同樣還是利用ST的開發(fā)工具,生成一個C語言程序的框架,然后修改其中的main.c,修改后的代碼如下。修改后的代碼編譯連接后,就可以下載到開發(fā)板上,運行后會看到LED的閃爍頻率有明顯的變化。/ 程序描述:通過修改CPU時鐘的分頻系數(shù),來改變CPU的運行速度#include STM8S207C_S.h/ 函數(shù)功能:延時函數(shù)/ 輸入?yún)?shù):ms - 要延時的毫秒數(shù),這里假設CPU的主頻為2MHZ/ 輸出參數(shù):無/ 返 回 值:無/ 備 注:無void DelayMS(unsigned int ms) unsigned char i; while(ms != 0) for(i=0;i250;i+) for(i=0;i75;i+) ms-; main()int i; PD_DDR = 0x08; PD_CR1 = 0x08; / 將PD3設置成推挽輸出 PD_CR2 = 0x00; CLK_SWR = 0xE1; / 選擇芯片內(nèi)部的16MHZ的RC振蕩器為主時鐘 for(;) / 進入無限循環(huán) / 下面設置CPU時鐘分頻器,使得CPU時鐘=主時鐘 / 通過發(fā)光二極管,可以看出,程序運行的速度確實明顯提高了 CLK_CKDIVR = 0x08; / 主時鐘 = 16MHZ / 2 / CPU時鐘 = 主時鐘 = 8MHZ for(i=0;i10;i+) PD_ODR = 0x08; DelayMS(100); PD_ODR = 0x00; DelayMS(100); / 下面設置CPU時鐘分頻器,使得CPU時鐘=主時鐘/4 / 通過發(fā)光二極管,可以看出,程序運行的速度確實明顯下降了 CLK_CKDIVR = 0x1A; / 主時鐘 = 16MHZ / 8 / CPU時鐘 = 主時鐘 / 4 = 500KHZ for(i=0;i10;i+) PD_ODR = 0x08; DelayMS(100); PD_ODR = 0x00; DelayMS(100); STM8的C語言編程(10) 修改CPU的時鐘在有些單片機的應用系統(tǒng)中,并不需要CPU運行在多高的頻率。在低頻率下運行,芯片的功耗會大大下降。STM8單片機在運行過程中,可以隨時修改CPU運行時鐘頻率,非常方便。實現(xiàn)這一功能,主要涉及到時鐘分頻寄存器(CLK_CKDIVR)。時鐘分頻寄存器是一個8位的寄存器,高3位保留,位4和位3用于定義高速內(nèi)部時鐘的預分頻,而位2到位0則用于CPU時鐘的分頻。這5位的詳細定義如下:位4 位3 高速內(nèi)部時鐘的分頻系數(shù)0 0 10 1 21 0 41 1 8位2 位1 位0 CPU時鐘的分頻系數(shù)0 0 0 10 0 1 20 1 0 40 1 1 81 0 0 161 0 1 321 1 0 641 1 1 128假設我們使用內(nèi)部的高速RC振蕩器,其頻率為16MHZ,當位4為0,位3為1時,則內(nèi)部高速時鐘的分頻系數(shù)為2,因此輸出的主時鐘為8MHZ。當位2為0,位1為1,位0為0時,CPU時鐘的分頻系數(shù)為4,即CPU時鐘=主時鐘/4=2MHZ。下面的實驗程序首先將CPU的運行時鐘設置在8MHZ,然后快速閃爍LED指示燈。接著,通過修改主時鐘的分頻系數(shù)和CPU時鐘的分頻系數(shù),將CPU時鐘頻率設置在500KHZ,然后再慢速閃爍LED指示燈。通過觀察LED指示燈的閃爍頻率,可以看到,同樣的循環(huán)代碼,由于CPU時鐘頻率的改變,閃爍頻率和時間長短都發(fā)生了變化。同樣還是利用ST的開發(fā)工具,生成一個C語言程序的框架,然后修改其中的main.c,修改后的代碼如下。修改后的代碼編譯連接后,就可以下載到開發(fā)板上,運行后會看到LED的閃爍頻率有明顯的變化。/ 程序描述:通過修改CPU時鐘的分頻系數(shù),來改變CPU的運行速度#include STM8S207C_S.h/ 函數(shù)功能:延時函數(shù)/ 輸入?yún)?shù):ms - 要延時的毫秒數(shù),這里假設CPU的主頻為2MHZ/ 輸出參數(shù):無/ 返 回 值:無/ 備 注:無void DelayMS(unsigned int ms) unsigned char i; while(ms != 0) for(i=0;i250;i+) for(i=0;i75;i+) ms-; main()int i; PD_DDR = 0x08; PD_CR1 = 0x08; / 將PD3設置成推挽輸出 PD_CR2 = 0x00; CLK_SWR = 0xE1; / 選擇芯片內(nèi)部的16MHZ的RC振蕩器為主時鐘 for(;) / 進入無限循環(huán) / 下面設置CPU時鐘分頻器,使得CPU時鐘=主時鐘 / 通過發(fā)光二極管,可以看出,程序運行的速度確實明顯提高了 CLK_CKDIVR = 0x08; / 主時鐘 = 16MHZ / 2 / CPU時鐘 = 主時鐘 = 8MHZ for(i=0;i10;i+) PD_ODR = 0x08; DelayMS(100); PD_ODR = 0x00; DelayMS(100); / 下面設置CPU時鐘分頻器,使得CPU時鐘=主時鐘/4 / 通過發(fā)光二極管,可以看出,程序運行的速度確實明顯下降了 CLK_CKDIVR = 0x1A; / 主時鐘 = 16MHZ / 8 / CPU時鐘 = 主時鐘 / 4 = 500KHZ for(i=0;i10;i+) PD_ODR = 0x08; DelayMS(100); PD_ODR = 0x00; DelayMS(100); STM8的C語言編程(11) 切換時鐘源STM8單片機的時鐘源非常豐富,芯片內(nèi)部既有16MHZ的高速RC振蕩器,也有128KHZ的低速RC振蕩器,外部還可以接一個高速的晶體振蕩器。在系統(tǒng)運行過程中,可以根據(jù)需要,自由地切換。單片機復位后,首先采用的是內(nèi)部的高速RC振蕩器,且分頻系數(shù)為8,因此CPU的上電運行的時鐘頻率為2MHZ。切換時鐘源,主要涉及到的寄存器有:主時鐘切換寄存器CLK_SWR和切換控制寄存器CLK_SWCR。主時鐘切換寄存器的復位值為0xe1,表示切換到內(nèi)部的高速RC振蕩器上。當往該寄存器寫入0xb4時,表示切換到外部的高速晶體振蕩器上。在實際切換過程中,應該先將切換控制寄存器中的SWEN(第1位)設置成1,然后設置CLK_SWCR的值,最后要判斷切換控制寄存器中的SWIF標志是否切換成功。下面的實驗程序首先將主時鐘源切換到外部的晶體振蕩器上,振蕩頻率為8MHZ,然后,然后快速閃爍LED指示燈。接著,將主時鐘源又切換到內(nèi)部的振蕩器上,振蕩頻率為2MHZ,然后再慢速閃爍LED指示燈。通過觀察LED指示燈的閃爍頻率,可以看到,同樣的循環(huán)代碼,由于主時鐘源的改變的改變,閃爍頻率和時間長短都發(fā)生了變化。同樣還是利用ST的開發(fā)工具,生成一個C語言程序的框架,然后修改其中的main.c,修改后的代碼如下。/ 程序描述:通過切換CPU的主時鐘源,來改變CPU的運行速度#include STM8S207C_S.h/ 函數(shù)功能:延時函數(shù)/ 輸入?yún)?shù):ms - 要延時的毫秒數(shù),這里假設CPU的主頻為2MHZ/ 輸出參數(shù):無/ 返 回 值:無/ 備 注:無void DelayMS(unsigned int ms) unsigned char i; while(ms != 0) for(i=0;i250;i+) for(i=0;i75;i+) ms-; main() int i; / 將PD3設置成推挽輸出,以便推動LED PD_DDR = 0x08; PD_CR1 = 0x08; PD_CR2 = 0x00; / 啟動外部高速晶體振蕩器 CLK_ECKR = 0x01; / 允許外部高速振蕩器工作 while(CLK_ECKR & 0x02) = 0x00); / 等待外部高速振蕩器準備好 / 注意,復位后CPU的時鐘源來自內(nèi)部的RC振蕩器 for(;) / 進入無限循環(huán) / 下面將CPU的時鐘源切換到外部的高速晶體振蕩器上,在開發(fā)板上的頻率為8MHZ / 通過發(fā)光二極管,可以看出,程序運行的速度確實明顯提高了 CLK_SWCR = CLK_SWCR | 0x02; / SWEN - 1 CLK_SWR = 0xB4; / 選擇芯片外部的高速振蕩器為主時鐘 while(CLK_SWCR & 0x08) = 0); / 等待切換成功 CLK_SWCR = CLK_SWCR & 0xFD; / 清除切換標志 for(i=0;i10;i+) / LED高速閃爍10次 PD_ODR = 0x08; DelayMS(100); PD_ODR = 0x00; DelayMS(100); / 下面將CPU的時鐘源切換到內(nèi)部的RC振蕩器上,由于CLK_CKDIVR的復位值為0x18 / 所以16MHZ的RC振蕩器要經(jīng)過8分頻后才作為主時鐘,因此頻率為2MHZ / 通過發(fā)光二極管,可以看出,程序運行的速度確實明顯下降了 CLK_SWCR = CLK_SWCR | 0x02; / SWEN - 1 CLK_SWR = 0xE1; / 選擇HSI為主時鐘源 while(CLK_SWCR & 0x08) = 0); / 等待切換成功 CLK_SWCR = CLK_SWCR & 0xFD; / 清除切換標志 for(i=0;i10;i+) / LED低速閃爍10次 PD_ODR = 0x08; DelayMS(100); PD_ODR = 0x00; DelayMS(100); STM8的C語言編程(12) AD轉(zhuǎn)換在許多的單片機應用系統(tǒng)中,都需要A/D轉(zhuǎn)換器,將模擬量轉(zhuǎn)換成數(shù)字量。在STM8單片機中,提供的是10位的A/D,通道數(shù)隨芯片不同而不同,少的有4個通道,多的則有16個通道。下面的實驗程序首先對A/D輸入進行采樣,然后將采樣結(jié)果的高8位(丟棄最低的2位),作為延時參數(shù)去調(diào)用延時子程序,然后再去驅(qū)動LED控制信號。因此不同的采樣值,決定了LED的閃爍頻率。當旋轉(zhuǎn)ST三合一開發(fā)板上的電位器時,可以看到LED的閃爍頻率發(fā)生變化。同樣還是利用ST的開發(fā)工具,生成一個C語言程序的框架,然后修改其中的main.c,修改后的代碼如下。/ 程序描述:通過AD模塊,采樣電位器的電壓,改變LED的閃爍頻率#include STM8S207C_S.h/ 函數(shù)功能:延時函數(shù)/ 輸入?yún)?shù):ms -

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論