陆超怎么不换衣服:STM32的CAN问题

来源:百度文库 编辑:中财网 时间:2024/03/29 20:54:28

备注:以下摘自论坛电子工程世界-论坛 | 传统BBS首页 ? 单片机 ? 【stm32/stm8】

下文中可以借鉴的东西:

(1)、CAN的查询初始以及查询发送和接收程序设计

(2)、在接收中的对于接收出错的处理方式。

STM32的CAN问题

提问:再次请教版主STM32CAN问题

上周就已经把CAN通讯调通了,不管是查询模式还是中断模式都跑的很好,这周给板子加了个UCOS2.86版本的。然后把CAN通讯加上去,CAN数据死活发不出来。用lookback模式自测,发现可以收到自己发出去的数据,但是用示波器测试发送脚,就是没见到波形,晚上突然有一次看到了波形,对着波形看数据,确实是我发出去的数据,害我纳闷半天,我什么都没改,怎么就好了,断电重启,又不行了,唯一好了一次,我晕。

 刚开始怀疑硬件问题,用原来的裸奔程序,CAN通讯就是OK的,硬件应该不会有问题了,问题应该就是出在我移植的UCOS上面,其实也不是移植,官方有现成的,我直接把UCOS那个文件夹就是核心的那块与处理器无关的加了进来,还有ports文件夹加了进来,改了2个中断向量,一个systick的,一个pendsv的,架构和我以前的裸奔程序是一样,在UCOS创建了几个任务,如点灯,LCD,按键,串口发送,接收(串口都是用的中断模式)都没有任何问题,就是CAN通讯死活不行,在发送脚上用示波器测,半点数据都没有,看版主或者其他兄弟有没有碰到过这种情况。

 简单点说,就是用lookback模式,程序里面自己可以接收到自己发的数据,但是tx脚就是不出数据(搞的我都以为我用的是静默方式了),各位兄弟碰到过没?

 

 

#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

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 = 0;

//   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_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_Init(GPIO_CAN, &GPIO_InitStructure);

    // 映射下

    GPIO_PinRemapConfig(GPIO_Remap_CAN , ENABLE);

    // 查询方式初始化

    CAN_Polling_init();

}

然后是设置速率和过滤器

/**

  * @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_Polling_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_LoopBack;

  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);

}

然后是查询发送的方式

 

TestStatus CAN_Polling(void)

{

  CanTxMsg TxMessage;

  CanRxMsg RxMessage;

  uint32_t i = 0;

  uint8_t TransmitMailbox = 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);

  i = 0;

// while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i != 0xFF))

  while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i <= 1000))

  {

    i++;

  }

  printf("1i is %d\r\n",i);

  i = 0;

  while((CAN_MessagePending(CAN1, CAN_FIFO0) < 1) && (i != 0xFF))

  {

    i++;

  }

   printf("2i is %d\r\n",i);

  /* receive */

  RxMessage.StdId=0x00;

  RxMessage.IDE=CAN_ID_STD;

  RxMessage.DLC=0;

  RxMessage.Data[0]=0x00;

  RxMessage.Data[1]=0x00;

  CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);

 

// printf("RxMessage.StdId is 0x%x,RxMessage.DLC is 0x%x,RxMessage.Data[0] is 0x%x,RxMessage.Data[1] is 0x%x\r\n",

//         RxMessage.StdId,RxMessage.DLC,RxMessage.Data[0],RxMessage.Data[1]);

  if (RxMessage.StdId!=0x6f1)

  {

    return FAILED; 

  }

  if (RxMessage.IDE!=CAN_ID_STD)

  {

    return FAILED;

  }

  if (RxMessage.DLC!=4)

  {

    return FAILED; 

  }

  if ((RxMessage.Data[0]<<8|RxMessage.Data[1])!=0x4002)

  {

    return FAILED;

  }

  return PASSED; /* Test Passed */

这段测试程序放到裸奔程序没有任何问题。

采用lookback方式打印出来接收到的数据也没有问题,用示波器测试CAN的发送脚就是没有任何数据,一直为高电平3.3V

问题解决了。的确跟UCOS没有关系,也跟其他引脚没有关系,设置CAN发送脚时,加了个

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

就可以用了,折腾了我2天,天啊。