CAN通讯的实现步骤:
1.CAN初始化,其中包括:a.配置CAN时钟,配置IO;
b.使能CAN中断向量;
c.CAN硬件寄存器配置初始化;
d.过滤器初始化;
e.打开CAN中断。
2.CAN发送函数
3.CAN接收函数
4.中断函数
依据上面的CAN通讯的实现步骤,开始编写代码,注意,我使用的是库函数。
一.CAN初始化
1 void CAN_Init(void) 2 3 { 4 5 GPIO_InitTypeDef GPIO_InitStructure; 6 7 NVIC_InitTypeDef NVIC_InitStructure; 8 9 CAN_InitTypeDef CAN_InitStructure; 10 11 CAN_FilterInitTypeDef CAN_FilterInitStructure; 12 13 //a.1.配置CAN时钟和对应的IO时钟 14 15 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE); //使能CAN1的时钟,注意:CAN1是挂载在APB1上,不要用错函数! 16 17 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE); //使能GPIO 18 19 //a.2.初始化CAN1_Tx(PA12)和CAN1_Rx(PA11)的IO 20 21 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PA12 —>CAN1_Tx 22 23 GIOP_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 24 25 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 26 27 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA12 28 29 30 31 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PA11 -> CAN1_RX 32 33 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入,注意:Rx必须使用上拉输入模式 34 35 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA11 36 37 //b.使能中断向量 38 39 NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; //我这使用的是CAN1的接收中断,实际上,CAN1还有发送中断:USB_HP_CAN1_TX_IRQn。注意,CAN1中断是和USB是共用的,所以如果你打开了CAN1中断,就不能再用USB中断了。 40 41 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 = 0 42 43 NVIC_InitStructure.NVIC_IRQChannelPreemPreemptionPriority = 3; //子优先级 = 3 44 45 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 46 47 NVIC_Init(&NVIC_InitStructure); 48 49 //c.CAN硬件寄存器配置初始化 50 51 CAN_DeInit(CAN1); 52 53 CAN_InitStructure.CAN_TTCM = DISABLE;//失能时间触发通讯模式 54 55 CAN_InitStructure.CAN_ABOM = DISABLE;//失能自动离线管理模式 56 57 CAN_InitStructure.CAN_AWUM = DISABLE;//失能自动唤醒模式 58 59 CAN_InitStructure.CAN_NART = DISABLE;//失能非自动重传输模式 60 61 CAN_InitStructure.CAN_RFLM = DISABLE;//失能接收FIFO锁定模式 62 63 CAN_InitStructure.CAN_TXFP = DISABLE;//失能发送FIFO优先级 64 65 CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;//CAN硬件工作在正常模式; 66 67 CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;//重新同步跳跃宽度1个时间单位; 68 69 CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq;//时间段1为9个时间单位; 70 71 CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;//时间段2为8个时间单位; 72 73 CAN_InitStructure.CAN_Prescaler = 3;//1个时间单位的长度为3 74 75 CAN_Init(CAN1&CAN_InitStructure); 76 77 //d.过滤器初始化 78 79 CAN_FIlterInitStructure.CAN_FilterNumber = 0;//制订带初始化的过滤器为0 80 81 CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;//标识符列表模式,该模式下屏蔽寄存器也被当作标识符寄存器使用,接收报文标识符的每一位都必须跟过滤器标识符相同 82 83 CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;//32位过滤器 84 85 CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;//过滤器标识符高段位:0x0000; 86 87 CAN_FilterInitStructure.CAN_FIlterIdLow = 0x0000;//过滤器标识符低段位:0x0000; 88 89 CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;//过滤器标识符高段位 90 91 CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;//过滤器屏蔽标识符低段位 92 93 CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;//使能过滤器 94 95 CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIlterFIFO0;//指向过滤器的FIFO0; 96 97 CAN_FilterInit(&CAN_FilterInitStructe); 98 99 //e.打开CAN中断 100 101 CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE)//FIFO0消息挂号中断屏蔽 102 103 }
二.CAN发送函数
1 void can_SendData(CanTxMsg* TxMessage) 2 3 { 4 5 unsigned char i = 0; 6 7 unsigned char TransmitMailbox; 8 9 TransmitMailbox = CAN_Transmit(CAN1,TxMessage);//发送数据,返回邮箱号 10 11 while((CAN_TransmitStatus(CAN1,TransmitMailbox) != CANTXOK)&&(i != 0xff)) 12 13 {//查看是否发送完成 14 15 i++; 16 17 } 18 19 i = 0; 20 21 while((CAN_MessagePendding(CAN1,CAN_FIFO0)<1)&&(i != 0xff)) 22 23 {//查看被挂起的报文是否为0 24 25 i++; 26 27 } 28 29 }
三.接收数据
今天不想写。。。。迟点补上蛤~~~~
四.中断函数
1 CanRxMsg RxMessage; 2 3 void USB_LP_CAN1_RX0_IRQHandler(void) 4 5 { 6 7 CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);//接收数据,存储到RxMessage中 8 9 。。。。。//自行脑补 10 11 } 12 13
因为我这篇文章是自己一个一个字敲进去的,可能会出现单词拼写错误~~~~~
欢迎指错蛤~~~~~~