stm32紅外遙控的定時器實現

2021-08-27 23:45:51 字數 2707 閱讀 5436

我用的紅外遙控是使用的nec協議,即使用pwm來調製傳送的資訊    nec協議,其特徵如下:

1、8位位址和8位指令長度;

2、位址和命令2次傳輸(確保可靠性)

3、pwm脈衝位置調製,以發射紅外載波的占空比代表「0」和「1」;

4、載波頻率為38khz;

5、位時間為1.125ms或2.25ms;

nec碼的位定義:乙個脈衝對應560us的連續載波,乙個邏輯1傳輸需要2.25ms(560us脈衝+1680us低電平),乙個邏輯0的傳輸需要1.125ms(560us脈衝+560us低電平)。而遙控接收頭在收到脈衝的時候為低電平,在沒有脈衝的時候為高電平,這樣,我們在接收頭端收到的訊號為:邏輯1應該是560us低+1680us高,邏輯0應該是560us低+560us高。

nec遙控指令的資料格式為:同步碼頭、位址碼、位址反碼、控制碼、控制反碼。同步碼由乙個9ms的低電平和乙個4.5ms的高電平組成,位址碼、位址反碼、控制碼、控制反碼均是8位資料格式。按照低位在前,高位在後的順序傳送。採用反碼是為了增加傳輸的可靠性(可用於校驗)。

紅外置收頭與stm32連線如上圖所示,既然是pwm調製,很容易想到了stm32的通用定時器的輸入捕獲和輸出比較功能,這裡由於stm32是接收紅外遙控傳送的資訊,所以與紅外置收頭連線的io口要設定位輸入模式,因為在空閒狀態的時候輸入始終要保持高電平,所以要配置成上拉輸入。

rcc->apb2enr|=1<<3;

gpiob->crh&=0xffffff0f; 

gpiob->crh|=0x00000080; 

gpiob->odr|=1<<9;

因為pb.9是通用定時器的通道四,所以還要對定時器進行配置,額。。。好長時間沒有用定時器了,都忘得差不多了,又得重新拾起來             

void time4_init()

rcc->apb1enr|=1<<2;//開啟定時器四的時鐘

tim4->sr=0;//其實復位值就是0,多此一舉了

tim4->dier|=1<<4;//允許定時器四的捕獲中斷

tim4->psc=71;//計數頻率設定為1m cnt每增加一 時間為1us

tim4->arr=10000;//計數器每隔10ms溢位一次

tim4->ccmr2|=1<<8;//cc4通道被配置為輸入,ic4對映在ti4上;

tim4->ccer&=~(1<<13);//通道四配置為上公升沿捕獲

tim4->ccmr2|=3<<12;//進行濾波處理

tim4->ccer|=1<<12;//通道四捕獲使能

tim4->cr1|=1<<0;//定時器四計數使能

因為紅外置收頭接收的訊號第乙個資料必然是同步碼,首先低電平保持9ms,然後乙個跳變,高電平保持4.5ms,而我們判斷接收的資料是邏輯0還是邏輯1,或者是同步碼,都是要根據高電平的持續時間來判定的,所以要關心高電平保持時間,故定時器四初始化時要配置為上公升沿捕獲,好了,定時器也設定好了,接下來該設定定時器四的中斷處理函式啦

對啦,要先把nvic中的tim4中斷開啟

void nvic_init()

nvic->iser[0]|=1<<30;//tim4的中斷編號為30

void tim4_irqhandler(void)

if(tim4->sr&0x10)

if(cs==1)//發生上公升沿捕獲

tim4->cnt=0;

tim4->ccer|=1<<13;

tim4->sr=0;

dcb=1;

if(cs==0)//發生下降沿捕獲

tim4->sr=0;

if(dcb==1)  

dcb=0;

temp=tim4->ccr4;

tim4->ccer&=~(1<<13);//改為上公升沿捕獲

if(temp>4200&&temp<4700)

led1=~led1;

ok1=1;

if(ok1==1)

if(temp>1400&&temp<1800)

data=(data<<1);

data|=1<<0;

ray_flag++;

if(temp>300&&temp<800)

data=(data<<1);

data&=~(1<<0);

ray_flag++;

if(ray_flag==32)

ok2=1;

led0=~led0;

if(ray_flag>=32)//nec協議 一次傳送的資料位為32位

ok2=1;

tim4->sr=0;

中斷服務程式配置好了,接下來就是中程式啦

int main()

stm32_clock_init(9);

delay_init(72);

gpio_init();

nvic_init();

time4_init();

usart1_init();

while(1)

if(ok1==1&&ok2==1)

usart1_senddata(temp);

ok1=0;

ok2=0;

ray_flag=0;

使用的是串列埠列印資料,串列埠配置程式就不寫啦

最大的教訓就是 if(temp>4200&&temp<4700)和if(4200

STM32 紅外遙控器

紅外 原理 遙控器作為發射器,發射38khz的載波,接收器在接收到載波時為低電平 按照nec protocol的pwm,該協議的特點 1 8位位址和8位指令長度 2 位址和命令分兩次傳送,並有傳送位址和命令反碼,便於校驗,確保傳輸的準確 3 pwm脈衝位置調製,以發射紅外載波的占空比來表示 0 和 ...

stm32關定時器 STM32定時器TIM3程式

include led.h include delay.h include key.h include sys.h include usart.h include timer.h stm32開發板實驗8 定時器中斷實驗 int main void delay init 延時函式初始化 nvic co...

stm32紅外遙控的外部中斷實現

花了整整兩天時間終於算是基本把紅外解碼搞明白了,其實並不是很難,用了兩天時間,說來慚愧啊,原因就是細節上的問題,不過最終總算找出問題來了。使用外部中斷來解碼,就先對外部中斷進行配置吧 void exti init rcc apb2enr 1 0 使用外部中斷要開afio復用時鐘,因為要用到用到它的暫...