利用stm32实现了1个简单的CAN功能,使用了队列缓存 can.c 文件 #include "includes.h" #define GPIO_CAN GPIOB #define RCC_APB2Periph_GPIO_CAN RCC_APB2Periph_GPIOB #define GPIO_Pin_RX GPIO_Pin_8 #define GPIO_Pin_TX GPIO_Pin_9 #define GPIO_Remap_CAN GPIO_Remap1_CAN1 #define MAX_MAIL_NUM 3 static u8 CAN_msg_num[MAX_MAIL_NUM]; // 发送邮箱标记 // /** * @brief Configures the CAN, transmit and receive by polling * @param None * @retval : PASSED if the reception is well done, FAILED in other case */ void CAN_config_init(void) { CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; /* CAN register init */ CAN_DeInit(CAN1); CAN_StructInit(&CAN_InitStructure); /* CAN cell init */ // 36M 250k速率 CAN_InitStructure.CAN_TTCM=DISABLE; CAN_InitStructure.CAN_ABOM=DISABLE; CAN_InitStructure.CAN_AWUM=DISABLE; CAN_InitStructure.CAN_NART=DISABLE; CAN_InitStructure.CAN_RFLM=DISABLE; CAN_InitStructure.CAN_TXFP=DISABLE; CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; CAN_InitStructure.CAN_BS1=CAN_BS1_12tq; CAN_InitStructure.CAN_BS2=CAN_BS2_3tq; CAN_InitStructure.CAN_Prescaler=9; CAN_Init(CAN1, &CAN_InitStructure); /* CAN filter init */ CAN_FilterInitStructure.CAN_FilterNumber=0; CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0; CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; CAN_FilterInit(&CAN_FilterInitStructure); } void CAN_init(void) { NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; // 首先打开电源及时钟 /* GPIO for CAN and GPIO for LEDs clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO |RCC_APB2Periph_GPIO_CAN, ENABLE); /* CAN1 Periph clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); /* Enable CAN1 RX0 interrupt IRQ channel */ NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable CAN1 TX0 interrupt IRQ channel */ NVIC_InitStructure.NVIC_IRQChannel = USB_HP_CAN1_TX_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 然后配置pin /* Configure CAN pin: RX */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_RX; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIO_CAN, &GPIO_InitStructure); /* Configure CAN pin: TX */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_TX; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIO_CAN, &GPIO_InitStructure); // 映射下 GPIO_PinRemapConfig(GPIO_Remap_CAN , ENABLE); // 波特率过滤器初始化 CAN_config_init(); CAN_ITConfig(CAN1, CAN_IT_FMP0 | CAN_IT_FF0 | CAN_IT_FOV0, ENABLE); // fifo0中断 CAN_ITConfig(CAN1, CAN_IT_FMP1 | CAN_IT_FF1 | CAN_IT_FOV1, ENABLE); // fifo1中断 CAN_ITConfig(CAN1, CAN_IT_TME, DISABLE); // 发送中断 CAN_ITConfig(CAN1, CAN_IT_EWG | CAN_IT_EPV | CAN_IT_BOF | CAN_IT_LEC | CAN_IT_ERR | CAN_IT_WKU | CAN_IT_SLK, ENABLE); // ERR中断 // CAN缓存初始化 memset(CAN_msg_num,0,MAX_MAIL_NUM); ClearCanQueue(); } int CAN_tx_msg(CanTxMsg TxMessage) { uint8_t TransmitMailbox = 0; OS_CPU_SR cpu_sr = 0; TransmitMailbox = CAN_Transmit(CAN1, &TxMessage); if(CAN_NO_MB == TransmitMailbox) { printf("tx can fail\r\n"); return 0; } else { OS_ENTER_CRITICAL(); CAN_msg_num[TransmitMailbox] = 1; OS_EXIT_CRITICAL(); } CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE); return 1; } int CAN_tx_data(void) { CanTxMsg TxMessage; uint8_t TransmitMailbox = 0; OS_CPU_SR cpu_sr = 0; /* transmit */ TxMessage.StdId=0x6f1; TxMessage.RTR=CAN_RTR_DATA; TxMessage.IDE=CAN_ID_STD; TxMessage.DLC=4; TxMessage.Data[0]=0x40; TxMessage.Data[1]=0x02; TxMessage.Data[2]=0x1a; TxMessage.Data[3]=0x80; TransmitMailbox = CAN_Transmit(CAN1, &TxMessage); if(CAN_NO_MB == TransmitMailbox) { printf("tx can fail\r\n"); return 0; } else { OS_ENTER_CRITICAL(); CAN_msg_num[TransmitMailbox] = 1; OS_EXIT_CRITICAL(); } CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE); return 1; } // 发送中断 void USB_HP_CAN1_TX_IRQHandler(void) { if(CAN_msg_num[0]) { if(SET == CAN_GetITStatus(CAN1,CAN_IT_RQCP0)) { CAN_ClearITPendingBit(CAN1,CAN_IT_RQCP0); CAN_ITConfig(CAN1, CAN_IT_TME, DISABLE); CAN_msg_num[0] = 0; } } if(CAN_msg_num[1]) { if(SET == CAN_GetITStatus(CAN1,CAN_IT_RQCP1)) { CAN_ClearITPendingBit(CAN1,CAN_IT_RQCP1); CAN_ITConfig(CAN1, CAN_IT_TME, DISABLE); CAN_msg_num[1] = 0; } } if(CAN_msg_num[2]) { if(SET == CAN_GetITStatus(CAN1,CAN_IT_RQCP2)) { CAN_ClearITPendingBit(CAN1,CAN_IT_RQCP2); CAN_ITConfig(CAN1, CAN_IT_TME, DISABLE); CAN_msg_num[2] = 0; } } } /** * @brief This function handles USB Low Priority or CAN RX0 interrupts * requests. * @param None * @retval : None */ void USB_LP_CAN1_RX0_IRQHandler(void) { // u32 i; CanRxMsg RxMessage; if(SET == CAN_GetITStatus(CAN1,CAN_IT_FF0)) { CAN_ClearITPendingBit(CAN1,CAN_IT_FF0); } else if(SET == CAN_GetITStatus(CAN1,CAN_IT_FOV0)) { CAN_ClearITPendingBit(CAN1,CAN_IT_FOV0); } else { CAN_Receive(CAN1, CAN_FIFO0, &RxMessage); InsertCanQueue(RxMessage); // printf("CAN_FIFO0 RxMessage.StdId is 0x%x\r\n",RxMessage.StdId); // printf("RxMessage.DLC is 0x%x\r\n",RxMessage.DLC); // for(i = 0; i < RxMessage.DLC; i++) // { // printf("data[%d] is 0x%x\r\n",i,RxMessage.Data); // } // printf("\r\n"); } } void CAN1_RX1_IRQHandler(void) { // u32 i; CanRxMsg RxMessage; if(SET == CAN_GetITStatus(CAN1,CAN_IT_FF1)) { CAN_ClearITPendingBit(CAN1,CAN_IT_FF1); } else if(SET == CAN_GetITStatus(CAN1,CAN_IT_FOV1)) { CAN_ClearITPendingBit(CAN1,CAN_IT_FOV1); } else { CAN_Receive(CAN1, CAN_FIFO1, &RxMessage); InsertCanQueue(RxMessage); // printf("CAN_FIFO1 RxMessage.StdId is 0x%x\r\n",RxMessage.StdId); // printf("RxMessage.DLC is 0x%x\r\n",RxMessage.DLC); // for(i = 0; i < RxMessage.DLC; i++) // { // printf("data[%d] is 0x%x\r\n",i,RxMessage.Data); // } // printf("\r\n"); } } void CAN1_SCE_IRQHandler(void) { } can.h文件 #ifndef __CAN_H__ #define __CAN_H__ void CAN_init(void); int CAN_tx_data(void); int CAN_tx_msg(CanTxMsg TxMessage); #endif can_queue.c文件 #include "includes.h" struct _CANQueue CANQueue; /******************************************************************* 作 者: 版 权: 函数名称: 函数功能: 清除通信队列 入口参数: 无 返 回 值: 无 相关调用: 备 注: 修改信息: ********************************************************************/ void ClearCanQueue(void) { int i; for(i = 0; i < MAX_CAN_SIZE; i++) { memset(&CANQueue.Elem,0,sizeof(CanRxMsg)); } CANQueue.front = 0; CANQueue.rear = 0; } /******************************************************************* 作 者: 版 权: 函数名称: 函数功能: 判断串口队列是否为空 入口参数: 返 回 值: 1: 空; 0:非空 相关调用: 备 注: 修改信息: ********************************************************************/ u8 IsEmptyCanQueue(void) { if(CANQueue.front == CANQueue.rear) { return 1; } else { return 0; } } /******************************************************************* 作 者: 版 权: 函数名称: 函数功能: 判队列是否满 入口参数: 返 回 值: 1: 满; 0:非满 相关调用: 备 注: 修改信息: ********************************************************************/ u8 IsFullCanQueue(void) { if( CANQueue.front == (CANQueue.rear+1) % MAX_CAN_SIZE) { return 1; } else { return 0; } } /******************************************************************* 作 者: 版 权: 函数名称: 函数功能: 将数据插入队列 入口参数: element:被插元素 返 回 值: 1: 成功; 0:失败 相关调用: 备 注: 修改信息: ********************************************************************/ u8 InsertCanQueue(CanRxMsg element) { if(!IsFullCanQueue()) //是否为满 { memcpy(&CANQueue.Elem[CANQueue.rear],&element,sizeof(CanRxMsg)); CANQueue.rear = (CANQueue.rear + 1) % MAX_CAN_SIZE; return 1; } else //队列满 { // printf("CAN queue is full\r\n"); return 0; } } /******************************************************************* 作 者: 版 权: 函数名称: 函数功能: 重新设置队列头指针 入口参数: head: 新头 返 回 值: 无 相关调用: 备 注: 修改信息: ********************************************************************/ void SetHeadCanQueue(u16 head) { if(CANQueue.front != CANQueue.rear) { CANQueue.front = head; } } /******************************************************************* 作 者: 版 权: 函数名称: 函数功能: 取对头 入口参数: head:对头;*element;数据 返 回 值: 1: 成功 0: 失败 相关调用: 备 注: 修改信息: ********************************************************************/ u8 GetCanQueue(u16 head,CanRxMsg *element) { if(head != CANQueue.rear) //到队列尾 { memcpy(element,&CANQueue.Elem[head],sizeof(CanRxMsg));//得到数据 return 1; } else { return 0; //无指定对头数据 } } /******************************************************************* 作 者: 版 权: 函数名称: 函数功能: can数据处理 入口参数: 返 回 值: 相关调用: 备 注: 修改信息: ********************************************************************/ void Can_data_process(void) { u16 head; // u32 i; CanRxMsg RxMessage; CanTxMsg TxMessage; head = CANQueue.front; if(1 == GetCanQueue(head,&RxMessage)) { head = (head + 1) % MAX_CAN_SIZE; //查询头前滚 SetHeadCanQueue(head); // printf("RxMessage.StdId is 0x%x\r\n",RxMessage.StdId); // printf("RxMessage.DLC is 0x%x\r\n",RxMessage.DLC); // for(i = 0; i < RxMessage.DLC; i++) // { // printf("data[%d] is 0x%x\r\n",i,RxMessage.Data); // } // printf("\r\n"); // 把接收到的数据发回去 /* transmit */ // TxMessage.StdId=RxMessage.StdId; TxMessage.StdId=0x5f1; TxMessage.RTR=RxMessage.RTR; TxMessage.IDE=RxMessage.IDE; TxMessage.DLC=RxMessage.DLC; memcpy(TxMessage.Data,RxMessage.Data,TxMessage.DLC); CAN_tx_msg(TxMessage); } else { // printf("CAN queue is empty\r\n"); } } can_queue.h文件 #ifndef CAN_QUEUE_H_ #define CAN_QUEUE_H_ #define MAX_CAN_SIZE 50 struct _CANQueue { CanRxMsg Elem[MAX_CAN_SIZE]; u16 front; u16 rear; }; void ClearCanQueue(void); u8 IsEmptyCanQueue(void); u8 IsFullCanQueue(void); u8 InsertCanQueue(CanRxMsg element); void SetHeadCanQueue(u16 head); u8 GetCanQueue(u16 head,CanRxMsg *element); void Can_data_process(void); #endif 参考一下吧!!
回复第 2 楼 于2013-08-31 10:07:37发表: PC机上没有CAN接口,直接通信不可行的,必须用一个转换模块,比如232转CAN接口, USB转CAN接口,这样才能让计算机和你的STM32 CAN接口通信,买了这样的接口后,只需要实现CAN协议代码即可 不好意思 很久没有进来了,这个问题已经解决了,谢谢!但是现在又出现一个新的问题了,STM32 CAN 通信中发送邮箱空中断,不管怎么样配置都进不去主要代码如下: void Can_Normal(void) { CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; CanTxMsg TxMessage; volatile u8 TransmitMailbox = 0; /* CAN register init */ CAN_DeInit(CAN1); CAN_StructInit(&CAN_InitStructure); /* CAN cell init */ CAN_InitStructure.CAN_TTCM=DISABLE; //???1ê±??′¥·¢í¨???£ê? CAN_InitStructure.CAN_ABOM=DISABLE; //???1×??ˉà????£ê? CAN_InitStructure.CAN_AWUM=DISABLE; //???1×??ˉ??D??£ê? CAN_InitStructure.CAN_NART=DISABLE; //???1·?×??ˉ??′??£ê? CAN_InitStructure.CAN_RFLM=DISABLE; //???1?óê?FIFO???¨?£ê? CAN_InitStructure.CAN_TXFP=DISABLE; //???1·¢?íFIFOó??è?? CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; // CAN_Mode_Normal; CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; CAN_InitStructure.CAN_BS1=CAN_BS1_8tq; //ò??-????o?á? CAN_InitStructure.CAN_BS2=CAN_BS2_7tq; CAN_InitStructure.CAN_Prescaler=5; CAN_Init(CAN1,&CAN_InitStructure); CAN_OperatingModeRequest( CAN1, CAN_OperatingMode_Normal); /* CAN filter init */ CAN_FilterInitStructure.CAN_FilterNumber=0; CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //?á±????£ê? CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0; CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; CAN_FilterInit(&CAN_FilterInitStructure); /* transmit 1 message */ /* TxMessage.StdId=0x11; //TxMessage.ExtId=0x1234; TxMessage.IDE=CAN_ID_STD; //à??1??ê? TxMessage.RTR=CAN_RTR_DATA; //′?ê????¢μ???ààDí?aêy?Y??£¨?1óD??3ì??£? TxMessage.DLC=6; // TxMessage.Data[0]='?'; TxMessage.Data[0]=0x55; TxMessage.Data[1]=0x55; TxMessage.Data[2]=0x55; TxMessage.Data[3]=0x55; TxMessage.Data[4]=0x55; TxMessage.Data[5]=0x55; */ CAN_ITConfig(CAN1,CAN_IT_TME,ENABLE); TransmitMailbox = CAN_Transmit(CAN1,&TxMessage); // printf("receive data:0X%X,0X%X,0X%X,0X%X,0X%X,0X%X",TxMessage.Data[0], TxMessage.Data[1], TxMessage.Data[2], TxMessage.Data[3], TxMessage.Data[4], TxMessage.Data[5]); } 是不是哪里配置错了呢?求指教
所在话题
参与活动
-
滴滴押注社区团购,明确“投入不设上限,要做市场第一”
线下 2020-10-16 -
滴滴押注社区团购,明确“投入不设上限,要做市场第一”
网络 2020-10-16 -
滴滴押注社区团购,明确“投入不设上限,要做市场第一”
网络 2020-10-16 -
滴滴押注社区团购,明确“投入不设上限,要做市场第一”
网络 2020-10-16 -
滴滴押注社区团购,明确“投入不设上限,要做市场第一”
线下 2020-10-16 -
滴滴押注社区团购,明确“投入不设上限,要做市场第一”
线下 2020-10-16



