OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4744|回复: 2

求助: 关于双串口发送中断问题

[复制链接]

28

主题

360

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1028
金钱
1028
注册时间
2021-2-4
在线时间
146 小时
发表于 2022-7-15 21:08:43 | 显示全部楼层 |阅读模式
1金钱
手上有个项目 目前用了两个串口一个接串口屏(115200) 一个接电机(9600)

都采用在中断内发送数据


需求是:
屏输入数据发给单片机
单片机处理后发给屏幕用作显示
单片机发给电机执行动作

目前在屏幕上输入数据后
单片机只发送了一个字符给屏(串口4,抢占优先级0)后,就执行485发送了
进入了485的那个串口中断(串口1,抢占优先级1)
485发送数据是完整发出的 电机可以执行相应动作
但是屏幕上不会显示数据

代码贴在下方 希望大佬可以看看

//这是串口屏初始化的

// TFT屏 串口4 IO初始化
void TFT_GPIO_Init(TFT_Conf *TFT_GPIO_Init_Struct)
{
    GPIO_InitTypeDef GPIO_Init_Struct;

    GPIO_Init_Struct.GPIO_Pin = TFT_GPIO_Init_Struct->Tx_PINx;
    GPIO_Init_Struct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init_Struct.GPIO_Mode = GPIO_Mode_AF_PP;                 //推挽复用输出
    GPIO_Init(TFT_GPIO_Init_Struct->Tx_PORTx, &GPIO_Init_Struct); //初始化输出引脚

    GPIO_Init_Struct.GPIO_Pin = TFT_GPIO_Init_Struct->Rx_PINx;
    GPIO_Init_Struct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init_Struct.GPIO_Mode = GPIO_Mode_IN_FLOATING;           //浮空输入
    GPIO_Init(TFT_GPIO_Init_Struct->Rx_PORTx, &GPIO_Init_Struct); //初始化输入引脚
}

// TFT屏 串口4初始化
void TFT_Init(void)
{
    TFT.Tx_PINx = TFT_RS232_TX_PIN;
    TFT.Tx_PORTx = TFT_RS232_TX_PORT;

    TFT.Rx_PINx = TFT_RS232_RX_PIN;
    TFT.Rx_PORTx = TFT_RS232_RX_PORT;

    for (uint8_t i = 0; i < TFT_SUM; i++)
    {
        TFT_GPIO_Init(&TFT_Array[i]); //初始化串口4的IO
    }

    USART_InitTypeDef TFT_UART_Init_Struct;
    TFT_UART_RCC_ENABLE(); //使能TFT_UART的时钟

    // USART 初始化设置
    TFT_UART_Init_Struct.USART_BaudRate = 115200;                                    //设置波特率
    TFT_UART_Init_Struct.USART_WordLength = USART_WordLength_8b;                     //字长为8
    TFT_UART_Init_Struct.USART_StopBits = USART_StopBits_1;                          //一个停止位
    TFT_UART_Init_Struct.USART_Parity = USART_Parity_No;                             //无奇偶校验位
    TFT_UART_Init_Struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件控制流
    TFT_UART_Init_Struct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                 //收发模式

    USART_Init(TFT_UART, &TFT_UART_Init_Struct);     //初始化TFT串口
    USART_ITConfig(TFT_UART, USART_IT_RXNE, ENABLE); //使能串口4的接收中断
    USART_Cmd(TFT_UART, ENABLE);                     //串口4使能

    //配置中断优先级
    NVIC_InitTypeDef NVIC_TFT_UART_Init_Struct;
    NVIC_TFT_UART_Init_Struct.NVIC_IRQChannel = TFT_UART_IRQn;       //串口4中断入口
    NVIC_TFT_UART_Init_Struct.NVIC_IRQChannelCmd = ENABLE;           //使能
    NVIC_TFT_UART_Init_Struct.NVIC_IRQChannelPreemptionPriority = 0; //优先级
    NVIC_TFT_UART_Init_Struct.NVIC_IRQChannelSubPriority = 0;
    NVIC_Init(&NVIC_TFT_UART_Init_Struct);
}




//这是串口屏的发送与接收中断

/*************************************************中断函数***********************************************/
//串口4中断处理函数
void TFT_UART_IRQHandler(void)
{
    // uint8_t CLear_Flag = CLear_Flag; //清除警告
    //    uint8_t Temp_Rx;

    // RXNE的标志位不为空。它表明移位寄存器的内容被转移到RDR。
    if (USART_GetITStatus(TFT_UART, USART_IT_RXNE) != RESET) //接收到一帧数据
    {
        TFT.TFT_Rx_Buffer[TFT.TFT_Rx_Count++] = USART_ReceiveData(TFT_UART);
        if (TFT.TFT_Rx_Count >= TFT_RX_MAX) //超过最大长度
        {
            TFT.TFT_Rx_Count = TFT_RX_MAX;
        }
        if (TFT.TFT_Rx_Count == TFT_LEN + 3) //已经接收完有效数据
        {
            TFT.Flag_Rx = 1; //接收到一帧数据
            TFT.TFT_Rx_Count = 0;
        }
    }

    //发送中断触发
    if (USART_GetITStatus(TFT_UART, USART_IT_TXE) != RESET)
    {
        USART_SendData(TFT_UART, TFT.TFT_Tx_Buffer[TFT.TFT_Tx_Count++]);

        if (TFT.TFT_Tx_Count >= TFT.TFT_Tx_Len) //所有帧都发完了
        {
            TFT.TFT_Tx_Count = 0; //字节数
            TFT.TFT_Tx_Len = 0;   //帧数
            memset(TFT.TFT_Tx_Buffer, 0, TFT_TX_MAX);

            USART_ITConfig(TFT_UART, USART_IT_TXE, DISABLE); //关闭发送中断
        }
        USART_ClearFlag(TFT_UART, USART_IT_TXE); //清除字节发送完成中断
    }
}



//这是485的初始化

void RS485_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_Init_Struct;

    GPIO_Init_Struct.GPIO_Pin = RS485_EN_PIN;
    GPIO_Init_Struct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init_Struct.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
    GPIO_Init(RS485_EN_PORT, &GPIO_Init_Struct);

    GPIO_Init_Struct.GPIO_Pin = RS485_TX_PIN;
    GPIO_Init_Struct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init_Struct.GPIO_Mode = GPIO_Mode_AF_PP; //推挽复用输出
    GPIO_Init(RS485_TX_PORT, &GPIO_Init_Struct);

    GPIO_Init_Struct.GPIO_Pin = RS485_RX_PIN;
    GPIO_Init_Struct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init_Struct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_Init(RS485_RX_PORT, &GPIO_Init_Struct);
}

void RS485_Init(void)
{
    RS485_GPIO_Init();

    USART_InitTypeDef RS485_UART_Init_Struct;

    RS485_UART_RCC_ENABLE();

    // USART 初始化设置
    RS485_UART_Init_Struct.USART_BaudRate = 9600;                                      //设置波特率
    RS485_UART_Init_Struct.USART_WordLength = USART_WordLength_8b;                     //字长为8
    RS485_UART_Init_Struct.USART_StopBits = USART_StopBits_1;                          //一个停止位
    RS485_UART_Init_Struct.USART_Parity = USART_Parity_No;                             //无奇偶校验位
    RS485_UART_Init_Struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件控制流
    RS485_UART_Init_Struct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                 //收发模式

    USART_Init(RS485_UART, &RS485_UART_Init_Struct);   //初始化485串口
    USART_ITConfig(RS485_UART, USART_IT_RXNE, ENABLE); //使能串口1的接收中断
    USART_Cmd(RS485_UART, ENABLE);                     //串口1使能

    //配置中断优先级
    NVIC_InitTypeDef NVIC_RS485_UART_Init_Struct;
    NVIC_RS485_UART_Init_Struct.NVIC_IRQChannel = RS485_UART_IRQn;     //串口1中断入口
    NVIC_RS485_UART_Init_Struct.NVIC_IRQChannelCmd = ENABLE;           //使能
    NVIC_RS485_UART_Init_Struct.NVIC_IRQChannelPreemptionPriority = 1; //优先级
    NVIC_RS485_UART_Init_Struct.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&NVIC_RS485_UART_Init_Struct);
}


//这是485的中断

//串口1中断处理函数
void RS485_UART_IRQHandler(void)
{
    // RXNE的标志位不为空。它表明移位寄存器的内容被转移到RDR。
    //在单缓冲器模式里,由软件读USART_DR寄存器完成对RXNE位清除
    if (USART_GetITStatus(RS485_UART, USART_IT_RXNE) != RESET) //接收中断非空表示接收到一帧数据
    {
        // USART_ClearITPendingBit(RS485_UART, USART_IT_RXNE);                          //清除接收中断标志位
        Rx485_Buff.Rx_Buff[Rx485_Buff.Rx_Count++] = USART_ReceiveData(RS485_UART); //保存数据

        //一帧数据接收完成
        if (Rx485_Buff.Rx_Count == MODBUS_LEN + 5 + 1) //数据长度 + 3(帧头 长) + 2(校验)
        {
            memcpy(Rx485_Buff.Rx_Temp_Buff, Rx485_Buff.Rx_Buff, Rx485_Buff.Rx_Count - 1); //拷贝至临时数组
            Rx485_Buff.Flag_Rx = 1;
        }
    }
    //发送中断
    //发送先往DR填数据然后使能发送中断
    if (USART_GetITStatus(RS485_UART, USART_IT_TXE) != RESET) //可以填充数据了
    {
        USART_SendData(RS485_UART, Rx485_Buff.Tx_Buff[Rx485_Buff.Tx_Count++]); //发送数据

        if (Rx485_Buff.Tx_Count == Rx485_Buff.Tx_Len) //一帧数据发送完了
        {
            Rx485_Buff.Tx_Count = 0;
            Rx485_Buff.Tx_Len = 0;
            memset(Rx485_Buff.Tx_Buff, 0, RS485_TX_BUFF_MAX);  //清除缓存
            BLDC.CMD = CMD_BLDC_IDLE;                          //清除繁忙标志位
            USART_ITConfig(RS485_UART, USART_IT_TXE, DISABLE); //关闭发送中断

            //发送完成处理
            while (USART_GetFlagStatus(RS485_UART, USART_FLAG_TC) != SET)
                ; //当一帧发送完成时(停止位发送后)并且置位了TXE位,TC位被置起

            RX485_RX_MODE();
        }
        USART_ClearFlag(RS485_UART, USART_IT_TXE); //清除字节发送完成中断标志位
    }
}



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

28

主题

360

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1028
金钱
1028
注册时间
2021-2-4
在线时间
146 小时
 楼主| 发表于 2022-8-6 21:09:36 | 显示全部楼层
问题解决了, 是没有判断485的标志位,每次发送都直接拉引脚了
加上一个空闲判断就行了
总线空闲时置位标志位, 发送时等待总线空闲

帖子就不删了,就当做个记录吧
回复

使用道具 举报

28

主题

360

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1028
金钱
1028
注册时间
2021-2-4
在线时间
146 小时
 楼主| 发表于 2022-8-6 21:09:57 | 显示全部楼层
问题解决了, 是没有判断485的标志位,每次发送都直接拉引脚了
加上一个空闲判断就行了
总线空闲时置位标志位, 发送时等待总线空闲

帖子就不删了,就当做个记录吧
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-4-26 18:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表