就我個人看來,研究一塊單片機,分為新手和老手兩種模式,新人迫切的想先用,你得告訴他們怎么樣最快的寫出一個能跑起來的程序,告訴他們每一個外設的使用方式,老手不同,用的單片機多了外設對於他們而言沒太多好奇的,中斷,無非配置中斷,連接中斷,打開中斷,中斷模式,中斷函數,定時器,無非打開時鍾,設置分頻率,設置值,等中斷到來計數,千篇一律,沒什么花樣
但是老手關注的是不同,這個和那個的差異是什么,這樣就能避免慣性思維,不會用錯,學起來差不多,都是對着手冊讀唄,但是學的心態不一樣,更加的舉重若輕
閑話少敘,下面說說STM8的時鍾系統
STM8時鍾系統看起來是這樣的,有一個外部輸入時鍾OSC,一個外部輸出時鍾CCO,CCO可選輸出
內部的時鍾五大塊,CPU時鍾,外設時鍾,看門狗時鍾,CAN總線時鍾以及自動喚醒時鍾
CPU時鍾的來源包括外部晶振,外部振盪器輸入,內部高速振盪器輸入,三種輸入經過主時鍾選擇,再經過主時鍾分頻輸出CPU以及內部窗口看門狗
外設時鍾和CPU時鍾來源一樣,並不經過主時鍾分頻,二十有一個外設使能控制,輸入到各個外設,從這里我們可以判斷,外設里面肯定還有分頻器
自動喚醒時鍾直接來源於內部低速振盪器或者直接來源於外部始終,經過選項字節選擇輸入
獨立看門狗的時鍾只可能來自於內部高速振盪器
而CAN總線的時鍾也是直接從晶振上獲取的,同時內部低速振盪器是可以關掉的
接下來我們看看寄存器
控制內部低速振盪器和內部高速振盪器的開關以及開關狀態標識,細節是什么,觀察這個復位值,0x01,也就是說,復位的時候內部低速振盪器使能這代表着系統復位的時候肯定是使用內部低速振盪器的,不用看文檔的其他部分這一點幾乎就能確定
外部時鍾使能以及時鍾狀態
八個位都是只讀,標識當前我們選用的系統主時鍾是誰,也就是框圖中master clock switch的標識
讓你來選擇哪一個做主時鍾
對時鍾切換的過程進行監控
時鍾分頻,一是內部高速時鍾的分頻,二是外部高速時鍾的分頻
還有一個2,用來確定各個外設是否連接到時鍾上,相當於外設使能,外設沒有時鍾是跑不起來的
時鍾安全系統配置
時鍾輸出的配置,也就是剛才說的CCO的來源
CAN總線的時鍾分頻
剩下來的一個是HIS的始終修正,另一個是SWIM時鍾的配置,都是不需要我們去關注的
初始化時鍾的流程包括
1. 想要選擇的主時鍾使能,等待穩定
2. 選擇主時鍾並進行切換,等待切換完成
3. 選擇系統時鍾分頻數
4. 選擇相應的外設時鍾
代碼如下
Clock.c
#include "clock.h" void ClockInit(u8 clockSel) { if(clockSel == HSE_CLOCK) { //切換到外部始終之前,因為我使用的是24M時鍾,所以需要修改插入flash等待時間 //此處講解選項字節再補上 //注意,下面這一段只能在使用16M一下時鍾的時候有用 CLK->ECKR |= 0x01;//使能外部晶振 while(!(CLK->ECKR & 0x02));//等待時鍾准備就緒 CLK->SWCR &= ~((1<<2)|(1<<3));//時鍾切換中斷禁止並清除中斷標志 CLK->SWR = 0xB4;//時鍾選擇為HSE while(CLK->SWCR & 0x01);//等待時鍾切換慢的結束 CLK->SWCR |= 0x01;//使能時鍾切換 while(CLK->CMSR != 0xB4);//等待系統時鍾切換到0xb4 CLK->CKDIVR = 0x00;//設置時鍾預分頻,設置為fmaster = fclock CLK->CCOR &= ~(1<<0);//禁止CCO輸出 //此時,應當關閉內部始終 CLK->ICKR &= ~0x01; } else if(clockSel == HSI_CLOCK) { CLK->ICKR |= 0x01;//使能內部高速時鍾 while(!(CLK->ICKR | 0x02));//等待准備就緒 CLK->SWCR &= ~((1<<2)|(1<<3));//時鍾切換中斷禁止並清除中斷標志 CLK->SWR = 0xE1;//時鍾選擇為HSI while(CLK->SWCR & 0x01);//等待時鍾切換慢的結束 CLK->SWCR |= 0x01;//使能時鍾切換 while(CLK->CMSR != 0xE1);//等待系統時鍾切換到0xb4 CLK->CKDIVR = 0x00;//設置時鍾預分頻,設置為fmaster = fclock CLK->CCOR &= ~(1<<0);//禁止CCO輸出 //此時,應當關閉外部時鍾 CLK->ECKR &= ~0x01;//使能外部晶振 } }
Clock.h
#ifndef __CLOCK_H_ #define __CLOCK_H_ #include "stm8s.h" #define HSE_CLOCK 0 #define HSI_CLOCK 1 //初始化系統時鍾,有兩個選擇,一個hse一個是hsi void ClockInit(u8 clockSel); #endif
另外,有一個時鍾安全系統,這是一個什么機構
也就是,當系統晶振由於外部干擾或者電路故障斷開的時候,自動切換到內部高速時鍾,這樣能夠保證實際的單片機電路系統不會失控,防止造成不良影響