Как получить строки из модуля Bluetooth HC05 с помощью микроконтроллера ATmega16 - PullRequest
0 голосов
/ 06 июля 2019

У меня проблема с получением строки из HC05 в ATmega16. Я могу получать символы, но не могу получать строки.

Я хочу управлять двигателем постоянного тока по беспроводной сети с помощью модуля ATmega16 и Bluetooth (HC05). Я отправляю значения таймера OCR1A из приложения последовательного монитора в ATmega16 по HC05, но не удалось.

#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" );
        }
    }
}

Ожидаемый результат: когда я ввожу номер в приложение последовательного монитора, я должен получить тот же номер в приложении последовательного монитора.

В реальных результатах я иногда получаю разные символы и иногда пустую.

1 Ответ

0 голосов
/ 07 июля 2019

Строка buff не определена, поэтому UART_SendString( buff ); будет отправлять любой мусор после полученных трех символов, пока не будет найден байт NUL (0).

char buff[4] = {0};

Будет место для NUL иинициализация гарантирует, что buff[3] является терминатором NUL.

В качестве альтернативы, отправьте три символа по отдельности, поскольку без терминатора они не составляют действительную строку C (ASCIIZ).

Помимоотсутствие нулевого завершения, ваш код требует ввода точно в форме 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" ) ;
}

Это также имеет то преимущество, что оно будет работать, когда введенный номер меньше трех цифр, и будет отбрасывать любую последовательность, содержащую нецифровые символы.

...