CanFestival移植到stm32f103zet(2)

转载自:http://www.openedv.com/thread-246479-1-1.html

上一节:https://blog.csdn.net/xiaoyink/article/details/89076829

一、移植步骤:

步骤一:在新建好的工程目录下新建文件夹CanFestival,再在CanFestival下新建文件夹driver、inc和src,再在inc文件夹下面新建stm32文件夹。
步骤二:将CanFestival-3-10\src目录下的dcf.c、emcy.c、lifegrd.c、lss.c、nmtMaster.c、nmtSlave.c、objacces.c、pdo.c、sdo.c、states.c、sync.c、timer.c共12个文件拷贝到 CanFestival\src目录下;

将CanFestival-3-10\include目录下的所有.h文件共19个文件全部拷贝到CanFestival\inc目录下,再把CanFestival-3-10\examples\AVR\Slave目录下的ObjDict.h文件拷贝过来,一共20个;

将CanFestival-3-10\include\AVR目录下的applicfg.h、canfestival.h、config.h、timerscfg.h共4个头文件拷贝canfestival\inc\stm32 目录下;

将CanFestival-3-10\examples\TestMasterSlave目录下的TestSlave.c、TestSlave.h、TestMaster.h、TestMaster.c拷贝到canfestival\driver目录下,并在该目录下新建 stm32_canfestival.c文件,注意,TestSlave.c和TestMaster.c是用对象字典编辑器生成的;
步骤三:将CanFestival\src目录下的所有.c文件添加到工程;将canfestival\driver目录下的stm32_canfestival.c文件添加到工程;如果实现的是从设备,再将canfestival\driver目录下的TestSlave.c文件添加到工程,如果实现的是主设备,则将TestMaster.c文件添加到工程。
步骤四:将文件目录canfestival\inc、canfestival\inc\stm32、canfestival\driver等路径添加到工程包含路径。
步骤五:在stm32_canfestival.c中包含头文件#include "canfestival.h",并定义如下函数:
            void setTimer(TIMEVAL value)
           {
                                                }
           TIMEVAL getElapsedTime(void)
           {
                   return 1;
                                                }

             unsigned char canSend(CAN_PORT notused, Message *m)
            {
                  return 1;
                                               }
           为什么这里要定义几个空函数呢?因为空函数编译的时候不会报错啊,我们现在把后面的都弄好了,最后来处理这边会更方便。我这只是针对新手,老鸟无视就好了。
           这几个函数都是定义来供canfestival源码调用的,如果找不到这几个函数编译就会报错。
步骤六;通过以上几步,所有的文件都弄齐了,但是编译一定会出现报错,注释或删除掉config.h文件中的如下几行就能编译通过:
            #include <inttypes.h>
            #include <avr\io.h>
            #include <avr\interrupt.h>
            #include <avr/pgmspace.h>
            #include <avr\sleep.h>
            #include <avr\wdt.h>
            如果还有其他错误,可能就是不同版本的源码导致的,也有可能是不同的DEMO引起的,不能解决这些问题的话,那就是GAMEOVER,如果能解决,那么我们继续,注意还有一点MDK对inline的处理,可能引起错误,我们要添加以下语句:

#define inline __inline

到inline函数定义之前;

二、源码修改部分

源代码参见:https://github.com/sallenkey-wei/CanFestival-transplanted2stm32

通过以上步骤处理掉所有错误,对于源码的操作已经结束了,下面就是我们的底层的操作了。
接下来实现刚才定义的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();
      }
}

 

上面讲过了定时器,下面就是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;
        }
}

下面就是main函数如何调用CanFestival了,可以参考github上的源码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值