This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C123和 RS485

Guru**** 2078700 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/800573/tm4c123-and-rs485

主题中讨论的其他器件:TM4C123
我正在将标准 UART 接口转换为 RS485。  

下面的流程图中介绍了该计划的流程。 传感器正在等待命令、接收到命令后、传感器会连续发送数据、直至发出停止命令

在传感器和 RS485至 USB 接口中、DE 引脚都连接到收发器的 RE 引脚。 在传感器中、两个引脚连接到芯片 FT232RL 的 CBUS2引脚(该引脚配置为 RXLED)。 在传感器中、两个引脚连接到 TM4C123微控制器的 PORTF.3。

测试中使用的 RS485链路长度为几厘米、传感器和接口都具有120欧姆的端接电阻器。 ISL83485用作收发器。 仅在接口中、A 引脚与560 Ω 上拉 电阻器连接、B 引脚与560 Ω 下拉电阻器连接。

波特率为230400、但在最终配置中将提升至500k 波特

关于固件方面、我进行了两项测试

1) 1)当程序启动时、DE 和 RE*为低电平。 发出命令后,DE 和 RE*在例程 UARTSEND()的开头被驱动为高电平,在该例程的末尾被驱动为低电平。 在该配置中、正确发出 START 命令、但 在传感器传输时接收到垃圾数据。 另一种意外行为是传感器无法正确接收 STOP 命令

2) 2) DE 和 RE*在程序启动时处于低电平。 发出命令后,DE 和 RE*在例程 UARTSEND()的开头被驱动为高电平,然后在例程的末尾不被驱动为低电平。 在该配置中、数据被正确接收

从通信的角度而言、我附加了代码中最相关的部分?

我缺少什么? 从固件的角度来看、驱动 RS485方向控制信号的合适方法是什么?

提前感谢

空
UART1 IntHandler (空)
{
uint32_t ui32StatusRX;

RingBufFlush (&rxRingBuf);
//
//获取中断状态。
//
ui32StatusRX = ROM_UARTIntStatus (UART1_BASE、TRUE);

//
//清除已发出的中断。
//
ROM_UARTIntClear (UART1_BASE、ui32StatusRX);
//接收超时中断在 FIFO 中接收到字节但尚未接收到字节时触发
//已足够触发您的 Rx 中断。 这是因为 FIFO 级别选择决定了何时进行
// T_RT)
{
// FIFO 中有要读取的字节和空间。
while (UARTCharsAvail (UART1_base)&& RingBufFull (&rxRingBuf)== false)
{
uint32_t ch =(uint8_t) ROM_UARTCharGet (UART1_base);
//将一个字节从硬件 FIFO 直接写入到我们的 Rx FIFO 中以供以后处理。
RingBufWriteOne (&rxRingBuf、ch);
}
}
if (((ui32StatusRX 和 UART_INT_RX)== UART_INT_RX)
{
//
//在接收 FIFO 中有字符时循环。
//
while (ROM_UARTCharsAvail (UART1_base)&& BufFull (&rxRingBuf)== false)
{
//
//从 UART 读取下一个字符
//
uint32_t ch =(uint8_t) ROM_UARTCharGet (UART1_base);
RingBufWriteOne (&rxRingBuf、ch);
}
}


空
UARTSend (const uint8_t * pui8Buffer、uint32_t ui32Count)
{

GPIO_PORTF_DATA_R |= TX_EN_RS485;

while (ui32Count---)
{
ROM_UARTCharPut (UART1_base、* pui8Buffer++);
}

GPIO_PORTF_DATA_R &=~ TX_EN_RS485;

}

void
ADXL357_SendAllAccData (void)
{
字符串[10];
//从传感器收集数据;变量 sample_in.z 包含传感器数据
sprintf (string、"%+.6F"、sample_in.z);
UARTSend ((uint8_t *) string、strlen (string));

UARTSend ("\n",1);

}

int
main (void){
uint8_t ret = false;
uint8_t acc_Continuous_scan = 0x00;
uint8_t MODULE_Continuous_scan = 0x00;
ROM_IntMasterDisable();
ConfigureMicroProcessor();
LEDsTest();
ROM_IntMasterEnable();
GPIO_PORTF_DATA_R &=~ TX_EN_RS485;

while (1)
{

if (RingBufEmpty (&rxRingBuf)=false)
{
//我们是否收到足够的字节,使其成为消息?
if (RingBufUsed (&rxRingBuf)=sizeof (uint8_t[8]))
{
uint8_t rec[8];
//将字节读入我们收到的消息结构。
RingBufRead (&rxRingBuf、(uint8_t*)&rec、sizeof (receivedMsg));
//附加地址
如果(rec[2]='0'& rec[3]='1')
{
ADXL357_SendAllAccData();

}
}


}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我认为您过早切换 RS485收发器。 仅仅因为 ROM_UARTCharPUT()函数已经返回、并不意味着串行传输完成。 使用函数 UARTBusy()确定所有字符的传输时间。

    void
    UARTSend (const uint8_t * pui8Buffer、uint32_t ui32Count)
    {
    GPIO_PORTF_DATA_R |= TX_EN_RS485;
    while (ui32Count---)
    {
    ROM_UARTCharPut (UART1_base、* pui8Buffer++);
    }
    while (ROM_UARTBusy (UART1_base))
    {
    //在传输完成之前延迟此处
    }
    GPIO_PORTF_DATA_R &=~ TX_EN_RS485;
    }
    
    
    
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的回复。 现在、传输也与例程 ADXL357_SendAllAccData (void)一起工作。

    我面临的唯一问题是、当传感器处于连续模式时、我必须多次发出相关的停止命令。

    我已按以下方式修改了代码

    1) 1)在中断处理程序开始时、我禁用了 RS485发送器

    2) 2)在例程 UARTSend 和 ADXL357_SendAllAccData 中、我使用了指令 ROM_UARTCharsAvail (UART1_base)

    3) 3)在 UARTSend()例程结束时 ,我已设置了一个较小的延迟

    但是,随着这些变化,停止运输的问题仍然存在



    空
    UART1 IntHandler (空)
    {
    GPIO_PORTF_DATA_R &=~ TX_EN_RS485;
    uint32_t ui32StatusRX;
    
    RingBufFlush (&rxRingBuf);
    
    //
    //获取中断状态。
    //
    ui32StatusRX = ROM_UARTIntStatus (UART1_BASE、TRUE);
    
    //
    //清除已发出的中断。
    //
    ROM_UARTIntClear (UART1_BASE、ui32StatusRX);
    //接收超时中断在 FIFO 中接收到字节但尚未接收到字节时触发
    //已足够触发您的 Rx 中断。 这是因为 FIFO 级别选择决定了何时进行
    // T_RT)
    {
    // FIFO 中有要读取的字节和空间。
    while (UARTCharsAvail (UART1_base)&& RingBufFull (&rxRingBuf)== false)
    {
    uint32_t ch =(uint8_t) ROM_UARTCharGet (UART1_base);
    
    if (ch='?')
    {
    
    JumpToBootLoader();
    }
    //将一个字节从硬件 FIFO 直接写入到我们的 Rx FIFO 中以供以后处理。
    RingBufWriteOne (&rxRingBuf、ch);
    }
    }
    if (((ui32StatusRX 和 UART_INT_RX)== UART_INT_RX)
    {
    //
    //在接收 FIFO 中有字符时循环。
    //
    while (ROM_UARTCharsAvail (UART1_base)&& BufFull (&rxRingBuf)== false)
    {
    //
    //从 UART 读取下一个字符
    //
    uint32_t ch =(uint8_t) ROM_UARTCharGet (UART1_base);
    RingBufWriteOne (&rxRingBuf、ch);
    }
    }
    
    
    空
    UARTSend (const uint8_t * pui8Buffer、uint32_t ui32Count)
    {
    
    if (!ROM_UARTCharsAvail (UART1_BASE))
    {
    GPIO_PORTF_DATA_R |= TX_EN_RS485;
    while (ui32Count---)
    {
    ROM_UARTCharPut (UART1_base、* pui8Buffer++);
    }
    
    }
    while (ROM_UARTBusy (UART1_base));
    GPIO_PORTF_DATA_R &=~ TX_EN_RS485;
    ROM_SysCtlDelay (200);
    
    }
    
    void
    ADXL357_SendAllAccData (void)
    {
    字符串[10];
    
    sprintf (string、"%+.6F"、sample_in.z);
    if (!ROM_UARTCharsAvail (UART1_BASE))
    {
    UARTSend ((uint8_t *) string、strlen (string));
    UARTSend ("\n",1);
    } 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您需要更高级别的协议来控制 RS485总线上的方向变化。 仅仅改变收发器的方向是不够的、因为持续传输的器件仍在通过总线进行通信。 另一种选择是实现4线全双工总线。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这是一个具有一个主设备和多个从设备的全双工 RS485总线的图片。 无需关闭主器件上的收发器。 然后、主器件发出命令、告知每个从器件何时可以通信(一次只有一个)。