0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于FPGA的紅外遙控實驗

CHANBAEK ? 來源:小小研究生 ? 作者:xxyjs2020 ? 2023-08-15 16:02 ? 次閱讀

理論基礎(chǔ)

可見光中紅光的波長范圍為620nm ~ 720nm,波長比紅光波長還長的的光叫紅外線。紅外線按波長范圍可分為近紅外、中紅外、遠紅外、極紅外。紅外線遙控是利用近紅外光傳送遙控指令的,波長為0.76um~1 .5um。

紅外遙控發(fā)射部分由遙控按鍵、編碼以及調(diào)制電路、紅外發(fā)光二極管等組成。紅外遙控接收部分由光敏二極管、解調(diào)電路等組成。最后將解調(diào)的信號輸入FPGA內(nèi)進行解碼輸出。接收信號是板載的HS0038B,該接收頭收到信號后輸出的波形剛好與發(fā)送的波形相反。發(fā)射信號是遙控器,鍵碼如下:

圖片

編碼協(xié)議NEC

紅外遙控的編碼協(xié)議有NEC、Philips RC-5、Philips RC-6、Sony SIRC等,而使用最多的是 NEC協(xié)議 。NEC協(xié)議采用的是PPM(Pulse Position Modulation,脈沖位置調(diào)制)進行編碼。當我們按下遙控器的一個按鍵時,會發(fā)送一幀的數(shù)據(jù)。這一幀數(shù)據(jù)由 引導碼、地址碼、地址反碼、數(shù)據(jù)碼、數(shù)據(jù)反碼以及一位結(jié)束位 (可忽略)組成。

圖片9ms的高電平+4.5ms的低電平組成了引導碼。后面是 地址碼和地址反碼 ,0和1是由時間間隔區(qū)分的(邏輯“1”由560us的高脈沖加上1.69ms的低電平組成,而邏輯“0”由560us的高脈沖加上560us的低電平組成)。如圖分別是0000_0000和1111_1111,再后面是 數(shù)據(jù)碼和數(shù)據(jù)反碼 ,如圖是1010_1101(注意低位和高位順序)和0101_0010。由于是正碼和反碼,因此總共0和1的數(shù)量一定都是8個,那么它們的總時長是不變的。最后是562.5um脈沖突發(fā)以表示消息傳輸?shù)慕Y(jié)束。

長按時,當發(fā)送完數(shù)據(jù)后,每隔110ms會發(fā)送一個重復碼,重復碼由9ms的高脈沖和2.25ms的低電平以及560us的高脈沖(結(jié)束標志)組成。們使用的一體化接收頭接收到信號后輸出到FPGA的波形剛好與發(fā)送的波形 相反 。即發(fā)送的高脈沖,接收后輸出就為低電平;發(fā)送的低電平,接收后輸出就為高電平。

設計規(guī)劃

使用紅外遙控器發(fā)送紅外信號,F(xiàn)PGA開發(fā)板上的接收頭接收到紅外信號后傳入FPGA芯片內(nèi),F(xiàn)PGA芯片接收到信號后進行解碼,將解碼后的按鍵碼顯示在數(shù)碼管上。若檢測到發(fā)送了重復碼,則讓led閃爍顯示,一個重復碼閃爍一次。

圖片

一共包括四個模塊,紅外模塊,led模塊,數(shù)碼管動態(tài)顯示模塊和頂層模塊。其中數(shù)碼管動態(tài)顯示模塊可以直接調(diào)用以前的,而led模塊比較簡單,因此重心放在紅外模塊上。

紅外模塊

輸入是時鐘,復位和紅外輸入信號,輸出是數(shù)據(jù)和重復使能信號。其中data是27位,我們的協(xié)議是8位,這里用27位是因為數(shù)碼管動態(tài)顯示模塊是27位的(顯示最大值9999_9999),所以在這里也定義成20位的位寬與之相匹配,防止出現(xiàn)未知的錯誤。我們收到數(shù)據(jù)后首先要判斷是否按照NEC協(xié)議發(fā)送的,只有是才能輸出相應的數(shù)據(jù)和重復使能信號。我們知道接收的數(shù)據(jù)與紅外發(fā)送的數(shù)據(jù)是相反的,發(fā)送的引導碼是9ms的高電平+4.5ms的低電平,那么只要判斷接收的引導碼是不是9ms的低電平和4.5ms的高電平,接下來的地址碼,數(shù)據(jù)碼和重復碼也是同理。

用狀態(tài)圖的跳轉(zhuǎn)來展示整個過程:

IDEL狀態(tài):初始狀態(tài),等待紅外信號的到來。當檢測到下降沿來臨時,表示9ms的低電平已經(jīng)開始發(fā)送,這時我們從IDLE跳轉(zhuǎn)到S_T9狀態(tài)。

S_T9:檢測9ms低電平狀態(tài)。檢測到上升沿時,這中間的低電平如果保持了9ms,跳轉(zhuǎn)到下一個狀態(tài),如果不是說明信息有誤,回到IDEL狀態(tài)重新開始。

S_JUDGE:由于9ms低電平后可能是4.5ms高電平(引導碼)也可能是2.25ms高電平(重復碼),如果是前者,說明后面是地址碼、地址反碼、數(shù)據(jù)碼和數(shù)據(jù)反碼,跳轉(zhuǎn)到S_IFR_DATA;如果是后者,說明這一段是重復碼,跳轉(zhuǎn)到S_REPEAT;若都不是,說明發(fā)送錯誤,回到IDEL。

S_IFR_DATA:地址碼、地址反碼和數(shù)據(jù)碼、數(shù)據(jù)反碼的接收與發(fā)送的電平相反,檢測到560us的低電平后,如果接的是1.69ms高電平說明邏輯1,560us高電平說明邏輯0。當接受完32位數(shù)據(jù)后回到IDEL,如果都不滿足說明發(fā)送錯誤,回到IDEL。

S_REPEAT:重復碼狀態(tài)。當上升沿到來的時直接回到IDEL。

通過判斷高低電平的持續(xù)時間去判斷狀態(tài),一共涉及到9ms(449_999)、4.5ms(224_999)、2.25ms(112_499)、1.69ms(84_499)、0.56ms(27_999)的時間間隔,因此需要5個計數(shù)器去產(chǎn)生fag信號。flag信號在以前章節(jié)都是持續(xù)一個時鐘周期的高電平,這里由于晶振可能不會剛好控制在9ms整,因此需要讓它在較大的時間范圍保持高電平。

時間信號產(chǎn)生波形圖

圖片

接下來要對紅外信號進行 采沿 ,采沿的代碼在工程上非常常見?。?!對需要采沿的信號打拍后經(jīng)過取反、相與操作即可獲得上升沿或下降沿標志信號。用always能檢測到信號狀態(tài)的改變,但是占用資源和時間。

上升沿下降沿信號產(chǎn)生波形圖

圖片

ifr_in_rise=infrared_in_d1&&(~infrared_in_d2)

ifr_in_fall=infrared_in_d2&&(~infrared_in_d1)

引導碼狀態(tài)跳轉(zhuǎn)波形圖

圖片

代碼編寫

module infrared_rcv
(
input wire sys_clk , 
input wire sys_rst_n , 
input wire infrared_in , 


output reg repeat_en , //重復碼使能信號
output reg [19:0] data //接收的控制碼
);
//parameter define
parameter CNT_0_56MS_L = 20000 , //0.56ms計數(shù)為0-27999
CNT_0_56MS_H = 35000 ,
CNT_1_69MS_L = 80000 , //1.69ms計數(shù)為0-84499
CNT_1_69MS_H = 90000 ,
CNT_2_25MS_L = 100000, //2.25ms計數(shù)為0-112499
CNT_2_25MS_H = 125000,
CNT_4_5MS_L = 175000, //4.5ms計數(shù)為0-224999
CNT_4_5MS_H = 275000,
CNT_9MS_L = 400000, //9ms計數(shù)為0-449999
CNT_9MS_H = 490000;


//state
parameter IDLE = 5'b0_0001, //空閑狀態(tài)
S_T9 = 5'b0_0010, //監(jiān)測同步碼低電平
S_JUDGE = 5'b0_0100, //判斷重復碼和同步碼高電平
S_IFR_DATA = 5'b0_1000, //接收數(shù)據(jù)
S_REPEAT = 5'b1_0000; //重復碼


//wire define
wire ifr_in_rise ; //檢測紅外信號的上升沿
wire ifr_in_fall ; //檢測紅外信號的下降沿


//reg define
reg infrared_in_d1 ; //對infrared_in信號打一拍
reg infrared_in_d2 ; //對infrared_in信號打兩拍
reg [18:0] cnt ; //計數(shù)器
reg flag_0_56ms ; //0.56ms計數(shù)完成標志信號
reg flag_1_69ms ; //1.69ms計數(shù)完成標志信號
reg flag_2_25ms ; //2.25ms計數(shù)完成標志信號
reg flag_4_5ms ; //4.5ms計數(shù)完成標志信號
reg flag_9ms ; //0.56ms計數(shù)完成標志信號
reg [4:0] state ; //狀態(tài)機狀態(tài)
reg [5:0] data_cnt ; //數(shù)據(jù)計數(shù)器
reg [31:0] data_tmp ; //數(shù)據(jù)寄存器


//檢測紅外信號的上升沿和下降沿
assign ifr_in_rise = (~infrared_in_d2) & (infrared_in_d1);
assign ifr_in_fall = (infrared_in_d2) & (~infrared_in_d1);


//對infrared_in信號打拍
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
begin
infrared_in_d1 <= 1'b0;
infrared_in_d2 <= 1'b0;
end
else
begin
infrared_in_d1 <= infrared_in;
infrared_in_d2 <= infrared_in_d1;
end


//cnt
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt <= 19'd0;
else
case(state)
IDLE: cnt <= 19'd0;
S_T9: if((ifr_in_rise==1'b1) && (flag_9ms==1'b1))
cnt <= 19'd0;
else
cnt <= cnt + 1;
S_JUDGE:if((ifr_in_fall==1'b1) && (flag_2_25ms==1'b1 ||
flag_4_5ms==1'b1))
cnt <= 19'd0;
else
cnt <= cnt + 1;
S_IFR_DATA: if((flag_0_56ms == 1'b1) && (ifr_in_rise==1'b1))
cnt <= 19'd0;
else if(((flag_0_56ms==1'b1) ||
(flag_1_69ms==1'b1)) && (ifr_in_fall==1'b1))
cnt <= 19'd0;
else
cnt <= cnt + 1;
default:cnt <= 19'd0;
endcase


//flag_0_56ms:計數(shù)到0.56ms范圍拉高標志信號
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
flag_0_56ms <= 1'b0;
 else if((state == S_IFR_DATA) && (cnt >= CNT_0_56MS_L) &&
 (cnt <= CNT_0_56MS_H))
 flag_0_56ms <= 1'b1;
 else
 flag_0_56ms <= 1'b0;


 //flag_1_69ms:計數(shù)到1.69ms范圍拉高標志信號
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 flag_1_69ms <= 1'b0;
 else if((state == S_IFR_DATA) && (cnt >= CNT_1_69MS_L) &&
 (cnt <= CNT_1_69MS_H))
 flag_1_69ms <= 1'b1;
 else
 flag_1_69ms <= 1'b0;


 //flag_2_25ms:計數(shù)到2.25ms范圍拉高標志信號
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 flag_2_25ms <= 1'b0;
 else if((state == S_JUDGE) && (cnt >= CNT_2_25MS_L) &&
 (cnt <= CNT_2_25MS_H))
 flag_2_25ms <= 1'b1;
 else
 flag_2_25ms <= 1'b0;


 //flag_4_5ms:計數(shù)到4.5ms范圍拉高標志信號
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 flag_4_5ms <= 1'b0;
 else if((state == S_JUDGE) && (cnt >= CNT_4_5MS_L) &&
 (cnt <= CNT_4_5MS_H))
 flag_4_5ms <= 1'b1;
 else
 flag_4_5ms <= 1'b0;


 //flag_9ms:計數(shù)到9ms范圍拉高標志信號
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 flag_9ms <= 1'b0;
 else if((state == S_T9) && (cnt >= CNT_9MS_L) &&
 (cnt <= CNT_9MS_H))
 flag_9ms <= 1'b1;
 else
 flag_9ms <= 1'b0;


 //狀態(tài)機:狀態(tài)跳轉(zhuǎn)
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 state <= IDLE;
 else
 case(state)


 IDLE:
 if(ifr_in_fall == 1'b1)
 state <= S_T9;
 else 
 state <= IDLE;


 S_T9: 
 if((ifr_in_rise == 1'b1) && (flag_9ms == 1'b1))
 state <= S_JUDGE;
 else if((ifr_in_rise == 1'b1) && (flag_9ms == 1'b0))
 state <= IDLE;
 else
 state <= S_T9;


 S_JUDGE: 
 if((ifr_in_fall == 1'b1) && (flag_2_25ms == 1'b1))
 state <= S_REPEAT;
 else if((ifr_in_fall == 1'b1) && (flag_4_5ms == 1'b1))
 state <= S_IFR_DATA;
 else if((ifr_in_fall == 1'b1) && (flag_2_25ms == 1'b0) &&
 (flag_4_5ms == 1'b0))
 state <= IDLE;
 else
 state <= S_JUDGE;


 S_IFR_DATA:
 if(ifr_in_rise == 1'b1 && flag_0_56ms == 1'b0)
 state <= IDLE;
 else if(ifr_in_fall == 1'b1 && (flag_0_56ms == 1'b0 &&
 flag_1_69ms == 1'b0))
 state <= IDLE;
 else if(ifr_in_rise == 1'b1 && data_cnt == 6'd32)
 state <= IDLE;


 S_REPEAT:
 if(ifr_in_rise == 1'b1)
 state <= IDLE;
 else
 state <= S_REPEAT;
 default:
 state <= IDLE;
 endcase


 //data_tmp
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 data_tmp <= 32'b0;
 else if(state == S_IFR_DATA && ifr_in_fall == 1'b1 &&
 flag_0_56ms == 1'b1)
 data_tmp[data_cnt] <= 1'b0;
 else if(state == S_IFR_DATA && ifr_in_fall == 1'b1 &&
 flag_1_69ms == 1'b1)
 data_tmp[data_cnt] <= 1'b1;
 else
 data_tmp <= data_tmp;


 //data_cnt
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 data_cnt <= 1'b0;
 else if(ifr_in_rise == 1'b1 && data_cnt == 6'd32)
 data_cnt <= 1'b0;
 else if(ifr_in_fall == 1'b1 && state == S_IFR_DATA)
 data_cnt <= data_cnt + 1'b1;
 else
 data_cnt <= data_cnt;


 //repeat_en
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 repeat_en <= 1'b0;
 else if(state == S_REPEAT && (data_tmp[23:16] ==
 ~data_tmp[31:24]))
 repeat_en <= 1'b1;
 else
 repeat_en <= 1'b0;


 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 data <= 20'b0;
 else if(data_tmp[23:16] == ~data_tmp[31:24] && data_tmp[7:0] ==
 ~data_tmp [15:8] && data_cnt==6'd32)
 data <= {12'b0,data_tmp[23:16]};


 endmodule

參數(shù)定義:我們需要規(guī)定flag信號拉起時的計數(shù)值,由于要保持一個時間段,5個計數(shù)值都要定義低值和高值

狀態(tài)定義:5個狀態(tài)用5位數(shù)值表示,每個狀態(tài)都有一個不同位為1。對于大型狀態(tài)機而言,如果上一個狀態(tài)到下一個狀態(tài)只改變一位會比這種定義好

檢測上升沿和下降沿:檢測方式是打拍之后取反求與,如果檢測到,對應的信號拉高

打拍:在第四節(jié)中介紹了阻塞賦值和非阻塞賦值,非阻塞賦值是并行的,always塊結(jié)束之后再完成賦值行為。所以在波形上看一條非阻塞賦值是有一個時鐘周期的延時。這個打拍可以理解為一次延時。

always塊中a=din;b=a;c=b; always塊中a=| | Q1 | Q2 | Q3 | Q4 | | Q1 | Q2 | Q3 | Q4 |
| ----- | ---- | ---- | ---- | ---- | ----- | ---- | ---- | ---- | ---- |
| din | 0 | 1 | 1 | 0 | din | 1 | 0 | 0 | 0 |
| a | 0 | 1 | 1 | 0 | a | 1 | 0 | 0 | 0 |
| b | 0 | 1 | 1 | 0 | b | 1 | 1 | 0 | 0 |
| c | 0 | 1 | 1 | 0 | c | 1 | 1 | 1 | 0 |

cnt計數(shù):非復位狀態(tài)時要看狀態(tài),IDEL狀態(tài)cnt一直保持0,S_T9狀態(tài)要判斷是否低電平持續(xù)9ms,條件是如果有上升沿的同時9ms的flag拉起,就要歸0重新準備計數(shù),否則+1。其他狀態(tài)也是同理。

flag信號:以1.69ms為例,若復位有效,flag為低電平;如果狀態(tài)位于S_IFR_DATA且滿足1.69ms計數(shù)值的低值到高值之間,就拉高,否則維持低電平,其他的flag信號也是同理

狀態(tài)跳轉(zhuǎn):復位有效是IDEL狀態(tài);當狀態(tài)處于IDEL時,如果檢測到下降沿則跳轉(zhuǎn)到S_T9,否則說明發(fā)送錯誤,維持在IDEL;當狀態(tài)處于S_T9時,如果檢測到上升沿且低電平維持了9ms左右則跳轉(zhuǎn)到S_JUDGE,如果不是維持9ms說明發(fā)送錯誤則跳轉(zhuǎn)到IDEL;當狀態(tài)處于S_JUDGE時,如果檢測到下降沿且高電平維持了2.25ms左右,說明是重復碼跳轉(zhuǎn)到S_REPEAT左右,如果維持4.5ms說明后面要接地址碼等跳轉(zhuǎn)到S_IFR_DATA狀態(tài),如果都不是說明發(fā)送錯誤回到IDEL狀態(tài);當狀態(tài)處于S_IFR_DATA時,如果檢測到上升沿但不是維持56ms說明發(fā)送錯誤回到IDEL狀態(tài),如果檢測到下降沿但是高電平時間不滿足邏輯0或1說明發(fā)送錯誤回到IDEL狀態(tài),如果檢測到上升沿且數(shù)據(jù)計數(shù)器滿足32位則接收完畢回到IDEL狀態(tài);當狀態(tài)處于S_REPEAT狀態(tài)時,如果檢測到上升沿直接回到IDEL狀態(tài),否則維持原態(tài)。case語句需要default。

數(shù)據(jù)緩存:在S_IFR_DATA狀態(tài)時接收的32位數(shù)據(jù)需要區(qū)分邏輯0和1,先緩存到data_tmp中。當狀態(tài)是S_IFR_DATA時,復位有效時32位緩存都為0;當檢測到下降沿且高電平維持0.56ms說明是邏輯0,將其寫入到對應位的緩存中;維持1.69ms說明是邏輯1,也寫入。

data_cnt:數(shù)據(jù)計數(shù)器,因此有32位數(shù)據(jù),每計數(shù)一次都要寫入一位。復位有效時為低電平;檢測到上升沿且data_cnt=32說明計滿且寫滿了,歸0;檢測到下降沿且處于S_IFR_DATA狀態(tài),+1;其他情況維持不變

repeat_en:重復使能信號,要傳遞給Led作為亮燈的控制信號。重復的判斷條件是1、處于重復S_REPEAT狀態(tài)2、確實檢測到了重復的數(shù)據(jù)。復位有效時歸0;狀態(tài)處于重復狀態(tài)且緩存中高8位和次8位相同時拉高;其他情況歸0

數(shù)據(jù)輸出:復位有效時數(shù)據(jù)所有位都歸0;32位數(shù)據(jù)校驗方式是地址碼和地址反碼是位反的,數(shù)據(jù)碼和數(shù)據(jù)反碼是位反的,數(shù)據(jù)計數(shù)器計滿32個數(shù)值,如果檢驗成功,就將數(shù)據(jù)碼進行輸出。由于data和之前數(shù)碼管動態(tài)顯示中的位數(shù)一致是27位,這里輸出數(shù)據(jù)只有8位,因此高位都賦0。數(shù)碼管只需要顯示低8位表示的數(shù)值即可

LED燈控制模塊

當有一次重復碼時,重復使能有效,led閃爍一次。如果讓燈在使能有效時亮,使能信號持續(xù)時間很短,led亮的時間也短,效果不明顯。長按紅外遙控按鍵那么每110ms會發(fā)送一次重復碼,那么如果讓led燈在110ms中亮50ms,led的顯示效果比較好。需要一個50ms的計數(shù)器,在repeat_en信號檢測出上升沿時開始計數(shù),此時led低電平點亮,計數(shù)完畢后led熄滅。

圖片

編寫代碼

module led_ctrl
(
input wire sys_clk , //系統(tǒng)時鐘,頻率50MHz
input wire sys_rst_n , //復位信號,低有效
input wire repeat_en , //重復碼使能信號


output reg led //輸出led燈信號
);


 //parameter define
 parameter CNT_MAX = 2500_000;


 //wire define
 wire repeat_en_rise ; //重復碼使能信號上升沿


 //reg define
 reg repeat_en_d1; //重復碼使能信號打一拍
 reg repeat_en_d2; //重復碼使能信號打兩拍
 reg cnt_en ; //計數(shù)器使能信號
 reg [21:0] cnt ; //計數(shù)器
 
 //獲得repeat_en上升沿信號
 assign repeat_en_rise = repeat_en_d1 & ~repeat_en_d2;


 //對repeat_en打兩拍
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 begin
 repeat_en_d1 <= 1'b0;
 repeat_en_d2 <= 1'b0;
 end
 else
 begin
 repeat_en_d1 <= repeat_en;
 repeat_en_d2 <= repeat_en_d1;
 end


 //當重復碼使能信號上升沿來到,拉高計數(shù)器使能信號,計到50ms后拉低
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt_en <= 1'b0;
 else if(cnt == CNT_MAX - 1)
 cnt_en <= 1'b0;
 else if(repeat_en_rise == 1'b1)
 cnt_en <= 1'b1;


 //當計數(shù)器使能信號為高時讓計數(shù)器開始計數(shù),為低時計數(shù)器清零
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt <= 22'b0;
 else if(cnt_en == 1'b1)
 cnt <= cnt + 1;
 else
 cnt <= 22'b0;


 //當計數(shù)器大于0時,點亮led燈,也就是當使能信號到來,led燈會亮50ms
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 led <= 1'b1;
 else if(cnt > 0)
 led <= 1'b0;
 else
 led <= 1'b1;


 endmodule

參數(shù)定義,獲取上升沿,打拍

使能信號cnt_en:復位時歸0;cnt計數(shù)到CNT_MAX-1時歸0,上升沿信號repeat_en_rise拉高時拉高

計數(shù)器cnt:復位時歸0;cnt_en為高電平時計數(shù)+1,其他情況歸0

led:復位時拉高表示熄滅,當cnt>0(1-250000)時led拉低表示點亮,否則熄滅

頂層模塊

module top_infrared_rcv
(
input wire sys_clk ,
input wire sys_rst_n , 
input wire infrared_in , 


output wire stcp , 
output wire shcp , 
output wire ds , 
 output wire oe , 
 output wire led 
 );


 //wire define
 wire repeat_en ; //重復碼使能信號
 wire [19:0] data ; //接收的控制碼


 infrared_rcv infrared_rcv_inst
 (
 .sys_clk (sys_clk ), 
 .sys_rst_n (sys_rst_n ), 
 .infrared_in (infrared_in), 
 .repeat_en (repeat_en ), 
 .data (data ) 
 );


 led_ctrl led_ctrl_inst
 (
 .sys_clk (sys_clk ) ,
 .sys_rst_n (sys_rst_n) ,
 .repeat_en (repeat_en) , 
 .led (led )
 );


 seg_595_dynamic seg_595_dynamic_inst
 (
 .sys_clk (sys_clk ), 
 .sys_rst_n (sys_rst_n), 
 .data (data ), 
 .point (6'd0 ), 
 .seg_en (1'b1 ), 
 .sign (1'b0 ), 
 .stcp (stcp ), 
 .shcp (shcp ), 
 .ds (ds ), 
 .oe (oe ) 
 );


 endmodule

圖片

testbench

`timescale 1ns/1ns
module tb_top_infrared_rcv();


//wire define
wire led ;
wire stcp ;
wire shcp ;
wire ds ;
//reg define
reg sys_clk ;
reg sys_rst_n ;
reg infrared_in ;


initial
begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
infrared_in <= 1'b1;
#100
sys_rst_n <= 1'b1;


//引導碼
#1000
infrared_in <= 1'b0; #9000000
infrared_in <= 1'b1; #4500000
//地址碼(發(fā)送地址碼8’h99)
//數(shù)據(jù)1
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #1690000
//數(shù)據(jù)0
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #560000
//數(shù)據(jù)0
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #560000
//數(shù)據(jù)1
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #1690000
//數(shù)據(jù)1
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #1690000
//數(shù)據(jù)0
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #560000
//數(shù)據(jù)0
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #560000
//數(shù)據(jù)1
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #1690000


//地址反碼(地址反碼為8’h66)
//數(shù)據(jù)0
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #560000
//數(shù)據(jù)1
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #1690000
//數(shù)據(jù)1
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #1690000
//數(shù)據(jù)0
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #560000
//數(shù)據(jù)0
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #560000
//數(shù)據(jù)1
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #1690000
//數(shù)據(jù)1
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #1690000
//數(shù)據(jù)0
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #560000
//數(shù)據(jù)碼(發(fā)送數(shù)據(jù)碼8’h22)
//數(shù)據(jù)0
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #560000
//數(shù)據(jù)1
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #1690000
//數(shù)據(jù)0
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #560000
//數(shù)據(jù)0
infrared_in <= 1'b0; #560000
infrared_in <= 1'b1; #560000
//數(shù)據(jù)0
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #560000
 //數(shù)據(jù)1
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #1690000
 //數(shù)據(jù)0
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #560000
 //數(shù)據(jù)0
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #560000
 //數(shù)據(jù)反碼(數(shù)據(jù)反碼為8’hdd)
 //數(shù)據(jù)1
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #1690000
 //數(shù)據(jù)0
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #560000
 //數(shù)據(jù)1
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #1690000
 //數(shù)據(jù)1
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #1690000
 //數(shù)據(jù)1
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #1690000
 //數(shù)據(jù)0
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #560000
 //數(shù)據(jù)1
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #1690000
 //數(shù)據(jù)1
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #1690000
 //重復碼
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1; #42000000
 infrared_in <= 1'b0; #9000000
 infrared_in <= 1'b1; #2250000
 infrared_in <= 1'b0; #560000
 infrared_in <= 1'b1;
 end


 //clk:產(chǎn)生時鐘
 always #10 sys_clk <= ~sys_clk;


 top_infrared_rcv top_infrared_rcv_inst
 (
 .sys_clk (sys_clk ), //系統(tǒng)時鐘,頻率50MHz
 .sys_rst_n (sys_rst_n ), //復位信號,低電平有效
 .infrared_in (infrared_in), //紅外接收信號
 .stcp (stcp ), //輸出數(shù)據(jù)存儲寄時鐘
 .shcp (shcp ), //移位寄存器的時鐘輸入
 .ds (ds ), //串行數(shù)據(jù)輸入
 .led (led ) //led燈控制信號
 );
 endmodule

初始化

引導碼:低電平9ms,高電平4.5ms

地址碼1001_1001:邏輯1是低電平延遲0.56ms后高電平延遲0.56ms,邏輯0是低電平延遲0.56ms后高電平延遲1.69ms

地址反碼0110_0110

數(shù)據(jù)碼0010_0010

數(shù)據(jù)反碼1101_1101,數(shù)據(jù)反碼后要以0.56ms的低電平作為結(jié)束標志

重復碼:維持一段時間高電平后再發(fā)送重復碼,低電平延遲9ms再高電平延遲2.25ms,以0.56ms的低電平作為重復碼的結(jié)束標志

產(chǎn)生時鐘,實例化

對比波形

圖片

data是27h'0000022與我們發(fā)送的數(shù)據(jù)一致,重復使能也按照預期實現(xiàn)。

管腳分配

紅外模塊的管腳圖,其他管腳之前都用過不重復

圖片

圖片

全編譯后上板驗證

長按才亮燈,按鍵對應的值顯示在數(shù)碼管上,視頻中我可能按的比較重。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1625

    文章

    21620

    瀏覽量

    601234
  • 發(fā)光二極管
    +關(guān)注

    關(guān)注

    13

    文章

    1192

    瀏覽量

    66143
  • NEC
    NEC
    +關(guān)注

    關(guān)注

    0

    文章

    238

    瀏覽量

    99068
  • 時鐘
    +關(guān)注

    關(guān)注

    10

    文章

    1714

    瀏覽量

    131274
  • 紅外遙控
    +關(guān)注

    關(guān)注

    22

    文章

    347

    瀏覽量

    45503
收藏 人收藏

    評論

    相關(guān)推薦

    紅外遙控解碼數(shù)碼管顯示實驗

    紅外遙控解碼數(shù)碼管顯示實驗[hide]紅外遙控解碼數(shù)碼管顯示實驗.rar[/hide] 
    發(fā)表于 12-07 18:22

    基于FPGA紅外遙控信號接收模塊的設計

    。本文提出的基于FPGA紅外遙控信號接收模塊的設計方案經(jīng)過電路仿真、FPGA實現(xiàn)及應用測試驗證該模塊完全符合紅外
    發(fā)表于 07-11 21:34

    紅外遙控解碼實驗

    本帖最后由 scan0123 于 2012-8-12 14:10 編輯 紅外遙控解碼實驗一. 實驗目的1. 了解紅外
    發(fā)表于 08-12 14:09

    正點原子開拓者FPGA開發(fā)板資料連載第二十四章 紅外遙控實驗

    的亮滅。系統(tǒng)框圖如下所示。圖 24.4.1 紅外遙控實驗系統(tǒng)框圖頂層模塊原理圖如下所示圖 24.4.2 頂層模塊原理圖FPGA頂層(top_remote_rcv)例化了以下兩個模塊:
    發(fā)表于 08-08 11:10

    紅外遙控系統(tǒng)設計與應用

    紅外遙控系統(tǒng)設計與應用一、實驗目的1.了解各種紅外收發(fā)器件,設計紅外收發(fā)電路。2.掌握紅外
    發(fā)表于 05-03 00:51 ?94次下載

    STM32_紅外遙控實驗

    STM32 紅外遙控實驗,很好的學習資料,快來下載吧
    發(fā)表于 02-15 17:08 ?33次下載

    ALIENTEK_MINISTM32_實驗21_紅外遙控實驗

    ALIENTEK MINISTM32 實驗21 紅外遙控實驗,很好的資料,快來下載吧
    發(fā)表于 02-19 11:40 ?13次下載

    紅外遙控實驗

    基于STM32開發(fā)板設計的紅外遙控實驗代碼,仿真成功,需要的朋友直接下載
    發(fā)表于 05-11 14:54 ?6次下載

    ARM基礎(chǔ)應用實驗_紅外遙控解碼

    電子專業(yè)單片機相關(guān)知識學習教材資料——ARM基礎(chǔ)應用實驗02紅外遙控解碼
    發(fā)表于 09-13 17:23 ?0次下載

    基于FPGA紅外遙控系統(tǒng)應用

    紅外遙控是目前使用廣泛的一種通信和遙控手段。在繼彩電、錄像機之后,在錄音機、音響設備、空調(diào)機以及玩具等其它小型電器裝置上也大量采用紅外遙控
    發(fā)表于 11-14 09:54 ?41次下載
    基于<b class='flag-5'>FPGA</b>的<b class='flag-5'>紅外</b><b class='flag-5'>遙控</b>系統(tǒng)應用

    基于STM32的紅外遙控實驗的資料,程序免費下載

    本文檔的主要內(nèi)容詳細介紹的是基于STM32的紅外遙控實驗的資料,程序免費下載。
    發(fā)表于 09-06 08:00 ?50次下載
    基于STM32的<b class='flag-5'>紅外</b><b class='flag-5'>遙控</b><b class='flag-5'>實驗</b>的資料,程序免費下載

    正點原子開拓者FPGA紅外遙控實驗

    紅外遙控是一種無線、非接觸控制技術(shù),具有抗干擾能力強,信息傳輸可靠,功耗低,成本低,易實現(xiàn)等顯著優(yōu)點,被諸多電子設備特別是家用電器廣泛采用,并越來越多的應用到計算機和手機系統(tǒng)中。
    的頭像 發(fā)表于 09-11 07:05 ?2188次閱讀
    正點原子開拓者<b class='flag-5'>FPGA</b>:<b class='flag-5'>紅外</b><b class='flag-5'>遙控</b><b class='flag-5'>實驗</b>

    Arduino的實驗例程之紅外遙控實驗

    本文檔的主要內(nèi)容詳細介紹的是Arduino的實驗例程之紅外遙控實驗。
    發(fā)表于 02-25 16:36 ?49次下載
    Arduino的<b class='flag-5'>實驗</b>例程之<b class='flag-5'>紅外</b><b class='flag-5'>遙控</b><b class='flag-5'>實驗</b>

    紅外遙控實驗的程序和工程文件免費下載

    本文檔的主要內(nèi)容詳細介紹的是紅外遙控實驗的程序和工程文件免費下載。
    發(fā)表于 03-05 16:34 ?23次下載

    基于單片機的紅外遙控通信實驗 紅外遙控器的發(fā)送和接收原理

    本章介紹紅外遙控通信試驗,通過本章的學習掌握紅外遙控器的編碼原理以及使用。在 RY-51 單片機開發(fā)板上,配備了一個紅外信號接收頭,用于接收
    的頭像 發(fā)表于 07-27 17:35 ?7403次閱讀
    基于單片機的<b class='flag-5'>紅外</b><b class='flag-5'>遙控</b>通信<b class='flag-5'>實驗</b> <b class='flag-5'>紅外</b><b class='flag-5'>遙控</b>器的發(fā)送和接收原理