再次请教版主STM32的CAN问题

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

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

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

回复评论 (12)

贴下代码,有用过的兄弟帮忙看下

#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();
      
}
点赞  2010-6-10 22:02
然后是设置速率和过滤器
/**
  * @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);

}
点赞  2010-6-10 22:03
然后是查询发送的方式
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 */
}
点赞  2010-6-10 22:04
这段测试程序放到裸奔程序没有任何问题。
采用lookback方式打印出来接收到的数据也没有问题,用示波器测试CAN的发送脚就是没有任何数据,一直为高电平3.3V。
点赞  2010-6-10 22:06

6楼 zlw 

                                 关注,我也准备实验这段程序
点赞  2010-6-11 08:45
                                 跟UCOS无关。从症状上来看,应该是CAN的发送引脚跟某些其它外设共用了引脚,导致CAN_TX不正常。其它外设不初始化,就可以找到问题了。
点赞  2010-6-11 09:10
问题解决了。的确跟UCOS没有关系,也跟其他引脚没有关系,设置CAN发送脚时,加了个
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
就可以用了,折腾了我2天,天啊。
点赞  2010-6-11 11:10
裸机跑的时候不加也没有问题,奇怪。我用的是3.0的版本,最新的版本好像已经加了这句。
看样子得用最新的库了,哪位兄弟提供个链接?
点赞  2010-6-11 11:14
你LINUX驱动搞的怎么样了?
搞的怎么样什么意思啊,呵呵
点赞  2010-6-11 11:15
CAN_Mode_LoopBack模式时,信号不会发送到TX引脚上,
你将模式改为正常模式
点赞  2010-6-11 16:35
                                 谢谢LS的回答,此问题已经解决,对stm32的CAN的lookback的理解,你可能有些问题,可以去看看STM32关于lookback方式的定义,
点赞  2010-6-11 21:35


哥哥我爱死你了 ,我就是这个问题 一摸一样的,看了你的帖子使我茅塞顿开
帮我大忙了,但是不知道为什么,原来的库不加也没事?
点赞  2010-12-14 18:40
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复