基于AT32F413CBT7芯片,实现LIN2.0主机的读写

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

上篇文章写了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主机的基本建立,测试效果个人感觉不错,仅供大家学习参考,要源码记得收藏加关注后,私信我

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值