CANOPEN协议栈的移植以及使用

2019-07-20 01:19发布

这是一篇入门帖,高手请指点一下,主要是记录我对CANOPEN协议的理解以及使用。图片还没研究好怎么上传,等后面研究好了补上。第一步;新建一个工程,配置好各种时钟之类的。当然你用的是原子的板子, 你也可以拿一个LED实验或者蜂鸣器实验的工程  直接来改,你把其他的注释掉就好了。
第二步;到网上下载CanFestival源码CanFestival-3-10,解压出来,并将文件夹名字改为CanFestival-3-10。移植需要用到的源文件在CanFestival-3-10src目录下,头文件在CanFestival-3-10include目录下。
第三部;开始移植。





友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
49条回答
whj467467274672
1楼-- · 2019-07-20 04:21
 精彩回答 2  元偷偷看……
whj467467274672
2楼-- · 2019-07-20 06:04
516182660 发表于 2018-2-3 18:55
不知道能否给我一份canopen源代码,谢谢,邮箱

看附件
雨天Al2
3楼-- · 2019-07-20 10:14
 精彩回答 2  元偷偷看……
whj467467274672
4楼-- · 2019-07-20 11:15
 精彩回答 2  元偷偷看……
whj467467274672
5楼-- · 2019-07-20 11:30
通过以上步骤处理掉所有错误,对于源码的操作已经结束了,下面就是我们的底层的操作了。
接下来实现刚才定义的3个空函数,函数void setTimer(TIMEVAL value)主要被源码用来定时的,时间到了就需要调用一下函数TimeDispatch(),函数TIMEVAL getElapsedTime(void)主要被源码用来查询距离下一个定时触发还有多少时间。
我们在stm32_canfestival.c文件里定义几个变量如下:
unsigned int TimeCNT=0;//时间计数
unsigned int NextTime=0;//下一次触发时间计数
unsigned int TIMER_MAX_COUNT=70000;//最大时间计数
static TIMEVAL last_time_set = TIMEVAL_MAX;//上一次的时间计数
setTimer和getElapsedTime函数实现如下:
void setTimer(TIMEVAL value)
{
        NextTime=(TimeCNT+value)%TIMER_MAX_COUNT;
}

TIMEVAL getElapsedTime(void)
{
        int ret=0;
        ret = TimeCNT> last_time_set ? TimeCNT - last_time_set : TimeCNT + TIMER_MAX_COUNT - last_time_set;
        last_time_set = TimeCNT;
        return ret;
}

另外还要开一个1毫秒的定时器,每1毫秒调用一下下面这个函数。
void timerForCan(void)
{
        TimeCNT++;
        if (TimeCNT>=TIMER_MAX_COUNT)
        {
                TimeCNT=0;
        }
        if (TimeCNT==NextTime)
        {
                TimeDispatch();
        }
}

下面我贴上定时器的初始化代码
void TIM3_Init(void)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
       
        TIM_TimeBaseInitStructure.TIM_Period = 1000-1;
        TIM_TimeBaseInitStructure.TIM_Prescaler= 84-1;  
        TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
        TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
       
        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
       
        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
        TIM_Cmd(TIM3,ENABLE);
       
        NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03;
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);
       
}

定时器3中断服务函数
void TIM3_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //òç3öÖD¶Ï
        {
                TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
       
//        TimerForCan();
              TimeCNT++;
        if (TimeCNT>=TIMER_MAX_COUNT)
        {
                TimeCNT=0;
        }
        if (TimeCNT==NextTime)

                TimeDispatch();
      }
}



whj467467274672
6楼-- · 2019-07-20 12:45
上面讲过了定时器,下面就是CAN的发送与接收函数。
u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{

          GPIO_InitTypeDef       GPIO_InitStructure;
        CAN_InitTypeDef        CAN_InitStructure;
          CAN_FilterInitTypeDef  CAN_FilterInitStructure;
           NVIC_InitTypeDef       NVIC_InitStructure;

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);                                                                                                          
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);       
       

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
       
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1);
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1);
          
         
           CAN_InitStructure.CAN_TTCM=DISABLE;       
          CAN_InitStructure.CAN_ABOM=DISABLE;       
          CAN_InitStructure.CAN_AWUM=DISABLE;
          CAN_InitStructure.CAN_NART=ENABLE;       
          CAN_InitStructure.CAN_RFLM=DISABLE;       
          CAN_InitStructure.CAN_TXFP=DISABLE;
          CAN_InitStructure.CAN_Mode= mode;       
          CAN_InitStructure.CAN_SJW=tsjw;       
          CAN_InitStructure.CAN_BS1=tbs1;
          CAN_InitStructure.CAN_BS2=tbs2;
          CAN_InitStructure.CAN_Prescaler=brp;  
          CAN_Init(CAN1, &CAN_InitStructure);   

               
        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_Filter_FIFO0;
          CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
          CAN_FilterInit(&CAN_FilterInitStructure);
               

       
          CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);                    

          NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;         
          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
          NVIC_Init(&NVIC_InitStructure);

          return 0;
}   






                    
void CAN1_RX0_IRQHandler(void)
{
         u32 i;
   Message m;
   CanRxMsg RxMessage;
   CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);

   m.cob_id=RxMessage.StdId;
   if(RxMessage.RTR == CAN_RTR_REMOTE)
   m.rtr=1;
   else if(RxMessage.RTR == CAN_RTR_DATA)
   m.rtr=0;
   m.len=RxMessage.DLC;
   for(i = 0; i < RxMessage.DLC; i++)
   m.data[i] = RxMessage.Data[i];
   canDispatch(&TestSlave_Data, &m);
}

unsigned char canSend(CAN_PORT notused, Message *m)
{
    uint32_t  i;
          CanTxMsg  TxMessage;
    CanTxMsg *ptx_msg=&TxMessage;
    ptx_msg->StdId = m->cob_id;

    if(m->rtr)
    ptx_msg->RTR = CAN_RTR_REMOTE;
    else
    ptx_msg->RTR = CAN_RTR_DATA;

    ptx_msg->IDE = CAN_ID_STD;
    ptx_msg->DLC = m->len;
    for(i = 0; i < m->len; i++)
    ptx_msg->Data[i] = m->data[i];
    if( CAN_Transmit( CAN1, ptx_msg )==CAN_NO_MB)
    {
        return 0xff;
    }
    else
    {
        return 0x00;
        }
}


一周热门 更多>