• CAN总线_生产线环境监测


    一、设备准备

    • PC一台‘
    • 网关一个
    • CAN节点三个
    • 温湿度传感器两个
    • 火焰传感器一个
    • USB接口CAN调试器

    二、系统拓扑图

     三、知识链接

     

        

     

    四、完善工程

     4.1在 user_can.c 的 void CAN_User_Config(CAN_HandleTypeDef* hcan )函数中添加如下代码

    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 失败
    ");
         }
                HAL_Status=HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
         if(HAL_Status!=HAL_OK)
         {
                printf("开启挂起中段允许失败
    ");
         } 
    }

     4.2在 user_can.c 的 void can_start(void)函数中添加如下代码

    /******************************************************************************
     * FunctionName : void can_start(void)
     * Description  : 启动CAN总线
     * Parameters   : none
     * Returns      : none
    *******************************************************************************/
    void can_start(void)
    {
        HAL_CAN_Start(&hcan);
    }

    4.3在 user_can.c 的 void can_stop (void)函数中添加如代码

    /******************************************************************************
     * FunctionName : void can_stop(void)
     * Description  : 停止CAN总线
     * Parameters   : none
     * Returns      : none
    *******************************************************************************/
    void can_stop(void)
    {
        HAL_CAN_Stop(&hcan);
    }

    4.4在 user_can.c 的 uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)函数中添加 如下代码

    /******************************************************************************
     * FunctionName : uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)
     * Description  : can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)    
     * Parameters   : len:数据长度(最大为8)
     *                msg:数据指针,最大为8个字节.
     * Returns      : 0,成功;
     *                    其他,失败;
    *******************************************************************************/
    uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)
    {    
        uint16_t i=0;
        uint8_t data[8];
    
        CAN_TxHeaderTypeDef TxMeg;
         
        TxMeg.StdId=0x12; // 标准标识符
        TxMeg.ExtId=0x12; // 设置扩展标示符
        TxMeg.IDE=CAN_ID_STD; // 标准帧
        TxMeg.RTR= CAN_RTR_DATA; // 数据帧
        TxMeg.DLC=len; // 要发送的数据长度
        for(i=0;i<len;i++)
        {
            data[i]=msg[i];
        }
    
        if (HAL_CAN_AddTxMessage(&hcan, &TxMeg, data, &TxMailbox) != HAL_OK)
        {
            printf("Can send data error
    ");
        }
        else
        {
            printf("Can send data success
    ");
        }
            return 0;
    }

    4.5在 user_can.c 的 uint8_t Can_Send_Msg_StdId(uint16_t My_StdId,uint8_t len,uint8_t Type_Sensor)函数中添加如下代码

    /******************************************************************************
     * FunctionName : uint8_t Can_Send_Msg_StdId(uint16_t My_StdId,uint8_t len,uint8_t Type_Sensor)
     * Description  : can发送一组数据(固定格式:ID为My_StdId,标准帧,数据帧)    
     * Parameters   : My_StdId:标准标识符 
     *                len:数据长度(最大为8)
     *                msg:数据指针,最大为8个字节.
     * Returns      : 0,成功;
     *                    其他,失败;
    *******************************************************************************/
    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[4] = (uint8_t)My_StdId;
        printf("Can_Send_Msg_StdId >>My_StdId 标准帧 ID= %x 
    ",My_StdId);
        printf("Can_Send_Msg_StdId >>Sensor_Type_t %d 
    ",data[0]);
        ValueType_t=ValueTypes(Type_Sensor);
        printf("Can_Send_Msg_StdId >>ValueType_t %d 
    ",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 
    ",data[1]);
                printf("Can_Send_Msg_StdId >> Value_ADC TxMessage.Data[2]=vol_L %d 
    ",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 
    ",data[1]);
                printf("Can_Send_Msg_StdId >> Value_I2C TxMessage.Data[2]=vol_L %d 
    ",data[2]);
                break;
            default:
                break;
        }
        
        if (HAL_CAN_AddTxMessage(&hcan, &TxMeg, data, &TxMailbox) != HAL_OK)
        {
            printf("Can send data error
    ");
        }
        else
        {
            printf("Can send data success
    ");
        }
    
        return 0;
    }

    4.6在 user_can.c 的 HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)函数中添加如下代码

    //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("
    ");
        flag_send_data=1;
        }
    }

    4.7将该工程配置为网关节点工程,在 main.c 的 int main(void)函数中添加如下代码

    对工程进行编译,并对生成的hex文件剪切到另一个文件夹(随意新建),并重命名为"网关节点,hex"

    int main(void)
    {
      /* USER CODE BEGIN 1 */
        ValueType Value_Type;
      /* USER CODE END 1 */
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_CAN_Init();
      MX_ADC1_Init();
      MX_USART1_UART_Init();
      MX_USART2_UART_Init();
      MX_TIM2_Init();
      /* USER CODE BEGIN 2 */
        SHT1x_init();    //温湿度传感器初始化
        InfraredSensor_Init();   
        CAN_User_Config(&hcan);  //CAN总线配置
        Can_STD_ID=STMFLASH_ReadHalfWord(FLASE_M3_ADDR);                                     //配置CAN节点发送的标准帧ID 
      Sensor_Type_t=STMFLASH_ReadHalfWord(FLASH_Sensor_Type);                                    //配置M3主控模块采集的传感器类型
        open_usart1_receive_interrupt();  //启动USART1串口中断
        can_start(); //启动CAN总线
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      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 
    ",vol);                
                        break;
                    case Value_Switch:                                         //人体 红外 声音
                        sensor_number=1; 
                        switching=Switching_Value();     
                        printf("switching=Switching_Value== %d 
    ",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 
    ",(int)sensor_tem,(int)sensor_hum);
                        break;
                    default:
                        break;
                }    
                //CAN 节点发送传感器数据至 CAN 总线
                Master_To_Gateway((uint8_t)Can_STD_ID, Value_Type, vol, switching, sensor_hum, sensor_tem );
                
            }    
            HAL_Delay(1500);
            
    
            //USART1 通过M3主控模块配置工具配置采集传感器类型 或 或者CAN发送标准帧ID (注标准帧不能超过0 to 0x7FF)
            if(flag_send_data==1)
            {
                CAN_Master_To_Gateway( Can_data,3);
                flag_send_data=0;
            }
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }

    4.8将该工程配置为终端节点工程,在 main.c 的 int main(void)函数中将上一步添加的代 码删除,添加新的代码,如粗体部分下

    对工程进行编译,并对生成的hex文件,并重命名为“终端节点.hex”

    int main(void)
    {
      ……
      while (1)
      {
        /* USER CODE END WHILE */
            if(1)
            {
                Value_Type=ValueTypes(Sensor_Type_t);
                switch(Value_Type)
                {
                    ……
                }    
                //CAN 节点发送传感器数据至 CAN 总线
                Can_Send_Msg_StdId(Can_STD_ID,8,Sensor_Type_t);
                
            }    
            HAL_Delay(1500);
            
    
            ……
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
  • 相关阅读:
    EF CORE EntityFrameworkCore中关系模式一对一、一对多、多对多的使用
    C# LINQ中Join与GroupJoin的区别
    C#中HttpWebRequest、WebClient、HttpClient的使用
    .Net 性能优化--EFCore(EntityFrameworkCore)
    .Net 性能优化--缓存--分布式缓存
    .Net 性能优化--缓存--http缓存
    .Net 性能优化--缓存--分布式缓存 --sqlserver缓存
    .Net 性能优化--缓存--分布式缓存--reids缓存
    获取Kafka每个分区最新Offset的几种方法
    Wireshark使用入门
  • 原文地址:https://www.cnblogs.com/jsit-dj-it/p/12087893.html
Copyright © 2020-2023  润新知