PIC 使能485/422_Part2.2_激活485半双工

1.485底层协议辨识

PIC 使能485/422_Part2.2_激活485半双工_第1张图片

黄色是PIC发出的,打头的字符是"\r\n\r\n"。绿色的是上位机485接口设备发送字符串“App1"的波形。波特率均为115200。上位机绿色的波形自发自收没有问题。

示波器设置为下降沿触发——485平时空闲状态,线路维持高电平,一旦开始传输,先拉低,然后在传输。串口传输参数是115200,n,8,1

先看下方绿色的数字解码,我们知道他是正确的,二进制码流为:

0-1-0-0-0-0-0-1-0-1-0-0

App的 A的ASCII码为:0x41 = 01000001

绿色的编码似乎是在逆序输出,对吧?把绿色的编码继续分析,找到字符间的分割处:

0-||1-0-0-0-0-0-1-0||-1-0-|| 0-0-0-0-1-1-1-0||-1-0-|| 0-0-0-0-1-1-1-0

 注意:p(ASCII码0x70 ,01110000)连发了两次,它的波形是清晰可辨的.

所以,485的发送规则是:平时高电平,发送时,先发送0起始位一个,1停止位一个,连续发送时,以起始位0打头,紧跟字符MSB的8个bits,中间用一个停止位1和一个起始位0隔开。然后是下一个字符的数据区。下面对它做了标注:

PIC 使能485/422_Part2.2_激活485半双工_第2张图片

 按照这个规则,可以看到,PIC一侧发送时,起始位和停止位与平台一侧一致。而第2~第9Bits应该是A,看它发送了什么:这是0d,0a。

2.PIC 485半双工激活

明确这个要点:485半双工的状态切换,仅仅涉及你是不是去发起读操作这一件事。 管教定义此时完全由已经激活的eusart模块接管了。Rx的动作其实一直在进行,它在检测到口线上出现哪怕是自发自收的信号,也会不断触起中断,关键是理不理它。

TXEN、RXEN不需要切换,因为相应的两根PIN管脚始终处于工作状态。GPIO的IN|OUT状态,我们也不需要控制,仅仅在最早的时候,我们需要把相关的Tx,Rx置1,标志由eusart模块接管了这些口线,相应的模拟量标志也需要清理掉。此时口线是 digital状态。

我们当前是去TX\RX管脚读还是写由谁来控制呢?

  • 对发送而言,仅仅是对TXREG1的写入动作。上一次写入操作完毕,eusart模块会触发状态通知我们。
  • 对接收而言,仅仅是等待485 Recv Char的中断,只要它收到了数,它就会通知我们,缓冲区溢出,帧错误的处理,MCC处理的很好。

但是,我们在Tx发送完毕后,什么时候再重新打开接收中断呢?需要定时器吗?

不需要。关闭Rx的时机,最佳的位置,就是发起写操作的时候,写完,发送完毕,其实发送中断也会有报告,此时:

        PIE1bits.TX1IE = 0;
        Rs485_ToRecv();

即可,而ToRecv()以及相对称的ToTransmit()函数,只是去切换一下读中断开关:

void Rs485_ToRecv(void)
{
    PIE1bits.RC1IE = 1;
}

void Rs485_ToTransmit(void)
{
    PIE1bits.RC1IE = 0;
}

在调整参数的时候,MCC的配置会冲毁你之前对mcc自动生成的代码的修改,我这段时间添加了一个侦测函数,来检查MCC是否覆盖了我们改写的代码:

void Peripheral_Params_Check(void)
{
    if(!Rs485_IsRegisterSetOK())
    {
        PromptProgramCrash();
    }
    else
    {
        Rs485_ToRecv();
    }
}


void PromptProgramCrash(void)
{
    char dumb[11];
    if(gErrorCode == 0)    
    {
        gErrorCode=0xcccc;
    }
    xlog("\r\nsys crashed!ErrorCode=%04x", gErrorCode);
    sprintf(dumb, "C%04x", gErrorCode);
    dumb[9] = '.';
    dumb[8] = dumb[4];
    dumb[7] = '.';
    dumb[6] = dumb[3];
    dumb[5] = '.';
    dumb[4] = dumb[2];
    dumb[3] = '.';
    dumb[2] = dumb[1];
    dumb[1] = '.';
    ShowLED((const char *)(&dumb[0]));
    SetLedBlink(false);
    while(1)
    {
        Proc_DealLedRefresh();
    }
}

检查到的配置错误状态会写入调试串口,写入LED,还会让故障报警灯闪烁。为了方便故障定位,我定义了一组全局故障码。

把mcc的eusart中断打开,mcc会给你实现一个读写缓冲,并且提供了串口的打印和读取函数(通过stdio.h的那一组标准io函数)。

为了防止后续维护人员不经意间在写入操作未完成之前,发起读485操作,我额外添加了一个防护,确保写入操作完成会,读操作才会启动。

    if(!((sizeof(eusart1TxBuffer) == eusart1TxBufferRemaining) && EUSART1_is_tx_done()))
    {
        return;
    }

记得,在发送函数中关闭读中段,在发送中断处理函数中,当发现发送缓冲区,所有字符已经发送完毕,再开读中断。

特别注意:485的阻抗问题,也就是端接电阻,绕不过去,你在搭建回路时,可能需要120欧姆的端接电阻。我的同事给我提供了一个电平转换模块,绕过了阻抗匹配的问题。

交叉索引:

PIC 使能485/422_Part2.1使能485_Tx_Only_子正的博客-CSDN博客工作中需要把目前设备的单向232转为485/422模式,实现双向通讯,目前查找相关资料。突然想到一件事,我是否能让232现有的单向上发线同时连工控机的tx,rx,然后靠协议,来定时切换PIC一侧的tx rx?PIC可能不支持这个,对吧? check 一下:pinmux如果能把一个io口既可以配成rx,也可以配成tx就可以。。。我觉得这不可能,放弃。https://blog.csdn.net/twicave/article/details/130981040

你可能感兴趣的:(仪器仪表,调试,测量,嵌入式硬件,单片机,测试工具,笔记)