CANopen在工业使用广泛,正好测试CAN于是乎就移植一个canfestival试试吧。
1.在网上下载canfestival源码,取出src和include目录,参考example的移植,一定要打开keil的C99模式。文件结构如下图:
2.打开对象字典编辑器,因为我的电脑装有python3,默认会用py3打开,就会闪退,所以使用cmd打开:py -2 objdictedit.py
使用测试的OD文件,我用的新版本canfestival,所以增加100C和100D,防止编译出错,生成头文件和.C文件
3.移植定时器,主要代码如下:
void setTimer(TIMEVAL value)
{
TIMER\_CAR(TIMER1) = value;
}
TIMEVAL getElapsedTime(void)
{
return TIMER\_CNT(TIMER1);
}
void time1\_init(void)
{
timer\_parameter\_struct timer\_initpara;
rcu\_periph\_clock\_enable(RCU\_TIMER1);
rcu\_timer\_clock\_prescaler\_config(RCU\_TIMER\_PSC\_MUL4);
timer\_struct\_para\_init(&timer\_initpara);
timer\_deinit(TIMER1);
/\* TIMER1 configuration \*/
timer\_initpara.prescaler = 200\*8-1;
timer\_initpara.alignedmode = TIMER\_COUNTER\_EDGE;
timer\_initpara.counterdirection = TIMER\_COUNTER\_UP;
timer\_initpara.period = TIMEVAL\_MAX-1;
timer\_initpara.clockdivision = TIMER\_CKDIV\_DIV1;
timer\_initpara.repetitioncounter = 0;
timer\_init(TIMER1,&timer\_initpara);
/\* auto-reload preload enable \*/
timer\_auto\_reload\_shadow\_enable(TIMER1);
timer\_interrupt\_enable(TIMER1,TIMER\_INT\_UP);
nvic\_irq\_enable(TIMER1\_IRQn, 0, 1);
/\* TIMER1 enable \*/
timer\_enable(TIMER1);
}
void TIMER1\_IRQHandler(void)
{
if(SET == timer\_interrupt\_flag\_get(TIMER1,TIMER\_INT\_UP)){
TimeDispatch();
/\* clear TIMER interrupt flag \*/
timer\_interrupt\_flag\_clear(TIMER1,TIMER\_INT\_UP);
}
}
4.can驱动,接收采用中断
void CAN0\_RX0\_IRQpro(void)
{
m.cob\_id=receive\_message.rx\_sfid;
if(receive\_message.rx\_ft == CAN\_FT\_REMOTE)
m.rtr=1;
else if(receive\_message.rx\_ft == CAN\_FT\_DATA)
m.rtr=0;
m.len = receive\_message.rx\_dlen;
for(int i = 0; i < receive\_message.rx\_dlen; i++)
m.data\[i\]=receive\_message.rx\_data\[i\];
canDispatch(&TestSlave\_Data, &m);
}
can发送函数:
/\*canSend函数实现如下:\*/
unsigned char canSend(CAN\_PORT notused, Message \*m)
{
uint32\_t i;
transmit\_message.tx\_sfid = m->cob\_id;
if(m->rtr)
transmit\_message.tx\_ft = CAN\_FT\_REMOTE;
else
transmit\_message.tx\_ft = CAN\_FT\_DATA;
transmit\_message.tx\_ff = CAN\_FF\_STANDARD;
transmit\_message.tx\_dlen = m->len;
for(i = 0; i < m->len; i++)
transmit\_message.tx\_data\[i\] = m->data\[i\];
can\_message\_transmit(CAN1, &transmit\_message);
return 0;
}
5.初始化canopen进入操作模式
void InitNodes(CO\_Data\* d, UNS32 id)
{
static unsigned char deviceid=0;
setNodeId(&TestSlave\_Data, id);
deviceid=\*(TestSlave\_Data.bDeviceNodeId);
/\* init \*/
/\* boot-up该节点 进入Pre-optional状态 \*/
setState(&TestSlave\_Data, Initialisation);
deviceid=\*(TestSlave\_Data.bDeviceNodeId);
setState(&TestSlave\_Data, Operational);
printf(" device ID is 0x\[%x\]\r\n",deviceid);
}
6.修改对象字典1017的心跳时间为1000,编译下载,开发板每隔1s发出心跳报文,一切OK。
原作者:兆易创新GD32 MCU 汪阳
|