1. 程式人生 > 其它 >微控制器私有通訊協議 密碼鎖

微控制器私有通訊協議 密碼鎖

曾經遇到一個案子,需要用到8位微控制器做密碼鎖,主mcu只有與8位微控制器完成互動(資料金鑰傳輸)才可以正常使用,案子雖然完成了但是至今我都沒有理解到底密碼是多少,寫案子總結的時候完全是通過示波器抓取通訊波形來表達的。

見原理圖 主要有PWM兩路輸入,一路按鍵,兩路通訊口,一路PWM輸出口。

至於為何要如此設計我的真的是頭大,設計上有很多冗餘的地方,還好我只需要完成與主mcu的互動就算完成了。

這個案子最麻煩的是通訊資料沒有說明,此時我也表示無奈,還好我有邏輯分析儀,只能通過模擬器模擬出下位機的應答波形,一步一步的給整個互動解碼,然後把波形記錄下來一個個的分析,總算是有所收穫。

/* =========================================================================
 * Project:       GPIO_Setting
 * File:          main.c
 * Description:   Set GPIO of PORTB
 *                  1. PORTB I/O state
 *                      - PB4 set input mode and enable pull-high resistor
 *                      - PB2 set output mode 
 *                      - PB1 set input mode and enable pull-low resistor
 *                      - PB0 set open-drain output mode                               
 *                                                          
 * Author:        JasonLee
 * Version:       V1.1                              
 * Date:          2018/09/07
 =========================================================================
*/ #include <ny8.h> #include "ny8_constant.h" #include <stdint.h> #define UPDATE_REG(x) __asm__("MOVR _" #x ",F") typedef union flg { uint8_t ff; struct { uint8_t flg0:1; // PWM輸出控制 uint8_t flg1:1; // syatem初始化完成 uint8_t flg2:1; // bus接收/傳送狀態 uint8_t flg3:1
; // bus讀取資料鎖定標誌 uint8_t flg4:1; // uint8_t flg5:1; // 按鍵延時鎖定 uint8_t flg6:1; // 按鍵標誌有效 uint8_t flg7:1; // }; }flg; volatile flg sysflg; volatile uint8_t timclk; //volatile uint8_t secclk; volatile uint8_t comclk; //volatile uint8_t pwmclk; uint8_t delayms;
//uint8_t delays; uint8_t delayclk; uint8_t revcount; //統計接收資料位 uint8_t counthi; //統計高電平連續的時間 uint8_t busdata1; //匯流排資料1 uint8_t busdata2; //匯流排資料2 uint8_t recvdata; //資料接收 //uint8_t countpwm; const uint8_t recinst1[2] = { 0x84,0x03 }; //10bit const uint8_t swinst1[2] = { 0x80,0x00 }; //10bit const uint8_t traninst7[2] = { 0x24,0x00}; const uint8_t traninst1[2] = { 0x84,0x00 }; //43bit const uint8_t traninst2[2] = { 0x24,0x00 }; //43bit const uint8_t traninst3[2] = { 0x48,0x00 }; //43bit const uint8_t traninst4[2] = { 0x50,0x00 }; //43bit const uint8_t traninst5[2] = { 0x8a,0x00 }; //43bit const uint8_t traninst6[2] = { 0x20,0x01 }; //43bit void isr_hw(void) __interrupt(0) { if(INTFbits.T0IF) { TMR0 = 56; // 32000/25/128/10 timclk++; INTFbits.T0IF = 0; } if(INTFbits.T1IF) { comclk++; if(sysflg.flg2 == 0) //bus狀態模式,主程式控制 { if(PORTBbits.PB0) { //高電平超過2ms把資料清零 //高電平時讀取一次資料,併發生移位 counthi++; if(counthi > 4) //判定為超時 { revcount = 0; recvdata = 0; } if(!sysflg.flg3) //鎖定標誌,低電平釋放 { sysflg.flg3 = 1; revcount++; recvdata <<= 1; //左移移位 recvdata = recvdata + (uint8_t)(PORTBbits.PB1); if(revcount == 8) { busdata1 = recvdata; } else if(revcount == 11) { revcount = 0; busdata2 = (recvdata >>1) & 0x03; //沒幀資料的結尾都會在clk低的時候拉高data,在將clk拉,需要取出掉最後一個數據位 if((busdata1 == recinst1[0] )&&(busdata2 == recinst1[1])) { //sysflg.flg4 = 1; //接收完成,接收完成清零 sysflg.flg2 = 1; } } } } else { //接收鎖定標誌釋放 counthi = 0; sysflg.flg3 = 0; } } INTFbits.T1IF = 0; } if(INTFbits.PBIF) { if(sysflg.flg0) { PORTBbits.PB3 = !(PORTBbits.PB5); } INTFbits.PBIF = 0; } } void transbus(void) { for(revcount = 0;revcount<8;revcount++) { PORTBbits.PB0 = 0; if(busdata1 & 0x01) { PORTBbits.PB1 = 1; } else { PORTBbits.PB1 = 0; } busdata1 >>= 1; delayclk = comclk + 4; TMR1 = 125; while(delayclk != comclk); //延時1ms PORTBbits.PB0 = 1; delayclk = comclk + 4; TMR1 = 125; while(delayclk != comclk); //延時2ms } } void transdata(uint8_t i) { for(revcount = 0;revcount<i;revcount++) { while(PORTBbits.PB0); if(busdata1 & 0x01) { PORTBbits.PB1 = 1; } else { PORTBbits.PB1 = 0; } busdata1 >>= 1; while(!(PORTBbits.PB0)); } } void main(void) { sysflg.flg2 = 0; //匯流排為接收狀態 DISI(); //;Initial GPIO BPHCON = (unsigned char)(~(C_PB2_PHB | C_PB0_PHB | C_PB1_PHB)); // Enable PB4 Pull-High Resistor,others disable IOSTB = C_PB0_Input | C_PB1_Input | C_PB2_Input | C_PB5_Input | C_PB4_Input; // Set PB4 & PB1 to input mode,others set to output mode PORTBbits.PB3 = 0; // PB2 & PB0 output high //Initial tim0 定時器中斷為 32768/200/82 = 2 //系統延時,pwm輸出 T0MD = C_PS0_WDT | C_TMR0_LowClk | C_TMR0_Clk; //分頻器給WDT,使用指令時鐘,i_lrc/ps0 = 4M, TMR0 = 56; //32000/500/53 PCON1 = C_TMR0_En; //開啟定時器中斷inttim1 INTE = C_INT_TMR0; //Initial tim1 //通訊時序 0.5ms TMR1 = 125; //到0下溢位中斷 //4M/32/125 = 1000 T1CR1 = C_TMR1_Reload | C_TMR1_En; //自動過載 T1CR2 = C_TMR1_ClkSrc_Inst | C_PS1_EN | C_PS1_Div16; //指令時鐘 //開啟定時器中斷inttim1 INTE = INTE | C_INT_TMR1; //PB5口電平變化中斷 BWUCONbits.WUPB5 = 1; INTEbits.PBIE = 1; ENI(); while(1) { CLRWDT(); if(sysflg.flg1 == 0) //sysem初始化 { if(sysflg.flg2) //匯流排為傳送狀態 { //sysflg.flg4 = 0; { delayclk = comclk + 5; TMR1 = 125; while(delayclk != comclk); //延時2.5ms delayclk = comclk + 5; TMR1 = 125; while(delayclk != comclk); //延時2.5ms PORTBbits.PB1 = 0; IOSTB = IOSTB & (uint8_t) (~ C_PB1_Input); //切換為輸出模式 busdata1 = traninst1[0]; transdata(8); busdata1 = traninst1[1]; transdata(2); while(PORTBbits.PB0); //停止位 PORTBbits.PB1 = 1; delayclk = comclk + 8; TMR1 = 125; while(delayclk != comclk); //延時4ms PORTBbits.PB1 = 0; busdata1 = traninst2[0]; transdata(8); busdata1 = traninst2[1]; transdata(2); while(PORTBbits.PB0); //停止位 PORTBbits.PB1 = 1; delayclk = comclk + 8; TMR1 = 125; while(delayclk != comclk); //延時4ms PORTBbits.PB1 = 0; busdata1 = traninst3[0]; transdata(8); busdata1 = traninst3[1]; transdata(2); while(PORTBbits.PB0); //停止位 PORTBbits.PB1 = 1; IOSTB = IOSTB | C_PB1_Input; delayclk = comclk + 126; TMR1 = 125; while(delayclk != comclk); //延時63ms PORTBbits.PB1 = 0; IOSTB = IOSTB & (uint8_t) (~ C_PB1_Input); //切換為輸出模式 busdata1 = traninst4[0]; transdata(8); busdata1 = traninst4[1]; transdata(2); while(PORTBbits.PB0); //停止位 PORTBbits.PB1 = 1; delayclk = comclk + 8; TMR1 = 125; while(delayclk != comclk); //延時2ms PORTBbits.PB1 = 0; busdata1 = traninst5[0]; transdata(8); busdata1 = traninst5[1]; transdata(2); while(PORTBbits.PB0); //停止位 PORTBbits.PB1 = 1; delayclk = comclk + 8; TMR1 = 125; while(delayclk != comclk); //延時4ms PORTBbits.PB1 = 0; busdata1 = traninst6[0]; transdata(8); busdata1 = traninst6[1]; transdata(2); while(PORTBbits.PB0); //停止位 PORTBbits.PB1 = 1; IOSTB = IOSTB | C_PB1_Input; delayclk = comclk + 8; TMR1 = 125; while(delayclk != comclk); //延時4ms PORTBbits.PB1 = 1; PORTBbits.PB0 = 1; IOSTB = IOSTB = IOSTB & (uint8_t) (~ (C_PB1_Input | C_PB0_Input)); //切換為輸出模式 PORTBbits.PB1 = 0; delayclk = comclk + 1; TMR1 = 125; while(delayclk != comclk); //延時0.5ms busdata1 = traninst7[0]; transbus(); revcount = 0; while(revcount < 2) { PORTBbits.PB0 = 0; PORTBbits.PB1 = 0; delayclk = comclk + 4; TMR1 = 125; while(delayclk != comclk); //延時2ms PORTBbits.PB0 = 1; delayclk = comclk + 4; TMR1 = 125; while(delayclk != comclk); //延時2ms revcount ++; } PORTBbits.PB0 = 0; PORTBbits.PB1 = 1; delayclk = comclk + 4; TMR1 = 125; while(delayclk != comclk); //延時2ms PORTBbits.PB0 = 1; delayclk = comclk + 4; TMR1 = 125; while(delayclk != comclk); //延時2ms sysflg.flg1 = 1; //切換匯流排輸出狀態 } } } else //初始化完成 { if(PORTBbits.PB2 == 0) //檢測按鍵 { if(sysflg.flg5 == 0) { sysflg.flg5 = 1; delayclk = comclk + 30; TMR1 = 125; //32000/500/53 } if(delayclk == comclk); //延時32ms { //按鍵標誌有效 sysflg.flg6 = 1; } } else { sysflg.flg5 = 0; if(sysflg.flg6) { sysflg.flg6 = 0; //向主mcu發資料 PORTBbits.PB1 = 0; delayclk = comclk + 1; TMR1 = 125; while(delayclk != comclk); //延時0.5ms busdata1 = swinst1[0]; transbus(); revcount = 0; while(revcount < 2) { PORTBbits.PB0 = 0; PORTBbits.PB1 = 0; delayclk = comclk + 4; TMR1 = 125; while(delayclk != comclk); //延時2ms PORTBbits.PB0 = 1; delayclk = comclk + 4; TMR1 = 125; while(delayclk != comclk); //延時2ms revcount ++; } PORTBbits.PB0 = 0; PORTBbits.PB1 = 1; delayclk = comclk + 4; TMR1 = 125; while(delayclk != comclk); //延時2ms PORTBbits.PB0 = 1; delayclk = comclk + 4; TMR1 = 125; while(delayclk != comclk); //延時2ms sysflg.flg0 ^= 1; //countpwm = 0; //PORTBbits.PB4 = 0; PORTBbits.PB3 = 0; //PORTBbits.PB5 = 0; } if((sysflg.flg0 == 1)&&(PORTBbits.PB5 == 0)&&(sysflg.flg6 == 0)) { if(sysflg.flg7 == 0) { sysflg.flg7 = 1; delayms = timclk + 82; TMR0 = 56; } if(delayms == timclk) { sysflg.flg0 = 0; PORTBbits.PB3 = 0; } } else { sysflg.flg7 = 0; } } } } }

8位微控制器專案可以找我:18665321219