打印
[STM32F2]

STM32F207VE RS485收发异常请教

[复制链接]
5958|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
viderpu|  楼主 | 2013-11-25 15:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
目前使用STM32F207VE做产品,结合ST库函数设计RS485的驱动程序。使用USART1(GPIOA pin9和pin10)做485的收发,GPIOA pin11做485使能控制信号。不太清楚GPIO配置和中断处理,请教高人指点!并且弱弱的问下,多字节的发送和接收,使用DMA和中断处理,效果差别大吗?
沙发
feilusia| | 2013-11-25 15:42 | 只看该作者
“不太清楚GPIO配置和中断处理”
这句话的意思是几乎什么都不懂?建议你先去看几遍485模块的资料,问题的内容具体到点再问吧。

“多字节的发送和接收,使用DMA和中断处理,效果差别大吗?”
没看懂你的问题是问什么和什么差别大,你是不是想问“多字节的发送和接收,使用DMA和不使用DMA,效果差别大吗?”
用DMA最大的好处就是发送过程由DMA去完成,这时候CPU是可以去做其他事情的,也就是节省CPU开支。

使用特权

评论回复
板凳
拿起书本| | 2013-11-25 16:04 | 只看该作者
GPIO故名思议就是输入输出,也就是高低电平,这个资料上应该都有详细介绍的。

使用特权

评论回复
地板
viderpu|  楼主 | 2013-11-25 16:20 | 只看该作者
feilusia 发表于 2013-11-25 15:42
“不太清楚GPIO配置和中断处理”
这句话的意思是几乎什么都不懂?建议你先去看几遍485模块的资料,问题的内 ...

怪我没讲清楚。我的意思是参考ST官方实例进行了相应的GPIO配置,串口调试没有问题,现在是将USART1转为485的方式进行数据收发。相对的增加了一个485的使能控制GPIOA pin11,由于485是半双工的通讯,所以不是很清楚接收使能和发送使能该怎么控制(对于多字节的传输)。DMA由于在传输时对于字节长度是很清楚的,现在对于不定长的数据传输方便吗?我是这么个意思!

使用特权

评论回复
5
feilusia| | 2013-11-25 16:37 | 只看该作者
viderpu 发表于 2013-11-25 16:20
怪我没讲清楚。我的意思是参考ST官方实例进行了相应的GPIO配置,串口调试没有问题,现在是将USART1转为48 ...

1)你可以看看这张图,RS232和RS485的区别就是一个是全双工,一个是半双工,RS485是靠两个控制引脚去控制此时是“发送”还是“接收”。建议平时待机时都选择接收模式,需要发送数据时转换成发送模式,发送完数据后再转回接收模式。
2)DMA的传输字节其实是可以改变的。
比如:两边的DMA都设置传输字节为3,其中一个DMA要发送数据了,先把两字节数据长度+1字节校验位发过去,另一个DMA收到数据长度以后,马上改变数据长度。这样数据长度就是活的啦。

QQ截图20131125163146.jpg (23.8 KB )

QQ截图20131125163146.jpg

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
viderpu + 1 很给力!
6
viderpu|  楼主 | 2013-11-25 17:44 | 只看该作者
下面是我的GPIO初始化函数,在关闭DE定义时可以发送数据,打开后就发送不了。
static void uart_init_gpio(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,  GPIO_AF_USART1);

    /* USART pins configuration
    * USART_TX: PA9
    * USART_RX: PA10
    */
    /* Configure USART1 Tx (PA.09) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure USART1 Rx (PA.10) as input floating */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

#if (0)
    /* Configure GPIOA.11 (DE pin) as output push-pull */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
#endif
}

下面是我的发送函数,在发送完后调用GPIO_WriteBit拉低,使可接受。
INT32S Uart1_Write(INT8U *buf, INT32S len)
{
    INT32S i = 0;
    INT32S send_len = 0;

#if (UART_SEND_TYPE)
    DMA1_UART1_TX(buf, len);

    send_len = len;
#else
    /* Set flag to send data */

    for (i = 0; i < len; ++i) {
        USART_SendData(USART1, *(buf + send_len));
        send_len++;

        while (RESET == USART_GetFlagStatus(USART1, USART_FLAG_TC));
    }

    /* Set flag to receive data */
//    GPIO_WriteBit(GPIOA, GPIO_Pin_11, Bit_RESET);
#endif

    return send_len;
}
因为我这个是在初始化后先发送数据,因此就没有先PIN11为低电平。
但是现在就DE使能的GPIO初始化不行,请高手帮忙查看一下GPIO该怎么定义?
谢谢了!

使用特权

评论回复
7
feilusia| | 2013-11-25 17:51 | 只看该作者
你用了重映射,但没有开复用功能的时钟,所以你的串口是不起作用的。

另外你的GPIO不能拉高拉低?

使用特权

评论回复
8
feilusia| | 2013-11-25 17:53 | 只看该作者
#if (0)
改为
#if (1)

使用特权

评论回复
9
viderpu|  楼主 | 2013-11-26 08:36 | 只看该作者
feilusia 发表于 2013-11-25 17:51
你用了重映射,但没有开复用功能的时钟,所以你的串口是不起作用的。

另外你的GPIO不能拉高拉低? ...

相对于STM32F1XX,STM32F207没有关于RCC_APB2Periph_AFIO的定义,你说的复用功能时钟应该是指这个吧,GPIO可以拉高或拉低,只是在我调试的时候去除了。

使用特权

评论回复
10
viderpu|  楼主 | 2013-11-26 08:38 | 只看该作者
feilusia 发表于 2013-11-25 17:53
#if (0)
改为
#if (1)

我前面已经说过了,改过后的结果就是本来还可以发送数据,结果就不能发送数据了。这个就是添加DE初始化时遇到的问题。所以请帮忙看看是初始化那个地方不对吗?

使用特权

评论回复
11
budonglene| | 2013-11-26 09:26 | 只看该作者
        /* Configure USART Rx as alternate function  */
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
                GPIO_Init(GPIOA,&GPIO_InitStructure);------接收用不用配置成AF啊,

使用特权

评论回复
12
viderpu|  楼主 | 2013-11-26 10:32 | 只看该作者
budonglene 发表于 2013-11-26 09:26
/* Configure USART Rx as alternate function  */
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
                GP ...

不用啊,只有TX必须是AF模式的,而且你这个应该是STM32F10X系列的吧?

使用特权

评论回复
13
viderpu|  楼主 | 2013-11-26 13:34 | 只看该作者
当前STM32F207的开发环境为ucosII, 之前发现时没有将中断处理添加到向量表中,现在添加后还是不进入中断。不知道哪位高手指点一下?
下面贴出初始化代码和中断服务程序:

/*******************************************************************************
** 函数名称: Uart_Open
** 功能描述: 打开串口
** 输    入:
**           baud,  波特率
** 输   出:
**           status, 打开串口是否成功
*******************************************************************************/
INT32S Uart1_Open(INT32U baud)
{
        INT32S status = USER_TRUE;

        uart_init_clk();
        uart_init_gpio();
        uart_init_config(baud);

        USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);
        USART_Cmd(USARTx, ENABLE);

        /* Rx interrupt enable */
        BSP_IntVectSet(USARTx_BSP_INT_ID, USARTx_IRQHandler);
        BSP_IntEn(USARTx_BSP_INT_ID);
        BSP_IntPrioSet(USARTx_BSP_INT_ID, 1);

        while (RESET == USART_GetFlagStatus(USARTx, USART_FLAG_TC));

        return status;
}

/*******************************************************************************
** 函数名称: USARTx_IRQHandler
** 功能描述: USARTx中断处理函数
** 输    入: 无
** 输   出: 无
*******************************************************************************/
static void USARTx_IRQHandler(void)
{
        OS_CPU_SR  cpu_sr;

        OS_ENTER_CRITICAL();
        OSIntNesting++;
        OS_EXIT_CRITICAL();

    if (SET == USART_GetFlagStatus(USARTx, USART_FLAG_RXNE)) {
                usart1_rx.data[usart1_rx.index_w++] = USART_ReceiveData(USARTx);
        }

        if ((BUF_SIZEOF_MAX - 1) <= usart1_rx.index_w) {
                usart1_rx.index_w = 0;
        }

        /* Clear the interrupt flags. */
        USART_ClearITPendingBit(USARTx, USART_FLAG_RXNE);

    OSIntExit();
}
请教高人指点一下。谢谢!

使用特权

评论回复
14
budonglene| | 2013-11-26 13:59 | 只看该作者
viderpu 发表于 2013-11-26 10:32
不用啊,只有TX必须是AF模式的,而且你这个应该是STM32F10X系列的吧?

我的是STM32F207,我配置输入都是配置成AF mode的,:handshake,暂时还没发现有什么问题,可能2种都可以吧

使用特权

评论回复
15
budonglene| | 2013-11-26 14:06 | 只看该作者
viderpu 发表于 2013-11-26 13:34
当前STM32F207的开发环境为ucosII, 之前发现时没有将中断处理添加到向量表中,现在添加后还是不进入中断。 ...


void USART1_IRQHandler(void)
{       
    OS_ERR err;
   CPU_SR_ALLOC();
    CPU_CRITICAL_ENTER();
    OSIntNestingCtr++;     //=OSIntEnter(); Tell uC/OS-III that we are starting an ISR             */
     OSTaskSemPost(&AppTaskUSART1_TCB,OS_OPT_POST_NONE,&err);     
    CPU_CRITICAL_EXIT();
   OSIntExit();
}       
我的是这样写的,你的几个USART共用一个中断处理吗

使用特权

评论回复
16
budonglene| | 2013-11-26 14:06 | 只看该作者
本帖最后由 budonglene 于 2013-11-26 14:07 编辑


:)

使用特权

评论回复
17
viderpu|  楼主 | 2013-11-26 17:40 | 只看该作者
budonglene 发表于 2013-11-26 14:06
void USART1_IRQHandler(void)
{       
    OS_ERR err;

不是共用一个中断,而是需要转为RS485进行通讯。目前数据收发都已经调通了。

使用特权

评论回复
18
香水城| | 2013-11-27 16:54 | 只看该作者

使用特权

评论回复
19
viderpu|  楼主 | 2013-11-28 12:51 | 只看该作者
香水城 发表于 2013-11-27 16:54
如何使用GPIO来做RS485控制

多谢香主,这个文档我在ST官网上下载过了。还是感谢香主的支招!

使用特权

评论回复
20
rtgchym| | 2013-11-28 15:30 | 只看该作者
feilusia 发表于 2013-11-25 16:37
1)你可以看看这张图,RS232和RS485的区别就是一个是全双工,一个是半双工,RS485是靠两个控制引脚去控制 ...

嗯,学习了。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

21

帖子

1

粉丝