LIN slave

该代码展示了LIN从机的初始化过程,包括UART配置、GPIO设置和中断处理。在接收到数据时,会触发中断并在`UartLIN_Handler`中处理,如检查同步字段、接收PID和数据段,并计算校验和。当接收到特定的PID时,从机会进入接收或发送数据的状态。
摘要由CSDN通过智能技术生成

void LIN_Slave_init(void)//LINslave初始化
{
	UART_ConfigType uartConfig;
	uint8_t linCtrl = 0;
	memset((void *)&uartConfig, 0, sizeof(UART_ConfigType));
	///Init GPIO
	GPIO_SetFunc(SWLIN_RX, RXPinFunc);
	GPIO_SetFunc(SWLIN_TX, TXPinFunc);
	GPIO_SetDir(SWLIN_SLP, GPIO_OUT);
	GPIO_SetPinLevel(SWLIN_SLP, GPIO_LEVEL_HIGH);
	uartConfig.baudrate = 19200;
	uartConfig.dataBits = UART_WORD_LEN_8BIT;
	uartConfig.stopBits = UART_STOP_1BIT;
	uartConfig.parity = UART_PARI_NO;
	uartConfig.dmaEn = UART_DMA_TXRX_NONE;
	uartConfig.fifoByteEn = ENABLE;
	uartConfig.sampleCnt = UART_SMP_CNT0;   ///<must set UART_SMP_CNT0 when use LIN function
	uartConfig.callBack = &UartLIN_Handler;
	UART_Init(UART_LIN, &uartConfig);   ///<Init UART

	// Set master or slave mode
	//g_mode = mode;
	g_state = LIN_STATE_IDLE;
	//g_schTblIdx = schTblIdx;

	linCtrl = UART_LINCR_LINEN_Msk | UART_LINCR_LBRKIE_Msk | (g_breakThre ? UART_LINCR_LBRKDL_Msk : 0) | (g_autoBaud ? UART_LINCR_LABAUDEN_Msk : 0);
	UART_SetLIN(UART_LIN, linCtrl);
	// Enable interrupt
	UART_SetRXNEInterrupt(UART_LIN, ENABLE);
	UART_SetTXEInterrupt(UART_LIN, DISABLE);//不使tx保持空中断
	NVIC_ClearPendingIRQ(UART_LIN_IRQn);
	NVIC_EnableIRQ(UART_LIN_IRQn);
}

LIN初始化

每收到一个字节数据都产生中断

void UartLIN_Handler(void *device, uint32_t wpara, uint32_t lpara)
{
	//printf("UartLIN_Handler\r\n");
	// Receive break field
	if (0 != (lpara & UART_LSR1_FBRK_Msk))
	{
		LIN_IfcAux();
		UART_LIN->LSR1 |= UART_LSR1_FBRK_Msk;   ///<write 1 to clear break status
	}
	// Receive data
	if (0 != (wpara & UART_LSR0_DR_Msk))
	{
		LIN_IfcRx();
	}
	// Transmit data done
	if (0 != (wpara & UART_LSR0_THRE_Msk))
	{
		LIN_IfcTx();
	}
}

 收到break field段后进中断,进入第一个if,在LIN_IfcAux中将标志从初始置为LIN_STATE_RECEIVE_SYNC,那么下一次收到中断将进入LIN_IfcRx()

void LIN_IfcAux(void)
{
	printf("LIN_Handler1\r\n");
	if (g_state == LIN_STATE_IDLE)
	{
		g_state = g_autoBaud ? LIN_STATE_RECEIVE_IDENTIFIER : LIN_STATE_RECEIVE_SYNC;
		//g_direction = DIR_RX;
		//g_txCount = 0;
		g_rxCount = 0;
	}
	else
	{
		printf("Frame err\r\n");
		g_state = g_autoBaud ? LIN_STATE_RECEIVE_IDENTIFIER : LIN_STATE_RECEIVE_SYNC;
		//g_direction = DIR_RX;
		//g_txCount = 0;
		g_rxCount = 0;
	}
	if (g_state == LIN_STATE_SEND_BREAK)
	{
		g_state = LIN_STATE_SEND_SYNC;
		UART_SetTXEInterrupt(UART_LIN, ENABLE);//使tx保持空中断
	}
}

void LIN_IfcRx(void)
{
	uint8_t data = 0, id = 0, index = 0, checksum = 0, frameNum = 0;
	data = UART_ReceiveData(UART_LIN);
	//printf("LIN_Handler2 data=0x%02x\r\n", data);
	if (g_state == LIN_STATE_RECEIVE_SYNC)
	{
		// Check sync field
		if (data == 0x55)
		{
			g_state = LIN_STATE_RECEIVE_IDENTIFIER;
			//printf("LIN_Handler2 0x55\r\n");
		}
		else
		{
			g_state = LIN_STATE_IDLE;
			//printf("Sync err\r\n");
		}
	}
	else if (g_state == LIN_STATE_RECEIVE_IDENTIFIER)
	{
		// Check protect id
		id = data & 0x3F;
		uint8_t check_pid = LIN_MakeProtId(id);
		//printf("LIN_Handler2 id=0x%02x, check_pid=0x%02x\r\n", id, check_pid);
		if(data == check_pid && id == 0x05)
		{
			g_state = LIN_STATE_RECEIVE_DATA;
		}
		else if (data == check_pid && id == 0x10)
		{
			g_state = LIN_STATE_SEND_DATA;

		}
		else
		{
			g_state = LIN_STATE_IDLE;
			//printf("Pid err\r\n");
		}
	}
	else if (g_state == LIN_STATE_RECEIVE_DATA)
	{
		//printf("LIN_Handler2 g_rxCount=0x%02x\r\n", g_rxCount);
		if (g_rxCount < 8)
        {
            g_buffer[g_rxCount] = data;
            g_rxCount++;
        }
		// Receive frame done
		if (g_rxCount >= 8)
		{
			printf("Receive frame done\r\n");
			for(int k = 0; k < 8;k++ )
			{
				printf(" %02x ", g_buffer[k]);
			}
			printf("\r\n");
			g_state = LIN_STATE_IDLE;
		}
	}

	if(g_state == LIN_STATE_SEND_DATA)
	{
		//UART_SendData(UART_LIN, 0x55);
		//UART_SendData(UART_LIN, LIN_MakeProtId(0x10));
		checksum = LIN_MakeChecksum( LIN_MakeProtId(0x10), 8, g_buffer);
		for(int k = 0; k<8; k++)
		{
			UART_SendData(UART_LIN, g_buffer[k]);
		}
		UART_SendData(UART_LIN, checksum);
		printf("checksum = %x\r\n",checksum);
		printf("Send frame done\r\n");

        g_state = LIN_STATE_IDLE;
	}

}

通过data = UART_ReceiveData(UART_LIN);获得收到的一字节数据

接收到同步段0x55后,在LIN_IfcRx中,状态为LIN_STATE_RECEIVE_SYNC时检测同步段,即0x55,此后标志置为LIN_STATE_RECEIVE_IDENTIFIER

收到PID,在LIN_IfcRx中,状态置为LIN_STATE_RECEIVE_IDENTIFIER,并校验收到的PID,如果收到的id为0x05(此处ID自己定的),说明master发的是写指令,对于从节点需要读取master写的数据,状态置为LIN_STATE_RECEIVE_IDENTIFIER继续接收数据段;如果收到的id为0x10,说明master发的是读指令,对于从节点需要发出需要发送的数据,状态置为LIN_STATE_SEND_DATALIN_STATE_SEND_DATA

如果收到的id为0x05,下一字节开始收到数据段,每收到一字节数据都放入g_buffer中

如果收到的id为0x10,开始发数据

checksum = LIN_MakeChecksum( LIN_MakeProtId(0x10), 8, g_buffer)   为计算校验和,函数如下代码所示。校验和有经典型和增强型两种,区别仅在于增强型校验需要计算的范围是除了数据段还要加上ID的数值,此处用的增强型。                                                             

从节点仅发送数据段与校验,通过UART_SendData(UART_LIN, g_buffer[k])发送数据段,UART_SendData(UART_LIN, checksum);发送了校验。

从节点发完数据将标志置为LIN_STATE_IDLE(初始状态)

g_state = LIN_STATE_IDLE;

其他注意:不要在接收与发送数据过程中放printf

使用队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值