CanFestival移植STM32F103

     Can通信介质是屏蔽双绞线,通过差分信号进行信号的传输,属于OSI七层网络结构的物理层和数据链路层。CanOpen是基于Can通信的上层协议,是属于网络层协议。需要用到CanOpen则需要根据下载的文档进行移植。

    移植环境:

    1、移植包  CanFestival-3-8bfe0ac00cdb

    2、Keil开发工具

    3、STM32F103系列新品(带收发器) 最小ROM 40K  RAM 2K

    4、Python2.7

    5、wxPython2.8

移植步骤:

    1、新建一个STM32工程文件,添加源文件和对应头文件

    2、在工程目录文件下新建CanFestival文件夹,在CanFestival文件夹新建Src、Inc、Driver三个文件夹。

    3、复制CanFestival-3-8bfe0ac00cdb包下的src文件夹内的全部源文件到工程文件的Src目录

    4、复制CanFestival-3-8bfe0ac00cdb包下的include文件夹内的头文件到工程文件的Inc目录下,并且将CanFestival-3-8bfe0ac00cdb下的example/AVR/Slave文件夹下的ObjDict.h复制到工程文件Inc文件夹内。

    5、复制CanFestival-3-8bfe0ac00cdb/include/AVR目录下applicfg.h、canfestival.h、config.h、timerscfg.h到工程文件夹Driver目录下,并在该目录下新建stm32文件夹。

    6、将CanFestival-3-8bfe0ac00cdb/examples/TestMasterSlave文件夹下的TestMaster.c、TestMaster.h、TestSlave.c 、TestSlave.h、TestMasterSlave.h复制到工程目录Driver/stm32目录下,并在该目录下新建stm32_festival.c。

    注:在CanFestival-3-8bfe0ac00cdb/examples/TestMasterSlave文件夹下并未发现上述的源文件和头文件,但可以发现有TestMaster.od、TestSlave.od文件。该文件为通讯对象字典,通过python解析可生成源文件。

   Python安装: Win10在Windows图标鼠标右键,打开管理员权限命令行,找到Python下载路径,会车可自动安装。

   wxPython2.8安装:一路Next,选择安装项最后一项原本为空,下拉选择第二项,然后开始安装成功。

    CanFestival-3-8bfe0ac00cdb/objdictgen目录下解压Gnosis_Utils-current.tar到当前目录,复制gnosis文件夹到CanFestival-3-8bfe0ac00cdb/objdictgen目录下,找到该目录下objdictedit.py,点击启动,有对象字典配置界面显示,环境成功安装。

    7、将所有的源码和头文件添加进工程,若是实现CanOpen主机,添加TestMaster.c,否则添加TestMaster.c。

    8、为stm32_festival.c源文件添加内容

#include "canfestival.h"
#include "stm32f10x.h"

unsigned int TimeCNT = 0 ;  //时间计数
unsigned int NextTime = 0 ;  //下一次触发时间计数
unsigned int TIMER_MAX_COUNT = 70000; //最大时间计数
static TIMEVAL last_time_set = TIMEVAL_MAX ; //上一次的时间计数


CanTxMsg TxMessage;
CanRxMsg RxMessage;

extern CO_Data TestMaster_Data;

//主要被源码用来定时的,时间到了就需要调用一下函数TimeDispatch()
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;
}

//发一个CAN包的,需要调用驱动来将一个CAN包发出去
unsigned char canSend(CAN_PORT notused, Message *m)
{
	uint32_t i;
	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;
  }
}

//1ms定时
void timerForCan(void)
{
	TimeCNT ++ ;
	if(TimeCNT >= TIMER_MAX_COUNT)
	{
		TimeCNT = 0 ;
	}
	if(TimeCNT == NextTime)
	{
		TimeDispatch();
	}
}

/* TIM4 configure */
static void TIM4_Configuration(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure ;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Prescaler =72-1; //72000 - 1;
	TIM_TimeBaseInitStructure.TIM_Period =0x03e8;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStructure);
	TIM_ITConfig(TIM4, TIM_IT_CC1, ENABLE);
	TIM_Cmd(TIM4, ENABLE);
}

static void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
	NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

static void RCC_Configuration(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA ,ENABLE);
}

void TIM4_Start(void)
{
	RCC_Configuration();
	NVIC_Configuration();
	TIM4_Configuration();
}

void TIM4_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM4,TIM_IT_CC1)!= RESET)
	{
		TIM_ClearITPendingBit(TIM4,TIM_IT_CC1);
		timerForCan();
	}
}

void CAN_Config(void)
{
	GPIO_InitTypeDef 		GPIO_InitStructure; 
	CAN_InitTypeDef CAN_InitStructure ;
	CAN_FilterInitTypeDef CAN_FilterInitStructure ;
	NVIC_InitTypeDef  		NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA时钟	                   											 

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽
	GPIO_Init(GPIOA, &GPIO_InitStructure);			//初始化IO

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	//上拉输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);			//初始化IO
	

    /* CAN register init */
    CAN_DeInit(CAN1);
    CAN_StructInit(&CAN_InitStructure);
    
    /* CAN1 cell init */
    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 = CAN_Mode_Normal;
    //Fpclk=72M/2/CAN_Prescaler
    //BitRate=Fpclk/((CAN_SJW+1)*((CAN_BS1+1)+(CAN_BS2+1)+1));
    //1M 
    /*CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
    CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;
    CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;
    CAN_InitStructure.CAN_Prescaler = 4;*/ 
    //125K
    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
    CAN_InitStructure.CAN_BS1 = CAN_BS1_8tq;
    CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq;
    CAN_InitStructure.CAN_Prescaler = 18;
    CAN_Init(CAN1, &CAN_InitStructure);

    
    /* CAN1 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);
		
		CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);				//FIFO0消息挂号中断允许.		    

		NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     // 主优先级为1
		NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
		NVIC_Init(&NVIC_InitStructure);
    
}


void USB_LP_CAN1_RX0_IRQHandler(void)
{
		u8 i ;
		Message m ;
    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];
			printf("%x ",m.data[i]);
		}	
    canDispatch(&TestMaster_Data, &m);
}

    9、编译,肯定会报错。注释掉config.h下的包含文件

#include 
#include 
#include 
#include 
#include 
#include 

  10、修改dcf.c中的函数前修饰inline

inline void start_node(CO_Data* d, UNS8 nodeId)
修改为
static __inline void start_node(CO_Data* d, UNS8 nodeId)

  10、主函数内添加如下代码:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "TestSlave.h"
#include "canfestival.h"
#include 
unsigned char nodeID=0x21;
extern CO_Data TestMaster_Data;

 int main(void)
 {	
	 u8 i = 0 ;
	 u8 res = 0 ;
	 u8 mes[8] = {0x2f,0x00,0x14,0x02,0xfd,0x00,0x00,0x00};
		void* st ;
	 Message mesg ;
	 mesg.cob_id = 0x607;  // SDO服务器地址
	 mesg.rtr = 0 ;    
	 mesg.len = 8 ;
	 for(i=0;i<8;i++)
		mesg.data[i] = mes[i] ;
	 
	delay_init();	    //延时函数初始化	  
	uart_init(115200);
	 LED_Init();		  	//初始化与LED连接的硬件接口
	 KEY_Init();
	 
	CAN_Config();
	setNodeId(&TestMaster_Data, nodeID);
	setState(&TestMaster_Data, Initialisation); // Init the state
	TIM4_Start();
	 
	 while(1)
	{		
		res = KEY_Scan(0);
		if(res == 1)
		{
			printf("KEY1 Press\r\n");
			canSend((void*)0x607,&mesg);
		}
		else if(res == 2)
		{
		}
		
		LED0=0;
		LED1=1;
		delay_ms(300);	 //延时300ms
		LED0=1;
		LED1=0;
		delay_ms(300);	//延时300ms
	}
}

CanOpen主机的移植完成。

你可能感兴趣的:(CANOpen,STM32,嵌入式)