cr315 发表于 2025-4-10 22:00

UART 发送问题求助

串口在主函数里循环发送没有问题,但是如果用定时发送就会有问题!只会发送一次,后面就没有数据发送出来了,用的中断方式。下面是发送函数

//==========================================================================
// 函数名称:sub_uartc0_write_send_buff
// 函数功能:写数据到 uartc0 发射缓冲区
// 入口参数:data:数据指针,length:数据长度
// 出口参数:UARTC_ERROR:数据太长,将导致缓冲区溢出,写入失败;UARTC_SUCCESS:写入成功
// 程序版本:1.0
// 编写日期:
// 程序作者:
// 修改次数:
// 修改作者:
// 修改日期:
// 修改内容:
// 版本升级:
//==========================================================================
INT8U sub_uartc0_write_send_buff( const INT8U * data, INT16U length )
{
    INT16Uuartc_tx_len;                                             //
    INT16Ui;                                                          //
    Ram_debug(0xFF);
    if( length > cUartcBuff0 ) {                                        //
      return UARTC_ERROR;                                             //
    }                                                                   //

    asm volatile("CLI");                                                //
    uartc_tx_len = uartc0_tx_buff_len + length;                         //
    asm volatile("SEI");                                                //
    if( uartc_tx_len > cUartcBuff0 ) {                                  // 数据太长,写入失败
      return UARTC_ERROR;                                             //
    }                                                                   //

    for( i=0; i         uartc0_tx_buff = data;                         //
      uartc0_tx_ep++;                                                 //
      if( uartc0_tx_ep >= cUartcBuff0 ){                              //
            uartc0_tx_ep = 0;                                           //
      }                                                               //
    }                                                                   //

    asm("CLI");                                                         // 临界保护
    uartc0_tx_buff_len += length;                                       //
    asm("SEI");                                                         //

    if( uartc0_mode_flag == 0 ) {                                       // 如果没有开启发射,那么设置进入发送模式
      uartc0_mode_flag = 1;                                           //
                Ram_debug(0xF3);
                USARTC0_CTRLA = 0x04;                                           // 设置发射完毕中断优先级为低
      USARTC0_CTRLB = 0x08;                                           // 开启发送允许,关闭接收
      asm volatile("CLI");                                          //
               
                USARTC0_DATA = uartc0_tx_buff;                  //
      uartc0_tx_sp++;                                                 //
      if( uartc0_tx_sp >= cUartcBuff0 ){                              //
            uartc0_tx_sp = 0;                                           //
      }                                                               //
      uartc0_tx_buff_len--;                                           // 发射缓冲区数据长度减1
      asm volatile("SEI");                                          //
    }                                                                   //

    return UARTC_SUCCESS;                                             // 写数据成功,返回成功
}

中断函数:

//==========================================================================
// 函数名称:uartc0 串口通信发送数据寄存器空中断
// 函数功能:用于发射串口缓冲区数据,当发送缓冲区为空时,停止发送
// 入口参数:无
// 出口参数:无
// 程序版本:1.0
// 编写日期:
// 程序作者:
// 修改次数:
// 修改作者:
// 修改日期:
// 修改内容:
// 版本升级:
//==========================================================================
ISR( uartc0_tx_int )
{
    asm volatile("CLI");                                                // 禁止中断嵌套
    if( uartc0_tx_buff_len == 0x00 ) {                                  // 发射缓冲区为空,关闭发射
      uartc0_mode_flag = 0;                                           //
      uartc0_tx_sp = uartc0_tx_ep;                                    //
      USARTC0_CTRLA = 0x10;                                           // 关闭发送中断允许,开启接收中断允许
      USARTC0_CTRLB = 0x10;                                           //
                Ram_debug(0xF5);
      }                                                                   //
    else {
      USARTC0_DATA = uartc0_tx_buff;                  //
      uartc0_tx_sp++;                                                 //
      if( uartc0_tx_sp == cUartcBuff0 ){                              //
            uartc0_tx_sp = 0;                                           //
      }                                                               //
      uartc0_tx_buff_len--;                                           // 发射缓冲区数据长度减1
                Ram_debug(0xF4);
      }                                                                   //
    asm volatile("SEI");                                                //
}

我用断点发现会进去,但是实际并没有数据出来。不知这个函数哪里有问题

gaoyang9992006 发表于 2025-4-11 14:18

需要你提供使用的哪个芯片,不然没法判断啊。

xixi2017 发表于 2025-4-11 14:49

中断使能配置错误:

在发送函数sub_uartc0_write_send_buff中,设置USARTC0_CTRLB = 0x08仅开启了发送使能(TXEN),但未使能数据寄存器空中断(UDRIE)。因此,写入第一个字节后,后续的中断未被触发,导致无法发送缓冲区中的剩余数据。

数据拷贝错误(次要问题):

在for循环中,代码错误地将指针data直接赋值给缓冲区,而非数据内容data。这导致缓冲区填充的是地址而非实际数据,但此错误不影响发送流程的中断触发。

xixi2017 发表于 2025-4-11 14:50

解决方案
使能数据寄存器空中断(UDRIE):

在启动发送时,需同时使能发送器(TXEN)和数据寄存器空中断(UDRIE)。假设UDRIE位于USARTC0_CTRLB的第5位(即值0x20),则修改发送函数的USARTC0_CTRLB设置:
USARTC0_CTRLB = 0x08 | 0x20; // 开启发送允许和UDRE中断具体寄存器位的值需根据实际MCU手册调整。
修正数据拷贝逻辑:
修改循环内的赋值语句,正确写入数据内容:
uartc0_tx_buff = data; // 使用data而非data

xixi2017 发表于 2025-4-11 14:50

修改后的发送函数代码片段
// 在启动发送时,正确设置中断使能位
if (uartc0_mode_flag == 0) {
    uartc0_mode_flag = 1;
    Ram_debug(0xF3);
    USARTC0_CTRLA = 0x04; // 设置中断优先级(根据实际需求)
    USARTC0_CTRLB = 0x28; // TXEN (0x08) + UDRIE (0x20),使能发送和中断
    asm volatile("CLI");
    USARTC0_DATA = uartc0_tx_buff;
    uartc0_tx_sp++;
    if (uartc0_tx_sp >= cUartcBuff0) {
      uartc0_tx_sp = 0;
    }
    uartc0_tx_buff_len--;
    asm volatile("SEI");
}

xixi2017 发表于 2025-4-11 14:51

中断函数注意事项
确保中断处理函数在发送数据后保持中断使能,直到缓冲区为空。当前中断函数逻辑正确,无需修改,但需验证寄存器操作是否影响中断使能位。

单片小菜 发表于 2025-4-11 15:41

没有看见芯片,怎么判断串口是否好用呢?

wahahaheihei 发表于 2025-4-11 16:01

哪个型号啊,UART可以用MCC生成的代码做,很简单。

逆鳞风暴 发表于 2025-4-11 20:50

可以尝试在发送函数中加入延时,看看是否能解决发送不成功的问题

不想起床喵星人 发表于 2025-4-11 23:56

是不是发送中断没有正确使能,导致数据发送不成功

复古留声机 发表于 2025-4-12 10:00

是不是定时器的中断优先级设置有问题,导致发送中断被阻塞了

暖心小太阳 发表于 2025-4-12 11:12

可以尝试在发送函数中加入调试信息,看看发送缓冲区的数据是否正确写入

幻想收藏家 发表于 2025-4-12 15:23

在定时发送时,是不是发送缓冲区的数据没有及时更新
页: [1]
查看完整版本: UART 发送问题求助