微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI Zigbee设计交流 > cc2530中UART转RS485,RS485通讯方向的控制问题

cc2530中UART转RS485,RS485通讯方向的控制问题

时间:10-02 整理:3721RD 点击:

如图所示,P0.0控制RS485的收发.。高电平发送数据,低电平接收数据。

UART转RS485的方法是发送前将P0.0置为高电平,发送完成后置为低电平。

我是在DMA发送完成的中断里加入的P0.0置低控制  P0 &= ~0x01;(见下面的图)

现在的问题是数据还没有发完,P0.0就变成低电平了,这样就导致了UART上的数据不能从RS485总线上发送出去。

P0 &= ~0x01;这一句究竟应该放在哪里?希望得到各位的帮助

ZIGBEE协议栈用的是2.3.0-1.4.0

你好,

如果在Tx Done的中断里面不加 P0 &= ~0x01的话,应该是可以把数据发送完成的对吧?

把DMA传输的MOSI信号和P0.0信号都放在示波器上看,应该在DMA一次发送过程中P0.0的信号一直为高的,对吗?还是说一次发送还没完成,P0.0就变低了?

比方说你传输10个字节,P0.0的变低是在什么位置?

关于DMA的配置是否有问题?

你好,谢谢你的回答。

不管在Tx Done的中断里加不加P0 &=~0x01,数据都是可以发送的。(uart波特率设置的9600)

把P0 &=~0x01加到Tx Done的中断里,在示波器上测发送引脚P0.3和485控制引脚P0.0,P0.0的高电平在数据还没发出时就变低了,如下图所示:

如果中断里不加P0 &=~0x01这句,P0.0就不会有电平变化,说明中断是执行了。我现在觉得这个中断是DMA将待发送到数据搬运到UART的BUFFER中产生的,但UART模块还没有将数据发送出去,但是DMA的中断却将P0.0提前变低了。不知道我理解的对不对?所以我认为要找的应该是UART发送完成的中断,但UART好像又没有设置中断,所以现在该如何解决这个问题,没有头绪了。

DMA的配置如下:

/******************************************************************************
* @fn HalUARTInitDMA
*
* @brief Initialize the UART
*
* @param none
*
* @return none
*****************************************************************************/
static void HalUARTInitDMA(void)
{
halDMADesc_t *ch;

P2DIR &= ~P2DIR_PRIPO;
P2DIR |= HAL_UART_PRIPO;

#if (HAL_UART_DMA == 1)
PERCFG &= ~HAL_UART_PERCFG_BIT; // Set UART0 I/O to Alt. 1 location on P0.
#else
PERCFG |= HAL_UART_PERCFG_BIT; // Set UART1 I/O to Alt. 2 location on P1.
#endif
PxSEL |= UxRX_TX; // Enable Tx and Rx peripheral functions on pins.
ADCCFG &= ~UxRX_TX; // Make sure ADC doesnt use this.
UxCSR = CSR_MODE; // Mode is UART Mode.
UxUCR = UCR_FLUSH; // Flush it.

// Setup Tx by DMA.
ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_TX );

// The start address of the destination.
HAL_DMA_SET_DEST( ch, DMA_UDBUF );

// Using the length field to determine how many bytes to transfer.
HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN );

// One byte is transferred each time.
HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_BYTE );

// The bytes are transferred 1-by-1 on Tx Complete trigger.
HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE );
HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_TX );

// The source address is incremented by 1 byte after each transfer.
HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_1 );

// The destination address is constant - the Tx Data Buffer.
HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_0 );

// The DMA Tx done is serviced by ISR in order to maintain full thruput.
HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_ENABLE );

// Xfer all 8 bits of a byte xfer.
HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS );

// DMA has highest priority for memory access.
HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH );

// Setup Rx by DMA.
ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_RX );

// The start address of the source.
HAL_DMA_SET_SOURCE( ch, DMA_UDBUF );

// Using the length field to determine how many bytes to transfer.
HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN );

/* The trick is to cfg DMA to xfer 2 bytes for every 1 byte of Rx.
* The byte after the Rx Data Buffer is the Baud Cfg Register,
* which always has a known value. So init Rx buffer to inverse of that
* known value. DMA word xfer will flip the bytes, so every valid Rx byte
* in the Rx buffer will be preceded by a DMA_PAD char equal to the
* Baud Cfg Register value.
*/
HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_WORD );

// The bytes are transferred 1-by-1 on Rx Complete trigger.
HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE_REPEATED );
HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_RX );

// The source address is constant - the Rx Data Buffer.
HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_0 );

// The destination address is incremented by 1 word after each transfer.
HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_1 );
HAL_DMA_SET_DEST( ch, dmaCfg.rxBuf );
HAL_DMA_SET_LEN( ch, HAL_UART_DMA_RX_MAX );

// The DMA is to be polled and shall not issue an IRQ upon completion.
HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_DISABLE );

// Xfer all 8 bits of a byte xfer.
HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS );

// DMA has highest priority for memory access.
HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH );
}

又用示波器测试了一下,测试结果如下:

1.发送一个字节时

2.发送两个字节时

3.发送四个字节

4.发送更多数据时

哪位大神出来指点一下

您好!请问您的MAX485控制问题解决了吗?我也遇到同样问题。还希望您多多赐教。我的邮箱puyunxk@163.com.QQ879882500

DMA的方式没能解决,后来改成中断的方式就可以了

我也遇到了类似的问题,我的是无法接收,改用中断单独写程序可以接收,在协议栈中就不知道如何入手了,楼主可以指点一下吗?谢谢 qq372160080

你也是用的485芯片吗?最好先排除485的问题,绕过485测试一下2530芯片串口输入引脚的波形是否正常。

刚开始是3485的问题,后来改好了,不用协议栈单独写发送接收程序都可以,协议栈不知道往哪里写程序,实现不了。。

像HalUARTWrite,HalUARTRead是协议栈基本的函数,直接用就可以了。如果这个也不知道的话恐怕别人也不知道怎么帮助你。

这个知道  但是这打不开_hal_uart_isr.c,是没有吗?

协议栈中默认使能的DMA方式,要使能中断方式需要在配置文件中修改宏定义。选择使能中断后_hal_uart_isr.c才会加入工程。

但我建议你首先在协议栈默认方式下(即DMA方式)先调通串口通讯。

谢谢你的建议,现在情况是这样的,我使用DMA方式只能使用HalUARTWrite函数发送数据,使用HalUARTRead却接收不到任何数据,方向控制位也是跟你说的一样在那里修改的。

建议你先测试不用485时通讯是否正常,正常后再往后进行。

使用DMA进行485通信中可以在DMA中断加延时如下:

谢谢了 ,我再试试。

你用的dma模式还是中断模式?我用的dma现在能收到数据,但是收到的是乱码。接收使能以后,发送之前是不是还得发送使能,还有发送以后是不是又要接收使能?

对比 4L 的图片

应该是因为UART 有2字节有效缓冲( 缓冲寄存器和移位寄存器 )的原因,需要延时2个字节耗时再设置P0.0

因为 倒数第二个字节 进入发送移位寄存器时,倒数第一个字节就会被DMA送到缓冲寄存器里面,DMA就完成所有数据传输,产生计数完成中断。

但实际上需要 2个字节 (2x10xBaud) 时间 后才真正完全把数据通过UART发送完成, 才能设置 P0.0口关闭485

例如

发送10个字节,发完第8个字节就会产生DMA中断

发送100个字节,发完第98个字节就会产生DMA中断

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top