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"); //
}
我用断点发现会进去,但是实际并没有数据出来。不知这个函数哪里有问题 需要你提供使用的哪个芯片,不然没法判断啊。 中断使能配置错误:
在发送函数sub_uartc0_write_send_buff中,设置USARTC0_CTRLB = 0x08仅开启了发送使能(TXEN),但未使能数据寄存器空中断(UDRIE)。因此,写入第一个字节后,后续的中断未被触发,导致无法发送缓冲区中的剩余数据。
数据拷贝错误(次要问题):
在for循环中,代码错误地将指针data直接赋值给缓冲区,而非数据内容data。这导致缓冲区填充的是地址而非实际数据,但此错误不影响发送流程的中断触发。
解决方案
使能数据寄存器空中断(UDRIE):
在启动发送时,需同时使能发送器(TXEN)和数据寄存器空中断(UDRIE)。假设UDRIE位于USARTC0_CTRLB的第5位(即值0x20),则修改发送函数的USARTC0_CTRLB设置:
USARTC0_CTRLB = 0x08 | 0x20; // 开启发送允许和UDRE中断具体寄存器位的值需根据实际MCU手册调整。
修正数据拷贝逻辑:
修改循环内的赋值语句,正确写入数据内容:
uartc0_tx_buff = data; // 使用data而非data
修改后的发送函数代码片段
// 在启动发送时,正确设置中断使能位
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");
} 中断函数注意事项
确保中断处理函数在发送数据后保持中断使能,直到缓冲区为空。当前中断函数逻辑正确,无需修改,但需验证寄存器操作是否影响中断使能位。 没有看见芯片,怎么判断串口是否好用呢? 哪个型号啊,UART可以用MCC生成的代码做,很简单。 可以尝试在发送函数中加入延时,看看是否能解决发送不成功的问题 是不是发送中断没有正确使能,导致数据发送不成功 是不是定时器的中断优先级设置有问题,导致发送中断被阻塞了 可以尝试在发送函数中加入调试信息,看看发送缓冲区的数据是否正确写入 在定时发送时,是不是发送缓冲区的数据没有及时更新
页:
[1]