c语言sscanf函数的用法是什么
340
2022-11-25
英创信息技术EM9287 Linux Socket CAN驱动简介
一、简述
本文将简要介绍EM9287在Linux-3.9.7内核上如何实现CAN驱动以及如何在应用程序中使用Socket CAN。
二、Linux内核配置
内核配置中增加以下选项(make menuconfig):
EM9287移植的是Linux-3.9.7版本,对于硬件的描述和配置都是通过device tree相关文件进行传递,除了内核的配置外,还需要在相应的dst文件中增加can0节点。如:
can0: can@80032000 { compatible = 'fsl,imx28-flexcan', 'fsl,p1010-flexcan'; reg = <0x80032000 0x2000>; interrupts = <8>; clocks = <&clks 58>, <&clks 58>; clock-names = 'ipg', 'per'; pinctrl-names = 'default'; pinctrl-0 = <&can0_pins_a>; };
内核编译成功后,板卡启动显示即表示flexcan驱动加载成功。
[ 2.022398] CAN device driver interface [ 2.031257] flexcan 80032000.can: device registered (reg_base=f5032000, irq=190)
三、Socket CAN的测试
Socket CAN 的使用会用到ip命令工具,由于busybox中的ip没有支持 socket can,所以需要重新移植ip工具,iproute2中的ip可以支持socket can。
这样ip命令工具就算是移植好了。
2、使用ip命令配置can0接口。 // 关闭can0接口,以便进行配置 ifconfig can0 down // 方法一:配置can0的波特率为250Kbps ip link set can0 type can bitrate 250000 // 方法二:配置can0的波特率为250Kbps ip link set can0 type can tp 250 prog-seg 5 phase-seg1 8 phase-seg2 2 sjw 2 // 启动can0接口 ifconfig can0 up
3、Scoket CAN测试代码
s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
在成功创建一个套接字之后,通常需要使用bind( )函数将套接字绑定在某个CAN接口上。在绑定 (CAN_RAW)套接字之后,就可以在套接字上使用read( )/write( )进行数据收发的操作。
基本的CAN帧结构体和套接字地址结构体定义在include/linux/can.h
/* * 扩展格式识别符由 29 位组成。其格式包含两个部分:11 位基本 ID、18 位扩展 ID。 * Controller Area Network Identifier structure * * bit 0-28 : CAN识别符 (11/29 bit) * bit 29 : 错误帧标志 (0 = data frame, 1 = error frame) * bit 30 : 远程发送请求标志 (1 = rtr frame) * bit 31 :帧格式标志 (0 = standard 11 bit, 1 = extended 29 bit) */ typedef __u32 canid_t; struct can_frame { canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ __u8 can_dlc; /* 数据长度: 0 .. 8 */ __u8 data[8] __attribute__((aligned(8))); };
以下为相关的测试代码:
int main( int argc,char* argv[] ) { int i1, ret; int nbytes, baudrate; int s; struct sockaddr_can addr; struct ifreq ifr; struct can_frame frame; printf( 'SocketCAN Test V1.0\n' ); // 解析命令行参数, CAN波特率 if( argc > 1 ) { baudrate = atoi( argv[1] ); } else { baudrate = 250000; } printf( 'bitrate is %d\n', baudrate ); set_can_bittiming( baudrate ); s = socket(PF_CAN, SOCK_RAW, CAN_RAW); printf( 'SOCK_RAW can sockfd:%d\n', s ); if( s < 0 ) { return -1; } int loopback = 0; /* 0 = disabled, 1 = enabled (default) */ setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback)); strcpy(ifr.ifr_name, 'can0' ); ret = ioctl(s, SIOCGIFINDEX, &ifr); if( ret < 0 ) { return -1; } addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; bind(s, (struct sockaddr *)&addr, sizeof(addr)); for( i1=0; i1<10; i1++ ) { nbytes = read(s, &frame, sizeof(struct can_frame)); if (nbytes < 0) { perror('can raw socket read'); return 1; } if( nbytes < (int)sizeof(struct can_frame)) { perror('read: incomplete CAN frame\n'); return 1; } /* do something with the received CAN frame: send back */ nbytes = write(s, &frame, sizeof(struct can_frame)); printf( '%d sendbytes: %d\n', i1+1, nbytes ); } close( s ); return 0; }
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~