紅外遙控(外部中斷)

目錄

1.紅外遙控簡介

通信方式:

紅外LED波長:

通信協議標準:

2.硬件電路

發送部分1:

內部元件介紹:

工作原理:

為什么要以38KHZ亮滅?

電路圖:

發送部分2:

電路圖:

接收部分:

電路圖:

接收部分原理圖:

3.基本發送與接收

4.NEC編碼

Data(數據格式):

5.NEC編碼:示波器采樣得到的圖

6.遙控器按鍵和鍵碼對比圖

7.51單片機的外部中斷

芯片圖:

中斷號:

8.外部中斷寄存器

9.紅外遙控代碼

第一步:

第二步:

第三步:

第四步:

模塊思路:

紅外解碼方法:

對于上述的闡述的理解圖:

第五步:

頭文件聲明:

第六步:

第七步:

第八步:

最終代碼:

模塊:

IR.c

IR.h

Int0.c

Int0.h

main.c

10.紅外遙控直流機調速代碼

第一步:

第二步:

第三步:

第四步:

第五步:

最終代碼:

模塊:

Timer1.c

Timer1.h

Motor.c

Motor.h

main.c


1.紅外遙控簡介

紅外遙控是利用紅外光進行通信的設備,由紅外LED將調制后的信號發出,由專用的紅外接收頭進行解調輸出

通信方式:

單工,異步

紅外LED波長:

940nm

通信協議標準:

NEC標準

2.硬件電路

發送部分1:

內部元件介紹:

LED1IR是紅外的發光二極管(我們的這款開發版沒有)

38KHZ的調制頻率,會一直輸入一個38KHZ的方波,固定的

IN是波形,IN給高電平LED都是不亮的,IN給低電平LED亮不亮取決于38KHZ的調制頻率

工作原理:

IN和38KHZ的調制頻率,加起來效果,給高電平LED不亮,給低電平LED會以38KHZ亮滅

為什么要以38KHZ亮滅?

這樣做的原因是抗干擾,自然界的紅外光會淹沒我們的紅外發射器的紅光,我們以38KHZ亮滅可以讓接受部分更容易接受我們的紅外光,外界的紅外光是不可能以38KHZ亮滅的

電路圖:

發送部分2:

IN輸入高電平就LED不亮,給低電平LED亮;所以就需要我們自行輸入一個38KHZ的方波,將IN接入I/O口中輸入

電路圖:

接收部分:

這個紅外接收器,很方便,里面的電路會自行濾波;接收時因為38KHZ頻率高,所以不能用掃描按鍵的方法了,我們要將OUT接入外部中斷,一旦有下降沿的信號,會立馬中斷,進行計時處理,這樣響應實時性高

電路圖:

接收部分原理圖:

OUT直接接入引腳P32

3.基本發送與接收

空閑狀態:紅外LED不亮,接收頭輸出高電平

發送低電平:紅外LED以38KHz頻率閃爍發光,接收頭輸出低電平

發送高電平:紅外LED不亮,接收頭輸出高電平

4.NEC編碼

Data(數據格式):

總共4個字節,一共32個bit位

第一個字節(地址碼):標識遙控器的地址,防止不同遙控器互相干擾

第二個字節(地址碼反碼):是跟隨第一個字節的,我們可以把第二個字節取反,看是否與第一個字節相同,用于一定的數據驗證

第三個字節(命令):寫入命令

四個字節(命令反碼):跟隨第三個字節,取命令反碼的反碼,可以進行一定的數據驗證

5.NEC編碼:示波器采樣得到的圖

6.遙控器按鍵和鍵碼對比圖

7.51單片機的外部中斷

STC89C52有4個外部中斷(傳統的89C52只有個中斷,但這里只引兩個中斷,所以我們就當只有兩個中斷)

STC89C52的外部中斷有兩種觸發方式: ?? ?下降沿觸發和低電平觸發

芯片圖:

中斷號:

8.外部中斷寄存器

9.紅外遙控代碼

第一步:

復制粘貼LCD液晶屏模塊、Delay模塊到本工程

第二步:

配置外部中斷;設置中斷優先級,這個實驗要求高,其他中斷來了要打斷他,達到外部中斷的絕對精度

第三步:

在主函數中,寫一個外部中斷的子函數,參考下表,這個是中斷輔助函數

下載進入單片機,我們按下K3獨立按鍵,會給與中斷一個下降沿,LCD液晶屏會加1;如果我們把ITO 賦值為0,初識給與下降沿,我們按下K3獨立按鍵數字會一直加

第四步:

建立新的模塊,外部中斷0模塊化Int0,將外部中斷函數注釋

模塊思路:

建立一個紅外解碼模塊,調用定時器模塊和外部中斷0模塊,main.c調用紅外模塊解碼模塊,進行邏輯的操作。

紅外解碼方法:

首先定義一個變量,這個變量表示當前狀態為空閑狀態,記為0狀態

然后空閑狀態收到一個下降沿,定時器打開開始計時,這個狀態會尋找start和repeat,這些頭部信號,尋找狀態,記為1狀態

尋找狀態給給一個下降沿,進入判斷狀態,會把定時器的值讀取出來,判斷0到1的時間,如果是start起始信號,就開始解碼1010 32bit這個數據,記為2狀態,如果是repeat重發信號,就直接回到0狀態。

狀態2會連續進行32次,每進行一次2狀態,就會計算出1 0這個時間差,會把這個數據填寫到一個變量緩存區,變量緩存區其中會再定義一個變量,指示現在存到第幾位了,存完32次以后就認為數據已經收到了,根據Data(數據格式)中的二、四字節取反驗證數據,驗證成功后置一個驗證成功的標志位,然后回到0狀態。

對于上述的闡述的理解圖:

第五步:

復制粘貼定時器模塊進行改造

頭文件聲明:

第六步:

紅外解碼模塊

第七步:

對按鍵的解碼,進行宏定義,在紅外解碼模塊的頭文件中

第八步:

主函數調用

最終代碼:

模塊:

IR.c

#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"unsigned int IR_Time;
unsigned char IR_State;unsigned char IR_Data[4];
unsigned char IR_pData;unsigned char IR_DataFlag;
unsigned char IR_RepeatFlag;
unsigned char IR_Address;
unsigned char IR_Command;/*** @brief  紅外遙控初始化* @param  無* @retval 無*/
void IR_Init(void)
{Timer0_Init();Int0_Init();
}/*** @brief  紅外遙控獲取收到數據幀標志位* @param  無* @retval 是否收到數據幀,1為收到,0為未收到*/
unsigned char IR_GetDataFlag(void)
{if(IR_DataFlag){IR_DataFlag=0;return 1;}return 0;
}/*** @brief  紅外遙控獲取收到連發幀標志位* @param  無* @retval 是否收到連發幀,1為收到,0為未收到*/
unsigned char IR_GetRepeatFlag(void)
{if(IR_RepeatFlag){IR_RepeatFlag=0;return 1;}return 0;
}/*** @brief  紅外遙控獲取收到的地址數據* @param  無* @retval 收到的地址數據*/
unsigned char IR_GetAddress(void)
{return IR_Address;
}/*** @brief  紅外遙控獲取收到的命令數據* @param  無* @retval 收到的命令數據*/
unsigned char IR_GetCommand(void)
{return IR_Command;
}//外部中斷0中斷函數,下降沿觸發執行
void Int0_Routine(void) interrupt 0
{if(IR_State==0)				//狀態0,空閑狀態{Timer0_SetCounter(0);	//定時計數器清0Timer0_Run(1);			//定時器啟動IR_State=1;				//置狀態為1}else if(IR_State==1)		//狀態1,等待Start信號或Repeat信號{IR_Time=Timer0_GetCounter();	//獲取上一次中斷到此次中斷的時間Timer0_SetCounter(0);	//定時計數器清0//如果計時為13.5ms,則接收到了Start信號(判定值在12MHz晶振下為13500,在11.0592MHz晶振下為12442)if(IR_Time>13500-500 && IR_Time<13500+500){IR_State=2;			//置狀態為2}//如果計時為11.25ms,則接收到了Repeat信號(判定值在12MHz晶振下為11250,在11.0592MHz晶振下為10368)else if(IR_Time>11250-500 && IR_Time<11250+500){IR_RepeatFlag=1;	//置收到連發幀標志位為1Timer0_Run(0);		//定時器停止IR_State=0;			//置狀態為0}else					//接收出錯{IR_State=1;			//置狀態為1}}else if(IR_State==2)		//狀態2,接收數據{IR_Time=Timer0_GetCounter();	//獲取上一次中斷到此次中斷的時間Timer0_SetCounter(0);	//定時計數器清0//如果計時為1120us,則接收到了數據0(判定值在12MHz晶振下為1120,在11.0592MHz晶振下為1032)if(IR_Time>1120-500 && IR_Time<1120+500){IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8));	//數據對應位清0IR_pData++;			//數據位置指針自增}//如果計時為2250us,則接收到了數據1(判定值在12MHz晶振下為2250,在11.0592MHz晶振下為2074)else if(IR_Time>2250-500 && IR_Time<2250+500){IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8));	//數據對應位置1IR_pData++;			//數據位置指針自增}else					//接收出錯{IR_pData=0;			//數據位置指針清0IR_State=1;			//置狀態為1}if(IR_pData>=32)		//如果接收到了32位數據{IR_pData=0;			//數據位置指針清0if((IR_Data[0]==~IR_Data[1]) && (IR_Data[2]==~IR_Data[3]))	//數據驗證{IR_Address=IR_Data[0];	//轉存數據IR_Command=IR_Data[2];IR_DataFlag=1;	//置收到連發幀標志位為1}Timer0_Run(0);		//定時器停止IR_State=0;			//置狀態為0}}
}

IR.h

#ifndef __IR_H__
#define __IR_H__#define IR_POWER		0x45
#define IR_MODE			0x46
#define IR_MUTE			0x47
#define IR_START_STOP	0x44
#define IR_PREVIOUS		0x40
#define IR_NEXT			0x43
#define IR_EQ			0x07
#define IR_VOL_MINUS	0x15
#define IR_VOL_ADD		0x09
#define IR_0			0x16
#define IR_RPT			0x19
#define IR_USD			0x0D
#define IR_1			0x0C
#define IR_2			0x18
#define IR_3			0x5E
#define IR_4			0x08
#define IR_5			0x1C
#define IR_6			0x5A
#define IR_7			0x42
#define IR_8			0x52
#define IR_9			0x4Avoid IR_Init(void);
unsigned char IR_GetDataFlag(void);
unsigned char IR_GetRepeatFlag(void);
unsigned char IR_GetAddress(void);
unsigned char IR_GetCommand(void);#endif

Int0.c

#include <REGX52.H>/*** @brief  外部中斷0初始化* @param  無* @retval 無*/
void Int0_Init(void)
{IT0=1;IE0=0;EX0=1;EA=1;PX0=1;
}/*外部中斷0中斷函數模板
void Int0_Routine(void) interrupt 0
{}
*/

Int0.h

#ifndef __INT0_H__
#define __INT0_H__void Int0_Init(void);#endif

main.c

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"unsigned char Num;
unsigned char Address;
unsigned char Command;void main()
{LCD_Init();LCD_ShowString(1,1,"ADDR  CMD  NUM");LCD_ShowString(2,1,"00    00   000");IR_Init();while(1){if(IR_GetDataFlag() || IR_GetRepeatFlag())	//如果收到數據幀或者收到連發幀{Address=IR_GetAddress();		//獲取遙控器地址碼Command=IR_GetCommand();		//獲取遙控器命令碼LCD_ShowHexNum(2,1,Address,2);	//顯示遙控器地址碼LCD_ShowHexNum(2,7,Command,2);	//顯示遙控器命令碼if(Command==IR_VOL_MINUS)		//如果遙控器VOL-按鍵按下{Num--;						//Num自減}if(Command==IR_VOL_ADD)			//如果遙控器VOL+按鍵按下{Num++;						//Num自增}LCD_ShowNum(2,12,Num,3);		//顯示Num}}
}

10.紅外遙控直流機調速代碼

第一步:

將寫好的直流機調速代碼,復制一份,這個代碼看小編的直流機博客

第二步:

將定時器模塊中的定時器0改為定時器1,避免沖突

第三步:

復制粘貼紅外遙控代碼中的紅外解碼模塊、改造后的定時器模塊、外部中斷0模塊到本工程

第四步:

將電機模塊化

第五步:

主函數調用

最終代碼:

模塊:

Timer1.c

#include <REGX52.H>/*** @brief  定時器1初始化,100us@12.000MHz* @param  無* @retval 無*/
void Timer1_Init(void)
{TMOD &= 0x0F;		//設置定時器模式TMOD |= 0x10;		//設置定時器模式TL1 = 0x9C;		//設置定時初值TH1 = 0xFF;		//設置定時初值TF1 = 0;		//清除TF1標志TR1 = 1;		//定時器1開始計時ET1=1;EA=1;PT1=0;
}/*定時器中斷函數模板
void Timer1_Routine() interrupt 3
{static unsigned int T1Count;TL1 = 0x9C;		//設置定時初值TH1 = 0xFF;		//設置定時初值T1Count++;if(T1Count>=1000){T1Count=0;}
}
*/

Timer1.h

#ifndef __TIMER1_H__
#define __TIMER1_H__void Timer1_Init(void);#endif

Motor.c

#include <REGX52.H>
#include "Timer1.h"//引腳定義
sbit Motor=P1^0;unsigned char Counter,Compare;/*** @brief  電機初始化* @param  無* @retval 無*/
void Motor_Init(void)
{Timer1_Init();
}/*** @brief  電機設置速度* @param  Speed 要設置的速度,范圍0~100* @retval 無*/
void Motor_SetSpeed(unsigned char Speed)
{Compare=Speed;
}//定時器1中斷函數
void Timer1_Routine() interrupt 3
{TL1 = 0x9C;		//設置定時初值TH1 = 0xFF;		//設置定時初值Counter++;Counter%=100;	//計數值變化范圍限制在0~99if(Counter<Compare)	//計數值小于比較值{Motor=1;		//輸出1}else				//計數值大于比較值{Motor=0;		//輸出0}
}

Motor.h

#ifndef __MOTOR_H__
#define __MOTOR_H__void Motor_Init(void);
void Motor_SetSpeed(unsigned char Speed);#endif

main.c

#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Motor.h"
#include "IR.h"unsigned char Command,Speed;void main()
{Motor_Init();IR_Init();while(1){if(IR_GetDataFlag())	//如果收到數據幀{Command=IR_GetCommand();		//獲取遙控器命令碼if(Command==IR_0){Speed=0;}		//根據遙控器命令碼設置速度if(Command==IR_1){Speed=1;}if(Command==IR_2){Speed=2;}if(Command==IR_3){Speed=3;}if(Speed==0){Motor_SetSpeed(0);}	//速度輸出if(Speed==1){Motor_SetSpeed(50);}if(Speed==2){Motor_SetSpeed(75);}if(Speed==3){Motor_SetSpeed(100);}}Nixie(1,Speed);						//數碼管顯示速度}
}

基于上述的兩個代碼在11.0592MHz晶振基礎上改造:51單片機紅外遙控(外部中斷)代碼(11.0592MHz晶振)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/83121.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/83121.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/83121.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C#】一個簡單的http服務器項目開發過程詳解

這跟安裝NoteJs程序運行腳本文件搭建一個簡單Http服務器一樣&#xff0c;相比起來&#xff0c;它的優點是可以開發的應用是免安裝&#xff0c;跨平臺的&#xff0c;放在移動盤上便捷的&#xff0c;這里著重講http服務器實現的過程&#xff0c;以便自主實現特定的功能和服務。 …

WPF【11_4】WPF實戰-重構與美化(MVVM 架構)

11-9 【理論】MVVM 架構 在 WPF 項目中&#xff0c;我們主要采用的是一種類似 MVC 的架構&#xff0c;叫做 MVVM。 MVVM 繼承了 MVC 的理念&#xff0c;是 Model-View-ViewModel 的縮寫&#xff0c;中文意思是模型、視圖、視圖模型。這三個詞分開看我們都能看懂&#xff0c;不…

使用PowerBI個人網關定時刷新數據

使用PowerBI個人網關定時刷新數據 PowerBI desktop連接mysql&#xff0c;可以設置定時刷新數據或在PowerBI服務中手動刷新數據,步驟如下&#xff1a; 第一步&#xff1a; 下載網關。以個人網關為例&#xff0c;如圖 第二步&#xff1a; 雙擊網關&#xff0c;點擊下一步&…

深度學習驅動的超高清圖修復技術——綜述

Deep Learning-Driven Ultra-High-Definition Image Restoration: A Survey Liyan Wang, Weixiang Zhou, Cong Wang, Kin-Man Lam, Zhixun Su, Jinshan Pan Abstract Ultra-high-definition (UHD) image restoration?? aims to specifically solve the problem of ??quali…

3 分鐘學會使用 Puppeteer 將 HTML 轉 PDF

需求背景 1、網頁存檔與文檔管理 需要將網頁內容長期保存或歸檔為PDF,確保內容不被篡改或丟失,適用于法律文檔、合同、技術文檔等場景。PDF格式便于存儲和檢索。 2、電子報告生成 動態生成的HTML內容(如數據分析報告、儀表盤)需導出為PDF供下載或打印。PDF保留排版和樣…

電子郵箱設置SSL:構建郵件傳輸的加密護城河

在數字化通信高度依賴的今天&#xff0c;電子郵件作為企業協作與個人隱私的核心載體&#xff0c;其安全性直接關系到數據主權與商業利益。SSL&#xff08;Secure Sockets Layer&#xff09;作為網絡通信加密的基石技術&#xff0c;通過為郵件傳輸建立加密隧道&#xff0c;有效抵…

Qt -使用OpenCV得到SDF

博客主頁&#xff1a;【夜泉_ly】 本文專欄&#xff1a;【暫無】 歡迎點贊&#x1f44d;收藏?關注?? 目錄 cv::MatdistanceTransform獲得SDF 本文的目標&#xff0c; 是簡單學習并使用OpenCV的相關函數&#xff0c; 并獲得QImage的SDF(Signed Distance Field 有向距離場) 至…

Compose仿微信底部導航欄NavigationBar :底部導航控制滑動并移動

文章目錄 1、準備工作1.1 參考1.2 依賴添加&#xff1a;1.3 主要控件NavigationBarHorizontalPager、VerticalPager 2、功能描述&#xff1a;3、實現過程3.1 創建一個數據類3.2 創建一個list變量3.3 具體實現3.3.1 創建共享的Pager狀態3.3.2 將頁面索引與頁面標題同步3.3.3 創建…

WindowServer2022下docker方式安裝dify步驟

WindowServer2022下docker方式安裝dify步驟&#xff08;穩定后考慮部署至linux中&#xff09; 教程&#xff1a;https://blog.csdn.net/qq_49035156/article/details/143264534 0、資源要求 ---windows&#xff1a;8核CPU、16G內存、200G500G存儲 ---10.21.31.122/administra…

【數據治理】要點整理-信息技術數據質量評價指標-GB/T36344-2018

導讀&#xff1a;指標為數據質量評估提供了一套系統化、標準化的框架&#xff0c;涵蓋規范性、完整性、準確性、一致性、時效性、可訪問性六大核心指標&#xff0c;助力組織提升數據處理效率、支持決策制定及業務流程優化&#xff0c;確保數據在數據生存周期各階段的質量可控。…

前端實現圖片壓縮:基于 HTML5 File API 與 Canvas 的完整方案

在 Web 開發中,處理用戶上傳的圖片時,前端壓縮可以有效減少服務器壓力并提升上傳效率。本文將詳細講解如何通過<input type="file">實現圖片上傳,結合 Canvas 實現圖片壓縮,并實時展示壓縮前后的圖片預覽和文件大小對比。 一、核心功能架構 我們將實現以…

通信算法之280:無人機偵測模塊知識框架思維導圖

1. 無人機偵測模塊知識框架思維導圖, 見文末章節。 2. OFDM參數估計,基于循環自相關特性。 3. 無人機其它參數估計

單片機寄存器的四種主要類型!

1. 控制寄存器&#xff08;Control Registers&#xff09;?? ??專業定義??&#xff1a;用于配置硬件行為或觸發操作的寄存器。 ??大白話??&#xff1a; 相當于設備的??“控制面板”??&#xff0c;通過寫入特定值來??開關功能??或??調整參數??。例如&am…

第100+41步 ChatGPT學習:R語言實現誤判病例分析

本期是《第33步 機器學習分類實戰&#xff1a;誤判病例分析》的R版本。 嘗試使用Deepseek-R1來試試寫代碼&#xff0c;效果還不錯。 下面上R語言代碼&#xff0c;以Xgboost為例&#xff1a; # 加載必要的庫 library(caret) library(pROC) library(ggplot2) library(xgboost)…

HTML Day04

Day04 0.引言1. HTML字符實體2. HTML表單2.1 表單標簽2.2 表單示例 3. HTML框架4. HTML顏色4.1 16進制表示法4.2 rgba表示法4.3 名稱表達法 5. HTML腳本 0.引言 剛剛回顧了前面幾篇博客&#xff0c;感覺寫的內容倒是很詳細&#xff0c;每個知識點都做了說明。但是感覺在知識組織…

comfyui 工作流中 視頻長度和哪些參數有關? 生成15秒的視頻,再加上RTX4060 8G顯卡,嘗試一下

想再消費級顯卡上生成15秒長視頻&#xff0c;還是比較慢的&#xff0c;不過動漫的畫質要求比較低 在ComfyUI中生成15秒視頻需綜合考慮視頻參數配置、模型選擇和硬件優化&#xff0c;尤其針對RTX 4060 8G顯存的限制。 ?? 一、影響視頻長度的核心參數 總幀數&#xff08;video_…

Netty 實戰篇:構建高性能聊天服務器

在前兩篇文章中&#xff0c;我們深入探討了 Netty 的 IO 模型以及其核心組件的工作原理。本篇文章將通過一個實際的聊天服務器示例&#xff0c;展示如何使用 Netty 構建高性能的網絡應用。 一、項目結構 項目主要包含以下幾個部分&#xff1a; ChatServer&#xff1a;服務器啟…

智紳科技——科技賦能健康養老,構建智慧晚年新生態

當老齡化浪潮與數字技術深度碰撞&#xff0c;智紳科技以 “科技賦能健康&#xff0c;智慧守護晚年” 為核心理念&#xff0c;錨定數字健康與養老服務賽道&#xff0c;通過人工智能、物聯網、大數據等技術集成&#xff0c;為亞健康群體與中老年人群構建 “監測 - 預防 - 輔助 - …

Tkinter軟件——顯示txt標簽的目標水平邊框圖像

代碼&#xff1a; import tkinter as tk from tkinter import filedialog from tkinter import messagebox import cv2 from PIL import Image, ImageTk import osclass ImageBoxApp:def __init__(self, master):self.master masterself.master.title("Image Box Drawer…

Linux 文件覆蓋機制與實踐:以 mv 命令為切入點

引言&#xff1a;文件覆蓋的本質 文件覆蓋是 Linux 文件系統中常見的操作&#xff0c;指的是在目標路徑已存在文件的情況下&#xff0c;將源文件的內容寫入目標文件&#xff0c;導致目標文件的原有內容被替換。在 Linux 中&#xff0c;文件覆蓋通常通過命令行工具&#xff08;…