当CAN邮箱中空时,发生中断,但是我配置的代码怎么也进不去中断,不知道为什么?求解决,非常感谢! 主要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]=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); } |
RE:stm32实现CAN发送邮箱空中断
RE:stm32实现CAN发送邮箱空中断
RE:stm32实现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
参考一下吧!!
这里的库是哪个版本的? 函数 CAN_GetITStatus()的参数2类型,在判断CAN发送完成的时候,给的参数是RQCP1,
我知道在发送一次完成的时候 手册确实写的是RQCP和 TXOK位都会置位,但是 在库函数的 参数参考值中 并没有判断此参数。我就想问一下,是不是就只能判断为第一类 参数参考值: CAN_IT_TME,发送邮箱empty空?它
This parameter can be one of the following flags:
* - CAN_IT_TME
* - CAN_IT_FMP0
* - CAN_IT_FF0
* - CAN_IT_FOV0
* - CAN_IT_FMP1
* - CAN_IT_FF1
* - CAN_IT_FOV1
* - CAN_IT_WKU
* - CAN_IT_SLK
* - CAN_IT_EWG
* - CAN_IT_EPV
* - CAN_IT_BOF
* - CAN_IT_LEC
* - CAN_IT_ERR
case CAN_IT_TME:
/* Check CAN_TSR_RQCPx bits */
itstatus = CheckITStatus(CANx->TSR, CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2);
确实是判断的这个寄存器 RQCP位!并且是直接判断3个发送邮箱的发送成功位 非常好用!