1. 程式人生 > >STM32之紅外通訊

STM32之紅外通訊

STM32之紅外通訊

概述

首先大家不要覺得紅外通訊很難,知道原理的話其實也就那麼回事兒,而本文講解的重點不是原理性的內容(原理性的這類比較底層的知識往往比較複雜,交個那些大佬慢慢研究吧),本文主要是教大家如何使用紅外通訊,希望大家看了本教程之後能夠進行簡單的紅外通訊,做做簡單的DIY。^_^


簡單的原理

紅外通訊是一線式通訊,也就是隻需要一根線就能夠通訊,GND接地,VDD接電源,最後一個根接晶片的IO口。具體的使用接線過程圖如下圖所示:

你需要知道的是:

  • 紅外資訊是由不同的紅外高低電平脈衝組合而成的

  • 當紅外接收頭捕獲到紅外訊號後,通訊線會表現為不同的高低電平

  • 晶片的一個IO管腳連線到這根通訊線,通過查詢的方式讀出這根線上面的高低電平資訊

  • 晶片按照根據統一的通訊協議將接收到的高低訊號轉化為鍵值(一串數字)

  • 不同的訊號具有不同的鍵值,根據不同的鍵值就能夠區分不同的紅外資訊

(這只是簡單的工作原理,不懂也沒關係,不影響後面的程式設計)


程式講解

程式知道原理之後是比較容易理解的,我將從三個部分講解主要的程式碼

配置階段

程式碼

void hwjs_init()
{
    GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* 開啟GPIO時鐘及管腳複用時鐘 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_15; //---紅外接收配置的管腳為PA15這個管腳,具體可以根據自己需要進行配置
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; GPIO_Init(GPIOA,&GPIO_InitStructure); /* 設定外部中斷的模式 */ EXTI_ClearITPendingBit(EXTI_Line15); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource15); //選擇GPIO管腳用作外部中斷線路 EXTI_InitStructure.EXTI_Line=EXTI_Line15; EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd=ENABLE; EXTI_Init(&EXTI_InitStructure); /* 設定NVIC引數 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //開啟EXTI15的全域性中斷 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //搶佔優先順序為0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //響應優先順序為1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能 NVIC_Init(&NVIC_InitStructure); }

程式碼說明

以上是配置過程的程式碼部分,將A15配置為輸入模式,同時開啟中斷
配置好後中斷函式為EXTI15_10_IRQHandler()


中斷函式

程式碼

void EXTI15_10_IRQHandler(void)   //紅外遙控外部中斷
{
    u8 Tim=0,Ok=0,Data,Num=0;
   while(1)
   {
      if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)==1)
        {
             Tim=HW_jssj();//獲得此次高電平時間
             if(Tim>=250) break;//不是有用的訊號
             if(Tim>=200 && Tim<250)
             {
                 Ok=1;//收到起始訊號
             }
             else if(Tim>=60 && Tim<90)
             {
                 Data=1;//收到資料 1
             }
             else if(Tim>=10 && Tim<50)
             {
                 Data=0;//收到資料 0
             }
             if(Ok==1)
             {
                    hw_jsm<<=1;
                    hw_jsm+=Data;

                if(Num>=32)
                {
                    hw_jsbz=1;
                  break;
                }
             }
             Num++;
        }
   }
   EXTI_ClearITPendingBit(EXTI_Line15); 
}

程式碼說明

  • HW_jssj()為獲得高電平持續時間的函式(具體程式碼見附錄)
  • 當收到訊號後,通過不停地查詢判斷將接收到的訊號解析到”hw_jsm”裡面同時將標誌位”hw_jsbz”置”1”
  • hw_jsbz”置”1”表示成功解析到一個完整地紅外訊號

主函式

程式碼

int main()
{   
  hwjs_init();                                      //紅外介面初始化
    while(1)
    {
        if(hw_jsbz==1)                              //如果紅外接收到資料了
        {
            if(hw_jsm==0x00FFA25D)          //---當接收到0x00FFA25D這個鍵值的紅外訊號時
            {
                /*程式1*/ 
            }
            else if(hw_jsm==0x00FF30CF) //---當接收到0x00FF30CF這個鍵值的紅外訊號時
            {
                /*程式2*/
            }   
            hw_jsbz=0;                                  //清零
            hw_jsm=0;                                       //接收碼清零(存放紅外編碼資料的地方)
        }           
    }           
}

程式碼說明

  • 進行初始化操作
  • 當接收到紅外訊號後就判斷紅外訊號的鍵值。
  • 根據鍵值選擇去執行哪一段程式。
  • 執行完之後就繼續等待。

你可能會遇到的問題以及建議解決方法

附錄的程式不能夠執行?

本程式是Keil4的程式碼,檢查Keil是否破解,路徑是否含有中文字元等。

程式碼不能夠下載到晶片裡面?

本程式使用的晶片是STM32F103C8T6,開啟配置串列埠(“Option for Target’Target1’”或者按快捷鍵”Alt+F7”)
選擇正確的晶片型別
選擇正確的燒錄工具
選正確的Flash的大小
檢查燒錄的連線以及供電(一般不會出現這個問題)


如果大家還有什麼疑問或者我講的有什麼不對的地方歡迎在評論區留言,一起交流討論^_^

附錄:

原始碼連結:https://pan.baidu.com/s/1jwkEQHB1-QH2mOf3xwYj4A 密碼:yh0n