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

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管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版