在发送前加上在句while( USART_GetFlagStatus( UART4, USART_FLAG_TC ) == RESET );就一直卡死在这里,在发送后加就只能收到最后一个字符。

我调在个485通信调了好久了,一直解决不了收发不定长数据问题,大佬帮忙看下,我把发送函数中的第一个 while( USART_GetFlagStatus( UART4, USART_FLAG_TC ) == RESET );加上就会一直卡死在这一句,如果不加在一句就只能收到不定长数据的最后一个字符,不管字符长度是多少都只能收到最后一个。(用的STM32的F103RE的芯片)

void uart4_Send( u8 *buf, u16 len )
{
    u16 t;
    CS_485_tx;
    for( t = 0; t < len; t++ )                                                                                         //循环发送数据
    {
   //     while( USART_GetFlagStatus( UART4, USART_FLAG_TC ) == RESET );
        USART_SendData( UART4, buf[t] );
    }
    while( USART_GetFlagStatus( UART4, USART_FLAG_TC ) == RESET );
    CS_485_rx;
}

具体代码如下:

点C文件;


u8 rec_buff[UART4_REC_LEN] = {0};
u16 uart4_rec_cnt = 0;                                //串口接收数据长度

u8 data_backup[UART4_REC_LEN] = {0};                                         //数据备份
u16 dataLen_backup = 0;                                                //长度备份
u8 receiveOK_flag = 0;                                        //接收完成标志位

/*
空闲中断是什么意思呢?
指的是当总线接收数据时,一旦数据流断了,此时总线没有接收传输,处于空闲状态,IDLE就会置1,产生空闲中断;又有数据发送时,IDLE位就会置0;
注意:置1之后它不会自动清0,也不会因为状态位是1而一直产生中断,它只有0跳变到1时才会产生,也可以理解为上升沿触发。
所以,为确保下次空闲中断正常进行,需要在中断服务函数发送任意数据来清除标志位。
*/

/***********************************************************************/
//*******函数名:rs485_init()
//*******用  途:与主板通讯
//*******说  明:传输控制和检测数据给主板
/***********************************************************************/

void rs485_init()
{
    GPIO_InitTypeDef GPIO_InitStructure;     //声明一个结构体变量,用来初始化GPIO

    USART_InitTypeDef USART_InitStructure;     //串口结构体定义

    NVIC_InitTypeDef NVIC_InitStructure;    //中断结构体定义

    //打开时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD|RCC_APB2Periph_AFIO,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);
//  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
//    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5,ENABLE);
    
    /*  配置GPIO的模式和IO口 */

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;    //TX-485    //串口输出PC10
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;          //复用推挽输出
//    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;       //推挽输出
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;    
    GPIO_Init(GPIOC,&GPIO_InitStructure);                     /* 初始化串口输入IO */
    
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_15;    //CS-485
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;       //推挽输出
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
    GPIO_Init(GPIOA,&GPIO_InitStructure);           

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;    //RX-485       //串口输入PC11
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;        //模拟输入
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOC,&GPIO_InitStructure);             /* 初始化GPIO */


    USART_InitStructure.USART_BaudRate = 9600;               //波特率设置为9600    //波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;       //数据长8位
    USART_InitStructure.USART_StopBits = USART_StopBits_1;            //1位停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;           //无效验
    USART_InitStructure.USART_HardwareFlowControl =USART_HardwareFlowControl_None; //失能硬件流
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;         //开启发送和接受模式
    USART_Init(UART4, &USART_InitStructure);       /* 初始化USART4 */
    USART_Cmd(UART4,ENABLE);    
    USART_ITConfig(UART4,USART_IT_RXNE,ENABLE);  //使能或者失能指定的USART中断 接收中断
    USART_ITConfig(UART4,USART_IT_IDLE,ENABLE);  //使能或者失能指定的USART中断 空闲中断
    USART_ClearFlag(UART4,USART_FLAG_TC);     //清除USARTx的待处理标志位

    /* 设置NVIC参数 */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;        //打开USART2的全局中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;     //抢占优先级为0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;          //响应优先级为1
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          //使能
    NVIC_Init(&NVIC_InitStructure);

    CS_485_rx;
}


/*
void  uart2_init( u16 baud )
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef  NVIC_InitStructure;

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                    //推挽复用模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;        //浮空输入模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init( &NVIC_InitStructure );

    USART_InitStructure.USART_BaudRate = baud;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

    USART_Init( USART2, &USART_InitStructure );

    USART_ITConfig( USART2, USART_IT_IDLE, ENABLE );                                             //使能串口空闲中断
    USART_ITConfig( USART2, USART_IT_RXNE, ENABLE );                                           //使能串口RXNE接收中断
    USART_Cmd( USART2, ENABLE );                                                                                     //使能串口2
}
*/


//发送len个字节
//buf:发送区首地址
//len:发送的字节数
void uart4_Send( u8 *buf, u16 len )
{
    u16 t;
    CS_485_tx;
    for( t = 0; t < len; t++ )                                                                                         //循环发送数据
    {
        while( USART_GetFlagStatus( UART4, USART_FLAG_TC ) == RESET );
        USART_SendData( UART4, buf[t] );
    }
    while( USART_GetFlagStatus( UART4, USART_FLAG_TC ) == RESET );
    CS_485_rx;
}


//备份接收到的数据
void copy_data( u8 *buf, u16 len )
{
    u16 t;
    dataLen_backup = len;                                                                                                         //保存数据长度
    for( t = 0; t < len; t++ )
    {
        data_backup[t] = buf[t];                                                                                             //备份接收到的数据,防止在处理数据过程中接收到新数据,将旧数据覆盖掉。
    }
}

//利用空闲中断接收串口不定长数据
//RXNE中断和IDLE中断的区别?
//当接收到1个字节,就会产生RXNE中断,当接收到一帧数据,就会产生IDLE中断。比如给单片机一次性发送了8个字节,就会产生8次RXNE中断,1次IDLE中断。

void UART4_IRQHandler( void )
{
    u8 tem = 0;

    if( USART_GetITStatus( UART4, USART_IT_RXNE ) != RESET )                           //接收中断  接收到一个字节产生一次中断
    {
        tem = USART_ReceiveData( UART4 );                                                                 //读取数据,可以自动将中断标志位RXNE清零
        rec_buff[uart4_rec_cnt++] = tem;                                                                 //存储接收到的数据
    }
    if( USART_GetITStatus( UART4, USART_IT_IDLE ) != RESET )                             //空闲中断 接收到一帧数据 产生一次中断
    {
        tem = UART4->SR;                                                                                                     //读取SR寄存器
        tem = UART4->DR;                                                                                                     //读取DR寄存器 (先读USART_SR,然后读USART_DR可以清除空闲中断标志位IDLE)
        //uart2_Send( rec_buff, uart2_rec_cnt );                                                     //一帧数据接收完毕,将接收到的数据发送出去
        copy_data( rec_buff, uart4_rec_cnt );                                                           //备份数据
        receiveOK_flag = 1;                                                                                                 //接收完成标志位置位
        uart4_rec_cnt = 0;                                                                                                 //接收数据长度清零
    }
}

main文件;

    


   rs485_init();

    while(1)
    {
      if( receiveOK_flag ==1 )                                                                        //一帧数据接收完成后开始处理数据
        {
            receiveOK_flag = 0;
            uart4_Send( data_backup, dataLen_backup );                    //发送数据
            memset( data_backup, 0, sizeof( data_backup ) );        //清空备份数组
            CS_485_rx;
        }

        

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值