無需外圍38KHZ晶振,STC8H系列芯片按道理都能用,萬能接受,萬能發射,EEPROM存儲數據,暫時只能存一個碼,串口輸出信息,按下遙控器按鍵,發送02可顯示剛剛收到的信息并保存,發送10可發射剛剛保存的數據,本人新手,程序有些亂,但有注釋,因為剛剛做出來所以并不完善,還請大佬多多指教!
紅外發射接P11,接受接P20。
原始波形:
6b9419f9689e075f40e092448763137.jpg (194.65 KB, 下載次數: 44)
下載附件
2023-8-9 11:22 上傳
經過學以后發射的波形:
62554aaa5cbda5f1f4ab8e2da105b2d.jpg (205.11 KB, 下載次數: 44)
下載附件
2023-8-9 11:22 上傳
單片機源程序如下:
- #include "stc8H.h"
- #include "intrins.h"
- #include <stdio.h>
- #include "uart.h"
- #include "eeprom.h"
- #include "launch.h"
- extern char ch;
- int ir1 = 0x0400;
- unsigned short xdata captures[VAL] = {0},eep_captures[VAL] = {0}; //緩存數組
- static unsigned int num = 0; //一共接受了幾個脈沖
- unsigned int two_num;
- static unsigned int Overflow = 0; //溢出次數
- static unsigned char val; //接收超時變量
- void Timer0_Init(void) //1毫秒@24.000MHz,定時器0
- {
- AUXR |= 0x80;
- TMOD &= 0xF0; //設置定時器模式
- // TL0 = 0x90; //設置定時初始值
- // TH0 = 0xE8; //設置定時初始值
-
- TL0 = 0x40; //設置定時初始值
- TH0 = 0xA2; //設置定時初始值
-
- TF0 = 0; //清除TF0標志
- TR0 = 1; //定時器0開始計時
- ET0 = 1;
- }
- void IR() //初始化
- {
- P1M0 = 0x00;
- P1M1 = 0x00;
- P3M0 = 0x00;
- P3M1 = 0x00;
- P5M0 = 0x00;
- P5M1 = 0x00;
- P_SW2 = 0x80;
- PWM1_PS = 0x05;
- //(CC1捕獲TI1上升沿,CC2捕獲TI1下降沿)
- PWMA_CCER1 = 0x00;
- PWMA_CCMR1 = 0x01; //CC1為輸入模式,且映射到TI1FP1上
- PWMA_CCMR2 = 0x02; //CC2為輸入模式,且映射到TI1FP2上
- PWMA_CCER1 = 0x11; //使能CC1/CC2上的捕獲功能
- PWMA_CCER1 |= 0x00; //設置捕獲極性為CC1的上升沿
- PWMA_CCER1 |= 0x20; //設置捕獲極性為CC2的下降沿
-
- PWMA_CR1 = 0x01;
-
- PWMA_PSCR = 0x09;
-
- PWMA_IER = 0x04; //使能CC2捕獲中斷
- PWMA_IER |= 0x02; //使能CC1捕獲中斷
- EA = 1;
- }
- void PWMA_ISR() interrupt 26 //PWM沿觸發中斷
- {
- unsigned int cnt_l;
- unsigned int cnt_h;
-
- if (PWMA_SR1 & 0x02)
- {
- PWMA_SR1 &= ~0x02;
- cnt_l = (PWMA_CCR1 - PWMA_CCR2)/24; //差值即為低電平寬度 cnt/時鐘頻率 = 脈寬(us)
- captures[num++] = cnt_l;
- }
-
-
- if (PWMA_SR1 & 0x04)
- {
- PWMA_SR1 &= ~0x04;
- cnt_h = (PWMA_CCR2 - PWMA_CCR1)/24; //差值即為高電平寬度
- captures[num++] = cnt_h;
- }
- }
- void TM0_Isr() interrupt 1 //定時器0中斷用來判斷脈沖接受是否超時,大于30ms為超時
- {
- if(P20 == 1)
- {
- val++;
- if(val > 30)
- {
- Overflow = 1;
- val = 0;
- }
- }else {val = 0;Overflow = 0;}
- }
- void UartReceiveHandler() interrupt 4 {
- if (RI) { // 接收中斷
- RI = 0; // 清除接收標志位
- ch = SBUF; // 讀取接收到的數據
- //UartSend(ch); // 原樣返回接收到的數據
- }
- }
-
- void TM3_Isr() interrupt 19 //定時器3中斷發生38K載波
- {
- P11 = !P11; //紅外1端口
- }
- //---------------------------------------------------------------------------------------------
- void main()
- {
- unsigned int i = 0,a = 0;
-
-
-
- Timer0_Init();
- Timer3_Init();
- UartInit();
- IR();
-
- UartSendString("Starting\r\n");
- lach1 = 1;
- while(1)
- {
- //lach1 = 1;
- if(Overflow == 1 && ch == 0x02)//如果超時溢出,并且接收到0x02
- {
- EraseUIntFromEEPROM(0x0400);
- EraseUIntFromEEPROM(0x0600);
- delays(5);
- EraseUIntFromEEPROM(0x0000);
- delays(5);
- for(i = 0; i <= num; i++)
- {
- SaveUIntToEEPROM(ir1+i*2, captures[i]); //寫入eeprom
- //SaveUIntToEEPROM(ir1+i*2, '3'); //寫入eeprom
- UartSendUint(captures[i]);//打印保存到數組里的數據
- captures[i] = 0;
- delays(1);
- }
- SaveUIntToEEPROM(0x0000, num); //將脈沖個數寫入eeprom
- UartSendString("End\r\n"); /*End結束*/
- UartSendUint(num);
- ir1 = 0x0400;
- ch = 0;
- num = 0;
- Overflow = 0;
- PWMA_IER = 0; //關閉PWM中斷使能
- ET0 = 0; //關閉定時器0中斷
- }else if(P20 == 0 && Overflow==0){
- PWMA_IER = 0x06; //打開PWM中斷使能
- ET0 = 1; //打開定時器0中斷
- }
-
-
- if(ch == 0x01)
- {
- two_num = ReadUIntFromEEPROM(0x0000);
- for(a = 0;a<=two_num;a++) //讀取紅外接收數組
- {
- eep_captures[a] = ReadUIntFromEEPROM(ir1+a*2);
- UartSendUint(eep_captures[a]);//打印保存到數組里的數據
- delays(1);
- }
- UartSendUint(two_num);
- ir1 = 0x0400;
- two_num = 0;
- ch = 0x00;
- }
- if(ch == 0x10)
- {
- two_num = ReadUIntFromEEPROM(0x0000);
- for(a = 0;a<=two_num;a++) //讀取紅外接收數組
- {
- eep_captures[a] = ReadUIntFromEEPROM(ir1+a*2);
- UartSendUint(eep_captures[a]);//打印保存到數組里的數據
- delays(1);
- }
- Launch_1(eep_captures,two_num);
- ch = 0;
- }
-
- }
- }
- 單片機源程序如下:
- [code]#include "stc8H.h"
- #include "intrins.h"
- #include <stdio.h>
- #include "uart.h"
- #include "eeprom.h"
- #include "launch.h"
- extern char ch;
- int ir1 = 0x0400;
- unsigned short xdata captures[VAL] = {0},eep_captures[VAL] = {0}; //緩存數組
- static unsigned int num = 0; //一共接受了幾個脈沖
- unsigned int two_num;
- static unsigned int Overflow = 0; //溢出次數
- static unsigned char val; //接收超時變量
- void Timer0_Init(void) //1毫秒@24.000MHz,定時器0
- {
- AUXR |= 0x80;
- TMOD &= 0xF0; //設置定時器模式
- // TL0 = 0x90; //設置定時初始值
- // TH0 = 0xE8; //設置定時初始值
-
- TL0 = 0x40; //設置定時初始值
- TH0 = 0xA2; //設置定時初始值
-
- TF0 = 0; //清除TF0標志
- TR0 = 1; //定時器0開始計時
- ET0 = 1;
- }
- void IR() //初始化
- {
- P1M0 = 0x00;
- P1M1 = 0x00;
- P3M0 = 0x00;
- P3M1 = 0x00;
- P5M0 = 0x00;
- P5M1 = 0x00;
- P_SW2 = 0x80;
- PWM1_PS = 0x05;
- //(CC1捕獲TI1上升沿,CC2捕獲TI1下降沿)
- PWMA_CCER1 = 0x00;
- PWMA_CCMR1 = 0x01; //CC1為輸入模式,且映射到TI1FP1上
- PWMA_CCMR2 = 0x02; //CC2為輸入模式,且映射到TI1FP2上
- PWMA_CCER1 = 0x11; //使能CC1/CC2上的捕獲功能
- PWMA_CCER1 |= 0x00; //設置捕獲極性為CC1的上升沿
- PWMA_CCER1 |= 0x20; //設置捕獲極性為CC2的下降沿
-
- PWMA_CR1 = 0x01;
-
- PWMA_PSCR = 0x09;
-
- PWMA_IER = 0x04; //使能CC2捕獲中斷
- PWMA_IER |= 0x02; //使能CC1捕獲中斷
- EA = 1;
- }
- void PWMA_ISR() interrupt 26 //PWM沿觸發中斷
- {
- unsigned int cnt_l;
- unsigned int cnt_h;
-
- if (PWMA_SR1 & 0x02)
- {
- PWMA_SR1 &= ~0x02;
- cnt_l = (PWMA_CCR1 - PWMA_CCR2)/24; //差值即為低電平寬度 cnt/時鐘頻率 = 脈寬(us)
- captures[num++] = cnt_l;
- }
-
-
- if (PWMA_SR1 & 0x04)
- {
- PWMA_SR1 &= ~0x04;
- cnt_h = (PWMA_CCR2 - PWMA_CCR1)/24; //差值即為高電平寬度
- captures[num++] = cnt_h;
- }
- }
- void TM0_Isr() interrupt 1 //定時器0中斷用來判斷脈沖接受是否超時,大于30ms為超時
- {
- if(P20 == 1)
- {
- val++;
- if(val > 30)
- {
- Overflow = 1;
- val = 0;
- }
- }else {val = 0;Overflow = 0;}
- }
- void UartReceiveHandler() interrupt 4 {
- if (RI) { // 接收中斷
- RI = 0; // 清除接收標志位
- ch = SBUF; // 讀取接收到的數據
- //UartSend(ch); // 原樣返回接收到的數據
- }
- }
-
- void TM3_Isr() interrupt 19 //定時器3中斷發生38K載波
- {
- P11 = !P11; //紅外1端口
- }
- //---------------------------------------------------------------------------------------------
- void main()
- {
- unsigned int i = 0,a = 0;
-
-
-
- Timer0_Init();
- Timer3_Init();
- UartInit();
- IR();
-
- UartSendString("Starting\r\n");
- lach1 = 1;
- while(1)
- {
- //lach1 = 1;
- if(Overflow == 1 && ch == 0x02)//如果超時溢出,并且接收到0x02
- {
- EraseUIntFromEEPROM(0x0400);
- EraseUIntFromEEPROM(0x0600);
- delays(5);
- EraseUIntFromEEPROM(0x0000);
- delays(5);
- for(i = 0; i <= num; i++)
- {
- SaveUIntToEEPROM(ir1+i*2, captures[i]); //寫入eeprom
- //SaveUIntToEEPROM(ir1+i*2, '3'); //寫入eeprom
- UartSendUint(captures[i]);//打印保存到數組里的數據
- captures[i] = 0;
- delays(1);
- }
- SaveUIntToEEPROM(0x0000, num); //將脈沖個數寫入eeprom
- UartSendString("End\r\n"); /*End結束*/
- UartSendUint(num);
- ir1 = 0x0400;
- ch = 0;
- num = 0;
- Overflow = 0;
- PWMA_IER = 0; //關閉PWM中斷使能
- ET0 = 0; //關閉定時器0中斷
- }else if(P20 == 0 && Overflow==0){
- PWMA_IER = 0x06; //打開PWM中斷使能
- ET0 = 1; //打開定時器0中斷
- }
-
-
- if(ch == 0x01)
- {
- two_num = ReadUIntFromEEPROM(0x0000);
- for(a = 0;a<=two_num;a++) //讀取紅外接收數組
- {
- eep_captures[a] = ReadUIntFromEEPROM(ir1+a*2);
- UartSendUint(eep_captures[a]);//打印保存到數組里的數據
- delays(1);
- }
- UartSendUint(two_num);
- ir1 = 0x0400;
- two_num = 0;
- ch = 0x00;
- }
- if(ch == 0x10)
- {
- two_num = ReadUIntFromEEPROM(0x0000);
- for(a = 0;a<=two_num;a++) //讀取紅外接收數組
- {
- eep_captures[a] = ReadUIntFromEEPROM(ir1+a*2);
- UartSendUint(eep_captures[a]);//打印保存到數組里的數據
- delays(1);
- }
- Launch_1(eep_captures,two_num);
- ch = 0;
- }
-
- }
- }
復制代碼
原理圖:無
仿真:無
程序:
8路紅外.zip
(125.01 KB, 下載次數: 64)
2023-8-9 11:21 上傳
點擊文件名下載附件
程序 下載積分: 黑幣 -5
|