CAN总线代码(二)

其实CAN总线是多主模式,并不是主从模式。我们平时称呼的主CAN,从CAN,其实除了称呼不同,在使用和功能上没有任何区别。

1.CAN 节点代码

can.c

//CAN初始化
//tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
//tbs2:时间段2的时间单元.   范围:CAN_BS2_1tq~CAN_BS2_8tq;
//tbs1:时间段1的时间单元.   范围:CAN_BS1_1tq ~CAN_BS1_16tq
//brp :波特率分频器.范围:1~1024; tq=(brp)*tpclk1
//波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
//mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
//Fpclk1的时钟在初始化的时候设置为42M,如果设置CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);
//则波特率为:42M/((6+7+1)*6)=500Kbps
//返回值:0,初始化OK;
//    其他,初始化失败; 

u8 CAN1_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{

  	GPIO_InitTypeDef 	   GPIO_InitStructure; 
	CAN_InitTypeDef        CAN_InitStructure;
  	CAN_FilterInitTypeDef  CAN_FilterInitStructure;
#if CAN1_RX0_INT_ENABLE 
   	NVIC_InitTypeDef  NVIC_InitStructure;
#endif
    //使能相关时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能PORTA时钟	                   											 

  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟	
	
    //初始化GPIO
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA11,PA12
	
	//引脚复用映射配置
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11复用为CAN1
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1); //GPIOA12复用为CAN1
	  
  	//CAN单元设置
   	CAN_InitStructure.CAN_TTCM=DISABLE;	//非时间触发通信模式   
  	CAN_InitStructure.CAN_ABOM=DISABLE;	//软件自动离线管理	  
  	CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
  	CAN_InitStructure.CAN_NART=ENABLE;	//禁止报文自动传送 
  	CAN_InitStructure.CAN_RFLM=DISABLE;	//报文不锁定,新的覆盖旧的  
  	CAN_InitStructure.CAN_TXFP=DISABLE;	//优先级由报文标识符决定 
  	CAN_InitStructure.CAN_Mode= mode;	 //模式设置 
  	CAN_InitStructure.CAN_SJW=tsjw;	//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
  	CAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
  	CAN_InitStructure.CAN_BS2=tbs2;//Tbs2范围CAN_BS2_1tq ~	CAN_BS2_8tq
  	CAN_InitStructure.CAN_Prescaler=brp;  //分频系数(Fdiv)为brp+1	
  	CAN_Init(CAN1, &CAN_InitStructure);   // 初始化CAN1 
    
	//配置过滤器
 	CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0
  	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID
  	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
   	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
  	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
  	CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
		
#if CAN1_RX0_INT_ENABLE
	
	CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.		    
  
	 NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
	 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    //抢占优先级0
	 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;    //子优先级0
	 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	 NVIC_Init(&NVIC_InitStructure);
		 
	 /* 中断设置 CAN1_RX1中断 */
	 NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX1_IRQn;
	 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    //抢占优先级2
	 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;    //子优先级1
	 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	 NVIC_Init(&NVIC_InitStructure);
#endif
	return 0;
} 


//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
//len:数据长度(最大为8)				     
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
//		 其他,失败;
u8 CAN1_Send_Msg(u8* msg,u8 len)
{	

   //Txmessage.StdId = 0x00;
	 TxMessage.ExtId = 0x0314;    //使用的扩展ID
	 TxMessage.IDE = CAN_ID_EXT;    //扩展模式
	 TxMessage.RTR = CAN_RTR_DATA;    //发送的是数据
	 TxMessage.DLC = 8;    //数据长度为8字节
	 
	 TxMessage.Data[0] = (uint8_t)DHT22_Data.temp;
	 TxMessage.Data[1] = (uint8_t)DHT22_Data.humi;
	 TxMessage.Data[2] = tplsb;
	 TxMessage.Data[3] = tpmsb;
	 TxMessage.Data[4] = Concentration;
	 TxMessage.Data[5] = Humidity;
	 TxMessage.Data[6] = BUF[0];
	 TxMessage.Data[7] = BUF[1];
						 // 发送两帧信息
}

//can口接收数据查询
//buf:数据缓存区;	 
//返回值:0,无数据被收到;
//		 其他,接收的数据长度;
u8 CAN1_Receive_Msg(u8 *buf)
{		   		   
	u32 i;
	CanRxMsg RxMessage;
    if( CAN_MessagePending(CAN1,CAN_FIFO0)==0)
		return 0;		//没有接收到数据,直接退出 
    CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//读取数据	
    for(i=0;i<RxMessage.DLC;i++)
    buf[i]=RxMessage.Data[i];  
	return RxMessage.DLC;	
}

stm32f10x_it.c

void USB_LP_CAN1_RX0_IRQHandler(void)
{
   /* 从邮箱读出报文 */
	 CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
	 
	 /* 比较ID和数据是否为 0x1314 及 DCBA */
	 if( (RxMessage.ExtId == 0x1C00) && (RxMessage.IDE == CAN_ID_EXT) && (RxMessage.DLC == 0) )
	    flag = 0;    //接收成功
	else
		flag = 0xff;    //接收失败
}

void CAN1_RX1_IRQHandler(void)
{
   /* 从邮箱读出报文 */
	 CAN_Receive(CAN1, CAN_FIFO1, &RxMessage);
	 
	 /* 比较ID是否为 0x1010 */
	 if( (RxMessage.ExtId == 0x1010) && (RxMessage.IDE == CAN_ID_EXT) && (RxMessage.DLC == 1) && (RxMessage.Data[0] == 0x00))
	    C_flag = 0;    //照明指令
	 
	 else if( (RxMessage.ExtId == 0x1010) && (RxMessage.IDE == CAN_ID_EXT) && (RxMessage.DLC == 1) && (RxMessage.Data[0] == 0x01))
		  C_flag = 1;    //通风指令
	 
	 else if( (RxMessage.ExtId == 0x1010) && (RxMessage.IDE == CAN_ID_EXT) && (RxMessage.DLC == 1) && (RxMessage.Data[0] == 0x02))
		  C_flag = 2;    //灌溉指令
	 
	 else if( (RxMessage.ExtId == 0x1010) && (RxMessage.IDE == CAN_ID_EXT) && (RxMessage.DLC == 1) && (RxMessage.Data[0] == 0x03))
		  C_flag = 3;    //卷帘指令
	 else
		  C_flag = 0xff;
}

main.c

void Control()
{
switch(c_flag)
	case 0;.......break;
	case 1;.......break;
	case 2;.......break;
	case 3;.......break;

}

2.CAN控制室代码

u8 CAN1_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{

  	GPIO_InitTypeDef 	   GPIO_InitStructure; 
	CAN_InitTypeDef        CAN_InitStructure;
  	CAN_FilterInitTypeDef  CAN_FilterInitStructure;

    //使能相关时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能PORTA时钟	                   											 

  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟	
	
    //初始化GPIO
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA11,PA12
	
	//引脚复用映射配置
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11复用为CAN1
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1); //GPIOA12复用为CAN1
	  
  	//CAN单元设置
   	CAN_InitStructure.CAN_TTCM=DISABLE;	//非时间触发通信模式   
  	CAN_InitStructure.CAN_ABOM=DISABLE;	//软件自动离线管理	  
  	CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
  	CAN_InitStructure.CAN_NART=ENABLE;	//禁止报文自动传送 
  	CAN_InitStructure.CAN_RFLM=DISABLE;	//报文不锁定,新的覆盖旧的  
  	CAN_InitStructure.CAN_TXFP=DISABLE;	//优先级由报文标识符决定 
  	CAN_InitStructure.CAN_Mode= mode;	 //模式设置 
  	CAN_InitStructure.CAN_SJW=tsjw;	//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
  	CAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
  	CAN_InitStructure.CAN_BS2=tbs2;//Tbs2范围CAN_BS2_1tq ~	CAN_BS2_8tq
  	CAN_InitStructure.CAN_Prescaler=brp;  //分频系数(Fdiv)为brp+1	
  	CAN_Init(CAN1, &CAN_InitStructure);   // 初始化CAN1 
    
	//配置过滤器
 	CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0
  	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID
  	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
   	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
  	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
  	CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
	CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);    //CAN通信中断使能
	
	return 0;
} 

void CAN_SetMsg_1(void)
{
   //Txmessage.StdId = 0x00;
	 TxMessage.ExtId = 0x1800;    //使用的扩展ID
	 TxMessage.IDE = CAN_ID_EXT;    //扩展模式
	 TxMessage.RTR = CAN_RTR_DATA;    //发送的是数据
	 TxMessage.DLC = 0;    //数据长度为0
}

void CAN_SetMsg_2(void)
{
   //Txmessage.StdId = 0x00;
	 TxMessage.ExtId = 0x1C00;        //使用的扩展ID
	 TxMessage.IDE = CAN_ID_EXT;      //扩展模式
	 TxMessage.RTR = CAN_RTR_DATA;    //发送的是数据
	 TxMessage.DLC = 0;   				    //数据长度为0
}

void CAN_SetMsg_Light(void)
{
   //Txmessage.StdId = 0x00;
	 TxMessage.ExtId = 0x1010;    //使用的扩展ID
	 TxMessage.IDE = CAN_ID_EXT;    //扩展模式
	 TxMessage.RTR = CAN_RTR_DATA;    //发送的是数据
	 TxMessage.DLC = 1;    //数据长度为1
	 
	 TxMessage.Data[0] = 0x00;
}

void CAN_SetMsg_Wind(void)
{
   //Txmessage.StdId = 0x00;
	 TxMessage.ExtId = 0x1010;    //使用的扩展ID
	 TxMessage.IDE = CAN_ID_EXT;    //扩展模式
	 TxMessage.RTR = CAN_RTR_DATA;    //发送的是数据
	 TxMessage.DLC = 1;    //数据长度为1
	 
	 TxMessage.Data[0] = 0x01;
}

void CAN_SetMsg_Irrigation(void)
{
   //Txmessage.StdId = 0x00;
	 TxMessage.ExtId = 0x1010;    //使用的扩展ID
	 TxMessage.IDE = CAN_ID_EXT;  //扩展模式
	 TxMessage.RTR = CAN_RTR_DATA;//发送的是数据
	 TxMessage.DLC = 1;    				//数据长度为1
	 
	 TxMessage.Data[0] = 0x02;
}

void CAN_SetMsg_Rolling(void)
{
   //Txmessage.StdId = 0x00;
	 TxMessage.ExtId = 0x1010;    //使用的扩展ID
	 TxMessage.IDE = CAN_ID_EXT;  //扩展模式
	 TxMessage.RTR = CAN_RTR_DATA;//发送的是数据
	 TxMessage.DLC = 1;    				//数据长度为1
	 
	 TxMessage.Data[0] = 0x03;
}

void CAN_SetMsg(void)
{
	 static float a = 0.5, b = 0.5, m;
    
	 m = a+b;
	 
	 /* 打包报文 */
   if(m == 1)   
		  CAN_SetMsg_1();
   else 
		  CAN_SetMsg_2();
			
	 b = -b;
}

stm32f10X_it.c

void USB_LP_CAN1_RX0_IRQHandler(void)
{
   /* 从邮箱读出报文 */
	 CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
	 
	 /* 比较ID是否为 0x1314 */
	 if( (RxMessage.ExtId == 0x1314) && (RxMessage.IDE == CAN_ID_EXT) && (RxMessage.DLC == 8) )	
	    flag = 0;    //“主机1”接收成功
	 
   else
		  flag = 0xff;    //接收失败
}

void CAN1_RX1_IRQHandler(void)
{
   /* 从邮箱读出报文 */
	 CAN_Receive(CAN1, CAN_FIFO1, &RxMessage);
	 
	 /* 比较ID是否为 0x0314 */
	 if( (RxMessage.ExtId == 0x0314) && (RxMessage.IDE == CAN_ID_EXT) && (RxMessage.DLC == 8) )	
	    flag = 1;    //“主机2”接收成功 
   else
		  flag = 0xff;    //接收失败   
}

void EXTI4_IRQHandler(void)
{
   if(EXTI_GetITStatus(EXTI_Line4) != RESET)     //4线 光照指令按键
	 {
      CAN_SetMsg_Light();
		  CAN_Transmit(CAN1, &TxMessage); 
	    
		  EXTI_ClearITPendingBit(EXTI_Line4);  		//清除中断标志位
	 }
}

void EXTI9_5_IRQHandler(void) 
{
   if(EXTI_GetITStatus(EXTI_Line5) != RESET)    //5线 通风指令按键
	 {
      CAN_SetMsg_Wind();
		  CAN_Transmit(CAN1, &TxMessage); 
	    
		  EXTI_ClearITPendingBit(EXTI_Line5);  		//清除中断标志位
	 }
}

void EXTI15_10_IRQHandler(void) 
{
   if(EXTI_GetITStatus(EXTI_Line13) != RESET)    //13线 灌溉指令按键
	 {
      CAN_SetMsg_Irrigation();
		  CAN_Transmit(CAN1, &TxMessage); 
	    
		  EXTI_ClearITPendingBit(EXTI_Line13);  		//清除中断标志位
	 }
	 
	 if(EXTI_GetITStatus(EXTI_Line14) != RESET)    //14线 卷帘指令按键
	 {
      CAN_SetMsg_Rolling();
	  CAN_Transmit(CAN1, &TxMessage); 
	    
	 EXTI_ClearITPendingBit(EXTI_Line14);  		//清除中断标志位
	 }
}

图示:

在这里插入图片描述
欢迎指正谢谢!

  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值