-
EV1527無線通信
先說一下這個通信協議的數據格式,這個圖片是我在手冊里截的。
- 大家按照單片機類型計算周期,我的是STM32f103vb (4CLK大致等於350um)
- 發送時按照 先發同步碼后發DATA 的順序 邏輯1或者邏輯0按照以上高低電平延時時間長度發送
-
無線通信發送模式
- 發送很簡單,按照數據格式發就行,就是在處理數據上有所變化。無論想發什么數據,16進制10進制最后都要轉化成2進制,01發送,從低位向高位發送。
- 初始化函數在發送模式里。
/* @Description 輸出高低電平按EV1527協議 @mode 邏輯0或1 */ void S433_SendBit(u8 mode){ if(mode==1) { PEout(9)=1; SysTick_Delay_Us(350*3); PEout(9)=0; SysTick_Delay_Us(350); }else if(mode==0) { PEout(9)=1; SysTick_Delay_Us(350); PEout(9)=0; SysTick_Delay_Us(350*3); }else{ debug_led(1, LED_TOGGLE); } } /* @Description 同步脈沖(或叫引導) */ //同步脈沖 4:124 void Sync_Pulse(){ PEout(9)=1; SysTick_Delay_Us(350); PEout(9)=0; SysTick_Delay_Us(350*31); } /* @Description 發送碼函數調用 @num 24位二進制的 10進制數 */ //對發送過來的10進制數進行處理 , 根據需求可以更改 void S433_Send(u32 num){ u8 i; u32 result=24,temp; temp = num; Sync_Pulse(); while(result){ i = temp%2; //對十進制數取余 結果等於最低位二進制數 S433_SendBit(i); temp = temp/2;//除二取整 result--; } }
-
無線通信接收模式
接收要比發送復雜得多,思路就是
通過觸發外部中斷處理函數,來檢測數據,每觸發一次上升或下降沿,記一下時間,根據時間長度來判段雜波,同步波還是數據波,接收關鍵在於判斷。
下面一段是一些值的初始化,和IO引腳的初始化
static volatile unsigned long long rx433_previous_time = 0;//上一次進入中斷時間 static volatile unsigned char Sync_Pulse_begin =0;//檢測同步脈沖完整性 1是同步脈沖 static volatile unsigned char rx433_begin= 0;//同步脈沖開啟標志1開啟 0沒開 static volatile unsigned short interval_previous_time=0;//上一個間隔時間 //////////// static volatile u8 Rx433Cnt=0; static volatile u8 Rx433bit[30]={0}; static volatile u8 rxbit=0; static volatile u8 firstbit=0; static volatile u32 Rx433[64]={0}; /////////// //對管腳初始化 參考普通IO管腳用通信 void S433_SR_Init(){ GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); //使能GPIOE時鍾 //E9使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_ResetBits(GPIOE, GPIO_Pin_9);// 引腳拉低 //接收 E7 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //輸入為低 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource7); EXTI_InitStructure.EXTI_Line=EXTI_Line7; EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd=ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; NVIC_InitStructure.NVIC_IRQChannelSubPriority=2; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStructure); }
是否是同步波判斷,以及檢測發送完成度
/* @Description 判斷是否是同步脈沖 @pre 之前時間段數 @now 現在時間段數 @return rebit開啟同步 success同步成功 synerror 不是同步脈沖 */ u8 Sync_PulseRx(u8 pre,u8 now){ if(!PEin(7)){//每次下降沿開始測 Sync_Pulse_begin=1;//開始檢測同步脈沖 }else if(Sync_Pulse_begin==1&&(pre==1)&&(now==31)){//滿足條件則判斷出時間脈沖 Sync_Pulse_begin=0;//同步成功將同步碼關掉 rx433_begin=1;//正式開始傳輸數據 rxbit=0;//將數據位數清零 firstbit=1;//置一等待下個跳變正式開始 return success; }else{ Sync_Pulse_begin=0;//不是脈沖置0 return synerror; } return rxbit; } /* @Description 判斷邏輯0和1 @pre 之前時間段數 @now 現在時間段數 @return rxerror 接收超位 */ u8 RX433_Bit(u8 pre,u8 now){ if(firstbit==1){ firstbit=0;//此步驟防止引導完成后直接進入此函數 }else if(rx433_begin==1&&PEin(7)){//上升沿檢測 if(rxbit>24){//能加到24 說明一幀數據獲取到了 rxbit=0;//歸零 rx433_begin=0;//歸零 及下一組做准備 } if(now==3&&pre==1){//邏輯0 Rx433bit[rxbit]=0; rxbit++; }else if(now==1&&pre==3){//邏輯1 Rx433bit[rxbit]=1; rxbit++; }else{ //跑飛 rx433_begin=0; rxbit=0; return rxerror; } return rxbit-1; } return 0; }
外部中斷處理函數,常常被觸發,因為接收各種雜波,但進入不了關鍵的處理函數。
//先判斷同步脈沖 //如果是同步脈沖,begin開啟判斷數據接收並判斷情況情況 //如果數據接收位超過預期24位,數據位數接收超量(狀態) //如果從一半開始接收,無視這一段,從下一段開始 void EXTI9_5_IRQHandler(void){ if(EXTI_GetITStatus(EXTI_Line7)!=RESET) { unsigned char skip_index = 0;//這次幾個數據位 unsigned char skip_pervious_index=0;//之前幾個數據位 unsigned long long now_time=sys_micros();//此刻時間 unsigned short interval_time = now_time - rx433_previous_time;//計算一個電平狀態持續的時長 rx433_previous_time = now_time;//為下次計算時長做准備 skip_index = (interval_time/349);//得出某個電平持續時長的倍數 計算出幾段高或低電平 skip_pervious_index=(interval_previous_time/349);//同上 不過是前一次的 Sync_PulseRx(skip_pervious_index,skip_index);//同步脈沖 RX433_Bit(skip_pervious_index,skip_index);//數據位 if(interval_time<45000){ interval_previous_time = interval_time; }else{ interval_previous_time = 0; } EXTI_ClearITPendingBit(EXTI_Line7);//清除中斷掛起標志位 } }