基于STM32和hs1527、ev1527、rt1527、fp1527的无线接收解码程序
1527的數據幀結構
無線遙控的編碼,從編碼類型上來說,分為2類,一類是固定碼,也就是編碼芯片的地址是不變的,芯片型號以 hs1527、ev1527、rt1527、fp1527、PT2262 為代表。另一種是滾動碼,芯片的地址碼是變化的,芯片以HS300、HS301為代表。
1 1527 數據幀結構
1527 是一片由 CMOS 設計制造的可預燒內碼的學習碼編碼IC ,由軟件解碼;內碼共有 20 個位元可預燒 1048576 組內碼組合,降低使用上編碼重復的機率。
1527 每幀數據由 24 個數據位組成,前 20 位為地址碼,對于一個芯片來說,地址位的內容是固定的,是出廠前就預制好的,并且理論上每個芯片的地址碼是唯一的。后面 4 位為按鍵碼,對應芯片上的K0-K3 4 根數據線,數據線的狀態不同,按鍵碼就不同。
在數據位之前,還有一個同步脈沖,也就是每幀數據都是從同步
脈沖開始的。數據位的“1”和“0”是由高低電平寬度(脈沖寬度)的比例決定的。如果高電平寬度為低電平寬度的 3 倍,就表示邏輯“1”,反過來如果低電平為高電平寬度的 3 倍,就表示邏輯“0”。同步脈沖高電平和低電平的比例固定為 4:124.
二、中斷方式的解碼
把串行輸入的編碼數據幀,還原成編碼之前的狀態,讀取其中
的地址碼和按鍵碼,稱之為解碼。
數據幀都是由同步頭開始,然后是 24位的數據碼,并且此數據幀在遙控器按鍵的過程中是重復出現的,我們首先要判斷同步碼,判斷出了同步碼,就知道數據碼是從那一位開始了。對于一款量產的無線遙控器來說,他的編碼芯片匹配的電阻是一個固定值,也就是說它發射的數據幀的脈沖寬度是不變的,所以我們可以通過測量高低脈沖寬度的方式來分辨同步碼、邏輯“1”、邏輯“0”。
具體的方法是這樣的,首先啟用定時器,裝入一個初值,打開
定時器中斷,讓其以固定的間隔進入中斷程序。在中斷程序中,我們查詢數據輸入管腳的狀態,如果為高電平,就在高電平狀態累加計數,反之就在低電平狀態計數,當電平發生上升沿變化的時候,判斷接收到的高低電平寬度的值是否符合同步信號的要求,如果符合就進入數據位的接收,以同樣的方式判斷邏輯“1”或邏輯“0”。如果接受過程中出現不符合要求的電平狀態,就退出接收,為了增加可靠性,我們一般要求規定時間內,成功接收到完全相同的 2 幀數據才算有效。
接收完成后,24 個數據位被放入 3 個字節中。下一步我們要對接收到的數據進行處理,判斷編碼的類型,分離地址碼和按鍵碼。
代碼如下
#include "1527.h" /*** @brief 初始化控制LED的IO* @param 無* @retval 無*/ uint8_t RF; uint8_t decode_ok; //解碼成功 uint8_t hh_w,ll_w; //高,低電平寬度 uint8_t ma_x; //接收到第幾位編碼了 uint8_t bma1,bma2,bma3,bma4; //用于接收過程存放遙控編碼,編碼比較兩次,這是第一次 uint8_t mma1,mma2,mma3,mma4; uint8_t mmb1,mmb2,mmb3,mmb4; // 用于接收過程存放遙控編碼,第二次 //extern uint8_t mmb1,mmb2,mmb3,mmb4;uint8_t rf_ok1,rf_ok2,rf_ok; //解碼過程中的臨時接收成功標志,接收到一個完整的遙控命令后置1,通知解碼程序可以解碼了 uint8_t old_rc5; //保存上一次查詢到的電平狀態 uint8_t tb_ok; //接收到同步的馬時置1 uint8_t D0,D1,D2,D3 ; uint16_t s ,s1; uint8_t bt_auto; //自動設置遙控接收波特率標志 extern uint8_t rf_data[4];void 1527_Init() //1527 IO口初始化 {GPIO_InitTypeDef GPIO_InitStruct;NVIC_InitTypeDef NVIC_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // PB9 輸入端GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStruct);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_TimeBaseStructure.TIM_Period = 100; TIM_TimeBaseStructure.TIM_Prescaler =7; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);TIM_ClearFlag(TIM4,TIM_FLAG_Update);TIM_Cmd(TIM4,ENABLE ); } void TIM4_IRQHandler() {if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET){TIM_ClearITPendingBit(TIM4, TIM_IT_Update); //接收數據的電平 PB9RF = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9); if (!RF) { ll_w++; // 檢測到低電平 低電平時間加1,記錄本次電平狀態old_rc5old_rc5=0; } else // 檢測到高電平{ hh_w++;if (!old_rc5) // 檢測到從低到高的跳變,已檢測到一個完整(高-低)電平周期 判同步碼 2/5 100/130{ if (((hh_w>=2)&&(hh_w<=5))&&((ll_w>=100)&&(ll_w<=130))) { tb_ok = 1 ;ma_x = 0;bma1=0; bma2=0; bma3=0; bma4=0; }else if ((tb_ok)&&((ll_w>=8)&&(ll_w<=13))) //8/13{ ma_x++; //已經接收到同步碼,判0if(ma_x>23){if(!rf_ok1) //rf_ok1臨時接收成功{ //將接收到的編碼復制到解碼寄存器中 mma1=bma1;mma2=bma2;mma3=bma3;mma4=bma4; // 通知解碼子程序可以解碼了 rf_ok1=1; tb_ok=0;s=1000; }else{//將接收到的編碼復制到解碼寄存器中 mmb1=bma1;mmb2=bma2;mmb3=bma3;mmb4=bma4; // 通知解碼子程序可以解碼了 rf_ok2=1; tb_ok=0; }}} else if ((tb_ok)&&((ll_w>=2)&&(ll_w<=7))) // 2/7{ switch (ma_x){ case 0 : { bma1=bma1 | 0x80; break; } //遙控編碼第1位case 1 : { bma1=bma1 | 0x40; break; }case 2 : { bma1=bma1 | 0x20; break; }case 3 : { bma1=bma1 | 0x10; break; }case 4 : { bma1=bma1 | 0x08; break; }case 5 : { bma1=bma1 | 0x04; break; }case 6 : { bma1=bma1 | 0x02; break; }case 7 : { bma1=bma1 | 0x01; break; }case 8 : { bma2=bma2 | 0x80; break; }case 9 : { bma2=bma2 | 0x40; break; }case 10: { bma2=bma2 | 0x20; break; }case 11: { bma2=bma2 | 0x10; break; }case 12: { bma2=bma2 | 0x08; break; }case 13: { bma2=bma2 | 0x04; break; }case 14: { bma2=bma2 | 0x02; break; }case 15: { bma2=bma2 | 0x01; break; }case 16: { bma3=bma3 | 0x80; break; }case 17: { bma3=bma3 | 0x40; break; }case 18: { bma3=bma3 | 0x20; break; }case 19: { bma3=bma3 | 0x10; break; }case 20: { bma3=bma3 | 0x08; break; }// 按鍵狀態第1位case 21: { bma3=bma3 | 0x04; break; }case 22: { bma3=bma3 | 0x02; break; }case 23: { bma3=bma3 | 0x01; if(!rf_ok1){mma1=bma1;mma2=bma2;mma3=bma3;// mma4=bma4; // 將接收到的編碼復制到解碼寄存器中 rf_ok1=1; // 通知解碼子程序可以解碼了tb_ok=0; // bt_auto=0;s=1000;break; }else{mmb1=bma1;mmb2=bma2;mmb3=bma3;//mmb4=bma4; // 將再次接收到的編碼復制到解碼寄存器中, rf_ok2=1; // 通知解碼子程序可以解碼了tb_ok=0;break; } }} ma_x++; }else{ma_x=0; tb_ok=0;bt_auto=0;bma1=0;bma2=0; bma3=0; hh_w=1;ll_w=0;} //接收到不符合的高-低電平序列ll_w=0;hh_w=1; } old_rc5=1; // 記錄本次電平狀態}if(rf_ok1) //規定時間內接受到2幀相同的編碼數據才有效{s--;if(!s) rf_ok1=0;if(rf_ok2) {if((mma1==mmb1)&&(mma2==mmb2)&&(mma3==mmb3)){rf_ok=1;rf_ok1=0;rf_ok2=0; }else{rf_ok=0;rf_ok1=0;rf_ok2=0;} } }if((rf_ok)) //判斷是否接收成功{ //TIM_ITConfig(TIM4, TIM_IT_Update, DISABLE);rf_ok=0; rf_data[0]=mma1;rf_data[1]=mma2;rf_data[2]=mma3;decode_ok=1;//TIM_ITConfig(TIM4 , TIM_IT_Update, ENABLE);}}}?
總結
以上是生活随笔為你收集整理的基于STM32和hs1527、ev1527、rt1527、fp1527的无线接收解码程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CatBoost参数解释
- 下一篇: 清明节。。。路人断魂。。。