打印

GD32F103串口奇偶校验不起作用

[复制链接]
3833|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hadio|  楼主 | 2021-6-11 16:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我在用GD32F103C8T6替代STM32F103C8T6,
遇到一个问题,GD32的串口奇偶校验不起作用,

我无论用 无校验\奇校验\偶校验, 寄存器USART_SR的PE位(校验错误时=1)都是0,

而STM32就正常,当我发送端设置错误的校验方式时,STM32接收后,会将USART_SR的PE位置1;


有遇到同样问题的吗?

使用特权

评论回复
沙发
chenqianqian| | 2021-6-15 07:35 | 只看该作者
代码贴出来看看

使用特权

评论回复
板凳
hadio|  楼主 | 2021-6-17 11:04 | 只看该作者

请帮忙看看,

//USARTx中断   
void USARTx_IRQHandler(void)                                 
{     
        vu16 dummy;
        u16 check;
  unsigned int len;
        unsigned int i;  


        if(USARTx->SR & 0X10)        //优化         //if(USART_GetITStatus(USARTx, USART_IT_IDLE) != RESET)         if(dummy & 0x10)
  {  
                               
                check = USARTx->SR & 0X01;        //获取校验是否成功
                //dummy = USARTx->SR;  
                dummy = USARTx->DR; //清USART_IT_IDLE标志

                //关闭DMA
                 USART_DMAx_CHx_RX->CCR &= ~0x00000001;        //DMA_Cmd(USART_DMAx_CHx_RX,DISABLE);  

                //len = USART_RX_LEN - DMA_GetCurrDataCounter(USART_DMAx_CHx_RX);
                len = USART_RX_LEN - USART_DMAx_CHx_RX->CNDTR;


                //串口接收回调
                //USARTx_Callback(UsartRxBuf, len);
                for(i=0; i<len; i++)
                {
                        ModBusRxBuf = UsartRxBuf;
                }

                //判断校验是否成功, GD32F103C8T6下,此处check 始终为0!!!
                if(check == 0)
                {
                        PostMessage(MsgModbus, len);
                }                       
                       
                //设置传输数据长度  
                // DMA_SetCurrDataCounter(USART_DMAx_CHx_RX, USART_RX_LEN);  //2.0库不支持
                USART_DMAx_CHx_RX->CNDTR = USART_RX_LEN;

                //打开DMA  
                USART_DMAx_CHx_RX->CCR |= 0x00000001;        //DMA_Cmd(USART_DMAx_CHx_RX, ENABLE);  
  }
       
  
        if(USARTx->SR & 0X60)        //优化         //if(USART_GetITStatus(USARTx, USART_IT_TC) != RESET)
        {  
                USARTx->SR &= ~0X60;         //USART_ClearITPendingBit(USARTx,USART_IT_TC);
                RS485_GPIOx->BRR = RS485_GPIO_Pin;   //GPIO_ResetBits(RS485_GPIOx, RS485_GPIO_Pin);//默认RS485为接收状态          
        }      
}


//////////////////以下是串口初始化部分,用的DMA发送接收////////////////////////////////////
void USARTx_init(u32 baud, u8 parity)
{
        GPIO_InitTypeDef GPIO_InitStructure;       
        USART_InitTypeDef USART_InitStructure;
        USART_ClockInitTypeDef  USART_ClockInitStructure;       
        NVIC_InitTypeDef NVIC_InitStructure;       
        DMA_InitTypeDef DMA_InitStructure;
       
        //关闭串口   
        USART_Cmd(USARTx, DISABLE);                
       
        //---------------------串口功能配置---------------------  
        //打开串口对应的外设时钟
        if(USART_RCC_APBxPeriph_USARTx == RCC_APB2Periph_USART1)
        {
                RCC_APB2PeriphClockCmd(USART_RCC_APBxPeriph_USARTx, ENABLE);  
        }
        else
        {
                RCC_APB1PeriphClockCmd(USART_RCC_APBxPeriph_USARTx, ENABLE);
        }

               
        //启动DMA时钟  
        RCC_AHBPeriphClockCmd(USART_RCC_AHBPeriph_DMAx, ENABLE);  
        //DMA发送中断设置  
        NVIC_InitStructure.NVIC_IRQChannel = USART_DMAx_CHx_TX_IRQn;  
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;  
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
        NVIC_Init(&NVIC_InitStructure);  
        //DMA1通道4配置  
        DMA_DeInit(USART_DMAx_CHx_TX);  
        //外设地址  
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USARTx->DR);  
        //内存地址  
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)UsartTxBuf;  
        //dma传输方向单向  
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  
        //设置DMA在传输时缓冲区的长度  
        DMA_InitStructure.DMA_BufferSize = USART_TX_LEN;  
        //设置DMA的外设递增模式,一个外设  
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
        //设置DMA的内存递增模式  
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  
        //外设数据字长  
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
        //内存数据字长  
        DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;  
        //设置DMA的传输模式  
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
        //设置DMA的优先级别  
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;  
        //设置DMA的2个memory中的变量互相访问  
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  
        DMA_Init(USART_DMAx_CHx_TX, &DMA_InitStructure);  
       
        //使能DMA发送完成中断
//        DMA_ITConfig(USART_DMAx_CHx_TX, DMA_IT_TC,ENABLE);  
        //串口发送完成中断
        USART_ITConfig(USARTx, USART_IT_TC, ENABLE);
       
                  
   //串口收DMA配置 //////////////////////////////////////////////////////////   
    //启动DMA时钟  
    RCC_AHBPeriphClockCmd(USART_RCC_AHBPeriph_DMAx, ENABLE);  
    //DMA1通道5配置  
    DMA_DeInit(USART_DMAx_CHx_RX);  
    //外设地址  
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USARTx->DR);  
    //内存地址  
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)UsartRxBuf;  
    //dma传输方向单向  
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  
    //设置DMA在传输时缓冲区的长度  
    DMA_InitStructure.DMA_BufferSize = USART_RX_LEN;  
    //设置DMA的外设递增模式,一个外设  
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
    //设置DMA的内存递增模式  
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  
    //外设数据字长  
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
    //内存数据字长  
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  
    //设置DMA的传输模式  
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
    //设置DMA的优先级别  
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;  
    //设置DMA的2个memory中的变量互相访问  
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  
    DMA_Init(USART_DMAx_CHx_RX,&DMA_InitStructure);  
  
    //使能通道5  
    DMA_Cmd(USART_DMAx_CHx_RX,ENABLE);  
                     
        //初始化参数
        USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
        USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
        USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
        USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
        /* Configure the USART3 synchronous paramters */
        USART_ClockInit(USARTx, &USART_ClockInitStructure);       
       
        USART_InitStructure.USART_BaudRate = baud;   
        USART_InitStructure.USART_StopBits = USART_StopBits_1;  

        switch(parity)
        {
                case PAR_ODD:
                        USART_InitStructure.USART_Parity = USART_Parity_Odd;
                        USART_InitStructure.USART_WordLength = USART_WordLength_9b;  //开启校验时,数据位必须设置为9位,否则校验位会覆盖数据最高位  
                        break;
                case PAR_EVEN:
                        USART_InitStructure.USART_Parity = USART_Parity_Even;
                  USART_InitStructure.USART_WordLength = USART_WordLength_9b;  //开启校验时,数据位必须设置为9位,否则校验位会覆盖数据最高位
                        break;
                case PAR_NONE:
                default:       
                        USART_InitStructure.USART_Parity = USART_Parity_No;
                        USART_InitStructure.USART_WordLength = USART_WordLength_8b;   
                        break;
        }               
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;   
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;      
        //初始化串口   
        USART_Init(USARTx,&USART_InitStructure);   
        //串口空闲中断
        USART_ITConfig(USARTx, USART_IT_IDLE, ENABLE);
       
          
        //配置UART1中断   
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);  
        NVIC_InitStructure.NVIC_IRQChannel = USARTx_IRQn;               //通道设置为串口1中断   
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;       //中断占先等级0   
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;              //中断响应优先级0   
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 //打开中断   
        NVIC_Init(&NVIC_InitStructure);                                 //初始化   
          
        //采用DMA方式发送  
        USART_DMACmd(USARTx,USART_DMAReq_Tx,ENABLE);
    //采用DMA方式接收  
    USART_DMACmd(USARTx,USART_DMAReq_Rx,ENABLE);   
        //启动串口   
        USART_Cmd(USARTx, ENABLE);     
          
        //设置IO口时钟        
        RCC_APB2PeriphClockCmd(USART_RCC_APB2Periph_GPIOx | RCC_APB2Periph_AFIO, ENABLE);
       
        //串口1的管脚初始化      
        GPIO_InitStructure.GPIO_Pin = USART_GPIO_Pin_TX;                //管脚9   
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;               //选择GPIO响应速度   
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                 //复用推挽输出   
        GPIO_Init(USART_GPIOx, &GPIO_InitStructure);                    //TX初始化
       
        GPIO_InitStructure.GPIO_Pin = USART_GPIO_Pin_RX;                //管脚10   
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;           //浮空输入   
        GPIO_Init(USART_GPIOx, &GPIO_InitStructure);                    //RX初始化  
       
        //设置485控制线时钟        
        RCC_APB2PeriphClockCmd(RS485_RCC_APB2Periph_GPIOx, ENABLE);
       
        //串口1的管脚初始化      
        GPIO_InitStructure.GPIO_Pin = RS485_GPIO_Pin;               
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                //选择GPIO响应速度   
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                //推挽输出   
        GPIO_Init(RS485_GPIOx, &GPIO_InitStructure);                    //TX初始化
                 
        GPIO_ResetBits(RS485_GPIOx, RS485_GPIO_Pin);                                        //默认RS485为接收状态         
}

使用特权

评论回复
地板
bigsea366123| | 2022-8-22 17:26 | 只看该作者
有,我也遇到了,不知道怎么解决,可以交流一下吗,我的QQ:2232648567

使用特权

评论回复
5
bigsea366123| | 2022-8-23 14:18 | 只看该作者
解决了,初步怀疑是GD32单片机的问题,后来我把奇偶校验错误中断打开了,我发现奇偶校验正确,上位机和单片机的奇偶数校验不一致时,单片机会进入奇偶校验错误中断。换个串口就可以了。被 帝特 的串口坑了一天半。换了一个 微雪 的串口就可以了。有问题可以交流啊,QQ:2232648567

使用特权

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

本版积分规则

3

主题

26

帖子

1

粉丝