有個項目用了STM8S103F3,因是電池供電,需要進入halt狀態并使用GPIO外部喚醒,因是初次使用STM8S,走了不少彎路,將過程記錄下來,好讓和我一樣的初次接觸STM8S的人有個啟發。
現象:進不了HALT狀態
硬件環境:使用PA1、PA2、PD2、PD5作為外部中斷輸入,來喚醒MCU。使用PD4作為輸出,使用PD3作為AD轉換口。
編程思路:
1、初始化系統(時鐘、gpio)部分代碼如下:
void JG_GPIO_Init(void)
{
PA_DDR = 0xf9;
PA_CR1 = 0x00;
PA_CR2 = 0x06; //pa1、pa2中斷
PB_DDR = 0xff; //PB浮空輸入
PB_CR1 = 0x00;
PB_CR2 = 0x00;
PC_DDR = 0x00; //
PC_CR1 = 0x00;
PC_CR2 = 0x00;
PD_DDR = 0xdb; //1101 1011
PD_CR1 = 0xdb; //1101 1011
PD_CR2 = 0x24; //0010 0100 //PD2\PD5中斷
PD_ODR_ODR4 = 0;
EXTI_CR1_PDIS = 3; //PD口中斷上下降沿觸發
EXTI_CR1_PAIS = 3; //PA口中斷上下降沿觸發
}
2、開中斷
asm("rim");
3、進入halt
asm("halt");
4、在PA口和PD口外部中斷服務函數中處理問題
#pragma vector = 5
__interrupt void PA_Intrsvr(void)
{
...
}
#pragma vector = 8
__interrupt void PD_Intrsvr(void)
{
...
}
結果發現根本不進入halt模式,百思不得其解。
問題分析過程:
首先懷疑端口被誤觸發,使得進入了HALT模式的mcu被喚醒了。用示波器查看PA1、PA2、PD2、PD5波形,均為高電平,沒有觸發的條件。
接著懷疑電源干擾,加大了電路的濾波電容,故障依舊。
開始從代碼入手查問題,修改代碼如下:
#define led PD_ODR_ODR4
void main(void)
{
PD_DDR_DDR4 = 1;
PD_CR1_C14 = 1;
PD_CR2_C24 = 0;
led = 1;
PA_DDR_DDR1 = 0;
PA_CR1_C11 = 0;
PA_CR2_C21 = 1;
EXTI_CR1_PAIS = 3;
asm("rim");
asm("halt");
led = 0;
while(1);
}
在PD4上經1k電阻接了一個LED到電源正極,這樣,當PD4為0時,led被點亮。配置PD4為推挽輸出,配置PA1為帶中斷浮空輸入,然后開中斷,進入halt狀態,接著在halt語句之后拉低PD4,以點亮led。如果mcu正常進入halt狀態,led不亮。
在IAR下編譯、下載并調試,程序無編譯錯誤,正常下載到MCU,全速運行,led沒有被點亮。哦噢,成功了...慢著,stop debuging,讓程序在MCU上跑一下看看,...led亮了!!發克!
這個什么狀況
看PDF、看STM8S參考手冊,沒有找到明顯的提示,暈!問度娘,度娘給了我一些不相干的東西,暈菜,在q群里吼吼,高手們都很忙,沒空理我。
怎么辦?
自己琢磨,瞎琢磨,這個問題折磨我好多天了,領導天天過來問我,搞定了沒有。下午的時候老大過來問我好了沒有,我說有點問題,老大說,聽老二(二老板)說這個項目很簡單的。。。言下之意,是不是我的水平問題,沒辦法,氣也沒用。
隨手把代碼改成下面的樣子:
#define led PD_ODR_ODR4
void main(void)
{
PD_DDR_DDR4 = 1;
PD_CR1_C14 = 1;
PD_CR2_C24 = 0;
led = 1;
PA_DDR_DDR2 = 0;
PA_CR1_C12 = 0;
PA_CR2_C22 = 1;
EXTI_CR1_PAIS = 3;
asm("rim");
asm("halt");
led = 0;
while(1);
}
有什么不同?換了一個口,用PA2口來觸發喚醒,編譯、下載并調試,全速沒問題,led沒亮。點一下stop debuging,讓MCU跑,led沒亮!!!哦哦哦,貌似ok了?!拉低一下PA2,led點亮了,成功了!
趕緊看產品手冊,PA1口是外部晶振的輸入口,手冊上有這么一句話:
關于STM8S的halt狀態及喚醒
不知道是不是這個原因引起的,有待考證。請知道的高手指點我一下。
并且在問度娘的時候,知道了另外一件事,就是在進入halt的時候,MCU會自動asm("rim");也就是說,如果要進入halt狀態,則可以省掉asm("rim");語句。對于偷懶的我,這個很受用。