何雨 燕子李三,傅泽星,酒泉市人事人才网
以下内容为学习canopen时对canfestival协议栈的移植记录,参考链接有strongerhuang。
examples文件夹 : 需要该文件夹下avr/slave/目录的config.h文件。
drivers文件夹 :该文件夹下提供了一些移植参考,例如cm3、cm4文件夹,提供的移植示例基于标准库。
inline void start_node(co_data* d, uns8 nodeid)
和inline void start_and_seek_node(co_data* d, uns8 nodeid)
的inline声明,分别位于该文件59行和98行。#ifndef #define #endif
三条。#ifdef __iar_systems_icc__ #include <ioavr.h> #include <intrinsics.h> #include "iar.h" #else // gcc #include <inttypes.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #include <avr/sleep.h> #include <avr/wdt.h> #endif // gcc
//#define wd_sleep // needed defines by atmel lib #define fosc 8000 // 16 mhz external cristal #ifndef f_cpu #define f_cpu (1000ul*fosc) // need for avr gcc #endif #define can_baudrate 250
修改 #define repeat_sdo_max_simultaneous_transferts_times(repeat)\
为 #define repeat_sdo_max_simultaneous_transfers_times(repeat)\
,删去了transferts中的t字符。
canfestival移植后有些函数需要自己实现,比如在 timer.h
中声明的两个函数,与协议栈内部定时器相关。
/** * @ingroup timer * @brief set a timerfor a given time. * @param value the time value. */ void settimer(timeval value); /** * @ingroup timer * @brief get the time elapsed since latest timer occurence. * @return time elapsed since latest timer occurence */ timeval getelapsedtime(void);
在canfestival.h
中声明的函数,这些接口可以实现功能后直接调用,使用者也可以使用自定义函数,实现这些功能即可。
void inittimer(void); void cleartimer(void); unsigned char cansend(can_port notused, message *m); unsigned char caninit(co_data * d, uint32_t bitrate); void canclose(void); void disable_it(void); void enable_it(void);
上面提到的 drivers 文件夹可以作为这些接口实现的参考。
static timeval last_counter_val = 0; static timeval elapsed_time = 0; void settimer(timeval value) { uint32_t timer = __hal_tim_get_counter(&can_tim); elapsed_time += timer - last_counter_val; last_counter_val = canopen_tim_period - value; __hal_tim_set_counter(&can_tim, canopen_tim_period - value); hal_tim_base_start_it(&can_tim); } timeval getelapsedtime(void) { uint32_t timer = __hal_tim_get_counter(&can_tim); if(timer < last_counter_val) { timer += canopen_tim_period; } timeval elapsed = timer - last_counter_val + elapsed_time; return elapsed; }
void inittimer(void) { can_tim.instance = canopen_timer; can_tim.init.prescaler = canopen_prescaler; can_tim.init.countermode = tim_countermode_up; can_tim.init.period = canopen_tim_period; can_tim.init.autoreloadpreload = tim_autoreload_preload_disable; hal_tim_base_init(&can_tim); __hal_tim_set_counter(&can_tim, 0); hal_tim_base_start_it(&can_tim); }
unsigned char caninit(can_handletypedef *handle) { can_filtertypedef hcan_filter; //can2控制器配置 handle->instance = canopen_handle; handle->init.prescaler = presc; handle->init.mode = can_mode_normal; handle->init.syncjumpwidth = sjw; handle->init.timeseg1 = ts1; handle->init.timeseg2 = ts2; handle->init.timetriggeredmode = disable; handle->init.autobusoff = disable; handle->init.autowakeup = disable; handle->init.autoretransmission = disable; handle->init.receivefifolocked = disable; handle->init.transmitfifopriority = disable; hal_can_init(handle); //can滤波器配置 hcan_filter.filterbank = 14; hcan_filter.filtermode = can_filtermode_idmask; hcan_filter.filteractivation = can_filter_enable; hcan_filter.filterfifoassignment = can_filter_fifo0; hcan_filter.filterscale = can_filterscale_32bit; hcan_filter.filteridhigh = 0x0000; hcan_filter.filteridlow = 0x0000; hcan_filter.filtermaskidhigh = 0x0000; hcan_filter.filtermaskidlow = 0x0000; hcan_filter.slavestartfilterbank = 14; hal_can_configfilter(handle, &hcan_filter); //启动can2,使能中断 hal_can_start(handle); hal_can_activatenotification(handle, can_it_rx_fifo0_msg_pending); return 0; }
unsigned char cansend(can_port notused, message *m) { struct can_tx pre_send; pre_send.txinfo.stdid = m->cob_id; if(m->rtr) pre_send.txinfo.rtr = can_rtr_remote; else pre_send.txinfo.rtr = can_rtr_data; pre_send.txinfo.ide = can_id_std; pre_send.txinfo.dlc = m->len; for(int i = 0; i < m->len; i++) { pre_send.tx_data[i] = m->data[i]; } if(rt_mq_send(can_txmq, &pre_send, sizeof(pre_send)) != rt_eok) return 0xff; return 0; }
void hal_tim_periodelapsedcallback(tim_handletypedef *htim) { if(htim == (&can_tim)) { last_counter_val = 0; elapsed_time = 0; timedispatch(); } } void hal_can_rxfifo0msgpendingcallback(can_handletypedef *hcan) { struct can_rx rs_msg; hal_can_getrxmessage(&canopen, can_rx_fifo0, &rs_msg.rxinfo, rs_msg.rx_data); rt_mq_send(can_rxmq, &rs_msg, sizeof(rs_msg)); hal_can_activatenotification(hcan, can_it_rx_fifo0_msg_pending); }
message
类型变量,送入协议栈if(rt_mq_recv(can_rxmq, &mq_recv, sizeof(mq_recv), rt_waiting_forever) == rt_eok) { rxmsg.cob_id = mq_recv.rxinfo.stdid; if(mq_recv.rxinfo.rtr == can_rtr_remote) rxmsg.rtr = 1; else rxmsg.rtr = 0; rxmsg.len = (uns8)mq_recv.rxinfo.dlc; for(int i = 0; i < mq_recv.rxinfo.dlc; i++) { rxmsg.data[i] = mq_recv.rx_data[i]; } hal_tim_base_stop_it(&can_tim); candispatch(¢er_data, &rxmsg); hal_tim_base_start_it(&can_tim); }
if(rt_mq_recv(can_txmq, &msg_send, sizeof(msg_send), rt_waiting_forever) == rt_eok) { hal_can_addtxmessage(&canopen, &msg_send.txinfo, msg_send.tx_data, &txmailbox); }
以上为移植内容,移植完成后建立任务初始化can之后就可以启动协议栈了。新手上路,不足的地方希望指出,共同学习。
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
如何在没有core文件的情况下用dmesg+addr2line定位段错误
用QT制作3D点云显示器——QtDataVisualization
网友评论