0-SIM波形解码

22 篇文章 ¥99.90 ¥299.90

SIM卡发送和应答的数据格式都是有规定的,以低电平为起始,高电平结束,以EUT为基本脉宽,8bit为一字节,与串口的协议一致。

数据格式.png

先看一段有逻辑分析仪抓出来的波形,如下:
逻辑分析仪数据.png

可以观察到最小脉宽为77.54us, 所以波特率为1/77.5=12903,进行如下配置:
8Bit、2位停止位,偶校验

逻辑分析仪配置.png

SIM数据的写比较容易,按着时序走即可,如下:

void Sim_Write_Byte(uint8_t ChannelID, uint8_t senddata) 
{
    uint8_t i; 
    bool parity_bit = 0;
    
    Set_Sim_Io(ChannelID, SIM_DATA, 0);
    Delay_One_ETU();
    for(i=0; i<8; i++) 
    {
        if(1 == (senddata & 0x01))
        {
            Set_Sim_Io(ChannelID, SIM_DATA, 1);
        }
        else
        {
            Set_Sim_Io(ChannelID, SIM_DATA, 0);        
        }
        parity_bit ^= senddata & 0x01;
        senddata >>= 1;
        Delay_One_ETU();
    }
    Set_Sim_Io(ChannelID, SIM_DATA, parity_bit);
    Delay_One_ETU();
    Set_Sim_Io(ChannelID, SIM_DATA, 1);
    Delay_One_ETU();
    Delay_One_ETU();
}

对于SIM数据的解码无非就是采样解码,所以我们以低电平为起始,等到低电平就开始解码,如下:

uint8_t Sim_Read_Byte(uint8_t ChannelID, uint32_t WaitTime) 
{
    uint32_t count = 0; 
    uint8_t i = 0;
    uint8_t recvdata = 0x00;
    bool parity_bit = 0;

    while(Get_Sim_Io(ChannelID, SIM_DATA))
    {
        if(0 == Get_Sim_Io(ChannelID, SIM_DATA)) 
        {
            break;
        }
        count++;
        if(count >= WaitTime)
        {
            pSimChannelCtl->bReadTimeOut = 1;
            return YFI_FAIL; 
        }
        Delay_Us(10);
    }
    Delay_One_ETU();
    Delay_Half_ETU();  //偏移1/2,使采样位于中间
    
    for(i=0; i<8; i++) 
    {
        recvdata >>= 1;
        if(Get_Sim_Io(ChannelID, SIM_DATA))
        {
            recvdata |= 0x80;
        }
        parity_bit ^= Get_Sim_Io(ChannelID, SIM_DATA); 
        Delay_One_ETU();
    }
    
    parity_bit ^= Get_Sim_Io(ChannelID, SIM_DATA);
    Delay_One_ETU();
    if (!parity_bit)
    {
        recvdata = recvdata;
    }
    else
    {
        recvdata = '\xbb';  //parity error
    }
    
    return recvdata; 
}

经测试,由于上面的采用相当于是1bit采样一个点,就算加了Little的偏移还是会出现解码错误,需要优化增加采样点。

一个bit里面采样10个点,一个数据采样100个点。

uint8_t Sim_Read_Byte(uint8_t ChannelID, uint32_t WaitTime) 
{
    uint32_t count = 0; 
    uint8_t i = 0, first = 0;
    uint8_t lnum = 0, hnum = 0;
    uint8_t recvdata = 0x00;
    uint32_t recvpoint = 0;
    bool parity_bit = 0;

    PSIMROOTST     pSimRootSt;
    PSIMCHANNELST  pSimChannelCtl;
    
    pSimRootSt     = (PSIMROOTST)&stSimRootSt;    
    pSimChannelCtl = &pSimRootSt->stChannelSt[ChannelID];

    while(Get_Sim_Io(ChannelID, SIM_DATA))
    {
        if(0 == Get_Sim_Io(ChannelID, SIM_DATA))  //检测到低电平,即起始位,开始解码
        {
            break;
        }
        count++;
        if(count >= WaitTime)                     //未检测到低电平,到达超时时间退出
        {
            pSimChannelCtl->bReadTimeOut = 1;
            return YFI_FAIL; 
        }
        Delay_Us(10);
    }
    //32point
    for(i=0; i<32; i++) 
    {
        recvpoint >>= 1;
        if(Get_Sim_Io(ChannelID, SIM_DATA))
        {
            recvpoint |= 0x80000000;
        }
        Delay_Us(31);
    } 

    lnum = 0;
    hnum = 0;
    first = 0;
    for(i=0; i<32; i++) 
    {
        if(1 == (recvpoint & 0x00000001))
        {
            if(0 == lnum)
            {
                hnum++;
            }
            else
            {
                if(0 == first)
                {
                    first = 1;
                    lnum = lnum - 2;
                }
                if((lnum > 0)&&(lnum <= 4))
                {
                    recvdata |= 0x00;
                    recvdata >>= 1;
                }
                else if((lnum > 4)&&(lnum <= 7))
                {
                    recvdata |= 0x00;
                    recvdata >>= 2;
                }
                else if((lnum > 7)&&(lnum <= 10))
                {
                    recvdata |= 0x00;
                    recvdata >>= 3;
                }
                else if((lnum > 10)&&(lnum <= 13))
                {
                    recvdata |= 0x00;
                    recvdata >>= 4;
                }
                else if((lnum > 13)&&(lnum <= 16))
                {
                    recvdata |= 0x00;
                    recvdata >>= 5;
                }
                else if((lnum > 16)&&(lnum <= 19))
                {
                    recvdata |= 0x00;
                    recvdata >>= 6;
                }
                else if((lnum > 18)&&(lnum <= 22))
                {
                    recvdata |= 0x00;
                    recvdata >>= 7;
                }
                else if((lnum > 22)&&(lnum <= 25))
                {
                    recvdata |= 0x00;
                    recvdata >>= 8;
                }
                else if((lnum > 25)&&(lnum <= 28))
                {
                    recvdata = 0x00;
                }
                else if((lnum > 28)&&(lnum <= 31))
                {
                    recvdata = 0x00;
                }
                lnum = 0;
                hnum = 1;
            }
        }
        else
        {
            if(0 == hnum)
            {
                lnum++;
            }
            else
            {
                if((hnum > 0)&&(hnum <= 4))
                {
                    recvdata &= 0x80;
                    recvdata >>= 1;
                }
                else if((hnum > 4)&&(hnum <= 7))
                {
                    recvdata &= 0xC0;
                    recvdata >>= 2;
                }
                else if((hnum > 7)&&(hnum <= 10))
                {
                    recvdata &= 0xE0;
                    recvdata >>= 3;
                }
                else if((hnum > 10)&&(hnum <= 13))
                {
                    recvdata &= 0xF0;
                    recvdata >>= 4;
                }
                else if((hnum > 13)&&(hnum <= 16))
                {
                    recvdata &= 0xF8;
                    recvdata >>= 5;
                }
                else if((hnum > 16)&&(hnum <= 19))
                {
                    recvdata &= 0xFC;
                    recvdata >>= 6;
                }
                else if((hnum > 18)&&(hnum <= 22))
                {
                    recvdata &= 0xFE;
                    recvdata >>= 7;
                }
                else if((hnum > 22)&&(hnum <= 25))
                {
                    recvdata &= 0xFF;
                    recvdata >>= 8;
                }
                else if((hnum > 25)&&(hnum <= 28))
                {
                    recvdata = 0xFF;
                }
                else if((hnum > 28)&&(hnum <= 31))
                {
                    recvdata = 0xFF;
                }
                hnum = 0;
                lnum = 1;
            }
        }
        recvpoint >>= 1;
    }
    
    /*if (!parity_bit)
    {
        recvdata = recvdata;
    }
    else
    {
        recvdata = '\xbb';  //parity error
    }*/
    return recvdata; 
}
### RS232通信协议波形测试方法 RS232是一种常见的串行通信协议,广泛用于短距离数据传输。在实际应用中,为了确保通信的可靠性,通常需要对RS232的通信波形进行测试。以下是几种常用的波形测试方法: #### 1. 使用示波器进行波形测试 示波器是最常用的工具之一,用于观察和分析电信号的波形。通过将示波器探头连接到RS232接口的TXD(发送数据)引脚上,可以直观地看到信号的波形- **设置参数**:确保示波器的时间基准和电压范围适合所测信号。例如,对于9600波特率的RS232信号,时间基准可设为1ms/div。 - **触发设置**:使用边沿触发来稳定波形显示,选择下降沿或上升沿根据具体情况调整。 - **测量内容**:检查信号的高电平、低电平是否符合标准(+3V至+15V表示逻辑“0”,-3V至-15V表示逻辑“1”),以及位周期是否正确[^1]。 #### 2. 利用逻辑分析仪进行测试 逻辑分析仪能够同时捕捉多个数字信号,并以图形方式展示,非常适合于分析复杂的时序关系。 - **配置通道**:将逻辑分析仪的一个或多个通道连接到待测设备上的相应信号线上。 - **设定阈值**:根据RS232电平标准设定合适的电压阈值,以便准确区分高低电平。 - **捕获与解码**:启动捕获后,利用内置的UART解码功能自动解析出数据帧结构,包括起始位、数据位、校验位(如果存在)及停止位等信息[^1]。 #### 3. 软件仿真测试 除了硬件工具外,还可以采用软件模拟的方式来验证设计的功能性。 - **ModelSim/QuestaSim**:这些是流行的FPGA开发环境中集成的仿真工具,支持Verilog/VHDL语言编写测试平台(testbench)来进行功能验证。 - **Testbench编写要点**: - 定义输入激励,如生成特定模式的数据流; - 监控输出响应并记录关键节点的状态变化; - 对比预期结果与实际行为差异,定位潜在问题所在。 #### 4. 回环测试(Loopback Testing) 回环测试是一种简单有效的诊断手段,它通过让发送端直接连通接收端形成闭环,从而实现自我检测的目的。 - **物理层实施**:最直接的方法是在DB9连接器处短接第2针(RXD)与第3针(TXD),这样从计算机发出的数据就会立即被其自身接收到。 - **虚拟化方案**:某些操作系统提供了创建虚拟串口的能力,允许用户无需任何额外硬件即可执行此类测试。 ```python # 示例代码 - Python中使用pyserial库完成基本的串口通信测试 import serial def test_rs232(): # 初始化串口配置 ser = serial.Serial('COM1', baudrate=9600, timeout=1) try: # 发送测试字符串 test_string = b'Hello World\n' ser.write(test_string) # 读取返回数据 response = ser.readline() # 验证反馈是否一致 if response == test_string: print("Communication successful.") else: print(f"Expected {test_string}, but got {response}") finally: # 关闭串口 ser.close() if __name__ == '__main__': test_rs232() ``` 以上就是关于RS232通信协议波形测试的一些常见方法及其操作指南。每种方法都有其适用场景,在具体实践中可以根据实际情况灵活选用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Creator_Ly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值