问题:
Xilinx的ZYNQ-7000,vitis库开发时串口发送数据总是上次接收的问题
UART串口接收的代码总是上一次发送的。无法实现发送本次中断的值是什么原因呢?
代码段:
中断处理:
void uart_intr_aihandler(void *CallBackRef, u32 Event, unsigned int EventData) {
if (Event == XUARTPS_EVENT_RECV_DATA)
{
u8 tmp = XUartPs_RecvByte(XPAR_XUARTPS_0_BASEADDR);//后改的试用;
if(recv_buf_index >= UART_BUFFER_SIZE-1)//如果超过发送还没有找到尾 重置
{
memset(recv_buf, 0, UART_BUFFER_SIZE);
memset(UartBuff,0,UART_BUFFER_SIZE);
recv_buf_index = 0;
IntrDone = 0;
}
else if (tmp == UART_TAIL)
{
memset(UartBuff,0,UART_BUFFER_SIZE);
memcpy(UartBuff,recv_buf,strlen((char *)recv_buf));
recv_buf_index = 0;
IntrDone = 1;
memset(recv_buf, 0, UART_BUFFER_SIZE);
}
else
{
recv_buf[recv_buf_index++] = tmp;
}
}
}
int init_uart_intr(XScuGic *InstancePtr, XUartPs *UartInstancePtr, u16 UartIntrId) {
int Status;
XScuGic_Config *IntcConfig;
XUartPs_Config *UartConfig;
// 初始化 UART 设备
UartConfig = XUartPs_LookupConfig(UART_DEVICE_ID);
if (NULL == UartConfig) {
return XST_FAILURE;
}
Status = XUartPs_CfgInitialize(UartInstancePtr, UartConfig, UartConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
// 初始化中断控制器
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (IntcConfig == NULL) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(InstancePtr, IntcConfig, IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
// Connect
Status = XScuGic_Connect(InstancePtr, UartIntrId,
(Xil_ExceptionHandler) XUartPs_InterruptHandler,
(void *) UartInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
// Open UART Handle
XUartPs_SetHandler(UartInstancePtr, (XUartPs_Handler)uart_intr_aihandler, UartInstancePtr);
XUartPs_SetInterruptMask(UartInstancePtr, XUARTPS_IXR_RXOVR | XUARTPS_IXR_TTRIG | XUARTPS_IXR_RXFULL);
XScuGic_Enable(InstancePtr, UartIntrId);
// enable Handle
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XScuGic_InterruptHandler, InstancePtr);
Xil_ExceptionEnable();
return XST_SUCCESS;
}
int main()
{
while(1)
{
if(IntrDone){
xil_printf("Recv[%s]\r\n",UartBuff);
IntrDone = 0;
}
}
}
串口端现象
先一个字节进行测试,可能是接收到打印不同步引起的!
jiyugpt
根据你提供的代码和描述,推测你可能在发送数据时存在数据缓存未清空的问题。可以尝试在发送数据之前先清空发送数据的缓存,以确保每次发送的都是最新的数据。
具体地,可以在发送数据前使用memset()函数清空缓存区,比如:
memset(send_buf, 0, sizeof(send_buf)); // 清空发送数据缓存
sprintf(send_buf, "Hello world!"); // 向发送数据缓存中写入最新的数据
此外,如果你还没在发送数据之前对串口进行初始化,需要在初始化时将发送缓冲区和接收缓冲区清空,可以使用memset()函数或bzero()函数。
如果以上方法还不能解决问题,可以尝试对串口发送和接收的中断进行调试,查看数据在传输过程中是否存在问题。
在你的代码中,串口中断处理函数 uart_intr_aihandler() 的作用是接收串口数据,如果接收到的数据是 UART_TAIL,则将接收到的数据复制到 UartBuff 中,并将 IntrDone 标志设置为 1,表示数据已经接收完毕。
然而,在你的主函数中,你的代码只有在 IntrDone 被设置为 1 时才会处理 UartBuff 中的数据。因此,如果 IntrDone 没有被设置为 1,则不会处理新接收到的数据,因此你会看到上一次接收到的数据被打印出来。
为了解决这个问题,你需要在中断处理函数中设置一个标志来表示数据已经接收完毕,并在主函数中处理接收到的数据。可以像这样修改代码:
void uart_intr_aihandler(void *CallBackRef, u32 Event, unsigned int EventData) {
if (Event == XUARTPS_EVENT_RECV_DATA)
{
u8 tmp = XUartPs_RecvByte(XPAR_XUARTPS_0_BASEADDR);//后改的试用;
if(recv_buf_index >= UART_BUFFER_SIZE-1)//如果超过发送还没有找到尾 重置
{
memset(recv_buf, 0, UART_BUFFER_SIZE);
memset(UartBuff,0,UART_BUFFER_SIZE);
recv_buf_index = 0;
IntrDone = 0;
}
else if (tmp == UART_TAIL)
{
memset(UartBuff,0,UART_BUFFER_SIZE);
memcpy(UartBuff,recv_buf,strlen((char *)recv_buf));
recv_buf_index = 0;
IntrDone = 1;
memset(recv_buf, 0, UART_BUFFER_SIZE);
}
else
{
recv_buf[recv_buf_index++] = tmp;
IntrDone = 0; // 数据还未接收完毕
}
}
}
int main()
{
while(1)
{
if(IntrDone){
// 处理接收到的数据
xil_printf("Recv[%s]\r\n",UartBuff);
memset(UartBuff, 0, UART_BUFFER_SIZE);
IntrDone = 0;
}
}
}
这样,每当接收到一个字符时,IntrDone 将被设置为 0,表示数据还没有接收完毕。只有当接收到的数据是 UART_TAIL 时,IntrDone 才会被设置为 1,表示数据已经接收完毕。在主函数中,只要 IntrDone 被设置为 1,就会处理 UartBuff 中的数据。
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
根据你提供的代码,问题可能出现在接收缓冲区(recv_buf)的清零时机上。在函数内部,在数据接收到尾部时,recv_buf被清零,但是在下一个数据接收中,recv_buf并没有被清零,导致上一次接收的数据仍然存在,从而造成发送数据时出现上一次接收的数据的问题。
为了解决这个问题,你可以尝试将清空recv_buf移到函数的开始部分:
void uart_intr_aihandler(void *CallBackRef, u32 Event, unsigned int EventData) {
if (Event == XUARTPS_EVENT_RECV_DATA)
{
memset(recv_buf, 0, UART_BUFFER_SIZE);// 在每个接收到数据的中断函数开始时清空
u8 tmp = XUartPs_RecvByte(XPAR_XUARTPS_0_BASEADDR);// 后改的试用;
if(recv_buf_index >= UART_BUFFER_SIZE-1)//如果超过发送还没有找到尾 重置
{
memset(UartBuff,0,UART_BUFFER_SIZE);
recv_buf_index = 0;
IntrDone = 0;
}
else if (tmp == UART_TAIL)
{
memcpy(UartBuff,recv_buf,strlen((char *)recv_buf));// 从recv_buf复制到UartBuff
recv_buf_index = 0;
IntrDone = 1;
}
else
{
recv_buf[recv_buf_index++] = tmp;
}
}
}
注意,这里的代码只是为了解决上述问题,没有经过完整的测试和优化,可能还存在其他问题。但是,理论上这个修改应该可以解决你遇到的问题。
如果我的回答解决了您的问题,请采纳!
void uart_intr_aihandler(void *CallBackRef, u32 Event, unsigned int EventData)
{
static u8 recv_buf[UART_BUFFER_SIZE];
static u32 recv_buf_index = 0;
if (Event == XUARTPS_EVENT_RECV_DATA)
{
recv_buf[recv_buf_index++] = XUartPs_RecvByte(XPAR_XUARTPS_0_BASEADDR);
if (recv_buf_index >= UART_BUFFER_SIZE)
{
recv_buf_index = 0;
}
if (recv_buf[recv_buf_index - 1] == UART_TAIL)
{
recv_buf[recv_buf_index - 1] = 0; // 删除 UART_TAIL 字符
IntrDone = 1;
memset(UartBuff, 0, UART_BUFFER_SIZE);
memcpy(UartBuff, recv_buf, UART_BUFFER_SIZE);
recv_buf_index = 0;
memset(recv_buf, 0, UART_BUFFER_SIZE);
}
}
}
int main()
{
while(1)
{
if(IntrDone){
xil_printf("Recv[%s]\r
",UartBuff);
IntrDone = 0;
}
}
}