OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 15320|回复: 10

CAN通信问题!(解决)

[复制链接]

43

主题

228

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1074
金钱
1074
注册时间
2012-1-10
在线时间
238 小时
发表于 2012-5-12 22:41:59 | 显示全部楼层 |阅读模式


/*****************************************************************
*
* 文件名: main.c
* 内容简述: 本实验测试开发板上的CAN接口是否正常(Normal方式)
*   
*
******************************************************************/
#include "stm32f10x.h"
#include "systick.h"
#include <stdlib.h>
#include <stdio.h>


/* Private variables ---------------------------------------------------------*/
uint16_t CAN_ID;
uint8_t CAN_DATA0,CAN_DATA1,CAN_DATA2,CAN_DATA3,CAN_DATA4,CAN_DATA5,CAN_DATA6,CAN_DATA7;
uint8_t CanFlag,Display;

 

/*************************************************
函数: void RCC_Configuration(void)
功能: 复位和时钟控制 配置
参数: 无
返回: 无
**************************************************/
void RCC_Configuration(void)
{
  ErrorStatus HSEStartUpStatus;                    //定义外部高速晶体启动状态枚举变量
  RCC_DeInit();                                    //复位RCC外部设备寄存器到默认值
  RCC_HSEConfig(RCC_HSE_ON);                       //打开外部高速晶振
  HSEStartUpStatus = RCC_WaitForHSEStartUp();      //等待外部高速时钟准备好
  if(HSEStartUpStatus == SUCCESS)                  //外部高速时钟已经准别好
  {
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //开启FLASH预读缓冲功能,加速FLASH的读取。所有程序中必须的用法.位置:RCC初始化子函数里面,时钟起振之后
    FLASH_SetLatency(FLASH_Latency_2);                    //flash操作的延时
       
    RCC_HCLKConfig(RCC_SYSCLK_Div1);               //配置AHB(HCLK)时钟等于==SYSCLK
    RCC_PCLK2Config(RCC_HCLK_Div1);                //配置APB2(PCLK2)钟==AHB时钟
    RCC_PCLK1Config(RCC_HCLK_Div2);                //配置APB1(PCLK1)钟==AHB1/2时钟
        
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  //配置PLL时钟 == 外部高速晶体时钟 * 9 = 72MHz
    RCC_PLLCmd(ENABLE);                                   //使能PLL时钟
  
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)    //等待PLL时钟就绪
    {
    }
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);            //配置系统时钟 = PLL时钟
    while(RCC_GetSYSCLKSource() != 0x08)                  //检查PLL时钟是否作为系统时钟
    {
    }
  }

}


/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : Configures the different GPIO ports.
* Input          : None
* Output         : None
* Return         : None
* Attention   : None
*******************************************************************************/
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  /* CAN Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD  | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF | RCC_APB2Periph_AFIO ,ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
  GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);
  /* Configure CAN pin: RX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOB, &GPIO_InitStructure);  
  /* Configure CAN pin: TX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);     
/**
 *  LED1 -> PE0 , LED2 -> PE1 , LED3 -> PE2 , LED4 -> PE3
 */     
//  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//  GPIO_Init(GPIOE, &GPIO_InitStructure);
  GPIO_Init(GPIOF, &GPIO_InitStructure);
}

/*******************************************************************************
* Function Name  : NVIC_Configuration
* Description    : Configures the nested vectored interrupt controller.
* Input          : None
* Output         : None
* Return         : None
* Attention   : None
*******************************************************************************/
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* 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);
}

/*******************************************************************************
* Function Name  : CAN_Configuration
* Description    : Configures the CAN
* Input          : None
* Output         : None
* Return         : None
* Attention   : None
*******************************************************************************/
void CAN_Configuration(void)
{
  CAN_InitTypeDef        CAN_InitStructure;
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;

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

  /* CAN cell init */
  CAN_InitStructure.CAN_TTCM = DISABLE; /* 时间触发禁止, 时间触发:CAN硬件的内部定时器被激活,并且被用于产生时间戳 */
  CAN_InitStructure.CAN_ABOM = DISABLE; /* 自动离线禁止,自动离线:一旦硬件监控到128次11个隐性位,就自动退出离线状态。在这里要软件设定后才能退出 */
  CAN_InitStructure.CAN_AWUM = DISABLE; /* 自动唤醒禁止,有报文来的时候自动退出休眠 */
  CAN_InitStructure.CAN_NART = DISABLE; /* 报文重传, 如果错误一直传到成功止,否则只传一次 */
  CAN_InitStructure.CAN_RFLM = DISABLE; /* 接收FIFO锁定, 1--锁定后接收到新的报文摘不要,0--接收到新的报文则覆盖前一报文 */
  CAN_InitStructure.CAN_TXFP = ENABLE;  /* 发送优先级  0---由标识符决定  1---由发送请求顺序决定 */
  CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;//CAN_Mode_LoopBack; /* 模式 */
  CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;      /* 重新同步跳宽,只有can硬件处于初始化模式时才能访问这个寄存器 */
  CAN_InitStructure.CAN_BS1 = CAN_BS1_8tq;      /* 时间段1 */
  CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq;      /* 时间段2 */
  CAN_InitStructure.CAN_Prescaler = 9;         /* 波特率预分频数 */ 
 //(pclk1/((1+8+7)*9)) = 36Mhz/16/9 = 250Kbits设定了一个时间单位的长度9

  /* 波特率计算方法 */
  /* CANbps= Fpclk/((BRP+1)*((Tseg1+1)+(Tseg2+1)+1)  此处计算为  CANbps=36000000/(45*(4+3+1))=100kHz */                   //此处Tseg1+1 = CAN_BS1_8tp
  /* 配置大方向: Tseg1>=Tseg2  Tseg2>=tq; Tseg2>=2TSJW */
   
  if (CAN_Init(CAN1,&CAN_InitStructure) == CANINITFAILED)   
  {
    /* 初始化时先设置CAN_MCR的初始化位 */                
    /* 然后查看硬件是否真的设置了CAN_MSR的初始化位来确认是否进入了初始化模式  */                                 
  } 
  /* 配置CAN过滤器 */
  /* 32位对应的id */
  /* stdid[10:0],extid[17:0],ide,rtr */
  /* 16位对应的id */
  /* stdid[10:0],ide,rtr,extid[17:15] */
  /* 一般使用屏蔽模式 */
  /* 要注意的是fifo接收存满了中断,还有就是fifo的概念,即取的一直是最早那一个数据, 要释放才能取下一个数据 */
  /* 常使用的中断有 */
  /* 1,有信息中断,即fifo挂号中断 */
  /* 2,fifo满中断 */
  /* 3,fifo满之后又有信息来则中断,即fifo溢出中断 */
  CAN_FilterInitStructure.CAN_FilterNumber=0;     /* 过滤器0 */
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;  /* 屏敝模式 */
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; /* 32位 */
  CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;  /* 以下四个都为0, 表明不过滤任何id */
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;  /* 能够通过该过滤器的报文存到fifo0中 */
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);

  CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);   /* 挂号中断, 进入中断后读fifo的报文函数释放报文清中断标志 */
}

/*******************************************************************************
* Function Name  : CanWriteData
* Description    : Can Write Date to CAN-BUS
* Input          : None
* Output         : None
* Return         : None
* Attention   : None
*******************************************************************************/
unsigned char CanWriteData(void)
{
  CanTxMsg TxMessage;
  u32 i = 0;
  u8 TransmitMailbox = 0;

  CAN_DATA0=rand()%0xff;  CAN_DATA1=rand()%0xff; 
  CAN_DATA2=rand()%0xff;  CAN_DATA3=rand()%0xff; 
  CAN_DATA4=rand()%0xff;  CAN_DATA5=rand()%0xff;
  CAN_DATA6=rand()%0xff;  CAN_DATA7=rand()%0xff;

  /* transmit */
  TxMessage.StdId = 0x11;  /* 设置标准id  注意标准id的最高7位不能全是隐性(1)。共11位 */
//  TxMessage.ExtId = 0x1234;     //设置扩展id  扩展id共18位
  TxMessage.RTR = CAN_RTR_DATA; /* 设置为数据帧 */
  TxMessage.IDE = CAN_ID_STD;   /* 使用标准id */
  TxMessage.DLC = 8;            /* 数据长度, can报文规定最大的数据长度为8字节 */
  TxMessage.Data[0] = CAN_DATA0;   
  TxMessage.Data[1] = CAN_DATA1;   
  TxMessage.Data[2] = CAN_DATA2;   
  TxMessage.Data[3] = CAN_DATA3;   
  TxMessage.Data[4] = CAN_DATA4;   
  TxMessage.Data[5] = CAN_DATA5;    
  TxMessage.Data[6] = CAN_DATA6;   
  TxMessage.Data[7] = CAN_DATA7;     
//  CAN_Transmit(CAN1,&TxMessage);  /* 返回这个信息请求发送的邮箱号0,1,2或没有邮箱申请发送no_box */
 
 
  TransmitMailbox = CAN_Transmit(CAN1,&TxMessage);//开始一个消息的传输
  i = 0;
  while(CAN_TransmitStatus(CAN1,TransmitMailbox) != CANTXOK)//通过检查CANTXOK位来确认发送是否成功
  {
    i++;
    }
  if(i==0xff)//发送超时,但发送不成功
  {
    return 0;
  }else{
    return 1; 
  } 
}

/*******************************************************************************
* Function Name  : USB_LP_CAN1_RX0_IRQHandler
* Description    : This function handles USB Low Priority or CAN RX0 interrupts
* Input          : None
* Output         : None
* Return         : None
* Attention   : None
*******************************************************************************/
void USB_LP_CAN1_RX0_IRQHandler(void)
{
  CanRxMsg RxMessage;
  CAN_Receive(CAN1,CAN_FIFO0, &RxMessage);  /* 此函数包含释放提出报文了的,在非必要时,不需要自己释放 */
  CAN_ID=RxMessage.StdId;
  CAN_DATA0=RxMessage.Data[0];
  CAN_DATA1=RxMessage.Data[1];
  CAN_DATA2=RxMessage.Data[2];
  CAN_DATA3=RxMessage.Data[3];
  CAN_DATA4=RxMessage.Data[4];
  CAN_DATA5=RxMessage.Data[5];
  CAN_DATA6=RxMessage.Data[6];
  CAN_DATA7=RxMessage.Data[7];
  CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);  /* 清除挂起中断 */
  CanFlag = ENABLE;
}

/*************************************************
函数: int main(void)
功能: main主函数
参数: 无
返回: 无
**************************************************/
int main(void)
{
 delay_init();       //初始化延迟函数

    RCC_Configuration();
 GPIO_Configuration();
    CAN_Configuration();


    /* Infinite loop */
    while (1)
 {
   if( CanFlag == ENABLE )
   {
     CanFlag = DISABLE;
        GPIO_SetBits(GPIOF , GPIO_Pin_7);
     delay_ms(1000);  /* delay 200ms */
   }
   GPIO_ResetBits(GPIOF , GPIO_Pin_7);  
   CanWriteData();

      if( Display )
   {
        /*====LED-ON=======*/

     GPIO_SetBits(GPIOF , GPIO_Pin_6); 
   } 
   else
   {
     /*====LED-OFF=======*/

     GPIO_ResetBits(GPIOF , GPIO_Pin_6);
 
   }
   Display = ~Display;    
   delay_ms(500);  /* delay 200ms */ 
    }
}

/*******************************************************************************
* Function Name  : fputc
* Description    : Retargets the C library printf function to the USART.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
int fputc(int ch, FILE *f)    //在源代码中添加fputc函数,可以用printf函数做为调试输出
{
  /* 将Printf内容发往串口 */
  USART_SendData(USART1, (u8) ch);
   
  /* 循环,直到传送完成 */
  while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
  {
  }
   
  return ch;
}


问题:CAN_Mode_LoopBack模式正常(单机),CAN_Mode_Normal模式时异常(两块CAN电路板连接),仿真单步执行发现CAN发送被“挂起”,无法发送数据。我在3块电路板上都测试得到相同结果。求高手帮忙。怀疑是硬件问题:连接问题或CAN芯片损坏。谁能帮我测试下软件!

程序换成战舰can的例子,问题依旧,发送不出,接收不到。确定一定是硬件问题。

仿真发送端,调出keil中的CAN:Controller中的Error Counter报ACK Error、stuff Error,总线异常,确定是接收端的硬件问题。拿了新做的板子做测试并将can芯片换成NXP的82c250,测试可以发送和接收。测试了第二块NXP芯片的板子,也可以收发。
买到次货了VP230。坑死了。。。。。。。买了3片都是坏的。

明天去买个can的协议分析器,没这东东,两眼黑呀!!!哪有问题都不知道。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-5-13 00:34:54 | 显示全部楼层
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

58

帖子

0

精华

初级会员

Rank: 2

积分
78
金钱
78
注册时间
2012-4-29
在线时间
0 小时
发表于 2012-5-13 01:16:34 | 显示全部楼层
帮你看 一是傻了  二是神经
1.环保数采仪监控系统?2.物联网、管网监控系统?3.水文水利监控系统?4.油烟在线监控系统.?5.智能小区水电表监控系统.?提供各种自动化监控解决方案!?有需要请联系,QQ 237324479!
回复 支持 反对

使用道具 举报

19

主题

156

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
291
金钱
291
注册时间
2011-3-23
在线时间
5 小时
发表于 2012-9-22 08:40:28 | 显示全部楼层
我也遇到这个问题啊,楼上的兄弟解决了吗?
回复 支持 反对

使用道具 举报

19

主题

156

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
291
金钱
291
注册时间
2011-3-23
在线时间
5 小时
发表于 2012-9-22 08:40:38 | 显示全部楼层
回复【楼主位】magicoctoy:
---------------------------------
解决了吗?
回复 支持 反对

使用道具 举报

3

主题

10

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2011-7-12
在线时间
0 小时
发表于 2012-9-22 10:59:05 | 显示全部楼层
            这个是我的CAN通讯测试程序,可接受可发送。你参考下

ALIENTEK MINISTM32 实验CAN通讯.rar

4.69 MB, 下载次数: 2973

回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-9-22 15:11:10 | 显示全部楼层
回复【6楼】jacky_shen:
---------------------------------
谢谢分享。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

46

主题

333

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
357
金钱
357
注册时间
2013-12-12
在线时间
63 小时
发表于 2014-1-17 21:11:39 | 显示全部楼层
回复【楼主位】magicoctoy:
---------------------------------
问题解决了么?
回复 支持 反对

使用道具 举报

5

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
132
金钱
132
注册时间
2014-3-8
在线时间
19 小时
发表于 2015-7-19 16:02:41 | 显示全部楼层
回复【6楼】jacky_shen:
---------------------------------
你的这个怎么用???
回复 支持 反对

使用道具 举报

0

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
58
金钱
58
注册时间
2015-5-22
在线时间
7 小时
发表于 2015-10-16 23:20:42 | 显示全部楼层
回复【6楼】jacky_shen:
---------------------------------
你好!我在程序中怎么没有看到CAN波特率的设置呀?
回复 支持 反对

使用道具 举报

2

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
72
金钱
72
注册时间
2015-10-2
在线时间
9 小时
发表于 2016-4-20 16:44:02 | 显示全部楼层
我都混乱了,好复杂啊,。
加油,加油
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-16 21:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表