S32K144芯片,串口(lpuart)中断接收不到数据问题。s32k144模拟空闲中断

问题描述:

  1. 接收中断每次接收1个字节,在一次性收到多个字节的数据时,会出现进入不了接收中断的问题。 
  2. 接收与发送同时触发时,导致接收的字节出现错误。 

问题解决:

对比与stm32的空闲中断,判断从机报文发送结束芯片进入中断。这样就可以保证不需要每次有数据过来都进入一次中断,只需要数据接收完毕处理一次即可。

先配置串口驱动,我这里使用lpuart,对于传输类型使用中断还是DMA,我认为都可以,但是DMA需要确定数组大小。我使用的是中断

 初始化串口,并安装中断回调函数。接收中断RS485_URT_RX_ISR 中,如果接收字节超过256,会触发接收满事件,这时候截断后面的数据重新接收。其中mb_rtu1.mb_adu_buff为接收的数组。

//缓存大小
#define MB_ADU_BUFF_SIZE 256
uint8_t mb_adu_buff[MB_ADU_BUFF_SIZE];

void RS485_URT_RX_ISR (void *driverState, uart_event_t event, void *userData)
{
	(void) driverState;
	(void) userData;

	//串口接收缓存满事件
	if(event == UART_EVENT_RX_FULL)
	{
		LPUART_DRV_AbortReceivingData(INST_RS485_LPUART);
		//等待发送完成
	    if (LPUART_DRV_GetTransmitStatus(INST_RS485_LPUART, &rs485_bytesRemaining) != STATUS_BUSY)
	    {
			LPUART_DRV_ReceiveData(INST_RS485_LPUART, mb_adu_buff, MB_ADU_BUFF_SIZE);
	    }
	    else
	    {
	    	//清除中断标志位并重新开始接收串口数据
	    	LPUART_DRV_ReceiveData(INST_RS485_LPUART, mb_adu_buff, MB_ADU_BUFF_SIZE);
	    }


	}
	else if(event == UART_EVENT_ERROR)//接收模式进的错误
	{
		LPUART_DRV_ReceiveData(INST_RS485_LPUART, mb_adu_buff, MB_ADU_BUFF_SIZE);
	}
	else
	{

	}

}

//uart485发送完成产生中断
void RS485_URT_TX_ISR (void *driverState, uart_event_t event, void *userData)
{
	(void) driverState;
	(void) userData;

	//发送完成
	if(event==UART_EVENT_END_TRANSFER)
	{
		LPUART_DRV_ReceiveData(INST_RS485_LPUART, mb_adu_buff, MB_ADU_BUFF_SIZE);
	}

}
void uart_Init(void)
{

	LPUART_DRV_Init(INST_RS485_LPUART, &rs485_lpuart_State, &rs485_lpuart_InitConfig0); //初始化串口
	LPUART_DRV_InstallTxCallback(INST_RS485_LPUART,RS485_URT_TX_ISR, NULL);//安装发送中断回调函数
	LPUART_DRV_InstallRxCallback(INST_RS485_LPUART,RS485_URT_RX_ISR, NULL);//安装接收中断回调函数

	LPUART_DRV_ReceiveData(INST_RS485_LPUART, mb_adu_buff, MB_ADU_BUFF_SIZE); //开启串口接收,每次接收一个字节,并安装中断

	INT_SYS_SetPriority(LPUART2_RxTx_IRQn,configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);

}

接收和发送中断写好,如何判断从机数据发送结束是一个问题。通过读UART寄存器的空闲标志位可以判断从机是否发送结束。空闲函数判断LPUART的STAT寄存器中空闲标志位来确定。并且通过LPUART_DRV_GetReceiveStatus函数可以确定本次数据还剩多少字节,定义的总字节数减去获取到的该值可得出数据一共接收了多少字节。最后重启接收就可以了。

void MB_IT_IDLE_IQR(MB_RCB_T * const p_mb_rtu)
{
	uint32_t empty_size = 0;
    uint8_t adu_buff_pos = 0;
	//读寄存器空闲标志位触发
	if((LPUART2->STAT >> 20 & 0x01))
	{
		LPUART2->STAT |= 0<<20;
		LPUART_DRV_GetReceiveStatus(INST_RS485_LPUART,&empty_size);
		adu_buff_pos = MB_ADU_BUFF_SIZE - empty_size;

        //增加信号量
		if(xSemaphore != NULL)
		{
			xSemaphoreGive(xSemaphore);
		}

		LPUART_DRV_SetRxBuffer(INST_RS485_LPUART,mb_adu_buff, MB_ADU_BUFF_SIZE);
		LPUART_DRV_ReceiveData(INST_RS485_LPUART, mb_adu_buff, MB_ADU_BUFF_SIZE);
	}
}

空闲函数放到一个任务或者定时器中,轮询空闲标志位是否触发。我使用信号量同步其他任务来处理报文。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值