我想使用at atmega16接收UART的字符串(指向字符指针)。我在套件上刻录了此代码,然后我使用了Hyperterminal(实过程),并进行了测试以输入字符串(" ON"),并且如果收到它,则将Portc(LED)设置为1,但它不起作用。。 任何人!?:D
实施功能
#include <avr/io.h>
#define F_CPU 8000000UL
unsigned char *x;
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
void uartinit()
{
UCSRB |= (1 << RXEN) | (1 << TXEN);
// Turn on the transmission and reception circuitry
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
// Use 8-bit character sizes
UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value..
// into the low byte of the UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value..
// into the high byte of the UBRR register
}
void uartsend( unsigned char *data )
{
while(*data != ' ')
{
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) );
/* Put data into buffer, sends the data */
UDR = *data;
data++;
}
while ( !( UCSRA & (1<<UDRE)) );
UDR = *data;
}
unsigned char * uartrecieve()
{
//unsigned char i=0;
// unsigned char * x;
/* Wait for data to be received */
// char * ptr = &UDR;
while ( !(UCSRA & (1<<RXC)) );
while(UDR != ' ')
{
*x = UDR;
x++;
while ( !(UCSRA & (1<<RXC)) );
}
*x = UDR;
return x;
}
这是主要功能
#include <avr/io.h>
#include "UARTInterface.h"
int main(void)
{
DDRC=0xFF;
uartinit();
while(1)
{
unsigned char *y;
y=uartrecieve();
if(strcmp(y,"on")==0)
{
PORTC=0xff;
}
//uartsend(y);
//TODO:: Please write your application code
}
}
您的代码有一些问题:
1。您不是为接收的字符分配任何空间。您有一个全局的unsigned char *x
(未初始化),您将其取消并将值分配给,然后增加 - 这只是内存中覆盖随机位置。
您应该通过从调用函数创建数组(在这种情况下为main
),并将指针传递给uartreceive
以及缓冲区的大小
unsigned char y[20]; // in main
unsigned char len;
len = uartreceive(y, 20);
...
然后(请注意,未经测试)
unsigned char uartrecieve(unsigned char *x, unsigned char size)
{
unsigned char i = 0;
if (size == 0) return 0; // return 0 if no space
while (i < size - 1) { // check space is available (including additional null char at end)
unsigned char c;
while ( !(UCSRA & (1<<RXC)) ); // wait for another char - WARNING this will wait forever if nothing is received
c = UDR;
if (c == ' ') break; // break on NULL character
x[i] = c; // write into the supplied buffer
i++;
}
x[i] = 0; // ensure string is null terminated
return i + 1; // return number of characters written
}
每次调用此功能时,它都会覆盖RX_Buffer的先前内容,因此请确保您首先使用它。如果您不确定这里发生了什么,请阅读阵列,指针和字符串。
更好的是将指针传递给uartreceive
,以便调用功能可以提供内存区域
2。您的串行终端软件不太可能默认终止NULL终止字符串(即末尾使用' 0'),通常会发送new-line(' n')字符。我相信实士可以做到这一点,但值得检查。
3。从UDR读取将清除RXC标志,允许AVR将另一个字符写入UDR,因此连续两次从UDR读取可能是一个坏主意
ubbrl必须在ubrrh之后写入以确保原子操作(即:同时在波特速率下,复制完整的16位UBRR。这在Atmega Doc上显示(例如Atmega16 Doc http://ww1.microchip.com/downloads/en/devedoc/doc2466.pdf Page 168):
编写UBRR将触发Baud Rate Prescaler的立即更新Atmel示例以这种方式写
void USART_Init( unsigned int ubrr){
/* Set baud rate */
UBRRH = (unsigned char)(ubrr>>8);
**UBRRL = (unsigned char)ubrr;**
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN)|(1<<TXEN);
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}*
当您编写错误的订单(ubrrh上次)时,在下一个UBRRL写入之前,ubrrh不会更新。在大多数情况下,大部分时间都不会因为大多数时间(直到Baud&gt; 100bit/s)