zhangxm6 发表于 2013-11-28 21:05:45

stm32实现CAN发送邮箱空中断

 当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=0x55;
        TxMessage.Data=0x55;
        TxMessage.Data=0x55;
        TxMessage.Data=0x55;
        TxMessage.Data=0x55;
        TxMessage.Data=0x55;
*/         
        CAN_ITConfig(CAN1,CAN_IT_TME,ENABLE);                       //发送邮箱空时中断
 
    TransmitMailbox = CAN_Transmit(CAN1,&TxMessage);
}

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_NUM3
static u8 CAN_msg_num;   // 发送邮箱标记
//

/**
* @briefConfigures the CAN, transmit and receive by polling
* @paramNone
* @retval : PASSED if the reception is well done, FAILED in other case
*/
void CAN_config_init(void)
{
CAN_InitTypeDef      CAN_InitStructure;
CAN_FilterInitTypeDefCAN_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_SRcpu_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 = 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_SRcpu_sr = 0;
    /* transmit */
    TxMessage.StdId=0x6f1;
    TxMessage.RTR=CAN_RTR_DATA;
    TxMessage.IDE=CAN_ID_STD;
    TxMessage.DLC=4;
    TxMessage.Data=0x40;
    TxMessage.Data=0x02;
    TxMessage.Data=0x1a;
    TxMessage.Data=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 = 1;
      OS_EXIT_CRITICAL();
    }
   
    CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);
    return 1;
}
// 发送中断
void USB_HP_CAN1_TX_IRQHandler(void)
{
    if(CAN_msg_num)
    {
      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;
      }
    }
   
    if(CAN_msg_num)
    {
      if(SET == CAN_GetITStatus(CAN1,CAN_IT_RQCP1))
      {
            CAN_ClearITPendingBit(CAN1,CAN_IT_RQCP1);
            CAN_ITConfig(CAN1, CAN_IT_TME, DISABLE);
            CAN_msg_num = 0;
      }
    }
   
    if(CAN_msg_num)
    {
      if(SET == CAN_GetITStatus(CAN1,CAN_IT_RQCP2))
      {
            CAN_ClearITPendingBit(CAN1,CAN_IT_RQCP2);
            CAN_ITConfig(CAN1, CAN_IT_TME, DISABLE);
            CAN_msg_num = 0;
      }
    }
   
}
/**
* @briefThis function handles USB Low Priority or CAN RX0 interrupts
*   requests.
* @paramNone
* @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,&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,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;
    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
参考一下吧!!
页: [1]
查看完整版本: stm32实现CAN发送邮箱空中断