AVR Xmega USART读取完整字符串时出现问题

时间:2018-09-26 13:13:23

标签: c avr arduino-ide serial-communication usart

在尝试读取完整的字符串时,我遇到了一些问题,并且行为异常。我使用的是配备有atxmega32a4u的自制演示板,基本上我想做的是通过串行通信设置参数(输出电压设定值),而MCU则执行其工作(控制降压转换器并通过串行方式发送回去)。数据作为电压和电流)。让我们看一下代码:这里有主要功能

int main(void)
{   
osc_init();
PORTC_OUTSET = PIN7_bm; //Let's make PC7 as TX
PORTC_DIRSET = PIN7_bm; //TX pin as output

PORTC_OUTCLR = PIN6_bm;
PORTC_DIRCLR = PIN6_bm; //PC6 as RX

adc_init();
timer_init();
timer1_init();              //init all the peripheral
Serial_init();
stdout = stdin = &usart_str;

char l[100];


while (1) 
{

    if(!((USARTC1_STATUS & USART_RXCIF_bm)==0))
    {
        printf("**MAIN**\n");
        uart_getstring(l);
        printf("**DIGITATO %s **\n ",l);
    }
    printf("tensione: %f V corrente: %f A\n",v_bat,cur);
}

}

正如您在外部while循环中看到的那样,我只是使用printf函数发送回数据(该函数很好用,并且给我很好的格式化字符串,可以像arduino ide那样在串行监视器中显示)。嵌套循环在找到设置的USART_RXCIF标志时开始,这意味着传入的缓冲区正在等待读取。然后,它调用uart_getstring()函数,这里有:

void uart_getstring(char* line)
{   
int z=0;

while( !(USARTC1_STATUS & USART_RXCIF_bm) ); //Wait until data has been received.

char data='a';

while((data!='\r')){

        while( !(USARTC1_STATUS & USART_RXCIF_bm) );

        data = USARTC1_DATA; //Temporarly store received data
        printf("**GOT** %d carattere %c \n",z,data);

        line[z] = data;
        z++;

    }
    line[z]='\0';   
}

请注意,所有控件都是在ISR函数中完成的,串行是在没有usart中断的主循环中完成的。但是我也尝试禁用所有其他进程并仅运行main函数,但是遇到了相同的问题

因此,我使用arduino ide的串行监视器进行了尝试,该监视器使我能够将命令发送到板并接收答案。发生的事情很棘手,如果我仅发送1或2个字符的字符串就可以正常工作!但是,如果我发送一个较长的字符串,它将失败,它只是将其发送回给我,因为它只有2个字符。让我们看一些例子:

>> a
<<
**MAIN**
**GOT** 0 carattere a 
**GOT** 1 carattere  
**DIGITATO a **

>> aa
<<
**MAIN**
**GOT** 0 carattere a 
**GOT** 1 carattere a
**GOT** 2 carattere 
**DIGITATO aa **

and then if i send something longer it fails

>> fail
<<
**MAIN**
**GOT** 0 carattere f
**GOT** 1 carattere a
**GOT** 2 carattere 
**DIGITATO fa **

我也通过python脚本尝试了它,也只是使用了screen命令,但是结果却是一样的。 任何帮助,将不胜感激。 非常感谢

2 个答案:

答案 0 :(得分:0)

好的,我自己看了数据表就得到了答案。似乎rx和tx缓冲区是共享的,所以我试图注释掉函数内部的调试printf,它才起作用!希望这可以对某人有所帮助

答案 1 :(得分:0)

共享的接收缓冲区不是您的问题。发生此问题,因为

的执行时间
printf("**GOT** %d carattere %c \n",z,data);

将代码阻塞太长时间,而字符串的其余部分由终端发送。 XMEGA接收缓冲区由两级FIFO组成。

让我们看看您尝试发送“失败”的情况。

while((data!='\r')){

    // This blocks until the first char 'f' is received, which is OK.
    while( !(USARTC1_STATUS & USART_RXCIF_bm) );

    // At this point, 'f' is located in the DATA buffer.
    // The reception of the next char 'a' immediately starts next and is handled
    // by the UART receiver hardware.
    data = USARTC1_DATA; //Temporarly store received data

    // You just cleared the DATA buffer by reading it, so there is room for 'a'
    // after it has been received completely.

    // printf() blocks the code for a very long time
    printf("**GOT** %d carattere %c \n",z,data);

    // While you sent data using printf(), the terminal program sent the remaining
    // characters 'i' and 'l'. However, because DATA was already holding 'a' and
    // it wasn't cleared in between, the other chars got lost.

    line[z] = data;
    z++;

}

我希望这可以弄清楚。