0

我在接收从 HC05 到 ATmega16 的字符串时遇到问题。我能够接收字符但无法接收字符串。

我想使用 ATmega16 和蓝牙模块(HC05)无线控制直流电机。我正在通过 HC05 将定时器 OCR1A 值从串行监视器应用程序发送到 ATmega16,但没有成功。

#define F_CPU 16000000UL 
#include<string.h>
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>

void UART_init()
{
    UCSRB |= (1 << RXEN) | (1 << TXEN);
    UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCS Z1);
    UBRRL = 0x67;
}

unsigned char UART_RxChar()
{
    while( (UCSRA & (1 << RXC)) == 0 );
    return(UDR);
}

void UART_TxChar( char ch )
{
    while( !(UCSRA & (1 << UDRE)) );  /* Wait for empty transmit buffer*/
    UDR = ch ;
}

void UART_SendString( char* str )
{
    unsigned char j = 0;

    while( j <= 2 )
    {
        UART_TxChar( str[j] );
        j++;
    }
}

int main( void )
{
    char buff[3];
    char j;
    int i = 0, k = 0;
    DDRD = (1 << PD5);

    UART_init();

    while( 1 )
    {
        buff[0] = UART_RxChar();
        buff[1] = UART_RxChar();
        buff[2] = UART_RxChar();

        j = UART_RxChar();

        if( j == '!' )
        {
            UART_SendString( buff );   // this is to check whether the atmega16 received correct values for timer or not.
            UART_SendString( "\n" );
        }
    }
}

预期的结果是当我在串行监视器应用程序中输入数字时,我应该在串行监视器应用程序上返回相同的数字。

在实际结果中,我有时会得到不同的字符,有时会空。

4

1 回答 1

0

该字符串buff未终止,因此UART_SendString( buff );将在收到的三个字符之后发送任何垃圾,直到找到 NUL (0) 字节。

char buff[4] = {0};

将为 NUL 留出空间,并且初始化将确保它buff[3]是 NUL 终止符。

或者,单独发送这三个字符,因为没有终止符,它们不构成有效的 C (ASCIIZ) 字符串。

除了缺少 nul 终止之外,您的代码还需要完全输入 表单nnn!nnn!nnn!...。如果另一端实际上正在发送带有 CR 或 CR+LF 终止符 的线路nnn!<newline>nnn!<newline>nnn!<newline>...-您的接收循环将不同步。

更安全的解决方案是在收到一个字符时使用之前收到的三个'!'字符。这可以通过多种方式完成 - 对于长缓冲区,建议使用环形缓冲区,但对于仅三个字符,在插入新字符时简单地向左移动字符可能足够有效 - 例如:

char buff[4] ;
for(;;)
{
    memset( buff, '0', sizeof(buff) - 1 ) ;

    char ch = 0 ;
    while( (ch != '!' )
    {   
        ch = UART_RxChar() ;
        if( isdigit(ch) )
        {
            // Shift left one digit
            memmove( buff, &buff[1], sizeof(buff) - 2 ) ; 

            // Insert new digit at the right
            buff[sizeof(buff) - 2] = ch ;
        }
        else if( ch != '!' )
        {
            // Unexpected character, reset buffer
            memset( buff, '0', sizeof(buff) - 1 ) ;
        }
    }

    UART_SendString( buff ) ;
    UART_SendString( "\n" ) ;
}

这还有一个优点,即当输入的数字小于三位数时它会起作用,并且会丢弃任何包含非数字字符的序列。

于 2019-07-07T08:04:06.540 回答