stm32f103讀取紅外接收HS0038A2
軟件:
IAR 7.4
STM32CubeMX 4.14.0
硬件:
STM32F103VBT6
原理圖,和手冊(cè)建議的基本一致,只是上拉電阻不是手冊(cè)建議的10K以上,這里的面板距離控制器比較遠(yuǎn),可能是考慮到線阻。
HAL配置,使用Cubemx。
HS0038A2的輸出,帶有上拉電阻,接著一個(gè)led燈,因此TIM3的IC腳浮空。
設(shè)計(jì)者恰好把IR設(shè)計(jì)在TIM3的通道4上。如果使用了通道1/2, 就可以使用PWM輸入方式來(lái)捕捉紅外脈沖,可以拿到每個(gè)脈沖的數(shù)據(jù)。
IC模式使用下降沿。
紅外控制這里是常用的NEC協(xié)議。遙控器輸出高電平,而HS0038A2轉(zhuǎn)換低電平輸出。 如,一個(gè)9ms高+4.5ms的低,組成一個(gè)header,OUT數(shù)據(jù)線上信號(hào)是 9ms低+4ms高,空閑時(shí)數(shù)據(jù)線是高(避免干擾)。
因此,我們只檢測(cè)下降沿中斷,就可以識(shí)別紅外的一個(gè)脈沖信號(hào)(1幀信號(hào)發(fā)出,9ms一開(kāi)始就拉底,而后4.5ms拉高再拉低)。邏輯1為2.25ms,邏輯0為1.12ms.
Tim3還給其他外設(shè)提供即時(shí),所以這里使用了1us的分辨率。
需要啟用Tim3的中斷,因?yàn)槭褂昧薋reertos,所以其中斷設(shè)置到最低15級(jí)。也不怕其他外設(shè)中斷紅外讀取。
代碼.h
/*
*HS0038A2
*ir.h
*
*/
#ifndef_IR_H
#define_IR_H
#include"tim.h"
#include"cmsis_os.h"
#defineDELTA200
#defineHEADER_MIN13500-DELTA
#defineHEADER_MAX13500+DELTA
#defineDATA1_MIN2250-DELTA
#defineDATA1_MAX2250+DELTA
#defineDATA0_MIN1120-DELTA
#defineDATA0_MAX1120+DELTA
#defineIR_ADDR2
typedefenum{
NECSTATE_IDLE=0,
NECSTATE_START=1,
NECSTATE_RECEIVE=2,
}NEC_State;
#endif
代碼.c:
/*
*ir.c
*/
#include"ir.h"
externosMessageQIdQ_IrHandle;
staticuint32_tccr_prev=0;
staticuint32_tccr_cur=0;
staticuint32_ttimeout=0;
staticuint8_tpulse_cnt=0;
staticuint32_tir_code;
NEC_Statestate=NECSTATE_IDLE;
voidHAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef*htim)
{
if(htim->Instance==TIM3&&htim->Channel==HAL_TIM_ACTIVE_CHANNEL_4){
ccr_cur=__HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_4);
uint32_tdelta_t;
if(ccr_cur>ccr_prev){
delta_t=ccr_cur-ccr_prev;
}
else{
delta_t=0xffff-ccr_prev+ccr_cur;//0xffff溢出
}
//接收到信息頭,就接收4個(gè)8字節(jié)
。
。
。
//校驗(yàn)
if((uint8_t)(~code[0])!=code[1]||(uint8_t)(~code[2])!=code[3])
return;
if(code[0]!=IR_ADDR)
return;
//放到隊(duì)列
if(Q_IrHandle!=NULL){
osMessagePut(Q_IrHandle,code[2],0);
}
}
//超時(shí)110ms
if(timeout>=110*1000){
state=NECSTATE_IDLE;
pulse_cnt=0;
ir_code=0;
timeout=0;
}
ccr_prev=ccr_cur;
}
//
}
檢測(cè)到信息頭后,連續(xù)讀32bit到一個(gè)uint32_t數(shù)據(jù)中。
這里沒(méi)有依靠最后1給560us來(lái)做結(jié)束判斷,只是一個(gè) pulse_cnt>=32 來(lái)做判斷,開(kāi)始寫(xiě)到 pulse_cnt>=31,結(jié)果反碼總是差0x80。
最后分離出4個(gè)字節(jié),做地址檢測(cè),以及校驗(yàn)。 校驗(yàn)是使用 ~ 取反碼,IAR下需要強(qiáng)制轉(zhuǎn)換到uint8_t,否則判斷條件為假。
也沒(méi)有做連續(xù)按鍵處理。
超時(shí)處理,一個(gè)是判斷脈沖持續(xù)時(shí)間在3ms內(nèi),另一個(gè)是判斷脈沖總時(shí)間在110ms內(nèi)。
因?yàn)榘遄佑每煽毓杩刂普謽O電機(jī),啟動(dòng)電機(jī)后,能看到OUT輸出干擾信號(hào),但是被headr判斷給擋掉了。