【串口收发不定长数据】使用中断的方式—以AT32为例

使用中断方式

这种在数据接收不频繁状态下使用,简单易实现。

既然是使用中断,所以自然需要硬件的支持,比如AT32,stm32就可以这么做,关于USART具体的原理、配置及使用详见:
【雅特力AT32】串口入门实战:轮询、中断、SWAP(收发管脚交换)功能

关键代码
uint8_t Serial_RxFlag;		// 定义串口接收的标志位变量

char rxdata[20];			// 接收数据缓存区
uint8_t rx_dat;				// 接收字节转运
uint32_t rx_pointer;		// 缓存区指针

/**
  * 函    数:USART收发中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异且与使能函数对应,否则中断函数将不能进入卡死(特别注意接收中断使能后测试)
  * 		  USART_RDBF_FLAG		USART_TDC_FLAG
  */
void USART2_IRQHandler(void)
{
    if(usart_flag_get(MY_USART, USART_RDBF_FLAG) != RESET) 	// 接收数据缓冲区满标志
	{
		Serial_RxFlag = 1;
		
		/* 读取并存放数据寄存器的数据 */
		rx_dat = usart_data_receive(MY_USART);				
		rxdata[rx_pointer++] = rx_dat;						
	}
}

/**
  * 函    数:USART接收不定长数据并进行发送测试
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为USART接收数据的处理函数
  *           可以放在主函数测试,xcom发送任意信息,AT32接收后再转发给xcom
  *           注意测试字符串长度与temp的大小,可自定义更改
  */
void usart_proc(void)
{
	
	if(rx_pointer != 0)
	{	
		uint16_t rx_test = rx_pointer;		
		delay_ms(1);
		/* 确保数据包已传输完毕	*/
		if(rx_pointer == rx_test)		
		{
			/* 打印接收的数据 */
			Serial_SendArray((uint8_t *)rxdata, strlen(rxdata));

			/* 更新缓冲区及指针状态 */
			rx_pointer = 0;
			memset(rxdata,0,20);
		}
	}
}


完整代码

my_usart.c
以AT32为例,包括串口收发配置、中断接收;发送字符(串)、数组、数字的函数封装。

#include "my_usart.h"


uint8_t Serial_RxData;		// 定义串口接收的数据变量
uint8_t Serial_RxFlag;		// 定义串口接收的标志位变量

char rxdata[20];			// 接收数据缓存区
uint8_t rx_dat;				// 接收字节转运
uint32_t rx_pointer;		// 缓存区指针

#define MY_USART USART2

/**
  * @brief  config usart
  * @param  none
  * @retval none
  */
void usart_configuration(void)
{
	
  gpio_init_type gpio_init_struct;

  /* enable the usart2 and gpio clock */
  crm_periph_clock_enable(CRM_USART2_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

  gpio_default_para_init(&gpio_init_struct);

  /* configure the usart2 tx, rx pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = GPIO_PINS_2 | GPIO_PINS_3;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOA, &gpio_init_struct);
  gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE2, GPIO_MUX_7);	//tx
  gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE3, GPIO_MUX_7);	//rx

	/* config usart nvic interrupt */
  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  nvic_irq_enable(USART2_IRQn, 0, 0);

  /* configure usart2 param */
  usart_init(MY_USART, 115200, USART_DATA_8BITS, USART_STOP_1_BIT);	

  /* USART2 Send and receive enable */
  usart_transmitter_enable(MY_USART, TRUE);							
  usart_receiver_enable(MY_USART, TRUE);							

  /* enable usart2 and usart3 interrupt */
  usart_interrupt_enable(MY_USART, USART_RDBF_INT, TRUE);					

   usart_enable(MY_USART, TRUE);	

}


/**
  * 函    数:USART2收发中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异且与使能函数对应,否则中断函数将不能进入卡死(特别注意接收中断使能后测试)
  * 		  USART_RDBF_FLAG		USART_TDC_FLAG
  */
void USART2_IRQHandler(void)
{
    if(usart_flag_get(MY_USART, USART_RDBF_FLAG) != RESET) 	// 接收数据缓冲区满标志
	{
		Serial_RxFlag = 1;
		
		/* 读取并存放数据寄存器的数据 */
		rx_dat = usart_data_receive(MY_USART);				
		rxdata[rx_pointer++] = rx_dat;						
	}
}

/**
  * 函    数:USART接收不定长数据并进行发送测试
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为USART接收数据的处理函数
  *           可以放在主函数测试,xcom发送任意信息,AT32接收后再转发给xcom
  *           注意测试字符串长度与temp的大小,可自定义更改
  */
void usart_proc(void)
{
	
	if(rx_pointer != 0)
	{	
		uint16_t rx_test = rx_pointer;		
		delay_ms(1);
		/* 确保数据包已传输完毕	*/
		if(rx_pointer == rx_test)		
		{
			/* 打印接收的数据 */
			Serial_SendArray((uint8_t *)rxdata, strlen(rxdata));

			/* 更新缓冲区及指针状态 */
			rx_pointer = 0;
			memset(rxdata,0,20);
		}
	}
}




/**
  * 函    数:串口发送一个数组
  * 参    数:data 要发送数组的首地址
  * 参    数:size 要发送数组的长度
  * 返 回 值:无
  */
void UART_Write_Blocking(uint8_t* data,uint16_t size)
{
	uint16_t i = 0;
	while(usart_flag_get(MY_USART, USART_TDBE_FLAG) == RESET);		//传输数据缓冲区空标志
	usart_flag_clear(MY_USART, USART_TDBE_FLAG);
	
	for(i=0;i<size;i++)
	{
		usart_data_transmit(MY_USART, (uint16_t)data[i]);
		
		while(usart_flag_get(MY_USART, USART_TDC_FLAG) == RESET);
		usart_flag_clear(MY_USART,USART_TDC_FLAG);
	}
}

/**
  * 函    数:串口发送一个字节
  * 参    数:Byte 要发送的一个字节
  * 返 回 值:无
  */
void Serial_SendByte(uint8_t Byte)
{
	while(usart_flag_get(MY_USART, USART_TDBE_FLAG) == RESET);		//传输数据缓冲区空标志
	usart_flag_clear(MY_USART, USART_TDBE_FLAG);
	
	 usart_data_transmit(MY_USART, Byte);		
	
	while(usart_flag_get(MY_USART, USART_TDC_FLAG) == RESET);	//等待发送完成
	
	/*下次写入数据寄存器会自动清除发送完成标志位,故此循环后,无需清除标志位*/
	usart_flag_clear(MY_USART,USART_TDC_FLAG);
	
}

/**
  * 函    数:串口发送一个数组
  * 参    数:Array 要发送数组的首地址
  * 参    数:Length 要发送数组的长度
  * 返 回 值:无
  */
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
	uint16_t i;
	for (i = 0; i < Length; i ++)		
	{
		Serial_SendByte(Array[i]);		
	}
}

/**
  * 函    数:串口发送一个字符串
  * 参    数:String 要发送字符串的首地址
  * 返 回 值:无
  */
void Serial_SendString(char *String)
{
	uint8_t i;
	for (i = 0; String[i] != '\0'; i ++)
	{
		Serial_SendByte(String[i]);		
	}
}


/**
  * 函    数:次方函数(内部使用)
  * 返 回 值:返回值等于X的Y次方
  */
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result = 1;	
	while (Y --)			
	{
		Result *= X;	
	}
	return Result;
}

/**
  * 函    数:串口发送数字
  * 参    数:Number 要发送的数字,范围:0~4294967295
  * 参    数:Length 要发送数字的长度,范围:0~10
  * 返 回 值:无
  */
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i ++)		
	{
		Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');	
	}
}

测试效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值