如何使用ATmega16微控制器从HC05蓝牙模块接收字符串

时间:2019-07-06 13:14:55

标签: embedded iot c-strings usart atmega16

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

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

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

1 个答案:

答案 0 :(得分:0)

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

char buff[4] = {0};

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

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

除了缺少nul终止之外,您的代码还要求以<{> 1}形式精确地输入 。如果另一端实际上正在发送带有CR或CR + LF终结器的{em> lines -nnn!nnn!nnn!...,则您的接收循环将不同步。

一种更安全的解决方案是,每当收到nnn!<newline>nnn!<newline>nnn!<newline>...字符时,都使用先前接收的三个字符。这可以通过多种方式完成-对于长缓冲区,建议使用环形缓冲区,但是对于三个字符,插入一个新字符时仅向左移动字符可能就足够有效了-例如:

'!'

这还具有以下优点:当输入的数字少于三位数字时,它将起作用,并且将丢弃任何包含非数字字符的序列。