AtmelStudio 7 ASF库学习笔记二:串口收发和printf打印

3 篇文章 0 订阅
2 篇文章 8 订阅

一、前言

这篇文章主要实现了串口单字节发送、printf格式化发送和通过接收中断接收数据。

用到的工具如下:

IDE:AtmelStudio 7

芯片:ATSAM4LS2C (M4内核,主频48M)

ASF版本:3.47

仿真器:JLink v9

 

二、串口初始化

2.1 ASF添加USART-Serial interface和Standard serial I/O 模块

2.2 官网找到串口的快速开发指南

https://asf.microchip.com/docs/latest/sam4l/html/serial_quickstart.html

2.3 根据快速指南的说法,通常将配置放在conf_uart_serial.h里

打开conf_uart_serial.h,添加配置代码,我们这里用串口0,波特率9600,数据宽度8位等等,如下:

#define USART_SERIAL                 USART0				//串口0
#define USART_SERIAL_BAUDRATE        9600				//波特率
#define USART_SERIAL_CHAR_LENGTH     US_MR_CHRL_8_BIT	//数据位8位
#define USART_SERIAL_PARITY          US_MR_PAR_NO		//无奇偶校验
#define USART_SERIAL_STOP_BIT        US_MR_NBSTOP_1_BIT	//1位停止位

#define USART_SERIAL_RX_PIN                PIN_PA11A_USART0_RXD//接收引脚
#define USART_SERIAL_RX_MUX                MUX_PA11A_USART0_RXD//复用Usart0接收

#define USART_SERIAL_TX_PIN                PIN_PA12A_USART0_TXD//发送引脚
#define USART_SERIAL_TX_MUX                MUX_PA12A_USART0_TXD//复用Usart0发送

串口0引脚复用PA11和PA12,可以在数据手册里的GPIO功能复用表里查到。

2.4 打开main.c,添加初始化代码,usart_options 变量用到上面定义的配置,串口初始化函数用stdio_serial_init而不是usart_serial_init,这样可以重定向printf。

#include <asf.h>

#define NVIC_PriorityGroup_2         ((uint32_t)0x5) /*!< 2 bits for pre-emption priority   2 bits for subpriority */

int main (void)
{
	/* Insert system clock initialization code here (sysclk_init()). */
	sysclk_init();
	board_init();
	delay_init();
	NVIC_SetPriorityGrouping(NVIC_PriorityGroup_2);	//中断分组2 2位抢占,2位响应
	/* Insert application code here, after the board has been initialized. */
	
	//配置TX端口模式
	ioport_set_pin_mode(USART_SERIAL_TX_PIN, USART_SERIAL_TX_MUX);
	ioport_disable_pin( USART_SERIAL_TX_PIN);//关闭普通io功能
	//配置RX端口模式
	ioport_set_pin_mode( USART_SERIAL_RX_PIN,  USART_SERIAL_RX_MUX);
	ioport_disable_pin( USART_SERIAL_RX_PIN);
	
	//串口配置选项
	usart_serial_options_t usart_options = {
		.baudrate = USART_SERIAL_BAUDRATE,		//波特率
		.charlength = USART_SERIAL_CHAR_LENGTH,	//数据位宽
		.paritytype = USART_SERIAL_PARITY,		//奇偶校验
	.stopbits = USART_SERIAL_STOP_BIT};			//停止位
	
	//usart_serial_init(USART_SERIAL, &usart_options);//只是初始化串口
	// 初始化串口,重定向printf
	stdio_serial_init(USART_SERIAL, &usart_options);
	//串口0总中断 抢占优先级0,响应优先级0
	NVIC_SetPriority(USART0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
	//使能USART0总中断
	NVIC_EnableIRQ(USART0_IRQn);
	//使能串口0接收中断
	usart_enable_interrupt(USART_SERIAL, US_IER_RXRDY);
	//使能发送
	usart_enable_tx(USART_SERIAL);
	//使能接收
	usart_enable_rx(USART_SERIAL);
	
	while(1)
	{

	}
}

三、串口发送

3.1 添加发送代码,usart_putchar函数是单字节发送,printf可以格式化打印数据,下载到板上,顺利的话能看到串口发出的数据:

	while(1)
	{
		usart_putchar(USART_SERIAL,'a');//单字节输出
		usart_putchar(USART_SERIAL,'\r');
		usart_putchar(USART_SERIAL,'\n');
		printf("%s:%0d\r\n","printf输出", 123);//格式化输出
		delay_ms(500);
	}

3.2 printf格式化输出浮点数可能会出错,例如代码:

		printf("%0.2f\r\n",12.3f);

会显示f:

到社区搜索一下,原来是工具链里面优化了,变成调用整型输出了。右击工程属性->Toolchain->ARM/GNU C Compiler->Symbols,找到scanf=iscanf和printf=iprintf删除,重新编译再试就可以了。

四、串口接收

4.1 先定义一个接收fifo结构体变量

#define TX_BUFFER_SIZE 128		//发送缓存长度
#define RX_BUFFER_SIZE 128		//接收缓存长度
//串口收发fifo
typedef struct  
{

	//volatile uint16_t  rxcount;                  // 接收计数
	volatile uint16_t  rxindex;                 	// 接收指针
	volatile uint16_t  rdindex;                 	// 读指针

	volatile uint8_t  txcount;                	// 发送计数
	volatile uint8_t  txindex;                	// 发送指针
	volatile uint8_t  wrindex;                	// 写指针

	volatile uint8_t  txsbuf[TX_BUFFER_SIZE];  // 发送数据缓冲区
	volatile uint8_t  rxsbuf[RX_BUFFER_SIZE];  // 接收数据缓冲区
} Uart_fifo;

Uart_fifo uart_fifo;//

4.2 编写串口0中断函数,初始化串口时使能了接收中断,所以当RXRDY为1时会触发接收中断,获取收到的字符可以用usart_getchar库函数,但是里面有个while,这里我们为了防止未知错误导致死循环,直接读取数据寄存器RHR,并且读完会自动清除RXRDY位,不用手动清除。

//串口0中断函数
void USART0_Handler(void)
{
	U32 u32_uart_status = usart_get_status(USART_SERIAL);
	/*-------------------------     接收中断处理	------------------------------*/
		
	if (u32_uart_status & US_CSR_RXRDY)//判断接收标志
	{
		//usart_getchar(USART_SERIAL,&uart_fifo.rxsbuf[uart_fifo.rxindex]);
		uart_fifo.rxsbuf[uart_fifo.rxindex] = (USART0->US_RHR & US_RHR_RXCHR_Msk);//读取数据,会自动清除接收标志

		if (++uart_fifo.rxindex==RX_BUFFER_SIZE) 						//接收指针到末尾
		{
			uart_fifo.rxindex=0; 										//指针置0,从头开始
		}	
		if(uart_fifo.rxindex>=3)
		{
			Rx_Process();//接收处理
		}
	}
}

4.3 接收处理,接收到3个字符以上开始判断指令,并回复。

//接收处理
void Rx_Process(void)
{
	if(uart_fifo.rxsbuf[0]==0xAA && uart_fifo.rxsbuf[1]==0x01 && uart_fifo.rxsbuf[2]==0x01)
	{
		printf("开灯\r\n");
	}
	else if(uart_fifo.rxsbuf[0]==0xAA && uart_fifo.rxsbuf[1]==0x01 && uart_fifo.rxsbuf[2]==0x00)
	{
		printf("关灯\r\n");
	}
	else
	{
		printf("错误\r\n");
	}
	
	uart_fifo.rxindex=0; 										//指针置0,从头开始
	
}

4.4 效果:

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哀歌与世无争

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值