如何使用ATmega16微控制器从HC05蓝牙模块接收字符串
How to receive strings from HC05 Bluetooth module using ATmega16 microcontroller
我在接收从 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" );
}
}
}
预期的结果是当我在串行监视器应用程序中输入数字时,我应该在串行监视器应用程序中返回相同的数字。
在实际结果中,我有时会得到不同的字符,有时会出现空白。
字符串 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>...
您的接收循环将不同步。
一个更安全的解决方案是在收到 '!'
个字符时使用先前收到的 三个 个字符。这可以通过多种方式完成——对于长缓冲区,建议使用 ring-buffer,但对于仅三个字符,在插入新字符时简单地向左移动字符可能就足够有效了——例如:
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" ) ;
}
这还有一个好处,当输入的数字少于三位数字时它会起作用,并且会丢弃任何包含 non-digit 个字符的序列。
我在接收从 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" );
}
}
}
预期的结果是当我在串行监视器应用程序中输入数字时,我应该在串行监视器应用程序中返回相同的数字。
在实际结果中,我有时会得到不同的字符,有时会出现空白。
字符串 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>...
您的接收循环将不同步。
一个更安全的解决方案是在收到 '!'
个字符时使用先前收到的 三个 个字符。这可以通过多种方式完成——对于长缓冲区,建议使用 ring-buffer,但对于仅三个字符,在插入新字符时简单地向左移动字符可能就足够有效了——例如:
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" ) ;
}
这还有一个好处,当输入的数字少于三位数字时它会起作用,并且会丢弃任何包含 non-digit 个字符的序列。