|
//*************************首先感嘆一下C語言的靈活性。
/************************************以下基于STM8單片機(jī)**************************/
/****為解決按鍵時(shí)采用死循環(huán),使CPU進(jìn)入假死機(jī)狀態(tài),大大浪費(fèi)單片機(jī)資源的情況*******/
/***以下文字為個(gè)人理解,大佬建議跳過,當(dāng)然,也歡迎各位指出偏駁之處***************/
/**單片機(jī)在一個(gè)時(shí)間點(diǎn)只能進(jìn)行一個(gè)動(dòng)作,并不能做到真正意義上的同時(shí)多任務(wù)動(dòng)作,只能在結(jié)束一個(gè)動(dòng)作后進(jìn)行下一個(gè)動(dòng)作,
由于每一個(gè)動(dòng)作所需要耗費(fèi)的時(shí)間特別短,所以在一定情況下可以看作多任務(wù)進(jìn)程。
以下利用中斷計(jì)時(shí)同理,在每一次計(jì)時(shí)的動(dòng)作耗費(fèi)時(shí)間特別短,做完這個(gè)動(dòng)作CPU就可以進(jìn)行其它動(dòng)作了,相當(dāng)于擺脫了死循環(huán),
不會(huì)讓CPU在那無意義地卡住,陷入要等待其它打破標(biāo)志的死循環(huán)**********************/
/***粗略非阻塞(不知道這算不算非阻塞)延時(shí)/計(jì)時(shí)思路:定時(shí)器進(jìn)行規(guī)定時(shí)間的中斷進(jìn)入,每進(jìn)一次中斷,(符合條件下)次數(shù)+1,以此作為粗略的基礎(chǔ)時(shí)間(1ms/5ms/10ms/100ms……)*****************************/
/*********************以下為代碼內(nèi)容***************************************/
#include <stm8s.h>
#include <stm8s_gpio.h>
#include <stm8s_tim4.h>
#include <stm8s_clk.h>
//按鍵K1-K2定義,只能讀取是否為“0”(按下)/不為“0”(松開),不能讀取是否為“1”或者其它的
#define K1 (GPIO_ReadInputData(GPIOC)&GPIO_PIN_1)
#define K2 (GPIO_ReadInputData(GPIOC)&GPIO_PIN_2)
//L1-L2燈亮/滅定義(繼電器K1-K2工作/不工作定義)
#define ON 1
#define OFF 0
#define L1(ON_OFF) if(ON_OFF==ON)GPIO_WriteHigh(GPIOB, GPIO_PIN_3);\
else GPIO_WriteLow(GPIOB, GPIO_PIN_3)
#define L2(ON_OFF) if(ON_OFF==ON)GPIO_WriteHigh(GPIOB, GPIO_PIN_2);\
else GPIO_WriteLow(GPIOB, GPIO_PIN_2)
//引腳初始化
void GPIO_Config()
{
//繼電器三極管控制引腳 PB2-3 初始化,高電平導(dǎo)通
GPIO_Init(GPIOB, GPIO_PIN_2|GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST);
//按鍵初始化:無中斷無浮點(diǎn)上拉輸入
GPIO_Init(GPIOC, GPIO_PIN_1|GPIO_PIN_2, GPIO_MODE_IN_PU_NO_IT);
}
//初始化定時(shí)器TIM4
void Init_Timer4(void)
{
TIM4_DeInit();
TIM4_TimeBaseInit(TIM4_PRESCALER_64, 0xFA); /*初始化時(shí)基單元。128分頻 ,x=16M/128 , 自動(dòng)重載寄存器值為0xfa=16*15+10=250,
中斷溢出=x/0xfa 進(jìn)中斷一次2ms。
64分頻下0xFA進(jìn)中斷一次1ms ; 128分頻下0x19進(jìn)中斷一次0.2ms***/
TIM4_ClearFlag(TIM4_FLAG_UPDATE);
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE); //使能TIM4更新中斷
TIM4_Cmd(ENABLE); //啟動(dòng)定時(shí)器
}
//定義全局變量:TIM4每1ms進(jìn)中斷一次 的各按鍵計(jì)次時(shí)間sk,各按鍵對(duì)應(yīng)上一次的計(jì)次時(shí)間skt
//因?yàn)槭侨肿兞浚梢栽谄渌胤秸{(diào)用數(shù)值后手動(dòng)進(jìn)行清零/賦值操作
u16 sk1=0;
u16 sk1t=0;
u16 sk2=0;
u16 sk2t=0;
//TIM4中斷服務(wù)函數(shù):按鍵按下開始計(jì)時(shí),按鍵松開停止計(jì)時(shí);
//上一次按鍵按下持續(xù)時(shí)間數(shù)值一直保持,直到下一次按鍵有效按下后松開(去抖動(dòng))。
//各按鍵獨(dú)立計(jì)時(shí),互不影響
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
{
//上一次K1按鍵按下時(shí)長:sk1t
if(K1==0) //按鍵按下
{
sk1++; //TIM4每1ms進(jìn)中斷一次,此時(shí)sk1+1
if(sk1==59999) //防止達(dá)到計(jì)數(shù)上限,約59秒
{
sk1=0;
}
}
if(K1!=0) //按鍵松開
{
if(sk1>=30) //防抖動(dòng),也可以避免時(shí)間一直刷新
{
sk1t=sk1; //因?yàn)槭侨肿兞浚梢栽谡{(diào)用數(shù)值結(jié)束后手動(dòng)進(jìn)行清零操作
}
sk1=0;
}
//上一次K2按鍵按下時(shí)長:sk2t
if(K2==0) //按鍵按下
{
sk2++; //TIM4每1ms進(jìn)中斷一次,此時(shí)sk2+1
if(sk2==59999) //防止達(dá)到計(jì)數(shù)上限,約59秒
{
sk2=0;
}
}
if(K2!=0) //按鍵松開
{
if(sk2>=30) //防抖動(dòng),也可以避免時(shí)間一直刷新
{
sk2t=sk2;
}
sk2=0;
}
TIM4_ClearITPendingBit(TIM4_IT_UPDATE); //清除標(biāo)志位
}
//控制LED亮滅:上一次按鍵達(dá)到一定時(shí)間后亮,否則滅。各按鍵獨(dú)立工作,互不影響
void LED12(void)
{
// 按鍵K1控制燈L1
if(sk1t>=500) //按鍵K1持續(xù)按下約500ms
{
L1(ON);
}
else
{
L1(OFF);
}
// 按鍵K2控制燈L2
if(sk2t>=5000) //按鍵K1持續(xù)按下約5000ms
{
L2(ON);
}
else
{
L2(OFF);
}
}
//主函數(shù)
void main(void)
{
/*下列語句除 while(1){}; 外,其余語句都只執(zhí)行一次,TIM4的定時(shí)器配置是只在函數(shù)Init_Timer4()里設(shè)置一次*/
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //系統(tǒng)時(shí)鐘初始化為內(nèi)部時(shí)鐘16M
Init_Timer4(); //初始化TIM4定時(shí)器配置
GPIO_Config(); //初始化IO口
enableInterrupts(); //使能中斷
while(1)
{
LED12();
};
}
//解決報(bào)錯(cuò)
#ifdef USE_FULL_ASSERT
void assert_failed(u8* file, u32 line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/***用我理解的方式,有些地方寫得不是很好,水平比較低,所以在網(wǎng)上看大佬寫的總是感覺云里霧里,復(fù)制下來編譯一哈發(fā)現(xiàn)總是會(huì)少些東西,
然后又不知道怎么補(bǔ),木得辦法咯,只能自己慢慢想,啊哈哈。最后祝各位61節(jié)日快樂,誰還不是個(gè)幼兒園沒畢業(yè)/剛畢業(yè)的孩子呢!***/
|
評(píng)分
-
查看全部評(píng)分
|