提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
上篇文章写了LIN的从机,这次做个LIN的主机
提示:以下是本篇文章正文内容,下面案例可供参考
一、LIN主机是什么?
在LIN2.0协议中,用于控制LIN网络中的从机,获取从机的状态,控制相应的从机,发送主机读和主机写的指令。
二、使用步骤
1.硬件准备
准备一块带LIN芯片的AT32F413RBT7的核心板,有能力的铁汁可以自己画板,本demo使用的是串口一来收发LIN信号
2.软件部分
串口配置
void lin_init(void)
{
gpio_init_type gpio_init_struct; //初始化引脚配置结构体
/* enable the uart1 and gpio clock */
crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE); //开启串口1时钟
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); //开启引脚端口A时钟
gpio_default_para_init(&gpio_init_struct); //清空结构体
/* configure the uart1 tx pin */
/* configure the TX pin */
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; //中等来源/下沉强度*/
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; //推挽输出
gpio_init_struct.gpio_mode = GPIO_MODE_MUX; //引脚复用模式
gpio_init_struct.gpio_pins = GPIO_PINS_9; //配置相关引脚
gpio_init_struct.gpio_pull = GPIO_PULL_NONE; //浮动输入,无上下拉
gpio_init(GPIOA, &gpio_init_struct); //初始化TX_pin
/* configure the RX pin */
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; //中等来源/下沉强度*/
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; //推挽输出
gpio_init_struct.gpio_mode = GPIO_MODE_INPUT; //引脚输入模式
gpio_init_struct.gpio_pins = GPIO_PINS_10; //配置相关引脚
gpio_init_struct.gpio_pull = GPIO_PULL_NONE; //浮动输入,无上下拉
gpio_init(GPIOA, &gpio_init_struct); //初始化RX_pin
gpio_bits_set(GPIOA, GPIO_PINS_8); //拉高LIN芯片片选
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; //中等来源/下沉强度*/
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; //推挽输出
gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT; //引脚输出模式
gpio_init_struct.gpio_pins = GPIO_PINS_8; //配置相关引脚
gpio_init_struct.gpio_pull = GPIO_PULL_NONE; //浮动输入,无上下拉
gpio_init(GPIOA, &gpio_init_struct); //初始化片选引脚
/* configure param */
usart_init(USART1, Lin_Speed, USART_DATA_8BITS, USART_STOP_1_BIT); //配置波特率
usart_transmitter_enable(USART1, TRUE); //串口发送器使能
usart_receiver_enable(USART1, TRUE); //串口接收器使能
usart_parity_selection_config(USART1, USART_PARITY_NONE); //无奇偶校验
usart_break_bit_num_set(USART1, USART_BREAK_11BITS); //Usart Lin模式断帧检测11位
usart_lin_mode_enable(USART1, TRUE); //Usart Lin模式使能
nvic_irq_enable(USART1_IRQn, 0, 0); //配置串口优先级
usart_enable(USART1, TRUE); //串口1使能
usart_interrupt_enable(USART1, USART_RDBF_INT, TRUE); //Usart接收数据缓冲区满中断
usart_interrupt_enable(USART1, USART_BF_INT, TRUE); //Usart中断帧中断使能
//参数初始化
linRxMsg.Length=8;
linTxMsg.Length=8;
}
接收中断部分:
**void USART1_IRQHandler()
{
if(usart_flag_get(USART1,USART_BFF_FLAG)!=RESET) //检测同步间隔段
{
usart_flag_clear(USART1,USART_BFF_FLAG); //清除检测到同步间隔的标志
}
if(usart_flag_get(USART1,USART_RDBF_FLAG)!=RESET) //接收数据寄存器不为空标志
{
u8 data;
data=usart_data_receive(USART1); //接收数据
if(linRxMsg.Index==1)
{
linRxMsg.Protected_ID=data; //接收PID
}
if(linRxMsg.Protected_ID==LIN_Master_Read_pid) //判断接收的PID是否为主机的写PID
{
if(linRxMsg.Index>2 && linRxMsg.Index<linRxMsg.Length+2)
{
linRxMsg.Data[linRxMsg.Index-2]=data; //接收数据
}
if(linRxMsg.Index==linRxMsg.Length+2)
{
linRxMsg.CheckSum=data; //接收校验场
}
if(linRxMsg.Index==linRxMsg.Length+2) //数据接收完毕
{
linRxMsg.Receive_Complete=ENABLE; //接收数据完成使
Lin_Mode=LIN_Mode_MasterRead; //将总线状态更新为主机机读
}
}
if(linRxMsg.Index>linRxMsg.Length+2) //当接收索引大于接收数据
{
linRxMsg.Index=0; //清空接收索引
}
linRxMsg.Index++; //接收数据索引加加
usart_flag_clear(USART1,USART_RDBF_FLAG); //接收完毕,清除接收数据寄存器不为空标志
}
}**
接收中断回调函数:
void Lin_SendData_Process(void(*Lin_Data_receiving_callback)(void))//接收数据的过程
{
if(linRxMsg.Receive_Complete)
{
linRxMsg.ID=linRxMsg.Protected_ID&0x3f; //从PID中获取ID
if(linRxMsg.ID==LIN_Master_Read_id) //判断接收判断接收的ID是否为主机的写ID
{
u16 checkSum=0;
for(u8 i=0;i<8;i++)
{
checkSum += linRxMsg.Data[i]; //校验和
if (checkSum >= 256) //判断校验值是否一个字节
checkSum = (checkSum+1)&0xff; //大于进行进位处理
}
checkSum=(u8)~checkSum;
if(linRxMsg.CheckSum==checkSum) //判断接收的校验是否和重新计算的校验一致
{
Lin_Data_receiving_callback(); //从机写接收回调函数
linRxMsg.Receive_Complete=DISABLE; //接收数据完成失能
}
}
}
}
主机读响应函数:
u8 lin_data[8];
void Lin_Data_receiving_callback() //Lin接收回调函数
{
if(Lin_Mode==LIN_Mode_MasterRead) //判断当前总线状态是否为从机读
{
if(linRxMsg.ID==LIN_Master_Read_id) //判断接收ID是否等于从机读ID
{
memcpy(lin_data,linRxMsg.Data,8); //拷贝数据到相应数组
Lin_Mode=LIN_Mode_Master_Idle; //将总线状态更新为从机等待ID
Lin_receive_Flag=DISABLE; //接收数据失能
linRxMsg.ID=0; //输入ID清零
linRxMsg.Index=0; //输入索引清零
linRxMsg.Protected_ID=0; //输入PID清零
}
}
}
主机读帧头发送:
void Lin_Send_Wharf() //发送主机读帧头
{
Lin_Sending_Flag=ENABLE;
linTxMsg.ID=LIN_Master_Read_id; //将要发送的帧头给发送结构体
linTxMsg.Protected_ID = lin_Check_ProtectedID(linTxMsg.ID,linTxMsg.Length); //校验和PID
usart_break_send(USART1); //同步时间间隔
while(usart_flag_get(USART1,USART_TDC_FLAG) == RESET); //等待数据传输完成标志
usart_data_transmit(USART1,0x55); //同步段
while(usart_flag_get(USART1,USART_TDC_FLAG) == RESET); //等待数据传输完成标志
usart_data_transmit(USART1,linTxMsg.Protected_ID); //发送PID
while(usart_flag_get(USART1,USART_TDC_FLAG) == RESET); //等待数据传输完成标志
linTxMsg.CheckSum=0;
Lin_Sending_Flag=DISABLE;
}
主机写发送数据
void Lin_Send_Msg()
{
linTxMsg.ID=LIN_Master_Write_id;
linTxMsg.Length=8;
linTxMsg.Data[0]=0x11;linTxMsg.Data[1]=0x22;linTxMsg.Data[2]=0x33;linTxMsg.Data[3]=0x44;linTxMsg.Data[4]=0x00;linTxMsg.Data[5]=0x00;linTxMsg.Data[6]=0x00;
Lin_Sending_Flag=ENABLE;
linTxMsg.Protected_ID = lin_Check_ProtectedID(linTxMsg.ID,linTxMsg.Length);//校验和PID
while(usart_flag_get(USART1,USART_TDC_FLAG) == RESET); //等待数据传输完成标志
usart_break_send(USART1); //同步时间间隔
while(usart_flag_get(USART1,USART_TDC_FLAG) == RESET); //等待数据传输完成标志
usart_data_transmit(USART1,0x55); //同步段
while(usart_flag_get(USART1,USART_TDC_FLAG) == RESET); //等待数据传输完成标志
usart_data_transmit(USART1,linTxMsg.Protected_ID); //发送PID
while(usart_flag_get(USART1,USART_TDC_FLAG) == RESET); //等待数据传输完成标志
for (u8 i = 0; i < linTxMsg.Length; i++)
{
usart_data_transmit(USART1,linTxMsg.Data[i]);
while(usart_flag_get(USART1,USART_TDC_FLAG) == RESET); //等待数据传输完成标志
linTxMsg.CheckSum += linTxMsg.Data[i]; //校验和
if (linTxMsg.CheckSum >= 256)
linTxMsg.CheckSum = (linTxMsg.CheckSum+1)&0xff;
}
linTxMsg.CheckSum=(u8)~linTxMsg.CheckSum;
usart_data_transmit(USART1,linTxMsg.CheckSum);
while(usart_flag_get(USART1,USART_TDC_FLAG) == RESET); //等待数据传输完成标志
linTxMsg.CheckSum=0;
Lin_Sending_Flag=DISABLE;
}
while中调用
Lin_SendData_Process(Lin_Data_receiving_callback);
Lin_Send_Msg();
Lin_Send_Wharf();
测试效果:
用LIN分析仪作为从机,设置响应数据,同时发送主机写数据,我们的板子都能正常接收从机反馈
总结
以上就是LIN主机的基本建立,测试效果个人感觉不错,仅供大家学习参考,要源码记得收藏加关注后,私信我