CAN总线通信应用

实验生产线环境检测系统构建

一、系统构成

 

 二、代码分析

 

//CAN总线配置
void CAN_User_Config(CAN_HandleTypeDef* hcan )  
{
	  CAN_FilterTypeDef  sFilterConfig;  
    HAL_StatusTypeDef  HAL_Status;  
    sFilterConfig.FilterBank = 0; //过滤器0   
    sFilterConfig.FilterMode =  CAN_FILTERMODE_IDMASK;//屏蔽位模式  
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //32位宽   
    sFilterConfig.FilterIdHigh = 0x0000;  //32位ID  
    sFilterConfig.FilterIdLow  = 0x0000;  
    sFilterConfig.FilterMaskIdHigh = 0x0000; //32位MASK  
    sFilterConfig.FilterMaskIdLow  = 0x0000;  
    sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; //接收到的报文放入到FIFO0中  
    sFilterConfig.FilterActivation = ENABLE; //激活过滤器    
    sFilterConfig.SlaveStartFilterBank  = 0;  
    HAL_Status=HAL_CAN_ConfigFilter(hcan, &sFilterConfig);  
    HAL_Status=HAL_CAN_Start(hcan);  //开启CAN     
    if(HAL_Status!=HAL_OK)  
    {  
        printf("开启CAN失败\r\n");  
    }  
    HAL_Status=HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING);     
    if(HAL_Status!=HAL_OK)  
    {  
        printf("开启挂起中段允许失败\r\n");         
    } 
}
//启动CAN总线
void can_start(void)
{
	HAL_CAN_Start(&hcan);   
}
//停止CAN总线
void can_stop(void)
{
	HAL_CAN_Stop(&hcan);  
}

//CAN数据发送函数
uint8_t Can_Send_Msg_StdId(uint16_t My_StdId,uint8_t len,uint8_t Type_Sensor)
{	
		CAN_TxHeaderTypeDef  TxMeg;   
    ValueType ValueType_t;  
    uint8_t vol_H,vol_L;  
    uint16_t i=0;  
    uint8_t data[8];  
  
    TxMeg.StdId=My_StdId;             // 标准标识符   
    TxMeg.ExtId=0x00;                       // 设置扩展标示符   
    TxMeg.IDE=CAN_ID_STD;   // 标准帧  
    TxMeg.RTR=CAN_RTR_DATA;           // 数据帧  
    TxMeg.DLC=len;                          // 要发送的数据长度  
    for(i=0;i<len;i++)  
    {  
        data[i]=0;  
    }  
      
    data[0] =   Sensor_Type_t;  
		data[3] =   (uint8_t)My_StdId&0x00ff;        //取低两位做ID  
    data[4] =  My_StdId>>8;   //高位在后
    printf("Can_Send_Msg_StdId >>My_StdId 标准帧ID= %x   \r\n",My_StdId);  
    printf("Can_Send_Msg_StdId >>Sensor_Type_t %d \r\n",data[0]);  
    ValueType_t=ValueTypes(Type_Sensor);  
    printf("Can_Send_Msg_StdId >>ValueType_t %d \r\n",ValueType_t);  
      
      
    switch(ValueType_t)  
    {  
        case Value_ADC:  
              
                    vol_H = (vol&0xff00)>>8;  
                    vol_L = vol&0x00ff;  
                    data[1]=vol_H;  
                    data[2]=vol_L;        
                    printf("Can_Send_Msg_StdId >> Value_ADC TxMessage.Data[1]=vol_L %d \r\n",data[1]);  
                    printf("Can_Send_Msg_StdId >> Value_ADC TxMessage.Data[2]=vol_L %d \r\n",data[2]);  
            break;  
        case Value_Switch:  
                    data[1]=switching;  
                    data[2]=0;  
            break;  
        case Value_I2C:  
                    data[1]=sensor_tem;  
                    data[2]=sensor_hum;  
                    printf("Can_Send_Msg_StdId >> Value_I2C TxMessage.Data[1]=vol_L %d \r\n",data[1]);  
                    printf("Can_Send_Msg_StdId >> Value_I2C TxMessage.Data[2]=vol_L %d \r\n",data[2]);   
            break;  
        default:  
            break;  
    }  
      
    if (HAL_CAN_AddTxMessage(&hcan, &TxMeg, data, &TxMailbox) != HAL_OK)  
    {  
        printf("Can send data error\r\n");  
    }  
    else  
    {  
        printf("Can send data success\r\n");  
    }  
  
    return 0;
}


//CAN中断回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)      
{
	CAN_RxHeaderTypeDef RxMeg;  
    uint8_t  Data[8] = {0};  
    HAL_StatusTypeDef   HAL_RetVal;  
    int i;  
      
    RxMeg.StdId=0x00;  
    RxMeg.ExtId=0x00;  
    RxMeg.IDE=0;  
    RxMeg.DLC=0;  
  
    HAL_RetVal=HAL_CAN_GetRxMessage(hcan,  CAN_RX_FIFO0, &RxMeg,  Data);  
    if ( HAL_OK==HAL_RetVal)  
    {                                         
        for(i=0;i<RxMeg.DLC;i++)  
        {    
            Can_data[i]= Data[i];  
            printf("%02X ",Data[i]);  
              
        }         
        printf("\r\n");  
        flag_send_data=1;  
    } 
}

        网关主函数

  while (1)
  {
    /* USER CODE END WHILE */
		if(1)
		{
			Value_Type=ValueTypes(Sensor_Type_t);
			switch(Value_Type)
			{
				case Value_ADC:                                    //光照 空气 火焰 可燃气体
					sensor_number=1;
					vol=Get_Voltage();
				  printf("vol=Get_Voltage  ===== %x \r\n",vol);				
					break;
				case Value_Switch:				                         //人体 红外 声音
					sensor_number=1; 
					switching=Switching_Value();	 
					printf("switching=Switching_Value== %d \r\n",switching);
					break;
				case Value_I2C:
					sensor_number=2;
				  SHT1x_get_temperature(&sensor_tem);           //温度
				  SHT1x_get_relative_humidity(&sensor_hum);     //湿度
				  printf("sensor_tem   ===== %d :;sensor_hum===%d \r\n",(int)sensor_tem,(int)sensor_hum);
					break;
				default:
					break;
			}	
			//把本块板子的传感数据发送到网关  
      Master_To_Gateway(Can_STD_ID, Value_Type, vol,  switching, sensor_hum, sensor_tem ); 
			
		}	
		HAL_Delay(1500);
		
		//发送从CAN总线接收的其他节点数据至网关  
		if(flag_send_data==1)  
		{     
				CAN_Master_To_Gateway( Can_data,9);   
				flag_send_data=0;  
		}  

		//USART1 通过M3主控模块配置工具配置采集传感器类型 或 或者CAN发送标准帧ID (注标准帧不能超过0 to 0x7FF)
		if(!usart1_data_fifo_is_empty())
		{			
			HAL_Delay(100);
			process_up();		
		} 
    /* USER CODE BEGIN 3 */
  }

        节点主函数

  while (1)
  {
    /* USER CODE END WHILE */
		if(1)
		{
			Value_Type=ValueTypes(Sensor_Type_t);
			switch(Value_Type)
			{
				case Value_ADC:                                    //光照 空气 火焰 可燃气体
					sensor_number=1;
					vol=Get_Voltage();
				  printf("vol=Get_Voltage  ===== %x \r\n",vol);				
					break;
				case Value_Switch:				                         //人体 红外 声音
					sensor_number=1; 
					switching=Switching_Value();	 
					printf("switching=Switching_Value== %d \r\n",switching);
					break;
				case Value_I2C:
					sensor_number=2;
				  SHT1x_get_temperature(&sensor_tem);           //温度
				  SHT1x_get_relative_humidity(&sensor_hum);     //湿度
				  printf("sensor_tem   ===== %d :;sensor_hum===%d \r\n",(int)sensor_tem,(int)sensor_hum);
					break;
				default:
					break;
			}	
			//把本块板子的传感数据发送到网关  
      Master_To_Gateway(Can_STD_ID, Value_Type, vol,  switching, sensor_hum, sensor_tem ); 
			
		}	
		HAL_Delay(1500);
		
		//发送从CAN总线接收的其他节点数据至网关  
		if(flag_send_data==1)  
		{     
				CAN_Master_To_Gateway( Can_data,9);   
				flag_send_data=0;  
		}  

		//USART1 通过M3主控模块配置工具配置采集传感器类型 或 或者CAN发送标准帧ID (注标准帧不能超过0 to 0x7FF)
		if(!usart1_data_fifo_is_empty())
		{			
			HAL_Delay(100);
			process_up();		
		} 
    /* USER CODE BEGIN 3 */
  }

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: CAN(Controller Area Network)总线通信协议是一种用于多个节点之间进行高速数据传输的协议。它最早是由德国博世公司于1986年开发的,用于汽车电子系统中的数据通信CAN总线通信协议的主要特点是高可靠性、实时性和抗干扰能力强。 CAN总线通信协议采用了主从节点的结构,主节点负责发送命令和控制数据的传输,从节点负责接收和执行主节点发送的命令。CAN总线通信协议的物理层采用了双绞线传输数据,可以实现较长的传输距离。 CAN总线通信协议的数据帧包括四个基本部分:帧起始符(SOF)、标识符(ID)、数据(Data)和校验码(CRC)。其中,标识符用于区分不同的帧,数据用于传输实际的命令和控制数据,校验码用于检验数据的正确性。 CAN总线通信协议具有以下优点:首先,CAN总线通信协议可以支持多个节点的同时通信,实现了高效的数据传输;其次,CAN总线通信协议具有较高的可靠性,即使在部分节点故障的情况下,不会影响整个系统的工作;再次,CAN总线通信协议具有较好的抗干扰能力,可以应对复杂的工作环境;最后,CAN总线通信协议具有实时性能,可以满足对数据传输时延较高的应用需求。 总之,CAN总线通信协议是一种可靠、高效的数据通信协议,广泛应用于汽车电子系统以及其他需要多个节点间进行高速数据传输的领域。 ### 回答2: CAN(Controller Area Network)总线通信协议是一种广泛应用于车载网络和工业自动化领域的串行通信协议。CAN总线通信协议采用了一种分布式通信结构,在一个网络中连接多个设备,并且允许这些设备在同一时间进行数据传输。 CAN总线通信协议的主要特点是高可靠性和实时性。它采用了差分信号传输和抗干扰技术,能够在恶劣的环境中保证数据的稳定传输。同时,CAN总线通信协议使用了先进的冲突检测与回避机制,能够实现多个设备同时发送消息而不发生冲突。 CAN总线通信协议还具有灵活的网络拓扑结构和高带宽的传输能力。它允许将多个设备通过总线连接起来,形成一个分布式的网络。同时,CAN总线通信协议支持多种数据传输速率,从几千bps到几百万bps都能满足不同领域的需求。 CAN总线通信协议在工业控制和汽车领域中有广泛的应用。在工业控制领域,CAN总线通信协议可以连接各种传感器和执行器,实现对生产过程的监控和控制。在汽车领域,CAN总线通信协议被广泛应用于车辆的电子控制系统,比如发动机管理、底盘控制和信息娱乐系统等。 总而言之,CAN总线通信协议是一种高可靠性、实时性和灵活性强的串行通信协议,应用于车辆和工业自动化领域,为各种设备之间的数据传输提供了可靠的解决方案。 ### 回答3: CAN总线通信协议是一种用于微控制器和其他设备之间进行实时通信的标准协议。CAN(Controller Area Network)总线是一种串行通信协议,通常用于汽车、工业控制和其他领域中的网络通信CAN总线通信协议通过一对互补的差分信号线来传输数据。它采用了CSMA/CD(载波监听多点冲突检测)的访问机制,允许多个设备共享同一总线,以实现实时通信和数据交换。 对于CAN总线通信协议的控制和管理,使用一种称为CAN帧的数据包来进行。CAN帧由四个主要部分组成:起始位、标识符、数据和校验位。起始位用于同步总线,标识符用于识别消息的发送者和接收者,数据部分包含要传输的实际数据,校验位用于检测传输过程中的错误。 CAN总线通信协议具有许多优点。首先,它具有高度可靠性和实时性,能够在多个设备之间进行快速、准确的数据传输。其次,CAN总线支持多主机结构,允许多个设备同时发送和接收数据。此外,CAN总线协议还具备较低的成本和复杂性,易于集成到各种应用中。 在实际应用中,CAN总线通信协议被广泛应用于汽车电子系统、工业自动化、医疗设备等领域。它可以用于车辆的发动机控制、底盘控制、仪表盘显示等方面,也可以用于工业控制系统中的传感器和执行器之间的通信。 总而言之,CAN总线通信协议是一种高效、可靠的数据通信协议,适用于各种实时要求较高的应用场景。它通过使用CAN帧来传输数据,具有多主机结构、低成本和复杂性的优点,被广泛应用于汽车、工业控制等领域。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李今天摸鱼了嘛?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值