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;
       //数据处理
}

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
第一讲:开发板和软件的操作使用 1、 介绍配件。 2、 安装软件(ICC AVRAVR STUDIO)及其使用,包括新建工程、程序下载,仿真调试;整板测试;板上资源。 3、 着重介绍一下USB接口的仿真器。 第二讲:AVR单片机的概述和C语言的基础知识 1、 AVR单片机的概述包括它的优点、片上资源。 2、 C语言的基础包括电平特性、2进制与16进制的表示及转换、二进制数的逻辑运算,数据类型,运算符。 3、 着重讲一下特有的BIT()操作,C中的各种语句。 4、 介绍一下AVR单片机IO口的配置。 第三讲:点亮发光二极管、驱动蜂鸣器、继电器 1、首先讲解一下原理图上开关电路、复位电路、时钟电路; 2、讲解573工作原理, 3、首先点亮一个发光二极管,然后让一个二极管亮灭变化。 4、编写函数证明573的工作原理:锁住后不导通就不能再更新数据。 5、编写延时函数,软件仿真查看延时的精确时间 6、子函数的编写(分带形参和不带形参)。 7、编写流水灯函数。 8、蜂鸣器,继电器的工作原理并编写程序。 第四讲:数码管工作原理 1、 共阴共阳数码管内部结构,显示原理。 2、 用数字万用表标定数码管的段选和位选 3、 编写程序使1个数码管上显示数字 4、 编写程序在6个数码管上滚动显示数字 5、 重点讲解动态显示,保持时间,以及扫描频率对闪烁和亮暗程度的影响。 第五讲:键盘检测原理(比较复杂) 1、 键盘作用,检测原理,如何消抖,独立键盘检测程序编写。 2、 矩阵键盘检测程序编写,涉及到返回值函数调用。 第六讲:1602液晶的使用 1、 看手册,管脚、写指令和数据、时序图。 2、 编写程序,显示光标 3、 编写程序显示字, 4、 编写程序,滚动显示字符 第七讲:中断、定时器的原理和应用(比较复杂) 1、 中断的概念,AVR单片机的中断 2、 定时/计数器1几种模式的寄存器配置 3、 定时器1普通模式下实现秒表 4、 CTC模式输出方波 5、 快速PWM模式输出PWM信号 6、 相位修正PWM模式输出PWM信号 第八讲:AD、DA简介及其应用 1、 AD简介,AVR内部AD寄存器设置 2、 编写程序控制AD读写电位器输出的模拟电压 3、 SPI串行通信简介 4、 DA简介,AD5300时序图 5、 编写程序控制DA输出模拟电压使发光二极管亮度变化 第九讲:TWI(IIC) 1、 TWI(IIC)协议简介 2、 AVR单片机内部TWI寄存器简介,操作流程 3、 具有IIC协议的数字电位器芯片AD5161的简介 4、 编写程序用独立键盘控制AD5161输出不同的阻值 第十讲:异步串口UART的简介和程序的编写 1、 UART简介 2、 AVR单片机内部与UART相关的寄存器的配置 3、 编写程序控制AVR单片机和电脑进行通信 4、 讲解串行通信时数字和字符之间的区别 第十一讲:PS2键盘、DS1302的工作原理和程序的编写 1、 AVR单片机外部中断的介绍 2、 PS2键盘的工作原理 3、 编写程序读取PS2键盘的按键值并在1602液晶上显示 4、 DS1302的工作原理 5、 编写程序控制1302工作并在1602液晶上显示时间

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值