stm8源碼
A. STM8是紅外通訊的絕配
有讀者私信我,要獲得更詳細的內情。很抱歉,因為時間實在有限,而且對於實際場景不了解,所以,簡單地更新,添加了點兒內容。至於更加詳細的電路圖和源碼需要額外時間繼續補充。
最近使用STM8L152做產品,需要基於紅外線通訊的Bootloader。發現STM8L05X/15X是紅外通訊的絕配。
紅外線大致有CIR和SIR兩種。前者主要用於5~10米距離的紅外遙控器,採用38kHz載波,有大量的廉價接收解碼器可用。後者是IrDa標准之一,曾經是功能手機和筆記本電腦的標准配置,其堆棧和配置實體設計與藍牙比較像,物理層採用3/16載波方式,需要單獨的收發模塊。
電子、DVD、機頂盒、空調等傳統消費電子中常見的遙控器,我們稱之為CIR, Consumer Infra Red。CIR通常使用980nm紅外線,還需要採用38KHz~40KHz載波以避免可見光干擾。CIR需要編碼和解碼電路。
我們可以找到若干編碼電路。如果由MCU來實現,則需要產生38~40KHz 載波,另外根據特定的紅外遙控協議,如SONY/Philips RC5等產生二進制碼流。並利用邏輯門或者三極體來實現二進制碼流對於載波的調制。理論上,二進制碼流和載波還有一定的時序關系,但是實踐下來,這種時序關系的容錯率很高。
至於CIR的紅外接收部分,因為產量比較大,有低成本模塊供應,內置38~40KHz載波發生器,並直接輸出解調後的二進制碼流。所以解碼接收部分任意MCU都可以實現。
綜上所述,STM8L的CIR方案中,主要考慮的是編碼發射端。
MCU產生38KHz載波最常見的方法是使用定時器。包括設定38KHz的中斷,並在中斷中去切換GPIO引腳。或者設定一個占空比為50%的PWM中斷。其道理是類似的。同時,由軟體或者另外一種定時器來產生定時中斷,產生二進制碼流。兩者在外部使用CIR二極體相連,當兩個GPIO壓差為VCC時,IR二極體點亮,壓差為零時,IR二極體關閉。這樣就形成了最簡單的CIR遙控器。
對於STM8L來說,其內部的低頻RC振盪器頻率正好在38KHz,當然有些誤差,但是對於CIR來說要求沒有那麼嚴格。由於是內部IRC,所以並不需要使用定時器來產生中斷。
通常38kHz載波採用定時器產生PWM。但是Bootloader狀態下必須關閉所有中斷。這就限制了許多MCU在這種狀態的使用。有部分設計只用了單向傳輸,但是這種方式試錯成本太高了。
STM8L05X內部低速RC就是38kHz。而且可以從引腳引出來為載波,實測37.2kHz。配合USART可以直接構成雙向紅外通訊和遙控器。比STM推薦的IRTM還好用。
消費者紅外線技術是單向的:遙控器負責編碼和發射紅外線,設備負責接收和解碼。在某些環境中,比如說水電煤表的自動抄表系統中,則需要建立起雙向紅外線通道。
紅外線和無線電通訊類似,採用半雙工通訊方式。所以軟體角度必須要確保時序,不要造成雙方的通訊沖突。同時硬體上也可以採取一些方法,保證己方在發射時不進行接收,避免自發自收。
由於38KHz載波的存在,其波特率收到限制,我測試過9.6kbps,但是工作在2.4kbps,誤碼率要少許多。
在Bootloader模式下,USART RXD可以採用polling方式實現,在低速率情況下不會掉數據。
這個其實和STM8無關了,可以參考Arino的紅外編碼和紅外解碼庫。總的思路是將紅外切割成一個個小的時間片,而無需太多考慮RC5/SONY/Toshiba/RCA等不同的紅外遙控協議,直接使用一串二進制數據來編碼。這也是大多數通用學習型紅外遙控器的原理。
具體實現請參考 How to make IR decoder 以及 How to setup an IR remote and receiver on an Arino .
STM8的片內USART外設是支持IRDA SIR收發標準的。這是一種國際標准,早期行動電話和其他數據終端中多採用此類標准,通訊速率較高,可達到115.2kbps。但相對應的,它的紅外收發模組成本在20多元人民幣,比消費紅外模塊貴許多。
STM8的原始MCU架構來自意法半導體的ST7,是意法自主開發的內核。這里額外提一下,意法的STR7和ST7不同,是基於ARM7TDMI內核的產品線。STM8在ST7上做了很多改變,與STM32保持了引腳一致性。所以,STM8是一個性價比較高的MCU。
警告
但是STM8的ITC(中斷控制)部分卻存在著較大的問題。通過模擬器,我覺得和STM8的虛擬存儲器以及壓棧的先後順序有關聯。在某些極端嵌套中斷情況下會導致堆棧溢出,或者一些莫名其妙的問題。具體請留意 STM8 Error Sheet 。
所以STM8在中斷設計方面不能夠採用過於復雜的嵌套設計,同時需要做些黑盒壓力測試。
本文中的某些做法,如利用IRC直接產生38~40KHz載波的方式,可以作為一種思路,在其他MCU中繼續使用。比如STM32F030F4 IRC40KHz/LPC812 SCT等。
B. 求 STM8L的modbus程序主機和從機
Modbus 協議是應用於電子控制器上的一種通用語言。通過此協議,控制器相互之間、控制器經由網路(例如乙太網)和其它設備之間可以通信。它已經成為一通用工業標准。有了它,不同廠商生產的控制設備可以成工業網路,進行集中監控。
此協議定義了一個控制器能認識使用的消息結構,而不管它們是經過何種網路進行通信的。它描述了一控制器請求訪問其它設備的過程,如果回應來自其它設備的請求,以及怎樣偵測錯誤並記錄。它制定了消息域格局和內容的公共格式。
C. stm8 硬體i2c從機接收程序
首先,iic做從機的程序源碼網上比較多,我就不發了,說下調試方法。
相信主機部分已經調試通過了,在這個前提下,樓主的思路是沒錯的,接收非空,讀數據。iic屬於一個硬體介面,出問題的時候需要藉助示波器,監測每個時候每個數據的波形,同時用JTAG在線調試,分析從機相關寄存器的狀態,與自己計算的理論值做對比看是否正確,最終會找到一個出錯的地方,看著一堆數據確實會枯燥一些,樓主加油,祝成功~
D. stm8s內部eeprom塊讀取失敗
$pngname = $openid.'.png';
if(imagepng($QR, $pngname)){
imagedestroy($QR);
$qrurl = W_DOMAIN.''.$pngname;
$this->assign('qrcode',$qrurl);
$this->display();
}
E. 求教stm8l將系統時鍾切換到外部晶振
首先看一下 STM8S103K3 的時鍾結構圖,可以幫助你很好的理解。
這里有幾個時鍾,就是圖中標識的時鍾,需要弄清楚一下:fHSE: 外部高速晶振時鍾,它是由外部晶振產生,大小由外部晶振大小決定,STM8S的外部晶振范圍:1-24M,看圖中的」HSE OSC 1-24M「。
fHSI:內部RC高速時鍾,它是由內部的RC震盪電路產生的,其值16M。但是可以經過後面的分頻器分頻,四個分頻系數可供選擇(1,2,4,8)。註:精準度比外部晶振的要稍差一些。
fMASTER:主時鍾,它是由HSE 或者 HSI提供時鍾,主要功能給外圍設備(peripherals,如I2C,SPI,ADC等)提供時鍾,還有給CPU提供時鍾源。
fCPU:cpu時鍾,它是由fMASTER經過分頻得到,其作用就是給CPU提供時鍾,一個機械周期就是一個fCPU的時鍾周期。
下面是時鍾的源碼部分,可供大家參考。
這里寫了四段程序,分別是:使用高速內部時鍾(寄存器版)
使用高速內部時鍾(庫函數版)
使用外部時鍾(寄存器版)
使用外部時鍾(庫函數版)
- /*******************************************************************************
- * Function Name : InitCpuClock.
- * Description : Initial CPU clock, .
- * Input : None.
- * Output : None.
- * Return : None.
- *******************************************************************************/static void InitCpuClock(void)
- {#if 1
- // 寄存器版本 - 使用高速內部時鍾
- //Use HSI @8MHZ, div = 2; 8=16/2
- CLK->ECKR &= ~CLK_ECKR_HSEEN; // 失能外時鍾
- CLK->CKDIVR &= (uint8_t)(~CLK_CKDIVR_HSIDIV); // 清零內部時鍾預分頻
- CLK->CKDIVR |= CLK_PRESCALER_HSIDIV2; // 設置內部時鍾預分頻 2; 具體可以參考數據手冊 (reference manual)
- CLK->ICKR |= CLK_ICKR_HSIEN; // 使能內部高速時鍾
- while(!(CLK->ICKR&CLK_ICKR_HSIRDY)); // 等待內部高速時鍾穩定, 穩定後則內部時鍾已經開跑了。 時鍾 = 16/2 M#endif#if 0
- // 庫函數版本 - 使用內部高速時鍾
- //Use HSI @8MHZ, div = 2; 8=16/2
- CLK_HSECmd(DISABLE); // 失能外時鍾
- CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV2); // 設置內部時鍾預分頻 2; 具體可以參考數據手冊 (reference manual)
- CLK_HSICmd(ENABLE); // 使能內部高速時鍾
- while(!(CLK->ICKR&CLK_ICKR_HSIRDY)); // 等待內部高速時鍾穩定, 穩定後則內部時鍾已經開跑了。 時鍾 = 16/2 M#endif#if 0// 寄存器版本 - 使用外部時鍾
- CLK->CKDIVR |= CLK_PRESCALER_CPUDIV1; // CPU 時鍾分頻 1,CPU時鍾 = 外部時鍾(即是外部晶振頻率)
- CLK->ECKR |= CLK_ECKR_HSEEN; // 允許外部高速振盪器工作
- while(!(CLK->ECKR & CLK_ECKR_HSERDY)); // 等待外部高速振盪器准備好
- CLK->SWCR |= CLK_SWCR_SWEN; // 使能切換
- CLK->SWR = CLK_SOURCE_HSE; // 選擇晶元外部的高速振盪器為主時鍾
- while(!(CLK->SWCR&CLK_SWCR_SWIF)); // 等待切換成功
- CLK->SWCR &= ~(CLK_SWCR_SWEN|CLK_SWCR_SWIF); // 清除切換標志#endif#if 0// 庫函數版本 - 使用外部時鍾
- CLK->CKDIVR |= CLK_PRESCALER_CPUDIV1; // CPU 時鍾分頻 1,CPU時鍾 = 外部時鍾(即是外部晶振頻率)
- CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, // 時鍾自動切換模式,注: 參數是自動切換,不然只使用這一個函數是不能切換成功的
- CLK_SOURCE_HSE, // 要切換的時鍾(這里是外部時鍾)
- DISABLE, // 是否使能切換完成中斷(這里失能)
- CLK_CURRENTCLOCKSTATE_ENABLE);// 是否還使能當前時鍾(這里選擇 關掉當前時鍾HSI)
- CLK->SWCR &= ~(CLK_SWCR_SWEN|CLK_SWCR_SWIF); // 清除切換標志#endif}
源碼如下,看注釋應該就可以了。
F. stm8s103f3p6的afr怎樣配置
本文使用的晶元是是stm8s103f3。
以下主要說明配置TIM2通道1為PWM輸出的過程。
1.寄存器配置
4位預分頻器,計數器的計數頻率Fck_cnt=Fck_psc/2^(PSC[3:0])=16M/2^0=16M
那麼計數周期為1/16us,也就是說計數器會每隔1/16us計數一次。
TIM2_PSCR=0x00; //分頻值=0 16M
自動重裝載寄存器,
當自動重裝載寄存器=0時,計數器處於阻塞狀態,也就是不計數狀態,因為當CNTR=ARR時,CNTR就會清零,所以配置時自動重裝載寄存器應該大於0。另外自動重裝載寄存器的值就是PWM波形的周期,比如ARR=0X0100,PWM的周期為0x0100*1/16=16us,PWM的周期就是16us
TIM2_ARRH=0x01; //自動重裝的值 0x0100
TIM2_ARRL=0x00;
捕獲/比較使能寄存器,這個寄存器的配置可以選通相應的Tim2通道。
bit5,bit4為ch2配置,bit1,bit0為ch1配置
如果當前OC1為輸出通道,則
bit1:OC1低電平有效
bit0:OC1信號被輸出到當前引腳上
TIM2_CCER1=bit0|bit1; //low level,OC1
捕獲/比較模式寄存器,
bit1,bit0
CC1S[1:0]為捕獲/比較選擇
00:CC1通道被配置為輸出
bit2保留
bit3輸出比較預載入使能
0:不使能
1:使能
bit6,bit5,bit4輸出比較模式
110:PWM1模式
PWM1和PWM2模式區別
PWM1:CNT<CCR,CH1被激活
PWM2:CNT>CCR,CH1被激活
TIM2_CCMR1=bit3|bit5|bit6; //MODE
捕獲/比較寄存器,這個寄存器決定著PWM的占空比。CCR/ARR=PWM的占空比,例如設置為0x0060,那麼占空比為0x0060/0x0100=6/16
TIM2_CCR1H=0x00;
TIM2_CCR1L=0x60;
中斷使能寄存器,如果需要中斷可以在此設置。
bit1:CC1E 捕獲/比較1中斷使能
0:CC1 中斷不使能
1:CC1中斷使能
TIM2_IER=0x00; //更新中斷使能
控制寄存器,bit0控制計數器的打開和關閉。
bit0,計數器使能
0:不使能
1:使能
TIM2_CR1=bit0; //enable counter
通過邏輯分析儀測試PD4管腳的輸出電平,波形圖如下所示。
源碼如下,
//*******************************************
1 #define bit0 0x01
2 #define bit1 0x02
3 #define bit2 0x04
4 #define bit3 0x08
5 #define bit4 0x10
6 #define bit5 0x20
7 #define bit6 0x40
8 #define bit7 0x80
9
10 void Timer2_Init(void)
11 {
12 CLK_ICKR|=0x01; //開啟內部HSI
13 while(!(CLK_ICKR&0x02));//HSI准備就緒
14 CLK_SWR=0xe1; //HSI為主時鍾源
15 CLK_CKDIVR=0x00; //HSI,8分頻=16M
16 TIM2_PSCR=0x00; //分頻值=0 16M
17 TIM2_ARRH=0x01; //自動重裝的值 0x0100
18 TIM2_ARRL=0x00;
19 TIM2_CCER1=bit0|bit1; //low level,OC1
20
21 TIM2_CCMR1=bit3|bit5|bit6; //MODE
22 TIM2_CCR1H=0x00;
23 TIM2_CCR1L=0x60;
24 TIM2_IER=0x00; //更新中斷使能
25
26 TIM2_CR1=bit0; //enable counter
27 }
28 int main( void )
29 {
30 Timer2_Init();
31 while(1){};
32 }
G. 誰有范紅剛寫的stm8單片機自學筆記書上的源碼啊
這個沒有,可以去單片機論壇找找類似的程序。
懂事電子設計 Vgz
H. stm8s003單片機解密能提供完整的源代碼嗎
解密得不到源代碼,得到的都是反匯編後的二進制數字