CAN总线代码(二)

编程入门 行业动态 更新时间:2024-10-19 13:29:31

CAN<a href=https://www.elefans.com/category/jswz/34/1769217.html style=总线代码(二)"/>

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时钟	//初始化GPIOGPIO_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;//100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA11,PA12//引脚复用映射配置GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11复用为CAN1GPIO_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_4tqCAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tqCAN_InitStructure.CAN_BS2=tbs2;//Tbs2范围CAN_BS2_1tq ~	CAN_BS2_8tqCAN_InitStructure.CAN_Prescaler=brp;  //分频系数(Fdiv)为brp+1	CAN_Init(CAN1, &CAN_InitStructure);   // 初始化CAN1 //配置过滤器CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位IDCAN_FilterInitStructure.CAN_FilterIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASKCAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化#if CAN1_RX0_INT_ENABLECAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.		    NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    //抢占优先级0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;    //子优先级0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);/* 中断设置 CAN1_RX1中断 */NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    //抢占优先级2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;    //子优先级1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
#endifreturn 0;
} //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
//len:数据长度(最大为8)				     
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
//		 其他,失败;
u8 CAN1_Send_Msg(u8* msg,u8 len)
{	//Txmessage.StdId = 0x00;TxMessage.ExtId = 0x0314;    //使用的扩展IDTxMessage.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;    //接收成功elseflag = 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;    //卷帘指令elseC_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时钟	//初始化GPIOGPIO_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;//100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA11,PA12//引脚复用映射配置GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11复用为CAN1GPIO_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_4tqCAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tqCAN_InitStructure.CAN_BS2=tbs2;//Tbs2范围CAN_BS2_1tq ~	CAN_BS2_8tqCAN_InitStructure.CAN_Prescaler=brp;  //分频系数(Fdiv)为brp+1	CAN_Init(CAN1, &CAN_InitStructure);   // 初始化CAN1 //配置过滤器CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位IDCAN_FilterInitStructure.CAN_FilterIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASKCAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);    //CAN通信中断使能return 0;
} void CAN_SetMsg_1(void)
{//Txmessage.StdId = 0x00;TxMessage.ExtId = 0x1800;    //使用的扩展IDTxMessage.IDE = CAN_ID_EXT;    //扩展模式TxMessage.RTR = CAN_RTR_DATA;    //发送的是数据TxMessage.DLC = 0;    //数据长度为0
}void CAN_SetMsg_2(void)
{//Txmessage.StdId = 0x00;TxMessage.ExtId = 0x1C00;        //使用的扩展IDTxMessage.IDE = CAN_ID_EXT;      //扩展模式TxMessage.RTR = CAN_RTR_DATA;    //发送的是数据TxMessage.DLC = 0;   				    //数据长度为0
}void CAN_SetMsg_Light(void)
{//Txmessage.StdId = 0x00;TxMessage.ExtId = 0x1010;    //使用的扩展IDTxMessage.IDE = CAN_ID_EXT;    //扩展模式TxMessage.RTR = CAN_RTR_DATA;    //发送的是数据TxMessage.DLC = 1;    //数据长度为1TxMessage.Data[0] = 0x00;
}void CAN_SetMsg_Wind(void)
{//Txmessage.StdId = 0x00;TxMessage.ExtId = 0x1010;    //使用的扩展IDTxMessage.IDE = CAN_ID_EXT;    //扩展模式TxMessage.RTR = CAN_RTR_DATA;    //发送的是数据TxMessage.DLC = 1;    //数据长度为1TxMessage.Data[0] = 0x01;
}void CAN_SetMsg_Irrigation(void)
{//Txmessage.StdId = 0x00;TxMessage.ExtId = 0x1010;    //使用的扩展IDTxMessage.IDE = CAN_ID_EXT;  //扩展模式TxMessage.RTR = CAN_RTR_DATA;//发送的是数据TxMessage.DLC = 1;    				//数据长度为1TxMessage.Data[0] = 0x02;
}void CAN_SetMsg_Rolling(void)
{//Txmessage.StdId = 0x00;TxMessage.ExtId = 0x1010;    //使用的扩展IDTxMessage.IDE = CAN_ID_EXT;  //扩展模式TxMessage.RTR = CAN_RTR_DATA;//发送的是数据TxMessage.DLC = 1;    				//数据长度为1TxMessage.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”接收成功elseflag = 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”接收成功 elseflag = 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);  		//清除中断标志位}
}

图示:


欢迎指正谢谢!

更多推荐

CAN总线代码(二)

本文发布于:2024-02-06 09:04:17,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1748151.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:总线   代码

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!