繁体   English   中英

从 AVR 的 UART 接收 char *

[英]receiving char * from UART of AVR

我想使用 ATMEGA16 通过 UART 接收一个字符串(指向字符的指针)。 我在套件上刻录了这段代码,然后我使用超级终端 (realterm) 并进行了输入字符串 ("on") 的测试,如果收到它,则 portc (LEDS) 将设置为 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 != '\0')
    {
        /* 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 != '\0')
    {
        *x = UDR;
        x++;
        while ( !(UCSRA & (1<<RXC)) );
    }
    *x = UDR;

     return x;
} 

这是主要的 function

#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 == '\0') 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'),通常它会发送一个换行符('\\ n')。 我相信realterm可以做到这一点,但值得检查。

3.从UDR读取将清除RXC标志,允许AVR将另一个字符写入UDR,因此连续两次从UDR读取可能是一个坏主意

UBBRL 必须在 UBRRH 之后写入以确保原子操作(即:在波特率除数上同时复制 ubrr 的完整 16 位。这在 ATMega 文档上有说明(例如 ATMEGA16 doc 882541222744288://ww1.microchip.com/downloads /en/devicedoc/doc2466.pdf第 168 页):

写 UBRRL 会触发波特率预分频器的立即更新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 最后),UBRRH 直到下一次 UBRRL 写时才会更新。 大多数时间并不重要,因为大多数时间 UBRRH = 0(直到 BAUD > 100bit/s)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM