基于STM32的LIN总线实现详解

LIN总线的实现

你好! 这是使用STM32F105RBT6单片机实现的LIN总线。ST其它型号也可,仔细阅读这篇文章,了解一下LIN总线的实现过程。

配置USART2

void init_LIN(void)
{
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1ENR_USART2EN,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2ENR_IOPAEN,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2ENR_AFIOEN,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_SetBits(GPIOA,GPIO_Pin_4);
	
	USART_InitStructure.USART_BaudRate = Lin_Speed;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART2, &USART_InitStructure);
	
	USART_LINBreakDetectLengthConfig(USART2,USART_LINBreakDetectLength_11b);
	USART_LINCmd(USART2,ENABLE);
	
	USART_ClearFlag(USART2,USART_FLAG_LBD);
	
	USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
	USART_ITConfig(USART2,USART_IT_LBD,ENABLE);
	
	NVIC_InitStructure.NVIC_IRQChannel=USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);	
	
	USART_Cmd(USART2,ENABLE);
	
	//参数初始化
	linTxMsg.Send_Complete=ENABLE;
	linRxMsg.Length=8;
}

校验和PID

u8 lin_Check_ProtectedID(u16 id,u8 len)//校验和PID
{
	u8 checkSum=id&0x3f;
	checkSum|=(((checkSum&0x01)^((checkSum&0x02)>>1)^((checkSum&0x04)>>2)^((checkSum&0x10)>>4))<<6)&0x40;
	checkSum|=(~((((checkSum&0x02)>>1)^((checkSum&0x08)>>3)^((checkSum&0x10)>>4)^((checkSum&0x20)>>5))<<7))&0x80;
	return checkSum;
}

LIN数据发送

void Lin_Send_Msg()
{
	Lin_Sending_Flag=ENABLE;
	linTxMsg.Protected_ID = lin_Check_ProtectedID(linTxMsg.ID,linTxMsg.Length);//校验和PID
	while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);//传输数据寄存器空标志
	USART_SendBreak(USART2);//同步时间间隔
	while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);//传输数据寄存器空标志
	USART_SendData(USART2,0x55);//同步段
	while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);//传输数据寄存器空标志
	USART_SendData(USART2,linTxMsg.Protected_ID);//发送PID
	for (u8 i = 0; i < linTxMsg.Length; i++) 
	{
		while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);//发送数据
		USART_SendData(USART2,linTxMsg.Data[i]);    
		linTxMsg.CheckSum += linTxMsg.Data[i];       //校验和
		if (linTxMsg.CheckSum >= 256)
			linTxMsg.CheckSum = (linTxMsg.CheckSum+1)&0xff;
	}
	linTxMsg.CheckSum=(u8)~linTxMsg.CheckSum;
	while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);//发送校验和
	USART_SendData(USART2,linTxMsg.CheckSum);
	while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);//等待发送结束
	linTxMsg.CheckSum=0;
	Lin_Sending_Flag=DISABLE;
}

lin数据接收

void Lin_SendData_Process(void(*Lin_Data_receiving_callback)(void))//接收数据的过程
{
	if(linRxMsg.Receive_Complete)
	{
		u16 checkSum;
		for(u8 i=0;i<8;i++)
		{
			checkSum += linRxMsg.Data[i];       //校验和
			if (checkSum >= 256)
				checkSum = (checkSum+1)&0xff;
		}
		checkSum=(u8)~checkSum;
		linRxMsg.ID=linRxMsg.Protected_ID&0x3f;
		if(linRxMsg.CheckSum==checkSum)
		{
			Lin_Reception_of_data=1;
			Lin_Data_receiving_callback();
		}
		linRxMsg.Receive_Complete=DISABLE;
	}
}


void Lin_Data_receiving_callback()//Lin接收回调函数
{
	if(Lin_Reception_of_data==1)
	{
		Lin_Reception_of_data=0;
		switch(linRxMsg.ID)
		{
			case 0x07:
				lin_data=linRxMsg.Data[1];
				break;
		}
	}
}

USART2作LIN的中断处理

void USART2_IRQHandler()
{
	if(USART_GetFlagStatus(USART2,USART_FLAG_LBD)!=RESET)//LIN中断检测标志
	{
		if(Lin_Sending_Flag==DISABLE)//没有发送数据
		{
			Lin_LBD_Flag=ENABLE;
		}
		USART_ClearFlag(USART2,USART_FLAG_LBD);//LIN断开
	}
	if(USART_GetFlagStatus(USART2,USART_FLAG_RXNE)!=RESET)//接收数据寄存器不为空标志
	{
		if(Lin_LBD_Flag==ENABLE)//lin中断使能可接收数据
		{
			u8 data=USART_ReceiveData(USART2);//接收数据
			
			if(linRxMsg.Index==1)
			{
				linRxMsg.Protected_ID=data;//接收PID
			}
			else if(linRxMsg.Index>1 && linRxMsg.Index<linRxMsg.Length+2)
			{
				linRxMsg.Data[linRxMsg.Index-2]=data;//接收数据				
			}
			else if(linRxMsg.Index==linRxMsg.Length+2)//接收校验场
			{
				linRxMsg.CheckSum=data;
			}
			linRxMsg.Index++;
			if(linRxMsg.Index>linRxMsg.Length+2)//数据接收完毕
			{
				linRxMsg.Receive_Complete=ENABLE;//接收数据使能
				Lin_LBD_Flag=DISABLE;//接收数据失能
				linRxMsg.Index=0;
			}
		}
		USART_ClearFlag(USART2,USART_FLAG_RXNE);//接收完毕,清除接收数据寄存器不为空标志
	}
}
物联沃分享整理
物联沃-IOTWORD物联网 » 基于STM32的LIN总线实现详解

发表评论