打印
[技术问答]

求助:HK32F103C8T6使能串口后死机

[复制链接]
1038|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hadio|  楼主 | 2021-3-21 23:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
芯片型号HK32F103C8T6,  串口1初始化了DMA发送和接收, 使能发送完成中断和空闲中断, 最后使能串口调用USART_Cmd(USARTx, ENABLE); 就死机了。 初始化代码如下:
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;
       
        //---------------------串口功能配置---------------------  
        //打开串口对应的外设时钟
        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);   
        //启动串口  
        //LedSwitch(0, LED_ON);         //在USART_Cmd(USARTx, ENABLE)前调用,可以正常点亮LED,
        USART_Cmd(USARTx, ENABLE);
         LedSwitch(0, LED_ON);         //此处死机, 点不亮LED!!!!!!! 貌似LED快闪了一下就灭了

        //设置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为接收状态         
}

使用特权

评论回复

相关帖子

沙发
xyz549040622| | 2021-3-22 08:16 | 只看该作者
你为什么要把串口io的初始化放在最后面呢?这样不死机才怪。请按照官方历程的顺序进行初始化。

使用特权

评论回复
板凳
hadio|  楼主 | 2021-3-22 15:49 | 只看该作者
xyz549040622 发表于 2021-3-22 08:16
你为什么要把串口io的初始化放在最后面呢?这样不死机才怪。请按照官方历程的顺序进行初始化。 ...

把串口GPIO的初始化放前面,也不行。这段代码是在STM32F103C8T6用过没问题的,只是换了HK32F103C8T6就不行了, 怀疑是芯片BUG, 厂家有个新的型号HK32F103C8T6A,  据说修复了串口和USB的某些BUG, 需要厂家确认是不是这个问题

使用特权

评论回复
地板
hadio|  楼主 | 2021-3-22 16:46 | 只看该作者
已解决,确定是HK32F103C8T6的BUG,  因为使能了IDLE中断,当串口使能后,会反复进入IDLE中断,导致CPU无法执行其它代码。只能通过额外的代码避免触发此BUG。

使用特权

评论回复
评论
xyz549040622 2021-3-22 19:28 回复TA
这些bug其实应该在手册中说明的,这点就欣赏stc,大大方方的。 
5
TEL17727938455| | 2021-3-22 19:00 | 只看该作者
可以试试我们的替代C8T6的料,软硬件通用,看ID

使用特权

评论回复
6
fanghuage| | 2021-3-23 15:28 | 只看该作者
你好,我也遇见了同样的问题,后来改成单字节中断接收,没啥问题。您这个  额外的代码避免触发此BUG 是咋实现的呢?

使用特权

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

本版积分规则

3

主题

25

帖子

1

粉丝