历史上的今天
返回首页

历史上的今天

今天是:2025年03月18日(星期二)

正在发生

2019年03月18日 | CanFestival移植到STM32F103

2019-03-18 来源:eefocus

1.创建工程


2.将CanFestival源码,拷贝到工程目录


3.删除其它架构和编译器的代码


查看include文件夹发现没有cortex-m3架构,因此我们这里借鉴AVR架构进行修改


将AVR文件夹重命名为STM32,并删除其它架构文件夹


打开STM32文件夹,将里面avr相关的文件删除,我们用的开发环境是MDK,因此将iar相关文件也删了


打开src文件夹,将其它架构、编译器和系统的文件给删了


4.将CanFestival文件添加进工程

添加好之后,编译出现错误,config文件中包含了很多iar相关头文件

将这些头文件删除

重新编译,依然存在错误,提示有很多函数没有定义

先解决start_and_seek_node和start_node的问题,打开def.c文件发现这两个函数定义了



其实,这是MDK开发环境的问题,不要太纠结这个问题,把inline删掉就好了


然后重新编译,还剩下三个错误canSend、getElapsedTime和setTimer没有定义。这三个接口是需要用户移植程序的时候自己进行添加的。


5.添加接口


分别创建rcc.h、rcc.c、nvic.h、nvic.c、CANOpen_can.h、CANOpen_can.c、CANOpen_timeBase.h、CANOpen_timeBase.c文件



/**

***********************************

* 文件名: nvic.h

* 作者: stone

* 版本: V0.1

* 日期: 2018-3-29

* 描述: 设置中断控制器

***********************************

*/

#ifndef __NVIC_H_

#define __NVIC_H_

 

/* 功能: 中断嵌套控制器配置

   参数: 无

   返回值:无

 */

void nvic_config(void);

 

#endif

/**

***********************************

* 文件名: nvic.c

* 作者: stone

* 版本: V0.1

* 日期: 2018-3-29

* 描述: 设置中断控制器

***********************************

*/

#include "stm32f10x.h"

#include "nvic.h"

 

/* 功能: 中断嵌套控制器配置

   参数: 无

   返回值:无

 */

void nvic_config(void)

{

/* 选择中断分组4 */

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

}

/**

***********************************

* 文件名:rcc.h

* 作者: stone

* 版本: V0.1

* 日期: 2018-3-29

* 描述: 配置时钟源

***********************************

*/

#ifndef __RCC_H_

#define __RCC_H_

 

/* 功能: RCC时钟配置

参数: 无

   返回值:无

 */

void rcc_config(void);

 

#endif

/**

***********************************

* 文件名: rcc.c

* 作者: stone

* 版本: V0.1

* 日期: 2018-3-29

* 描述: 配置时钟源

***********************************

*/

#include "stm32f10x.h"

#include "stm32f10x_flash.h"

#include "rcc.h"

 

/* 功能: RCC时钟配置

参数: 无

   返回值:无

 */

void rcc_config(void)

ErrorStatus HSEStartUpStatus;

 

/* RCC寄存器设置为默认配置 */

RCC_DeInit();


/* 打开外部高速时钟 */

RCC_HSEConfig(RCC_HSE_ON);

/* 等待外部高速时钟稳定 */

HSEStartUpStatus = RCC_WaitForHSEStartUp();

if(HSEStartUpStatus == SUCCESS) 

/* 设置HCLK = SYSCLK */

RCC_HCLKConfig(RCC_SYSCLK_Div1);

/* 设置PCLK2 = HCLK */

RCC_PCLK2Config(RCC_HCLK_Div1);

/* 设置PCLK1 = HCLK / 2 */

RCC_PCLK1Config(RCC_HCLK_Div2);


/* 设置FLASH代码延时 */

FLASH_SetLatency(FLASH_Latency_2);

/* 使能预取址缓存 */

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);


/* 设置PLL时钟源为HSE倍频9 72MHz */

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

/* 使能PLL */

RCC_PLLCmd(ENABLE);

/* 等待PLL稳定 */

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);


/* 设置PLL为系统时钟源 */

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

/* 等待系统时钟源切换到PLL */

while(RCC_GetSYSCLKSource() != 0x08);

 

/* 设置系统节拍器时钟源为FCLK */

SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);

}

}

/**

***********************************

* 文件名: CANOpen_timeBase.h

* 作者: stone

* 版本: V0.1

* 日期: 2018-3-29

* 描述: CANOPEN底层定时器接口文件

***********************************

*/

#ifndef __CANOPEN_TIMEBASE_H_

#define __CANOPEN_TIMEBASE_H_

 

/* 功能: canopen时基配置

参数: 无

返回值:无

 */

void canopen_timebase_config(void);

 

#endif

/**

***********************************

* 文件名: CANOpen_timeBase.c

* 作者: stone

* 版本: V0.1

* 日期: 2018-3-29

* 描述: CANOPEN底层定时器接口文件

***********************************

*/

#include "stm32f10x.h"

#include "canfestival.h"

#include "CANOpen_timeBase.h"

 

/* 功能: 定时器配置

参数: 无

返回值:无

 */

static void timer_config(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;


/* 允许TIM2的时钟 */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);


/* 将定时器2寄存器设为初始值 */

TIM_DeInit(TIM2);


/* 设置定时器2由内部时钟 */

TIM_InternalClockConfig(TIM2);


/* 预分频值 */

TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;

/* 时钟分割 */

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

/* 向上计数 */

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

/* 自动重载值 */

TIM_TimeBaseStructure.TIM_Period = 65535 - 1;

/* 初始化定时器2 */

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);


/* 清除溢出中断标志 */

TIM_ClearFlag(TIM2, TIM_FLAG_Update);


/* 禁止ARR预装载缓冲器 */

TIM_ARRPreloadConfig(TIM2, DISABLE);


/* 开启TIM2的中断 */

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);


/* 开启定时器2 */

TIM_Cmd(TIM2, ENABLE);

}

 

/* 功能: 中断配置

参数: 无

返回值:无

 */

static void nvic_config(void)

{

NVIC_InitTypeDef NVIC_InitStructure;


/* 选择TIM2的中断通道 */

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

/* 抢占式中断优先级设置为2 */

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;

/* 响应式中断优先级设置为2 */

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;

/* 使能中断 */

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

/* 中断初始化 */

NVIC_Init(&NVIC_InitStructure);

}

 

/* 功能: canopen时基配置

参数: 无

返回值:无

 */

void canopen_timebase_config(void)

{

/* 定时器配置 */

timer_config();


/* 中断配置 */

nvic_config();

}

 

/* 功能: 设置定时器触发时间

参数: 定时器触发时间

返回值:无 

 */

void setTimer(TIMEVAL value)

{

TIM2->ARR = value - 1;

}

 

/* 功能: 获取上次触发到现在的流逝时间

参数: 无

返回值:获取计数器值

 */

TIMEVAL getElapsedTime(void)

{

return TIM2->CNT;

}

 

/* 定时器2中断向量 */

void TIM2_IRQHandler(void)

{

/* 定时器2溢出标志位 */

if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)

{

/* 定时器2清除溢出标志位 */

TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);

 

TIM2->CNT = 0;

TimeDispatch();

}

}

/**

***********************************

* 文件名: CANOpen_can.h

* 作者: stone

* 版本: V0.1

* 日期: 2018-3-29

* 描述: CANOPEN协议底层总线接口

***********************************

*/

#ifndef __CANOPEN_CAN_H_

#define __CANOPEN_CAN_H_

 

/* 功能: can总线配置

参数: 无

返回值:无

 */

void CANOpen_can_config(void);

 

#endif

/**

***********************************

* 文件名: CANOpen_can.c

* 作者: stone

* 版本: V0.1

* 日期: 2018-3-29

* 描述: CANOPEN协议底层总线接口

***********************************

*/

#include "stm32f10x.h"

#include "CANOpen_can.h"

#include "canfestival.h"

 

/* CANOPEN字典 */

extern CO_Data masterObjdict_Data;

 

/* 功能: GPIO配置

参数: 无

返回值:无

 */

static void gpio_config(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

 

/* 开启GPIO时钟 */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

 

/* CAN_RX */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;

GPIO_Init(GPIOA, &GPIO_InitStructure);

 

/* CAN_TX */

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);

}

 

/* 功能: 中断嵌套控制器配置

参数: 无

返回值:无

 */

static void nvic_config(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

 

/* 设置CAN接收中断,先占优先级2,从站优先级2 */

NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;


/* 初始化中断 */

NVIC_Init(&NVIC_InitStructure);

}

 

/* 功能: CAN总线过滤器配置

参数: 无

返回值:无

 */

static void can_filter_config(void)

{

CAN_FilterInitTypeDef CAN_FilterInitStructure;

 

/* 配置过滤器0组,配置成标准标识符且低7位都为0时接受 */

CAN_FilterInitStructure.CAN_FilterNumber = 0; /* 设置过滤器组0 */

CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; /* 屏蔽模式 */

CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; /* 32位模式 */

CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000; /* 在CANOpen中标准标识符的低7位表示节点ID */

CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0004; /* 在CANOpen中只用标准标识符,数据帧/远程帧都有 */

CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000; /* 主节点ID为0 */

CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000; /* 标准帧 */

CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; /* 过滤器关联到FIFO0 */

CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; /* 使能过滤器 */

CAN_FilterInit(&CAN_FilterInitStructure);

}

 

/* 功能: can总线配置

参数: 无

返回值:无

 */

void CANOpen_can_config(void)

{

CAN_InitTypeDef CAN_InitStructure;

 

/* 配置IO */

gpio_config();

 

/* 中断嵌套控制器配置 */

nvic_config();

 

/* 配置CAN总线时钟 */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

 

/* CAN1默认参数 */

CAN_DeInit(CAN1);

 

/* 将结构体填入默认参数 */

CAN_StructInit(&CAN_InitStructure);

 

/* 关闭时间触发模式 */

CAN_InitStructure.CAN_TTCM = DISABLE;

/* 关闭自动离线管理 */

CAN_InitStructure.CAN_ABOM = ENABLE;

/* 关闭自动唤醒 */

CAN_InitStructure.CAN_AWUM = ENABLE;

/* 自动重传 */

CAN_InitStructure.CAN_NART = DISABLE;

/* 禁止FIFO溢出时覆盖原报文 */

CAN_InitStructure.CAN_RFLM = DISABLE;

/* 关闭优先级取决于ID */

CAN_InitStructure.CAN_TXFP = DISABLE;

/* 正常模式 */

CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;

 

/* 设置波特率:36MHz/9/(2+1+1)=1mbps */

CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;

CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq;

CAN_InitStructure.CAN_BS2 = CAN_BS2_1tq;

CAN_InitStructure.CAN_Prescaler = 9;

 

/* 初始化CAN总线 */

CAN_Init(CAN1, &CAN_InitStructure);

 

/* CAN总线过滤器配置 */

can_filter_config();


/* 接收挂起中断 */

CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

}

 

/* can总线接收中断回调函数 */

void USB_LP_CAN1_RX0_IRQHandler(void)

{

CanRxMsg message;

Message Rx_Message;


/* 接收消息 */

CAN_Receive(CAN1, CAN_FIFO0, &message);


/* 组装canopen数据包 */

Rx_Message.cob_id = message.StdId; /* 功能码和节点ID */

Rx_Message.rtr = (message.RTR == CAN_RTR_DATA) ? 0 : 1; /* 标识符类型 */

Rx_Message.len = message.DLC; /* 数据包长度 */

memcpy(Rx_Message.data, message.Data, message.DLC); /* 数据 */

 

/* canopen数据包分配处理函数 */

canDispatch(&masterObjdict_Data, &Rx_Message);

}

 

/* 功能: CAN发送数据函数

参数: notused can总线端口

message canopen数据包

返回值: 0 成功

1 失败

 */

uint8_t canSend(CAN_PORT notused, Message *message)

{

uint32_t i = 0xFFFFFF;

CanTxMsg TxMessage;

uint8_t TransmitMailbox = 0;

 

/* 组装CAN数据包 */

TxMessage.DLC = message->len; /* 数据长度 */

memcpy(TxMessage.Data, message->data, message->len); /* 数据 */

TxMessage.IDE = CAN_ID_STD; /* 标准ID */

TxMessage.StdId = message->cob_id; /* 标识符 */

TxMessage.RTR = (message->rtr == CAN_RTR_DATA) ? 0 : 2; /* 数据帧 */


/* 发送数据包 */

TransmitMailbox = CAN_Transmit(CAN1, &TxMessage);

/* 等待发送成功 */

while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && --i);


/* 成功0 超时1 */

return (i != 0) ? 0 : 1; 

}

/**

***********************************

* 文件名: main.c

* 作者: stone

* 版本: V0.1

* 日期: 2018-3-29

* 描述: 主文件

***********************************

*/

#include "stm32f10x.h"

#include "rcc.h"

#include "nvic.h"

#include "CANOpen_timeBase.h"

#include "CANOpen_can.h"

 

/* 主函数 */

int main(void)

{

/* 时钟配置 */

rcc_config();


/* 中断嵌套控制器配置 */

nvic_config();

 

/* canopen时基配置 */

canopen_timebase_config();


/* can总线配置 */

CANOpen_can_config();


while(1)

{


}

}

添加好之后,重新编译,提示没有定义CANOpen字典




 


 


6.创建CANOpen字典


打开objdictedit,创建字典










分别得到masterObjdict.h和masterObjdict.c文件




 


 


7.将字典文件添加进工程




重新编译,0错误,0警告




 


 


8.协议栈移植工作完成。下面要考虑的就是字典配置和协议栈使用的问题了。

推荐阅读

史海拾趣

Equinox公司的发展小趣事

在稳步发展健身业务的同时,Equinox还在不断探索新的领域。例如,公司推出了精品酒店品牌Equinox Hotels,将健身与旅游相结合;同时,Equinox还积极进军健康食品、健康科技等领域,以实现多元化的发展战略。未来,Equinox将继续秉承“健康、活力、高品质”的品牌理念,为全球消费者提供更优质的服务和体验。

DUBILIER公司的发展小趣事

在电子行业中,产品质量是企业生存和发展的关键。DUBILIER公司深知这一点,因此一直致力于提升产品质量和可靠性。公司建立了严格的质量管理体系,对生产过程进行全面监控和控制。通过采用先进的生产设备和工艺,以及实施严格的质量检测程序,DUBILIER公司确保了其产品的卓越品质。这种对品质的执着追求使得DUBILIER公司的产品在市场上备受信赖。

Display Engineering Services公司的发展小趣事

随着技术的不断进步和市场的不断变化,DUBILIER公司意识到必须不断拓展市场以保持竞争力。因此,公司决定采取多元化的市场战略,进入多个不同的细分市场。通过与行业合作伙伴建立紧密的合作关系,DUBILIER公司成功地将其产品推广到了更广泛的领域。同时,公司还积极开拓国际市场,将产品出口到世界各地。这些努力不仅为公司带来了更多的商业机会,还进一步巩固了其在全球电子行业的地位。

Cyrustek公司的发展小趣事

在电子行业的发展过程中,Cyrustek公司始终能够精准把握市场需求的变化。无论是智能家居、物联网还是可穿戴设备等领域,Cyrustek都能够迅速推出符合市场需求的产品。这种敏锐的市场洞察力和快速响应能力,使得Cyrustek在电子行业中始终保持领先地位。同时,Cyrustek还注重与客户的沟通和合作,不断收集客户反馈,优化产品设计,提高客户满意度。

Global Specialties公司的发展小趣事

在电子技术的不断推动下,Global Specialties始终保持对新技术的高度敏感。公司不断投入研发资源,对现有产品进行升级换代,并推出了一系列具有创新性的新产品。例如,公司开发的智能测试仪器能够自动完成复杂的测试任务,大大提高了测试效率和准确性。这些技术创新不仅巩固了Global Specialties在业内的领先地位,还为公司带来了更多的商业机会。

Box Enclosures公司的发展小趣事

Box Enclosures公司自创立之初,就明确了自己的定位——专注于为电子行业提供高品质的机箱和外壳产品。公司始终坚持严格的质量控制标准,从原材料采购到生产工艺,每一个环节都力求精益求精。这种对品质的执着追求,使得Box Enclosures的产品在市场上赢得了良好的口碑,逐渐在电子行业中占据了一席之地。

问答坊 | AI 解惑

我的嵌入式学习之路

前言 这个题目很大,给人一种感觉我好像很成功,其实不然。实际上自己水平不高,甚至很低,但是做过了一些曲折的学习道路,同时把自己真实的学习历程表达出来,希望对后来者有借鉴的意义,甚幸! 工作三年、几成废人! 我2000年毕业于华中地区的 ...…

查看全部问答>

windows mobile 5 裁剪

我使用PB for windwos mobile 5生成了一个diskimage.nb0的WM5映像,有32M 更改什么配置文件可以改变生成的映像文件的大小呢?多谢:P …

查看全部问答>

C51中断

在C51中断函数中,能否改变全局变量的值,若能是不是该变量必须声明为volatile?…

查看全部问答>

AXD 调试的问题

在Memory Start address文本框图上,用户可以根据要查看或修改的存储器地址输入起始地址,在下面的表格中会列出连续的64个地址。因为I/O模式控制寄存器和I/O数据控制寄存器都是32位的控制寄存器,所以从0x00000000开始的连续4个地址空间存放的是I/O ...…

查看全部问答>

关于SD卡的High-Speed模式。

查看SD的Spec可以发现,SD2.0开始支持High-Speed mode,即Clock Src为50MHz,速度可以达到25MB/Sec. 请问大家: 1、是不是所有支持SD2.0的卡都支持High-Speed Mode?使用何种方式判断SD卡是否支持这种模式? 2、High-Speed mode的初始化流程是否 ...…

查看全部问答>

直流无刷电机驱动WS-2406 急急急

请问一下直流无刷电机驱动WS-2406,用DC+12V驱动,怎么用,那个驱动上面 有两个+5V的接口,不知道怎么用,还有HALL A, HALL B,HALL C。现在要用这个东西做个项目,不知道应该注意些什么问题。哪位高手请指点一下吧,还有我手上的资料也很少,做 ...…

查看全部问答>

能不能在EVc中写代码让屏幕旋转180度

我作了一个Dialog的界面 能不能在EVC中写代码让屏幕旋转180度 小女子先谢谢了哈^v^ …

查看全部问答>

求电容式油位传感器探杆生产厂家

正在开发电容式的油位变送器,用于集团公司内部,年需求量比较可观,但是找过好些厂家都不愿意单独供货,有哪位熟悉电容探杆厂家这方面的吗?…

查看全部问答>

ucos在MCF52233DEMO上移植,例程代码都有,为什么就是不能正常运行……

本人小白,已经拿到了ucos在MCF52233DEMO上移植的例程,可是自己怎么也跑不起来……现在单任务可以执行,就是多任务不行,只能一直跑优先级最高的那个任务。按照邵贝贝老师翻译的书一步一步检查,发现是OS_Shed()调用OS_TASK_SW()以后没有执行起来O ...…

查看全部问答>