AVR串口 自定义printf

来源:互联网 发布:金蝶软件版本号 编辑:程序博客网 时间:2024/05/16 06:28

AVR串口

芯片:ATmega168P

晶振:8M

 

两种方法:

方法一:

1.   使用<stdio.h>定义的scanf和printf()输入输出数据

优点:使用非常方便

缺点:占用ROM和RAM空间比较多

(1)定义输入输出函数

#include <stdio.h>// 从串口输出一个字符static int uart_putchar(char c, FILE *stream){ if (c == '\n') uart_putchar('\r', stream); loop_until_bit_is_set(UCSR0A, UDRE0); UDR0 = c; return 0; }// 从串口输入一个字符static char uart_getchar(FILE *stream){loop_until_bit_is_set(UCSR0A, RXC0);return UDR0;}

(2)定义IO

这一句是关键


FILE uartio = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW); 

(3)设置波特率

// 波特率#define BAUD 9600#include <util/setbaud.h>

(4)初始化串口

stdout = &uartio;这一句比较重要

// 串口初始化void UartInit(){       cli();        /* 设置波特率 */       UBRR0H=UBRRH_VALUE;       UBRR0L=UBRRL_VALUE;        /* 接收器与发送器使能, 中断接收数据 */       UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);        /* 设置帧格式: 8 个数据位, 1个停止位 */       UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);             stdout = &uartio;             sei();}

(5)串口输入输出

//输出:printf("%d", 123);//输入://输入时,程序会停在scanf,等待从串口输入数据scanf("%c", &temp);

方法2:

2.自定义printf()

优点:占用ROM和RAM相对第一种方法少了很多

缺点:要自定义printf函数

 

(1)定义输出函数

// 输出一个字符static void uart_putchar(char c){       loop_until_bit_is_set(UCSR0A, UDRE0);       UDR0 = c;}

(2)设置波特率

同方法1

(3)初始化串口

同方法1

只是少了stdout = &uartio;这一句

(4)定义uart_printf()

// 从串口输出字符串,参数可变void uart_printf(const char *fmt, ...){    const char *s;    int d;char c;    char buf[6];    va_list ap;// 使ap指向fmt参数的下一个参数    va_start(ap, fmt);    while (*fmt) {        if (*fmt != '%') {            uart_putchar(*fmt++);            continue;        }        switch (*++fmt) {// %s            case 's':// 把参数按const char *型取出来,同时ap指向下一个参数                s = va_arg(ap, const char *);                for ( ; *s; s++) {                    uart_putchar(*s);                }                break;// %d            case 'd':                d = va_arg(ap, int);                itoa(d, buf, 10);                for (s = buf; *s; s++) {                    uart_putchar(*s);                }                break;// %ccase 'c':// Default Argument Promotion// 形参列表中有...,实参的char类型被提升为int型c = (char)va_arg(ap, int);uart_putchar(c);break;                 default:                  uart_putchar(*fmt);                break;        }        fmt++;    }    va_end(ap);}

当然也可以在uart_printf中使用更简洁的语句实现,如:

va_start(ap, fmt);vsprintf(buf, fmt, ap);va_end(ap);uart_putstr(buf);

但这样占用的ROM和RAM空间同样会占用较多


(5)中断接收数据

// 串口接收中断服务程序ISR(USART_RX_vect){       char val;             val = UDR0;       //数据处理}

 

原创粉丝点击