完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛|
前面对CAN原理进行了讲解,这里我用一个简单的例子来说明CAN的使用。我使用的STM32芯片是STM32F103ZE,几个基本的配置是:
1.配置CAN时钟: /* CAN Periph clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE); 2.CAN管脚配置,这里使用的PB11,PB12管脚: /* Configure CAN pin: RX */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure CAN pin: TX */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); 3.中断配置,这里打开CAN的接收和发送中断: /* CAN RX interrupt */ NVIC_InitStructure.NVIC_IRQChannel=USB_LP_CAN_RX0_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* CAN TX interrupt */ NVIC_InitStructure.NVIC_IRQChannel=USB_HP_CAN_TX_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); 这里需要注意的是CAN的发送中断,发送中断是发送邮箱中数据发送完毕后产生的发送完毕邮箱空中断–这和USART发送中断不同。详细点说CAN发送中断是指CAN的三个发送邮箱中的其中一个由满到发送数据完毕后空才产生的中断,当原来发送邮箱本来就是空的则不会产生发送中断。 4.CAN初始化配置: void CAN_Ini(void) { CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; /* CAN register init */ CAN_DeInit(); CAN_StructInit(&CAN_InitStructure); /* CAN cell init */ CAN_InitStructure.CAN_TTCM=DISABLE; //禁止时间触发通信模式 CAN_InitStructure.CAN_ABOM=DISABLE; //软件对CAN_MCR寄存器的INRQ位进行置1随后清0后,一旦硬件检测 //到128次11位连续的隐性位,就退出离线状态。 CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过清除CAN_MCR寄存器的SLEEP位,由软件唤醒 CAN_InitStructure.CAN_NART=DISABLE; //CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失) CAN_InitStructure.CAN_RFLM=DISABLE; //在接收溢出时FIFO未被锁定,当接收FIFO的报文未被读出,下一个收到的报文会覆盖原有的报文 CAN_InitStructure.CAN_TXFP=ENABLE; //用来使能或者失能发送FIFO优先级,由发送的请求顺序决定 CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;//CAN硬件工作在正常模式 switch(CAN_BPP) { //总体配置保持,tBS1>=tBS2,tBS2>=1个CAN时钟周期,tBS2>=2tSJW case 100000: CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //重新同步跳跃宽度 CAN_InitStructure.CAN_BS1=CAN_BS1_10tq; //设定时间段1的时间单位数目 CAN_InitStructure.CAN_BS2=CAN_BS2_7tq; //设定时间段2的时间单位数目 CAN_InitStructure.CAN_Prescaler=20; //一个时间单位的长度//(pclk1/((4+8+8)*9)) = 36Mhz/18/20 = 100Kbits break; case 50000: CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; CAN_InitStructure.CAN_BS1=CAN_BS1_10tq; CAN_InitStructure.CAN_BS2=CAN_BS2_7tq; CAN_InitStructure.CAN_Prescaler=40; //(pclk1/((4+8+8)*9)) = 36Mhz/18/40 = 50Kbits break; case 20000: CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; CAN_InitStructure.CAN_BS1=CAN_BS1_10tq; CAN_InitStructure.CAN_BS2=CAN_BS2_7tq; CAN_InitStructure.CAN_Prescaler=100; //(pclk1/((4+8+8)*9)) = 36Mhz/18/100 = 20Kbits break; case 250000: CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; CAN_InitStructure.CAN_BS1=CAN_BS1_8tq; CAN_InitStructure.CAN_BS2=CAN_BS2_7tq; CAN_InitStructure.CAN_Prescaler=9; //(pclk1/((1+8+7)*9)) = 36Mhz/16/9 = 250Kbits break; case 500000: CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //重新同步跳跃宽度1个时间单位 CAN_InitStructure.CAN_BS1=CAN_BS1_6tq; //时间段1为6个时间单位 CAN_InitStructure.CAN_BS2=CAN_BS2_5tq; //时间段2为5个时间单位 CAN_InitStructure.CAN_Prescaler=6; //(pclk1/((1+6+5)*6)) = 36Mhz/12/6 = 500Kbits设定了一个时间单位的长度9 break; default: break; } CAN_Init(&CAN_InitStructure); /* CAN filter init */ CAN_FilterInitStructure.CAN_FilterNumber=0; //指定了待初始化的过滤器0 CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //指定了过滤器将被初始化到的模式为标识符屏蔽位模式 CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //给出了过滤器位宽1个32位过滤器 CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; //用来设定过滤器标识符(32位位宽时为其高段位,16位位宽时为第一个) CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; //用来设定过滤器标识符(32位位宽时为其低段位,16位位宽时为第二个 CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; //用来设定过滤器屏蔽标识符或者过滤器标识符(32位位宽时为其高段位,16位位宽时为第一个 CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000; //用来设定过滤器屏蔽标识符或者过滤器标识符(32位位宽时为其低段位,16位位宽时为第二个 CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_IT_FMP0; //设定了指向过滤器的FIFO0 CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //使能过滤器 CAN_FilterInit(&CAN_FilterInitStructure); /* CAN FIFO0 message pending interrupt enable */ CAN_ClearITPendingBit(CAN_IT_FF0); CAN_ClearITPendingBit(CAN_IT_FOV0); CAN_ClearITPendingBit(CAN_IT_FF1); CAN_ClearITPendingBit(CAN_IT_FOV1); CAN_ClearITPendingBit(CAN_IT_RQCP0); CAN_ClearITPendingBit(CAN_IT_RQCP1); CAN_ClearITPendingBit(CAN_IT_RQCP2); CAN_ITConfig(CAN_IT_FMP0, ENABLE); //使能接收中断 //CAN_ITConfig(CAN_IT_TME, ENABLE); //TransmitMailbox empty,发送中断在CAN_Transmit()后才能打开,用来判断发送完毕发送下一个数据 } 5.实现CAN的发送中断和接收中断,这里我们只用了一个发送邮箱进行发送–简单方便: void USB_LP_CAN_RX0_IRQHandler(void) //接收中断 { CanRxMsg RxMessage; U8 i=0; U8 targetid=0; //如果是标准帧 CAN_Receive(CAN_FIFO0, &RxMessage); if(RxMessage.IDE==CAN_ID_STD)//只收标准帧数据 { if((RxMessage.StdId&0x1F)==PCL_ID+bmqnum) //接收到ID是取后5位是自己的ID { //每个完整的数据,以|开头,下面是ID while(!QIn(&Qlinecanrx,’|’)){} targetid=(RxMessage.StdId>>6)&0x1F; while(!QIn(&Qlinecanrx,targetid)){} for(i=0;i { while(!QIn(&Qlinecanrx,RxMessage.Data)){} } } } CAN_ITConfig(CAN_IT_FMP0, ENABLE); //中断退出 } void USB_HP_CAN_TX_IRQHandler(void) { CAN_ClearITPendingBit(CAN_IT_RQCP0); CAN_ClearITPendingBit(CAN_IT_RQCP1); CAN_ClearITPendingBit(CAN_IT_RQCP2); CAN_ITConfig(CAN_IT_TME, DISABLE); CANSendStr(); //时刻查询是否可以给上位发送数据 } void CANSendStr() { CanTxMsg TxMessage; TxMessage.StdId=PCL_ID+bmqnum; //用来设定标准标识符,0x08+2=0x0A TxMessage.ExtId=0; //用来设定扩展标识符 TxMessage.RTR=CAN_RTR_DATA; //用来设定待传输消息的帧类型,它可以设置为数据帧或者远程帧,使用数据帧 TxMessage.IDE=CAN_ID_STD; //用来设定消息标识符的类型,使用标准标识符 TxMessage.DLC = 8; //用来设定待传输消息的帧长度,它的取值范围是0到0x8 //20160822----zhang TxMessage.RTR=CAN_RTR_DATA; //数据帧 //20160822----zhang TxMessage.Data[0]=’~’; TxMessage.Data[1]=‘0’; TxMessage.Data[2]=‘1’; TxMessage.Data[3]=‘2’; TxMessage.Data[4]=‘3’; TxMessage.Data[5]=‘4’; TxMessage.Data[6]=‘5’; TxMessage.Data[7]=‘6’; CAN_Transmit(&TxMessage); CAN_ITConfig(CAN_IT_TME, ENABLE); //TransmitMailbox empty,发送中断在CAN_Transmit()后才能打开,用来判断发送完毕发送下一个数据 } 6.使用中先使用CANSendStr()发送一条数据,则发送完毕后进入发送空中断,则之后会循环发送数据 |
|
|
|
|
只有小组成员才能发言,加入小组>>
2071 浏览 0 评论
imx6ull 和 lan8742 工作起来不正常, ping 老是丢包
4792 浏览 0 评论
4273 浏览 9 评论
3863 浏览 16 评论
4433 浏览 1 评论
4261浏览 3评论
3435浏览 0评论
1202浏览 0评论
2888浏览 0评论
3952浏览 0评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-14 13:40 , Processed in 0.743223 second(s), Total 76, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
2280