RS485:微控制器的传输问题

时间:2017-03-02 09:55:17

标签: microcontroller microchip mplab rs485 dspic

我遇到了与#34;传输相关的问题"从微控制器。 微控制器能够接收,但无法传输。

这是我之前提出的问题[here]

的另一个问题

以下是带微控制器的max485接口:

max485 interface with microcontroller

这是我的代码快照:

// RS485
TRISBbits.TRISB6    = INPUT_PIN;        // RX - RB6/RP38 PIN<42>
TRISBbits.TRISB7    = OUTPUT_PIN;       // TX - RB7/RP39 PIN<43>
TRISBbits.TRISB8    = OUTPUT_PIN;       // !RE/DE Control Pin RB8/RP40 PIN<44>

// RS485 Config
#define RS485_TX    PORTBbits.RB6           // RS485 Transmitter
#define RS485_RX    LATBbits.LATB7          // RS485 Reciever
#define RS485_CTRL  LATBbits.LATB8          // RS485 Control Pin

// UART ISR
void __attribute__((interrupt, no_auto_psv)) _U4RXInterrupt(void) 
{
    rs485Char = U4RXREG;
    RS485_CTRL = 1;         // Enable driver
    U4TXREG = rs485Char;
    RS485_CTRL = 0;         // disable driver RE/DO
}  

void InitRs485(void){
        // configure U1MODE
    U4MODEbits.UARTEN = 0;      // Bit15 TX, RX DISABLED, ENABLE at end of func

    U4MODEbits.URXINV = 1;      // 1:URXINV Idle state is '0' ; 0=UxRX Idle state is '1';
    U4MODEbits.ABAUD = 0;       // Bit5 No Auto baud (would require sending '55')
    U4MODEbits.BRGH  = 0;       // Bit3 16 clocks per bit period
    U4MODEbits.PDSEL = 0;       // 0 : 8 bit,no parity; 1 : 8 bit,even parity; 2 : 8 bit,odd parity; 3 : 9 bit,no Parity
    U4MODEbits.STSEL = 1;       // 1 : 2 Stop bits; 0 : 1 Stop bits 
    U4MODEbits.LPBACK = 0;      // Lookback disable
    U4STAbits.URXISEL = 0;      // Interrupt flag bit is set when a character is received

    // Load a value into Baud Rate Generator.
    U4BRG = BRGVAL_RS485;             // 60Mhz osc, 9600 Baud

    // Load all values in for U1STA SFR
    U4STAbits.UTXISEL1 = 0;     // Bit15 Int when Char is transferred (1/2 config!)
    U4STAbits.UTXISEL0 = 0;     // Bit13 Other half of Bit15
    U4STAbits.UTXINV = 1;       // 1:UxTX Idle state is '0' ; 0=UxTX Idle state is '1';

    U4STAbits.UTXBRK = 0;       // Bit11 Disabled
    U4STAbits.UTXEN = 0;        // Bit10 TX pins controlled by peripheral
    U4STAbits.URXISEL = 0;      // Bits6,7 Int. on character received
    IPC22bits.U4RXIP = 7;
    IPC22bits.U4TXIP = 7;

    IFS5bits.U4TXIF = 0;        // Clear the Transmit Interrupt Flag
    IEC5bits.U4TXIE = 0;        // Enable Transmit Interrupts
    IFS5bits.U4RXIF = 0;        // Clear the Receive Interrupt Flag
    IEC5bits.U4RXIE = 0;        // Enable Receive Interrupts

    RPOR2bits.RP39R = 0x1D;     // dsPic33EP512GM604 => RP39 as U4TX PIN<43>
    _U4RXR = 38;                // dsPic33EP512GM604 => RP38 as U4RX PIN<42>

    U4MODEbits.UARTEN = 1;      // And turn the peripheral on
    U4STAbits.UTXEN = 1;

    // Hardware control bits
    IEC5bits.U4RXIE = 1;
    IFS5bits.U4RXIF = 0;
    RS485_CTRL = 0;             // disable driver; Receive Enable
}

在上面的代码中,我有一个UART接收中断例程。

每当收到任何字符时,UART ISR会收到它,但无法传回任何内容。

在我的ISR中,我试图收回收到的角色。

此问题可能与max485控制引脚(!RE / DE)有关,在我的代码中称为 RS485_CTRL

所以,我试图纠正这个问题如下:

  1. 如果ISR写为

    rs485Char = U4RXREG;
    RS485_CTRL = 1;         // Enable driver
    U4TXREG = rs485Char;
    

    然后微控制器发送2Bytes,第一个是收到的字符,第二个字节是假字节,即 0x00 。之后ISR没有收到任何字符。

  2. 如果ISR写成:

    rs485Char = U4RXREG;
    RS485_CTRL = 0;         // Disable driver
    U4TXREG = rs485Char;
    RS485_CTRL = 1;         // Enable driver
    
  3. 传送收到的第一个字符。但是在ISR进入无限循环后即可。收到一个NULL字符并发送一个NULL字符。

    根据RS485实施规则,

    1. RS485_CTRL(!RE / DE)应为0才能接收数据

    2. RS485_CTRL(!RE / DE)应为1以传输数据。

    3. 我的微控制器充当SLAVE,因此默认情况下我将其保持在聆听模式。但是当收到数据时,我无法传输。

      请帮我弄清楚我的错误???

      根据@linuxfan的建议,正确的ISR应如下所示:

      // UART ISR
      void __attribute__((interrupt, no_auto_psv)) _U4RXInterrupt(void) 
      {
          rs485Char = U4RXREG;
          RS485_CTRL = 1;         // Enable driver
          U4TXREG = rs485Char;
          while(!U4STAbits.TRMT); // wait until character is transffered successfully
          RS485_CTRL = 0;         // disable driver RE/DO
      } 
      

      现在我的代码正常运行。

1 个答案:

答案 0 :(得分:1)

LTE-485(RS-485线路驱动器)具有&#34;驱动器使能引脚&#34;必须断言以便传输。您必须在开始发送字符之前断言它,并且必须在最后一个字节完成传输后取消断言(您为了能够接收数据而取消断言,或者让其他设备来开公共汽车。如果你不想接收,而你没有任何其他设备愿意传输,你可以保持它的断言。

在您的代码中有:

  

RS485_CTRL = 1; //启用驱动程序
  U4TXREG = rs485Char;

启用RS485_CTRL = 1的驱动程序,然后加载UART移位寄存器,但也许你不会等待所有数据移出的时间。

为了等待数据移出,您可以加载一个定时器,该定时器将在固定时间后触发:一个字符(可能是10位)以您编程的波特率移出的时间。每次发送字符时,启动此计时器。当计时器到期时,禁用OE(输出驱动程序启用)。

另一种方法是等待你刚发出的角色的接收。你加载发送寄存器;当所有位都移出时,您将收到字符(RS-485是总线)。那时,您可以根据需要禁用发射器。当然,如果您想要背靠背传输字符流,这不是很好。此外,在您的硬件设置中,您无法执行此操作,因为您禁用了接收器(接收器启用和驱动程序启用一起短路)。

但你可以做我认为最好的事情。发送char时,启用接口OE的驱动程序;然后使用UART的TX中断发送下一个字符(如果有的话),或者如果没有其他字符要发送则取消断言驱动程序。注意使用正确的发送中断:某些UART(我不知道你正在使用的那个)有缓冲 - 你需要在数据移出时发出的中断,而不是那个它说&#34;你可以加载更多数据&#34;。

注意:您正在使用DB9连接器,使用引脚2和3,并将它们标记为TX和RX。那么,RS-485中有无TX和RX线:两根线分别命名为A和B,两者都带有相同的平衡信号。如果悬空,这些导线用于接收数据,如果由LTC-485驱动器驱动,则使用相同的导线传输数据。你可以很好地启用发送驱动程序并保持&#34; listen&#34;在电线上。您将收到刚发送的信息(这也可以诊断电线短路或驱动器烧断)。您可以选择使用常用于RS-232的连接器,也可以选择使用与RS-232相同的引脚2和3,但RS-485绝对不能与RS-232同化。