AVR串口 自定义printf

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;
			// %c
			case '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;
       //数据处理
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值