单片机私有通信协议 密码锁

曾经遇到一个案子,需要用到8位单片机做密码锁,主mcu只有与8位单片机完成交互(数据密钥传输)才可以正常使用,案子虽然完成了但是至今我都没有理解到底密码是多少,写案子总结的时候完全是通过示波器抓取通信波形来表达的。

见原理图 主要有PWM两路输入,一路按键,两路通信口,一路PWM输出口。

00

至于为何要如此设计我的真的是头大,设计上有很多冗余的地方,还好我只需要完成与主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

posted @ 2021-10-26 15:51  steven_lg  阅读(205)  评论(0编辑  收藏  举报