打印
[STM32F1]

串口USART3,UART4,UART5中断无法进入问题

[复制链接]
3029|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
元方义城|  楼主 | 2015-8-11 16:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
首先点进来的大神先说生感谢,本人刚刚进入STM32世界没有多久,希望大神给点指点。

从百度上看了很多类似的问题,均无法解决。首先我的启动文件startup_stm32f10x_cl.s里已经包含了Usart123,Uart4,5.。配置如下:
void NVIC_GroupConfig(void)
{
    /* 配置NVIC中断优先级分组:
     - 1比特表示主优先级  主优先级合法取值为 0 或 1
     - 3比特表示次优先级  次优先级合法取值为 0..7
     - 数值越低优先级越高,取值超过合法范围时取低bit位
    */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    /*==================================================================================
      NVIC_PriorityGroup   |  主优先级范围  |  次优先级范围  |   描述
      ==================================================================================
     NVIC_PriorityGroup_0  |      0         |      0-15      |   0 比特表示主优先级
                           |                |                |   4 比特表示次优先级
     ----------------------------------------------------------------------------------
     NVIC_PriorityGroup_1  |      0-1       |      0-7       |   1 比特表示主优先级
                           |                |                |   3 比特表示次优先级
     ----------------------------------------------------------------------------------
     NVIC_PriorityGroup_2  |      0-3       |      0-3       |   2 比特表示主优先级
                           |                |                |   2 比特表示次优先级
     ----------------------------------------------------------------------------------
     NVIC_PriorityGroup_3  |      0-7       |      0-1       |   3 比特表示主优先级
                           |                |                |   1 比特表示次优先级
     ----------------------------------------------------------------------------------
     NVIC_PriorityGroup_4  |      0-15      |      0         |   4 比特表示主优先级
                           |                |                |   0 比特表示次优先级   
    ==================================================================================*/
}

void __SZ_STM32_COMInit(COM_TypeDef COM, USART_InitTypeDef* USART_InitStruct)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /* Enable GPIO clock */
    /* 使能STM32的USART对应GPIO的Clock时钟 */

void NVIC_COMConfiguration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
//          NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);//将中断矢量放到Flash的0地址
    USART_ITConfig(SZ_STM32_COM1, USART_IT_RXNE, ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = SZ_STM32_COM1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

    USART_ITConfig(SZ_STM32_COM3, USART_IT_RXNE, ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = SZ_STM32_COM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);
}

    RCC_APB2PeriphClockCmd(COM_TX_PORT_CLK[COM] | COM_RX_PORT_CLK[COM] | RCC_APB2Periph_AFIO, ENABLE);

    if (COM == COM1)
    {
        /* 使能STM32的USART1的Clock时钟 */
        RCC_APB2PeriphClockCmd(COM_USART_CLK[COM], ENABLE);
    }
    else
    {
        /* Enable the USART2 Pins Software Remapping */
        /* 使能STM32的USART2的管脚重映射 */
        GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);
        /* 使能STM32的USART的Clock时钟 */
        RCC_APB1PeriphClockCmd(COM_USART_CLK[COM], ENABLE);
    }

    /* Configure USART Tx as alternate function push-pull */
    /* 初始化STM32的USART的TX管脚,配置为复用功能推挽输出 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = COM_TX_PIN[COM];
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(COM_TX_PORT[COM], &GPIO_InitStructure);

    /* Configure USART Rx as input floating */
    /* 初始化STM32的USART的RX管脚,配置为复用功能输入 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Pin = COM_RX_PIN[COM];
    GPIO_Init(COM_RX_PORT[COM], &GPIO_InitStructure);

    /* USART configuration */
    /* 根据传入的参数初始化STM32的USART配置 */
    USART_Init(COM_USART[COM], USART_InitStruct);

    /* Enable USART */
    /* 使能STM32的USART功能模块 */
    USART_Cmd(COM_USART[COM], ENABLE);
}


void SZ_STM32_COMInit(COM_TypeDef COM, uint32_t BaudRate)
{
  
    USART_InitTypeDef USART_InitStructure;
  
    /* USARTx 默认配置:
          - BaudRate = 115200 baud  
          - Word Length = 8 Bits
          - One Stop Bit
          - No parity
          - Hardware flow control disabled (RTS and CTS signals)
          - Receive and transmit enabled
    */
    USART_InitStructure.USART_BaudRate = BaudRate;              //串口的波特率,例如115200 最高达4.5Mbits/s
    USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据字长度(8位或9位)
    USART_InitStructure.USART_StopBits = USART_StopBits_1;      //可配置的停止位-支持1或2个停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;         //无奇偶校验  
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //双工模式,使能发送和接收
  
    __SZ_STM32_COMInit(COM, &USART_InitStructure);  // 调用STM32的USART初始化底层函数

    SystemCoreClockUpdate();

}


以下是开发板里我摘录的接收和中断

SZ_USART_DATA_TypeDef SZ_USART1_DATA, SZ_USART2_DATA, SZ_USART3_DATA;

/**-------------------------------------------------------
  * @函数名 UsartIrqHandlerUser
  * @功能   共用的串口中断处理函数
  * @参数   SZ_USART 串口数据结构体指针
  * @返回值 无
***------------------------------------------------------*/
void UsartIrqHandlerUser(SZ_USART_DATA_TypeDef* SZ_USART)
{
    uint8_t uartRxData = 0;

    if(USART_GetITStatus(SZ_USART->uart, USART_IT_RXNE) != RESET)
    {
        /* save on rx buffer */
        while (SZ_USART->uart->SR & USART_FLAG_RXNE)
        {
            /* save character */
            uartRxData = SZ_USART->uart->DR & 0xff;
            SZ_USART->uartRxBuffer[SZ_USART->uart_rx_write_point] = uartRxData;
            SZ_USART->uart_rx_write_length ++;
            SZ_USART->uart_rx_write_point ++;
            if (SZ_USART->uart_rx_write_point >= UART_RX_BUFFER_SIZE)
                    SZ_USART->uart_rx_write_point = 0;

            /* if the next position is read index, discard this 'read char' */
            if (SZ_USART->uart_rx_write_point == SZ_USART->uart_rx_read_point)
            {
                //即将覆盖未读的数据,如何处理用户根据需要自己添加
                       
            }
        }

        /* clear interrupt */
        USART_ClearITPendingBit(SZ_USART->uart, USART_IT_RXNE);

        /* 接收完成 */
        if ((uartRxData == 0x05) || (SZ_USART->uart_rx_write_length >= UART_RX_BUFFER_SIZE))
        {
            SZ_USART->uart_rx_length = SZ_USART->uart_rx_write_length;
            SZ_USART->uart_rx_done= 1;
            SZ_USART->uart_rx_write_length = 0;
        }
    }


    /* If overrun condition occurs, clear the ORE flag
                              and recover communication */
    if (USART_GetFlagStatus(SZ_USART->uart, USART_FLAG_ORE) != RESET)
    {
        (void)USART_ReceiveData(SZ_USART->uart);
    }
  
        if (USART_GetITStatus(SZ_USART->uart, USART_IT_TC) != RESET)
        {
                /* clear interrupt */
                USART_ClearITPendingBit(SZ_USART->uart, USART_IT_TC);
        }
}

/**-------------------------------------------------------
  * @函数名 UsartReadData
  * @功能   共用的串口数据读取子函数
  * @参数1  SZ_USART 串口数据结构体指针
  * @参数2  串口数据存放的Buffer
  * @返回值 无
***------------------------------------------------------*/
uint32_t UsartReadData(SZ_USART_DATA_TypeDef* SZ_USART,  uint8_t* Buffer)
{
    uint32_t uartRxLength = 0, i;

    /* if the next position is read index, discard this 'read char' */
    if (SZ_USART->uart_rx_length != 0)
    {
        /* 开始临界资源访问,禁止中断 */
        __disable_irq();

        uartRxLength = SZ_USART->uart_rx_length;
        SZ_USART->uart_rx_length = 0;
        SZ_USART->uart_rx_done = 0;

        /* 结束临界资源访问,开放中断 */
        __enable_irq();

        for(i=0; i<uartRxLength; i++)
        {
            Buffer[i] = SZ_USART->uartRxBuffer[SZ_USART->uart_rx_read_point];
            SZ_USART->uart_rx_read_point++;

            if (SZ_USART->uart_rx_read_point >= UART_RX_BUFFER_SIZE)
            {
                SZ_USART->uart_rx_read_point = 0;
            }
        }

       Buffer[i] = '\0';
    }
               
    return uartRxLength;
}

/**-------------------------------------------------------
  * @函数名 USART1_IRQHandler
  * @功能   串口1中断处理函数
  * @参数   无
  * @返回值 无
***------------------------------------------------------*/
void USART1_IRQHandler(void)
{
    /* 开始临界资源访问,禁止中断 */
        __disable_irq();

    /* 串口1中断时将指示灯1状态取反 */
        LED1OBB = !LED1OBB;

    /* 调用共用的串口中断处理子函数 */
    UsartIrqHandlerUser(&SZ_USART1_DATA);
   
    /* 结束临界资源访问,开放中断 */
    __enable_irq();
}

/**-------------------------------------------------------
  * @函数名 USART2_IRQHandler
  * @功能   串口2中断处理函数
  * @参数   无
  * @返回值 无
***------------------------------------------------------*/
void USART3_IRQHandler(void)
{
    /* 开始临界资源访问,禁止中断 */
        __disable_irq();
   
    /* 串口2中断时将指示灯2状态取反 */
        LED3OBB = !LED3OBB;

    /* 调用共用的串口中断处理子函数 */
  //  UsartIrqHandlerUser(&SZ_USART3_DATA);

    /* 结束临界资源访问,开放中断 */
    __enable_irq();
}


主函数如下:
int main(void)
{
    /*!< 在系统启动文件(startup_stm32f10x_xx.s)中已经调用SystemInit()初始化了时钟,
         所以main函数不需要再次重复初始化时钟。默认初始化系统主时钟为72MHz。
         SystemInit()函数的实现位于system_stm32f10x.c文件中。
       */
    uint8_t ucStr[UART_RX_BUFFER_SIZE+1];//多一个用于存放'\0'
      
    /* 初始化板载LED指示灯 */
    SZ_STM32_LEDInit(LED1);
    SZ_STM32_LEDInit(LED2);
    SZ_STM32_LEDInit(LED3);
    SZ_STM32_LEDInit(LED4);
   
    SZ_STM32_SysTickInit(1000);

    SZ_USART1_DATA.uart = SZ_STM32_COM1;
    SZ_USART1_DATA.uart_rx_done = 0;
    SZ_USART1_DATA.uart_rx_length= 0;
    SZ_USART1_DATA.uart_rx_read_point = 0;
    SZ_USART1_DATA.uart_rx_write_point = 0;
    SZ_USART1_DATA.uart_rx_write_length = 0;
   
    SZ_USART3_DATA.uart = SZ_STM32_COM3;
        SZ_USART3_DATA.uart_rx_done = 0;
    SZ_USART3_DATA.uart_rx_length= 0;
    SZ_USART3_DATA.uart_rx_read_point = 0;
    SZ_USART3_DATA.uart_rx_write_point = 0;
    SZ_USART3_DATA.uart_rx_write_length = 0;
   
    /* 注意串口2使用Printf时"SZ_STM32F107VC_LIB.c"文件中fputc定义中设备改为SZ_STM32_COM2 */
    /* 串口2初始化 */
    SZ_STM32_COMInit(COM3, 115200);
        
    /* 串口1初始化 注意JP3和JP5跳到2<->3侧 */
    xPrintf_Init();

    NVIC_GroupConfig();
    NVIC_COMConfiguration();


    printf("\n\n\r 提示: 当前显示的窗口为串口2/COM2/USART2。 请将注意JP4跳到2<->3侧。\r\n");
    xprintf("\n\n\r 提示: 当前显示的窗口为串口1/COM1/USART1。请将注意JP3和JP5跳到2<->3侧。\r\n");
        
    /* Infinite loop 主循环 */
         LED1OBB = 1;
         LED3OBB = 1;
         LED4OBB = 0;
    while (1)
    {
        if(SZ_USART1_DATA.uart_rx_done == 1)
        {
             if(UsartReadData(&SZ_USART1_DATA, ucStr))
                         {
                         LED4OBB = 1;
            // xprintf("\n\n\r 串口1/COM1/USART1接收到-->%s\r\n", ucStr);
                         Usart1SendStr(ucStr,8);
                         LED4OBB = 0;
                         }
        }
        
        if(SZ_USART3_DATA.uart_rx_done == 1)
        {
             if(UsartReadData(&SZ_USART3_DATA, ucStr))
            // printf("\n\n\r 串口2/COM2/USART2接收到-->%s\r\n", ucStr);
                          Usart3SendStr(ucStr,8);
        }

        /* 此处可以添加用户的程序 */
    }   
}
这里我还省略的部分代码,USART1的Xprint功能均能正常使用,两个串口发送我自己写的Usart3SendStr();也没问题。可中断一直无法进入USART3_IRQHandler(void),可原先我使用USART2,接收和发送完全没问题。
补充一下,使用的是STM32F103VC 我这里USART3重映射到PC10,PC11.原先我是想使用UART4,可惜没弄出来。退而求其次想弄USART3,发现问题依旧,于是没有办法了。希望可以解决。
沙发
元方义城|  楼主 | 2015-8-13 11:10 | 只看该作者
看来是没人回答我的问题了。我尝试了不使用USART3重映射功能,将USART3的RX,TX连接在PB11,PB10上。令人疑惑的事情发生了。USART3的中断竟然神一般的复活了。于是我又将重映射打开,映射到PC10,PC12上,令人沮丧的是,还是老样子,用仿真看依旧无法进入USART3_IRQHandler(void);还有个奇怪的现象:由于无法进入USART3中断,我就用串口助手使劲的发数据,竟然还返回一些乱码,我呵呵了。继续摸索吧,已经两天了,努力自己结贴。

使用特权

评论回复
板凳
fanchendeyezi| | 2015-8-13 13:26 | 只看该作者
除了设置出错误外,遇到过两次中断无法进入的奇怪现象:
1,中断中有延时函数,延时函数使用了systick
2,stack overflow。启动文件中stack空间分配不够,程式中又用了几个比较大的数组,导致中断函数没有办法运行。

使用特权

评论回复
地板
元方义城|  楼主 | 2015-8-13 13:38 | 只看该作者
fanchendeyezi 发表于 2015-8-13 13:26
除了设置出错误外,遇到过两次中断无法进入的奇怪现象:
1,中断中有延时函数,延时函数使用了systick
2,s ...

感谢你的回复,我的中断里没有使用systick的延时函数。2,关于stack空间分配我不是很理解,用的是3.5的库。程序中数组使用不是很多呀。还有就是,USART123,如果直接用的话,我试了接收中断和发送都能直接进入。USART3我尝试映射到PD8,PD9使用也没有多大问题,接收发送正常.可是就是映射PC10,PC11,接收进不了中断。同理UART4也是如此。我怀疑是PC10,11这两个IO是不是很特殊。

使用特权

评论回复
5
元方义城|  楼主 | 2015-8-13 14:40 | 只看该作者
最后被国产MAX3232坑了。程序没有问题

使用特权

评论回复
6
amanda_s| | 2015-8-13 14:51 | 只看该作者
那为啥只是映射到PC10,PC11不行?

使用特权

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

本版积分规则

26

主题

158

帖子

4

粉丝