你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32实现CAN发送邮箱空中断

[复制链接]
zhangxm6 提问时间:2013-11-28 21:05 /
 当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);
}
1 收藏 评论5 发布时间:2013-11-28 21:05

举报

5个回答
Hiker天下 回答时间:2013-11-29 13:14:02

RE:stm32实现CAN发送邮箱空中断

怎么没看到CAN时钟分频配置呢?CAN_InitStructure.CAN_Prescaler
勒布朗 回答时间:2013-11-29 21:34:16

RE:stm32实现CAN发送邮箱空中断

can时钟问题。没有分频
hlt512 回答时间:2013-11-30 10:23:39

RE:stm32实现CAN发送邮箱空中断

利用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
参考一下吧!!
stm32liusheng 回答时间:2022-10-27 16:59:01
hlt512 发表于 2013-11-30 10:23
利用stm32实现了1个简单的CAN功能,使用了队列缓存
can.c 文件
#include "includes.h"

这里的库是哪个版本的? 函数  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

stm32liusheng 回答时间:2022-10-27 17:00:17
看了一下 函数原型 ,的确是判断 RQCP, 哈哈,见笑了
    case CAN_IT_TME:
               /* Check CAN_TSR_RQCPx bits */
                     itstatus = CheckITStatus(CANx->TSR, CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2);

确实是判断的这个寄存器 RQCP位!并且是直接判断3个发送邮箱的发送成功位 非常好用!

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版