这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 物联网技术 » 【武汉芯源CW32】OTA升级系列之七串口空闲中断实现不定长接收

共6条 1/1 1 跳转至

【武汉芯源CW32】OTA升级系列之七串口空闲中断实现不定长接收

助工
2024-10-11 11:43:36     打赏

【前言】

在前一篇:【武汉芯源CW32】OTA升级系列之三串口驱动-电子产品世界论坛 (eepw.com.cn)

我分享了如何驱动串口,如果需要用到升级固件,或者是AT等非固定长度的数据交互,那收就需要实现不定长度的接收,并实现串口空闲中断来实现功能。由于CW32L083串口外设中没有串口空闲的中断,所以需要使用普通定时器+接收中断来实现空闲中断。

【程序设计】

1、开启串口中断,在接收到一个Byte后产生中断回调。

2、配置一个普通定时器中断,中断触发为10ms,在串口中断回调函数中启动定时器中断,如果产生溢出,说明产生了空闲中断。

3、在定时器中断回调函数中,把接收到缓冲区的位置处理并记录。来实现各个帧数据的标志。

【代码实现】

1、创建一个数组,用于存放串口接收的Buff。

2、创建两个结构体,一个为存放一帧数据的起始位与结束位置。

/* 用于存放一帧数据指向的起始位置,与结束位置 */
typedef struct{
	uint8_t start;
	uint8_t end;
}UCB_URxBuffptr;
	

typedef struct{
	uint32_t URxCounter;
	UCB_URxBuffptr URxDataPtr[U1_RX_NUM];
	uint8_t IN;
	uint8_t OUT;
	uint8_t MAX;
}UCB_CB;


extern volatile uint8_t U1_RxBuff[U1_RX_SIZE];
extern UCB_CB UCB_UART1;

3、创更新串口初始化函数,初始化接收结构体,接收标志位初始到接收缓冲的首位,同时清空接收缓冲。使能串口接收中断。

		/* 接收Buff初始化 */
		
		//memset(&UCB_UART1,0,sizeof(UCB_UART1));
		UCB_UART1.IN = 0;                     /* 将接收初始体指定接收缓冲区地始地址 */ 
		
		UCB_UART1.OUT = 0;                     /* 将处理初始体指定接收缓冲区地始地址 */     
		UCB_UART1.MAX = U1_RX_NUM;
		UCB_UART1.URxCounter = 0;   
		
		//优先级,无优先级分组
    NVIC_SetPriority(UART1_UART4_IRQn, 0);
    //UARTx中断使能
    NVIC_EnableIRQ(UART1_UART4_IRQn);
		UART_ITConfig(CW_UART1, UART_IT_RC, ENABLE);

4、编写串口接收回调函数,接收到一个字节后,把他存入缓存,并称位接收标志,同时开启定时器标志。

void UART1_Call_Back(void)
{
		uint8_t rx_data;
    if(UART_GetITStatus(CW_UART1, UART_IT_RC) !=RESET)
    {
        rx_data=UART_ReceiveData_8bit(CW_UART1);
        if(UCB_UART1.URxCounter<U1_RX_SIZE)
        {
					  U1_RxBuff[UCB_UART1.URxCounter] = rx_data;

        }
        else
        {
						UCB_UART1.URxCounter = 0;
        }
				 CW_GTIM1->CR0_f.EN=0;
         CW_GTIM1->ARR=40000-1;
         CW_GTIM1->CR0_f.EN=1;
        UCB_UART1.URxCounter++;
        UART_ClearITPendingBit(CW_UART1, UART_IT_RC);
    }
	
}

5、编写定时器中断,当定时器中断到达时,表示串口接收一帧数据到位,把接收到的结束地址放入结构体中,同时更新下一个开始接收的地址。

void GTM_UART1_Call_Back(void)
{
		if(GTIM_GetITStatus(CW_GTIM1, GTIM_IT_OV))
    {
        GTIM_ClearITPendingBit(CW_GTIM1, GTIM_IT_OV);
        UCB_UART1.URxDataPtr[UCB_UART1.IN].end = UCB_UART1.URxCounter-1;     
	
				UCB_UART1.IN ++;                                           
				if(UCB_UART1.IN == UCB_UART1.MAX){                   
					UCB_UART1.IN = 0;
					}
		}
		

	if(U1_RX_SIZE - UCB_UART1.URxCounter >= U1_RX_MAX)                
	{
		UCB_UART1.URxDataPtr[UCB_UART1.IN].start = UCB_UART1.URxCounter;
	}
	else{
	//	__NVIC_DisableIRQ(UART1_UART4_IRQn);
		UCB_UART1.URxDataPtr[UCB_UART1.IN].start =0;
		UCB_UART1.URxCounter = 0;
	//	NVIC_EnableIRQ(UART1_UART4_IRQn);
	}
	
}

6、测试代码,在测试代码中,首先判断接收与处理标志位是否一致,如果不一样,说明还有未处理的数据,使用串口回调输出:

		if(UCB_UART1.OUT != UCB_UART1.IN)
		{
			CW_U1_printf("本次接收到了%d字节数据\r\n",UCB_UART1.URxDataPtr[UCB_UART1.OUT].end - UCB_UART1.URxDataPtr[UCB_UART1.OUT].start +1);
			for(i=0;i<UCB_UART1.URxDataPtr[UCB_UART1.OUT].end - UCB_UART1.URxDataPtr[UCB_UART1.OUT].start +1;i++)
			{
				CW_U1_printf("%c",U1_RxBuff[UCB_UART1.URxDataPtr[UCB_UART1.OUT].start+i]);
			}
			CW_U1_printf("\r\n");
			UCB_UART1.OUT ++;
			if(UCB_UART1.OUT == UCB_UART1.MAX)
			{
				UCB_UART1.OUT = 0;
			}
		}
	}

使用串口发送,进行测试,结果如下:

image.png

【讨论】

CW32L083没有串口空闲中断,使用定时器中断进行配置可以实现“空闲中断”,能如期实现即定的需求。




关键词: 武汉     芯源     串口     空闲     中断     不定     接收    

专家
2024-10-11 14:39:12     打赏
2楼

谢谢分享


专家
2024-10-11 21:36:00     打赏
3楼

感谢分享


专家
2024-10-11 21:52:59     打赏
4楼

感谢分享


工程师
2024-10-12 09:19:18     打赏
5楼

感谢分享


院士
2024-10-13 15:37:26     打赏
6楼

学习了,谢谢分享。


共6条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]