白开水123 发表于 2017-5-19 09:43:53

STM32485串口只能发送第一个字符问题

STM32调试时发现当波特率为9600时串口助手收到程序发送出来的字符只有第一个字符,但是当把USART的波特率设置成38400时,串口助手就能收到完整的命令,哪位大神能解释下原因吗??
void USART1_IRQHandler(void)
{
u8 ucUartTemp;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
    ucUartTemp = USART_ReceiveData(USART1);
    Usart1.TimeOutCounter = Reset;
    if(Usart1.Usart_RxStatus == RX_IDLE)
    {
      if(ucUartTemp == Usart_StartMark )
      {
      
      Usart1.Usart_RxStatus = RX_HEAD;
      Usart1.Usart_ReceiveCache = ucUartTemp;
      Usart1.Usart_Cache_Where = CPOS_CMD;
      }
    }
    else if(Usart1.Usart_RxStatus == RX_HEAD )
    {
      if(Usart1.Usart_Cache_Where == CPOS_Length-1)
      Usart1.Usart_RxStatus = RX_Length;
      Usart1.Usart_ReceiveCache = ucUartTemp;
      Usart1.Usart_Cache_Where ++;
    }
    else if(Usart1.Usart_RxStatus == RX_Length)
    {
      Usart1.Usart_ReceiveCache = ucUartTemp;
      Usart1.Usart_Cache_Where++;
//      if((Usart1.Usart_Cache_Where > Usart1_ReceiveLength) ||
//         (Usart1.Usart_Cache_Where > (Usart1.Usart_ReceiveCache -'0')*10 + (Usart1.Usart_ReceiveCache -'0')*1))
//      {//接收超过限定长度
//      Usart1.Err_Code = ERR_OutLength;
//      Usart1.Usart_RxStatus = RX_END;
//      }
      if((Usart1.Usart_ReceiveCache == Usart_StartMark ) &&
         Usart1.Usart_Cache_Where == Usart1.Usart_ReceiveCache )
      {//正确接收完成
      Usart1.Usart_RxStatus = RX_END;
      }
    }
}
    ucUartTemp=USART1->SR;
    //if(ucUartTemp==RESET)ucUartTemp=Reset;
    ucUartTemp=USART1->DR;
    //if(ucUartTemp==RESET)ucUartTemp=Reset;
}

void Usart1Comm_app(void)
{


if(Usart1.Usart_RxStatus == RX_END)
{
    u8 i=0;
    //u8* crc;
    //CRC
   
    //for(i=0;i<Usart1.Usart_Cache_Where-4;i++)
   // temp8 ^= Usart1.Usart_ReceiveCache;
//    if(temp8 != (u8)AsciiHEXtoInt(Usart1.Usart_ReceiveCache+Usart1.Usart_Cache_Where-2,2))
//    {
//      if(Usart1.Err_Code == Reset)
//      Usart1.Err_Code = ERR_CRC;//CRC校验错误
//    }
//    else
    //CRC正确
      for(i=0;i<Usart1_ReportLength;i++)
      Usart1.Usart_ReportCache = 0;
      for(i=0;i<CPOS_CMD+1;i++)
      Usart1.Usart_ReportCache = Usart1.Usart_ReceiveCache;
      DeviceCode = (u8)AsciiHEXtoInt(Usart1.Usart_ReceiveCache+CPOS_Device,2);
      switch (Usart1.Usart_ReceiveCache)
      {
      case CMD_GetVER:
      {   
      /////////////////////////////////////Report////////////////////////////////////////////
      //memcpy(Usart1.Usart_ReportCache+7,Usart1.Usart_ReceiveCache+7,Usart1.Usart_Cache_Where);
      //步骤代码
      Usart1.Usart_ReportCache = 0x07;
      Usart1.Usart_ReportCache = 0x40;
      Usart1.Usart_ReportCache = 0x96;
      Usart1.Usart_RxStatus = RX_IDLE;
      Usart1.Err_Code = Reset;
      break;}
    default:
      Usart1.Err_Code = ERR_NoDefCMD;//未定义命令
      break;
      }
      
      Uart_PutChar(1,Usart1.Usart_ReportCache,7);
      DelayNms(1);
       RS485_DE_L();
      /*   
    //REPROT
    if(Usart1.Err_Code == Reset)
    {
      u16 SendCharLength = 0;
      SendCharLength = strlen((char *)Usart1.Usart_ReportCache);
      if(SendCharLength > Usart1_ReportLength) SendCharLength = Usart1_ReportLength;
      Usart1.Usart_ReportCache = SendCharLength + CrcLength;
      //Usart1.Usart_ReportCache = (SendCharLength + CrcLength)% 10/1+ '0';;
      //CRC
      //temp8 = 0;
      //for(i=0;i<SendCharLength;i++)
          //temp8 ^= Usart1.Usart_ReportCache;
      //Usart1.Usart_ReportCache = (((u16)temp8/16)<=9)?((u16)temp8/16+'0'):((u16)temp8/16-9+'@');
      //Usart1.Usart_ReportCache = (((u16)temp8%16)<=9)?((u16)temp8%16+'0'):((u16)temp8%16-9+'@');

      //crc=CRC162(Usart2.Usart_ReportCache,i);//计算CRC校验值
      //Usart2.Usart_ReportCache = *(crc+i);
      //i++;
      //Usart2.Usart_ReportCache = *(crc+i);
      //i++;
      //Usart2.Usart_ReportCache = *(crc+i);
      //i++;
      //Usart2.Usart_ReportCache = *(crc+i);
      //i++;

      Uart_PutChar(1,Usart1.Usart_ReportCache, SendCharLength);
      //for (i=0;i<7;i++)
      //Usart1.Usart_ReceiveCache=0;
      SYS_ReStart = Reset;
    }
    else
   {//
      SYS_ERRStatus = Set;
   Usart1.Usart_RxStatus = RX_IDLE;
   
    }*/
}
}

voidUsart2Comm_app (void)
{
if(Usart2_Receiver_Over)
{
    Usart2_Receiver_Over = 0;
}
}
voidUsart3Comm_app (void)
{
if(Usart3_Receiver_Over)
{
    Usart3_Receiver_Over = 0;
}
}
voidUsart4Comm_app (void)
{
if(Usart4_Receiver_Over)
{
    Usart4_Receiver_Over = 0;
}
}
voidUsart5Comm_app (void)
{
if(Usart5_Receiver_Over)
{
    Usart5_Receiver_Over = 0;
}
}
/*
void Usart3_init(u32 bdr)
{
USART_Cmd(USART1, DISABLE);//

USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = bdr;                   //设定传输速率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //设定传输数据位数偶校验9位
USART_InitStructure.USART_StopBits = USART_StopBits_1;      //设定停止位个数
USART_InitStructure.USART_Parity = USART_Parity_No ;       //偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不用流量控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                  //使用接收和发送功能

USART_Init(USART1, &USART_InitStructure);//初始化串口1
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
USART_Cmd(USART1, ENABLE);//使能串口1

}
*/
void Five_usart_init(void)
{
/* Timer Clock configuration ------------------------------------------------*/
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 ,ENABLE);
//RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2 ,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);
//RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5,ENABLE);



/* Timer Interrupt configuration ---------------------------------------------*/
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//4组抢占 4组从优先
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStructure);
//NVIC_InitStructure.NVIC_IRQChannel = USART5_IRQChannel;
//NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
//NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//NVIC_Init(&NVIC_InitStructure);

/* Usart configuration ---------------------------------------------*/
Usart_init(USART1,Usart1_BandRate,USART_WordLength_8b,USART_StopBits_1,USART_Parity_No,USART_HardwareFlowControl_None);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
USART_Cmd(USART1, ENABLE);
//使能u1-tx DMA发送
Usart_DMAtx_init(USART1,DMA1_Channel4);
DMA_Cmd(DMA1_Channel4, ENABLE);
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);

Usart_init(USART2,Usart2_BandRate,USART_WordLength_8b,USART_StopBits_1,USART_Parity_No,USART_HardwareFlowControl_None);
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
//USART_Cmd(USART2, ENABLE);//使能串口2

Usart_init(USART3,Usart3_BandRate,USART_WordLength_8b,USART_StopBits_1,USART_Parity_No,USART_HardwareFlowControl_None);
USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
// USART_Cmd(USART3, ENABLE);//使能串口3

Usart_init(UART4,Usart4_BandRate,USART_WordLength_8b,USART_StopBits_1,USART_Parity_No,USART_HardwareFlowControl_None);
USART_ITConfig(UART4,USART_IT_RXNE,ENABLE);
//USART_Cmd(UART4, ENABLE);//使能串口4

Usart_init(UART5,Usart5_BandRate,USART_WordLength_8b,USART_StopBits_1,USART_Parity_No,USART_HardwareFlowControl_None);
USART_ITConfig(UART5,USART_IT_RXNE,ENABLE);
//USART_Cmd(UART5, ENABLE);//使能串口5
DelayNms(50);
/* Timer GPIO configuration ------------------------------------------------*/
Set_Port_Status(GPIO_A,GPIO_Pin_9,GPIO_Mode_AF_PP);          //TX1
Set_Port_Status(GPIO_A,GPIO_Pin_10,GPIO_Mode_IN_FLOATING);   //RX1
Set_Port_Status(GPIO_A,GPIO_Pin_2,GPIO_Mode_AF_PP);      //TX2
Set_Port_Status(GPIO_A,GPIO_Pin_3,GPIO_Mode_IN_FLOATING);//RX2
Set_Port_Status(GPIO_B,GPIO_Pin_10,GPIO_Mode_AF_PP);       //TX3
Set_Port_Status(GPIO_B,GPIO_Pin_11,GPIO_Mode_IN_FLOATING); //RX3
Set_Port_Status(GPIO_C,GPIO_Pin_10,GPIO_Mode_AF_PP);       //TX4
Set_Port_Status(GPIO_C,GPIO_Pin_11,GPIO_Mode_IN_FLOATING); //RX4
//Set_Port_Status(GPIO_C,GPIO_Pin_12,GPIO_Mode_AF_PP);       //TX5
//Set_Port_Status(GPIO_C,GPIO_Pin_13,GPIO_Mode_IN_FLOATING); //RX5
}
/*******************************************************************************
*函数名称:
*******************************************************************************/
void Usart_init(USART_TypeDef* USARTx,u32 Usartx_BandRate,u16 USARTx_WordLength,u16 USARTx_StopBits,u16 USARTx_Parity,u16 USARTx_HardwareFlowControl)
{
USART_InitTypeDef USART_InitStructure;                        
USART_InitStructure.USART_BaudRate = Usartx_BandRate;         
USART_InitStructure.USART_WordLength = USARTx_WordLength;   
USART_InitStructure.USART_StopBits = USARTx_StopBits;         
USART_InitStructure.USART_Parity = USARTx_Parity;            
USART_InitStructure.USART_HardwareFlowControl = USARTx_HardwareFlowControl;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USARTx, &USART_InitStructure);
}
/*******************************************************************************
*函数名称:
*******************************************************************************/
void Usart_DMAtx_init(USART_TypeDef* USARTx,DMA_Channel_TypeDef * DMAx_Channelx)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USARTx->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(&USARTx->DR);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMAx_Channelx, &DMA_InitStructure);
}

//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;// | 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_10;
//GPIO_Init(GPIOB, &GPIO_InitStructure);
//
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 ;//| GPIO_Pin_12;
//GPIO_Init(GPIOC, &GPIO_InitStructure);
//*/
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;// | GPIO_Pin_3;
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//GPIO_Init(GPIOA, &GPIO_InitStructure);
//
////GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
////GPIO_Init(GPIOB, &GPIO_InitStructure);
//
////GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
////GPIO_Init(GPIOC, &GPIO_InitStructure);
//
////GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
////GPIO_Init(GPIOD, &GPIO_InitStructure);

//******************************************************************************
// 函数名称    : UART1_PutChar()
// 功能描述    : 串口1发送数据函数.
// 输入      : u8 ch 要发送的数据
// 输出      : None
// 返回      : None
//******************************************************************************

voidUart_PutChar(u8 CH,u8 *p,u8 NUM)
{
u16 i=0;
u8 j=0;
switch(CH)
{
case 1:
   //USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);
    //USART_ClearITPendingBit(USART1,USART_IT_RXNE);
    //USART_ClearITPendingBit(USART1,USART_IT_IDLE);
    //USART_ClearITPendingBit(USART1,USART_IT_ORE);
    //USART_ClearFlag(USART1,USART_FLAG_RXNE);
    //USART_ClearFlag(USART1,USART_FLAG_IDLE);
    //USART_ClearFlag(USART1,USART_FLAG_ORE);
    //GPIOA->CRH |= 0x00000300; //RX端口设置 设为输出模式 防止进入usart-ORE中断
    //DMA_Send585_END=0;
    //DMA_Send585_END_Timer=0;//用于延迟485使能端
    //GPIO_SetBits(GPIOA, GPIO_Pin_10);
    RS485_DE_H();
    DelayNms(5);
    DMA_Cmd(DMA1_Channel4, DISABLE);
    DMA1_Channel4->CNDTR=NUM;
    DMA1_Channel4->CMAR=(u32)p;
    DMA_Cmd(DMA1_Channel4, ENABLE);

    break;
case 2:
    for(i=0;i<NUM;i++)
    {
      j = *(p+i);
      USART2->DR = (j & (u16)0x01FF);
      while(!(USART2->SR & USART_FLAG_TXE));
    }
    break;
case 3:
    for(i=0;i<NUM;i++)
    {
      j = *(p+i);
      USART3->DR = (j & (u16)0x01FF);
      while(!(USART3->SR & USART_FLAG_TXE));
    }
    break;
case 4:
    for(i=0;i<NUM;i++)
    {
      j = *(p+i);
      UART4->DR = (j & (u16)0x01FF);
      while(!(UART4->SR & USART_FLAG_TXE));
    }
    break;
case 5:
    for(i=0;i<NUM;i++)
    {
      j = *(p+i);
      UART5->DR = (j & (u16)0x01FF);
      while(!(UART5->SR & USART_FLAG_TXE));
    }
    break;
}
}
下面串口助手接收的信息


oujisang 发表于 2017-5-19 09:43:54

485芯片是半双工芯片,发送的时候要把芯片置为发送模式,在发送完成后芯片置为接收模式,你的问题是在发送完毕后,程序内部状态是发送完毕,但是实质最后一个字节数据在硬件层没有发送完毕,这时候你将485芯片置为接收状态,最后一个字节会发送失败,在波特率越低状态下越明显,所以你检测到发送完成后。人为延时1ms,问题就会解决了,你可以试一试。

发表于 2017-5-19 09:59:57

楼主,从现象来看,是发生了数据丢失,如果不用DMA会不会发生丢失的情况。

白开水123 发表于 2017-5-19 10:33:45

安 发表于 2017-5-19 09:59
楼主,从现象来看,是发生了数据丢失,如果不用DMA会不会发生丢失的情况。 ...

如果是数据丢失的话也应该是延时的问题感觉,毕竟在38400波特率下数据并没有丢失而只在9600的情况下才丢失了

发表于 2017-5-19 10:53:51

波特率越高,发送时间越短。波特率低的情况下丢失,很多是因为数据传输太快导致。

白开水123 发表于 2017-5-19 11:16:21

明白,我去试试不用DMA传送数据。

wolfgang2015 发表于 2017-5-19 13:18:58

DMA发送后中断标识位未清空

白开水123 发表于 2017-5-19 13:44:00

wolfgang2015 发表于 2017-5-19 13:18
DMA发送后中断标识位未清空

清空的
void DMA1_Channel4_IRQHandler(void)
{//485发送完成中断
if(DMA_GetITStatus(DMA1_IT_TC4))
{
    DMA_ClearITPendingBit(DMA1_FLAG_TC4);
    DMA_Send585_END=1;
    //TIM_Cmd(TIM8, ENABLE);
}
}

stary666 发表于 2017-5-19 13:49:35

进来看看了,吗,,,,

发表于 2017-5-19 13:55:39

楼主,用DMA传输的时候,能不能一次多传输一些数据,不要一个字节一个字节的传输。如果单字节传输时,考虑判断一下上次数据发送完成,再进行下次发送。
页: [1]
查看完整版本: STM32485串口只能发送第一个字符问题