你好! 这是使用STM32F105RBT6单片机实现的LIN总线。ST其它型号也可,仔细阅读这篇文章,了解一下LIN总线的实现过程。
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;
}
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;
}
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;
}
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;
}
}
}
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);//接收完毕,清除接收数据寄存器不为空标志
}
}