打印

求助!STM32F107的CAN1CAN2互发连续发送多个报文后面的报文丢失

[复制链接]
5186|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yinhao_1989|  楼主 | 2013-7-25 17:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
根据网上前辈们的指示,现在已经能用CAN1发送,CAN2接收中断处理,可以实现了CAN互发通信了。但是当连续发送3个以上报文时,接收到的后面的报文将会丢失。但是在调试的时候又不会丢失,直接运行就会丢失。
我觉得是FIFO只有3级,只能储存3个报文的原因,但是现实情况需要连续发送很多报文,请教各位前辈如何实现好。
下面是我的程序主要代码:
//main.c文件
#include "stm32f10x.h"
#include "GLCD.h"
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
volatile TestStatus TestRx;
vu32 ret; /* for return of the interrupt handling */
u8 Row = 0;
TestStatus CAN_Interrupt(void);
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
   /* Configure PD.02, PD.03, PD.04 and PD.07 as Output push-pull */
   // For STM3210B-LK1 use PD.02 -PC.07
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_7;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOD, &GPIO_InitStructure);
   /* Configure CAN pin: RX */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
   GPIO_Init(GPIOD, &GPIO_InitStructure);
  
   /* Configure CAN pin: TX */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
   GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_Remap2_CAN1, ENABLE );    //重影射CAN IO脚到 PD0,PD1
/* Configure CAN2 pin: RX */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
   GPIO_Init(GPIOB, &GPIO_InitStructure);
  
   /* Configure CAN2 pin: TX */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
   GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_Remap_CAN2, ENABLE );    //重影射CAN2 IO脚到 PB5,PB6
}
//系统中断管理
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
/* enabling interrupt */
   NVIC_InitStructure.NVIC_IRQChannel=CAN2_RX0_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
}
//配置系统时钟,使能各外设时钟
void RCC_Configuration(void)
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOD
         | RCC_APB2Periph_AFIO , ENABLE );
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2, ENABLE);
}
//LCD上显示工程标题
void LCD_Configuration(void)

{
   GLCD_init();
   GLCD_clear(White);
   GLCD_setTextColor(Blue);
   GLCD_displayStringLn(Line1, "     GoldBull");//在液晶上显示字符串
   GLCD_displayStringLn(Line2, "   CAN1 send");
   GLCD_setTextColor(Red);
   GLCD_displayStringLn(Line3, "   CAN2 receive");
}
//配置所有外设
void Init_All_Periph(void)
{
RCC_Configuration();
LCD_Configuration();
GPIO_Configuration();
NVIC_Configuration();
}
int main(void)
{  
Init_All_Periph();
    TestRx = CAN_Interrupt();
   if (TestRx == FAILED)
   {
     GPIO_SetBits(GPIOD, GPIO_Pin_7);  //LED4
   }
   else
   {
     GPIO_SetBits(GPIOD, GPIO_Pin_3); //LED2
  }  
  while(1)
   {
   }
}
/* 中断收发函数 */
TestStatus CAN_Interrupt(void)
{
CAN_InitTypeDef        CAN_InitStructure;
CAN_FilterInitTypeDef  CAN_FilterInitStructure;
CanTxMsg TxMessage;
u32 i = 0;

/* CAN register init */
CAN_DeInit(CAN1);
CAN_DeInit(CAN2);
CAN_StructInit(&CAN_InitStructure);

/* CAN cell init */
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_8tq;
CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
CAN_InitStructure.CAN_Prescaler=9;
CAN_Init(CAN1,&CAN_InitStructure);
CAN_Init(CAN2,&CAN_InitStructure);

/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber=14;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0220;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);

/* CAN FIFO0 message pending interrupt enable */
CAN_ITConfig(CAN2,CAN_IT_FMP0, ENABLE);
CAN_ITConfig(CAN2,CAN_IT_FOV0, ENABLE);

/* transmit 1 message */
TxMessage.StdId=0x11;
TxMessage.ExtId=0;
TxMessage.IDE=CAN_ID_STD;
TxMessage.RTR=CAN_RTR_DATA;
TxMessage.DLC=8;
TxMessage.Data[0]=0x30;
TxMessage.Data[1]=0x31;
TxMessage.Data[2]=0x32;
TxMessage.Data[3]=0x33;
TxMessage.Data[4]=0x34;
TxMessage.Data[5]=0x35;
TxMessage.Data[6]=0x36;
TxMessage.Data[7]=0x37;
CAN_Transmit(CAN1,&TxMessage);
TxMessage.Data[0]=0x31;
CAN_Transmit(CAN1,&TxMessage);
TxMessage.Data[0]=0x32;
CAN_Transmit(CAN1,&TxMessage);
/*
ret = 0xFF;
i=0;
while((ret == 0xFF) && (i < 0xFFF))
{
  i++;
}
//加上这一段代码就能接收到6条报文,但我不能每各3个报文就加一段这个吧
*/
TxMessage.Data[0]=0x33;
CAN_Transmit(CAN1,&TxMessage);
TxMessage.Data[0]=0x34;
CAN_Transmit(CAN1,&TxMessage);
   
TxMessage.Data[0]=0x35;
CAN_Transmit(CAN1,&TxMessage);

ret = 0xFF;
i=0;
while((ret == 0xFF) && (i < 0xFFF))
{
  i++;
}

if (i == 0xFFF)
{
  ret=0;  
}

/* disable interrupt handling */
CAN_ITConfig(CAN2,CAN_IT_FMP0, DISABLE);

return (TestStatus)ret;
}
/* 中断响应函数 */
void CAN2_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
RxMessage.StdId=0x00;
RxMessage.ExtId=0x00;

CAN_Receive(CAN2,CAN_FIFO0, &RxMessage);

if((RxMessage.StdId==0x11) && (RxMessage.IDE==CAN_ID_STD)
  && (RxMessage.DLC==8))
{
  ret = 1;
  Row += 24;//液晶里每一行高度为24
  GLCD_displayStringLn(Line3 + Row, RxMessage.Data);
}
else
{
  ret = 0;
}
}

//can.c里
uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage)
{
  uint8_t transmit_mailbox = 0;
  /* Check the parameters */
  assert_param(IS_CAN_ALL_PERIPH(CANx));
  assert_param(IS_CAN_IDTYPE(TxMessage->IDE));
  assert_param(IS_CAN_RTR(TxMessage->RTR));
  assert_param(IS_CAN_DLC(TxMessage->DLC));

  /* Select one empty transmit mailbox */
  if ((CANx->TSR&TSR_TME0) == TSR_TME0)
  {
    transmit_mailbox = 0;
  }
  else if ((CANx->TSR&TSR_TME1) == TSR_TME1)
  {
    transmit_mailbox = 1;
  }
  else if ((CANx->TSR&TSR_TME2) == TSR_TME2)
  {
    transmit_mailbox = 2;
  }
  else
  {
    transmit_mailbox = CAN_NO_MB;
  }

  if (transmit_mailbox != CAN_NO_MB)
  {
    /* Set up the Id */
    CANx->sTxMailBox[transmit_mailbox].TIR &= TMIDxR_TXRQ; //TIR清空
    if (TxMessage->IDE == CAN_ID_STD)
    {
      assert_param(IS_CAN_STDID(TxMessage->StdId));  
      CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage->StdId << 21) | TxMessage->RTR);
    }
    else
    {
      assert_param(IS_CAN_EXTID(TxMessage->ExtId));
      CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage->ExtId<<3) | TxMessage->IDE |
                                               TxMessage->RTR);
    }
   

    /* Set up the DLC */
    TxMessage->DLC &= (uint8_t)0x0000000F;
    CANx->sTxMailBox[transmit_mailbox].TDTR &= (uint32_t)0xFFFFFFF0;
    CANx->sTxMailBox[transmit_mailbox].TDTR |= TxMessage->DLC;

    /* Set up the data field */
    CANx->sTxMailBox[transmit_mailbox].TDLR = (((uint32_t)TxMessage->Data[3] << 24) |
                                             ((uint32_t)TxMessage->Data[2] << 16) |
                                             ((uint32_t)TxMessage->Data[1] << 8) |
                                             ((uint32_t)TxMessage->Data[0]));
    CANx->sTxMailBox[transmit_mailbox].TDHR = (((uint32_t)TxMessage->Data[7] << 24) |
                                             ((uint32_t)TxMessage->Data[6] << 16) |
                                             ((uint32_t)TxMessage->Data[5] << 8) |
                                             ((uint32_t)TxMessage->Data[4]));
    /* Request transmission */
    CANx->sTxMailBox[transmit_mailbox].TIR |= TMIDxR_TXRQ;  //TIR的TXRQ(最低位)为1则请求发送邮箱数据
  }
  return transmit_mailbox;
}
void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage)
{
  /* Check the parameters */
  assert_param(IS_CAN_ALL_PERIPH(CANx));
  assert_param(IS_CAN_FIFO(FIFONumber));
  /* Get the Id */
  RxMessage->IDE = (uint8_t)0x04 & CANx->sFIFOMailBox[FIFONumber].RIR;
  if (RxMessage->IDE == CAN_ID_STD)
  {
    RxMessage->StdId = (uint32_t)0x000007FF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 21);
  }
  else
  {
    RxMessage->ExtId = (uint32_t)0x1FFFFFFF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 3);
  }
  
  RxMessage->RTR = (uint8_t)0x02 & CANx->sFIFOMailBox[FIFONumber].RIR;
  /* Get the DLC */
  RxMessage->DLC = (uint8_t)0x0F & CANx->sFIFOMailBox[FIFONumber].RDTR;
  /* Get the FMI */
  RxMessage->FMI = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDTR >> 8);
  /* Get the data field */
  RxMessage->Data[0] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDLR;
  RxMessage->Data[1] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 8);
  RxMessage->Data[2] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 16);
  RxMessage->Data[3] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 24);
  RxMessage->Data[4] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDHR;
  RxMessage->Data[5] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 8);
  RxMessage->Data[6] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 16);
  RxMessage->Data[7] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 24);
  /* Release the FIFO */
  CAN_FIFORelease(CANx, FIFONumber);
}
沙发
trumpxp| | 2013-7-25 19:19 | 只看该作者
帮你顶一个   楼主   这一块不是很了解啊   顶一个

使用特权

评论回复
板凳
trumpxp| | 2013-7-25 19:22 | 只看该作者
呼唤一下版主   看看版主能不能解决这个问题  

使用特权

评论回复
地板
978462113| | 2013-10-30 15:11 | 只看该作者
楼主,能把这程序发给我一份吗?我最近也在弄这个,一直没有调通,希望楼主能指点一下我,我的邮箱是978462113@qq.com有机会一起学习,万分感谢。

使用特权

评论回复
5
hrt323447| | 2014-5-15 21:44 | 只看该作者
这个应该是一块f10x板子,can1和can2之间的通信,硬件连接所有tx、rx连一块,是这样吧?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

6

帖子

0

粉丝