저번 C221-S3C6410 보드 활용기 [ CAN 통신편 I ]에 이어서 CAN통신을 테스트하는 방법 및
테스트 프로그램을 만들어 보도록 하겠습니다.

먼저 C221-S3C6410의 CAN 통신은 소켓통신을 하므로 다음과 같이 설정을 해 주어야 합니다.
즉, Ethnet을 설정하기 위해 ifconfig를 사용하는 방식으로 CAN 설정을 해 주면 됩니다.

CAN0를 500Kbps의 속도로 설정합니다.
 $ echo "500000" > /sys/class/net/can0/can_bittiming/bitrate 

 $ ifconfig can0 up 


CAN1를 500Kbps의 속도로 설정합니다.
 $ echo "500000" > /sys/class/net/can1/can_bittiming/bitrate 

 $ ifconfig can1 up 


 
정상적으로 설정되었다면 CAN0와 CAN1을 연결하여 통신 테스트를 하는 프로그램을 작성해 보도록 하겠습니다.


can_sender 프로그램

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/ioctl.h>

#include <net/if.h>


#include <linux/can.h>

#include <linux/can/raw.h>


int main( int argc, char *argv[])

{

int fd_can;

struct sockaddr_can addr;

struct can_frame frame;

int nbytes;

struct ifreq ifr;

int ifindex;


    if ( 2 > argc){

    printf( "인수가 모자릅니다. 시리얼 포트를 입력하여 주시오\n");

    printf( "실행방법: ]$ ./app_can_sender can0\n");

    exit( 0);

}


if ( 0 > ( fd_can = socket(PF_CAN, SOCK_RAW, CAN_RAW)) ) {

perror("socket");

return 1;

}


strcpy(ifr.ifr_name, argv[1]);

ioctl( fd_can, SIOCGIFINDEX, &ifr);

ifindex = ifr.ifr_ifindex;


addr.can_family  = AF_CAN;

addr.can_ifindex = 0; /* bind to all interfaces */


if ( 0 > bind( fd_can, (struct sockaddr *)&addr, sizeof(addr)) ) {

perror("bind");

return 1;

}



/* fill CAN frame */

frame.can_id  = 0x32;

frame.can_dlc = 8;

frame.data[0] = 0x46; // 'F'

frame.data[1] = 0x41; // 'A'

frame.data[2] = 0x4C; // 'L'

frame.data[3] = 0x69; // 'i'

frame.data[4] = 0x6E; // 'n'

frame.data[5] = 0x75; // 'u'

frame.data[6] = 0x78; // 'x'

frame.data[7] = 0x21; // '!'



addr.can_family  = AF_CAN;

addr.can_ifindex = ifindex; /* send via this interface */


nbytes = sendto( fd_can, &frame, sizeof(struct can_frame), 0, (struct sockaddr*)&addr, sizeof(addr));


close( fd_can);


return 0;



can_receiver 프로그램

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/ioctl.h>

#include <net/if.h>


#include <linux/can.h>

#include <linux/can/raw.h>


int main( int argc, char *argv[])

{

int sock;

struct sockaddr_can addr;

struct can_filter rfilter[4];

struct can_frame frame;

int ndx;

struct ifreq ifr;

int ifindex;


    if ( 2 > argc){

    printf( "인수가 모자릅니다. 시리얼 포트를 입력하여 주시오\n");

    printf( "실행방법: ]$ ./app_can_receiver can0\n");

    exit( 0);

}


// can 포트를 open


if ( 0 > (sock = socket(PF_CAN, SOCK_RAW, CAN_RAW))) {

perror("socket");

return 1;

}


rfilter[0].can_id   = 0x32;

rfilter[0].can_mask = CAN_SFF_MASK;


rfilter[1].can_id   = 0x200;

rfilter[1].can_mask = 0x700;


rfilter[2].can_id   = 0x80123456;

rfilter[2].can_mask = 0x1FFFF000;


rfilter[3].can_id   = 0x80333333;

rfilter[3].can_mask = CAN_EFF_MASK;


setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));


strcpy( ifr.ifr_name, argv[1]); // 사용할 CAN 번호

ioctl(sock, SIOCGIFINDEX, &ifr);

ifindex = ifr.ifr_ifindex;


addr.can_family = AF_CAN;

addr.can_ifindex = ifindex;


if (bind( sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {

perror("bind");

return 1;

}


while ( 1 )

{

int rd_size;


rd_size = read( sock, &frame, sizeof(struct can_frame));

if ( 0 > rd_size) {

fprintf(stderr, "read error");

} else if ( rd_size < sizeof( struct can_frame)) {

fprintf(stderr, "read: incomplete CAN frame\n");

return 1;

} else {

if (frame.can_id & CAN_EFF_FLAG)

printf("%8X  ", frame.can_id & CAN_EFF_MASK);

else

printf("%3X  ", frame.can_id & CAN_SFF_MASK);


printf("[%d] ", frame.can_dlc);


for ( ndx = 0; ndx < frame.can_dlc; ndx++) {

printf("%02X ", frame.data[ndx]);

}

if (frame.can_id & CAN_RTR_FLAG)

printf("remote request");

printf("\n");

fflush(stdout);

}

}

close( sock);

return 0;



■ socket() 함수는 socket을 생성합니다. 
■ setsockopt () 함수는 생성된 socket의 옵션을 재설정합니다. 
■ bind() 함수는 생성된 socket을 bind 합니다. 
■ sendto() 함수는 데이타를 전송합니다.
■ read() 함수는 데이타를 수신합니다.
■ close() 함수는 client socket을 제거하고 작업을 종료합니다.
 


위의 프로그램을 작성하였다면 C221-S3C6410 보드에서 테스트하는 방법을 아래와 같습니다.


http://forum.falinux.com/zbxe/?mid=hardware&document_srl=567687 에서 C221-S3C6410보드의 CAN0 와 CAN1 포트를 
연결하는 방법을 다시 한번 확인해 보세요.


CAN0 포트로 데이타를 전송합니다.

 $ ./app_can_sender can0 &  


CAN1 포트로 데이타를 수신합니다.

 $ ./app_can_receiver can1 



===========

위의 소스 및 실행 프로그램은 C221-S3C6410 보드를 구매하시면 제공되는 소스들입니다.

다음 강좌에서는 C221-S3C6410 보드에 있는 WLAN 설정 방법을 소개하도록 하겠습니다.