NUC980开发板CAN开发笔记

一、内核开启CAN

CAN 设置
NUC980 系列带有2个CAN(Controller Area Network), 可以分别独立设置。 请按以下的说明来使能CAN功能. 每个CAN可以单独的开关. CAN0有多组管脚可以选择, 需要一并设置。
使用者也可以设置CAN的唤醒功能。步骤如下:
进入 NUC980-linux-4.4.y-master在这里插入图片描述
打开终端,输入

make menuconfig

选择 Networking support
在这里插入图片描述
选择 CAN bus subsystem support
在这里插入图片描述
选择 CAN Device Drivers
在这里插入图片描述
选择 NUC980 CAN0~CAN3 devices
在这里插入图片描述
根据电路选择对应的引脚
在这里插入图片描述
保存,退出。
重新编译镜像,下载到开发板即可。

注意:
内核配置中,查看使用的CAN引脚是否和其它功能比如串口有冲突有的话需要取消未使用的功能配置。

电路设计,使用 CAN芯片 SN65HVD230 (SN65HVD23x 3.3V CAN 总线收发器)。
在这里插入图片描述
需要注意RS引脚,该引脚是模式配置。
在这里插入图片描述

二、测试代码

指令查看

ifconfig -a

在这里插入图片描述

或者

ls /sys/class/net

在这里插入图片描述

官方测试代码

/*
 * Copyright (c) 2014 Nuvoton technology corporation
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 */

/* libsocketcan.c
 *
 * (C) 2009 Luotao Fu <l.fu@pengutronix.de>
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <getopt.h>
#include <libgen.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <poll.h>


#include <net/if.h>

#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>

#include <linux/types.h>

#include <linux/can.h>
#include <linux/can/raw.h>

#include <linux/rtnetlink.h>
#include <linux/netlink.h>


/*
 * CAN bit-timing parameters
 */
struct can_bittiming {
	__u32 bitrate;		/* Bit-rate in bits/second */
	__u32 sample_point;	/* Sample point in one-tenth of a percent */
	__u32 tq;		/* Time quanta (TQ) in nanoseconds */
	__u32 prop_seg;		/* Propagation segment in TQs */
	__u32 phase_seg1;	/* Phase buffer segment 1 in TQs */
	__u32 phase_seg2;	/* Phase buffer segment 2 in TQs */
	__u32 sjw;		/* Synchronisation jump width in TQs */
	__u32 brp;		/* Bit-rate prescaler */
};

/*
 * CAN harware-dependent bit-timing constant
 */
struct can_bittiming_const {
	char name[16];		/* Name of the CAN controller hardware */
	__u32 tseg1_min;	/* Time segement 1 = prop_seg + phase_seg1 */
	__u32 tseg1_max;
	__u32 tseg2_min;	/* Time segement 2 = phase_seg2 */
	__u32 tseg2_max;
	__u32 sjw_max;		/* Synchronisation jump width */
	__u32 brp_min;		/* Bit-rate prescaler */
	__u32 brp_max;
	__u32 brp_inc;
};

/*
 * CAN clock parameters
 */
struct can_clock {
	__u32 freq;		/* CAN system clock frequency in Hz */
};

/*
 * CAN operational and error states
 */
enum can_state {
	CAN_STATE_ERROR_ACTIVE = 0,	/* RX/TX error count < 96 */
	CAN_STATE_ERROR_WARNING,	/* RX/TX error count < 128 */
	CAN_STATE_ERROR_PASSIVE,	/* RX/TX error count < 256 */
	CAN_STATE_BUS_OFF,		/* RX/TX error count >= 256 */
	CAN_STATE_STOPPED,		/* Device is stopped */
	CAN_STATE_SLEEPING,		/* Device is sleeping */
	CAN_STATE_MAX
};

/*
 * CAN bus error counters
 */
struct can_berr_counter {
	__u16 txerr;
	__u16 rxerr;
};

/*
 * CAN controller mode
 */
struct can_ctrlmode {
	__u32 mask;
	__u32 flags;
};

#define CAN_CTRLMODE_LOOPBACK	0x01	/* Loopback mode */
#define CAN_CTRLMODE_LISTENONLY	0x02 	/* Listen-only mode */
#define CAN_CTRLMODE_3_SAMPLES	0x04	/* Triple sampling mode */
#define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */
#define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */

/*
 * CAN device statistics
 */
struct can_device_stats {
	__u32 bus_error;	/* Bus errors */
	__u32 error_warning;	/* Changes to error warning state */
	__u32 error_passive;	/* Changes to error passive state */
	__u32 bus_off;		/* Changes to bus off state */
	__u32 arbitration_lost; /* Arbitration lost errors */
	__u32 restarts;		/* CAN controller re-starts */
};

/*
 * CAN netlink interface
 */
enum {
	IFLA_CAN_UNSPEC,
	IFLA_CAN_BITTIMING,
	IFLA_CAN_BITTIMING_CONST,
	IFLA_CAN_CLOCK,
	IFLA_CAN_STATE,
	IFLA_CAN_CTRLMODE,
	IFLA_CAN_RESTART_MS,
	IFLA_CAN_RESTART,
	IFLA_CAN_BERR_COUNTER,
	__IFLA_CAN_MAX
};


#define parse_rtattr_nested(tb, max, rta) \
	(parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))

#define NLMSG_TAIL(nmsg) \
	((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))

#define IFLA_CAN_MAX	(__IFLA_CAN_MAX - 1)

#define IF_UP 1
#define IF_DOWN 2

#define GET_STATE 1
#define GET_RESTART_MS 2
#define GET_BITTIMING 3
#define GET_CTRLMODE 4
#define GET_CLOCK 5
#define GET_BITTIMING_CONST 6
#define GET_BERR_COUNTER 7
#define GET_XSTATS 8

struct get_req {
	struct nlmsghdr n;
	struct rtgenmsg g;
};

struct set_req {
	struct nlmsghdr n;
	struct ifinfomsg i;
	char buf[1024];
};

struct req_info {
	__u8 restart;
	__u8 disable_autorestart;
	__u32 restart_ms;
	struct can_ctrlmode *ctrlmode;
	struct can_bittiming *bittiming;
};

#define PF_CAN 29

#define SIOCGIFINDEX    0x8933          /* name -> if_index mapping     */
#define SIOCGIFFLAGS    0x8913          /* get flags                    */

/* Standard well-defined IP protocols.  */
enum
{
    IPPROTO_IP = 0,         /* Dummy protocol for TCP       */
    IPPROTO_ICMP = 1,       /* Internet Control Message Protocol    */
    IPPROTO_IGMP = 2,       /* Internet Group Management Protocol   */
    IPPROTO_IPIP = 4,       /* IPIP tunnels (older KA9Q tunnels use 94) */
    IPPROTO_TCP = 6,        /* Transmission Control Protocol    */
    IPPROTO_EGP = 8,        /* Exterior Gateway Protocol        */
    IPPROTO_PUP = 12,       /* PUP protocol             */
    IPPROTO_UDP = 17,       /* User Datagram Protocol       */
    IPPROTO_IDP = 22,       /* XNS IDP protocol         */
    IPPROTO_DCCP = 33,      /* Datagram Congestion Control Protocol */
    IPPROTO_RSVP = 46,      /* RSVP protocol            */
    IPPROTO_GRE = 47,       /* Cisco GRE tunnels (rfc 1701,1702)    */
    IPPROTO_IPV6 = 41,      /* IPv6-in-IPv4 tunnelling      */
    IPPROTO_ESP = 50,           /* Encapsulation Security Payload protocol */
    IPPROTO_AH = 51,                /* Authentication Header protocol       */
    IPPROTO_BEETPH = 94,            /* IP option pseudo header for BEET */
    IPPROTO_PIM    = 103,       /* Protocol Independent Multicast   */
    IPPROTO_COMP   = 108,           /* Compression Header protocol */
    IPPROTO_SCTP   = 132,       /* Stream Control Transport Protocol    */
    IPPROTO_UDPLITE = 136,      /* UDP-Lite (RFC 3828)          */
    IPPROTO_RAW  = 255,     /* Raw IP packets           */
    IPPROTO_MAX
};

/* particular protocols of the protocol family PF_CAN */
#define CAN_RAW         1 /* RAW sockets */
#define CAN_BCM         2 /* Broadcast Manager */
#define CAN_TP16        3 /* VAG Transport Protocol v1.6 */
#define CAN_TP20        4 /* VAG Transport Protocol v2.0 */
#define CAN_MCNET       5 /* Bosch MCNet */
#define CAN_ISOTP       6 /* ISO 15765-2 Transport Protocol */
#define CAN_NPROTO      7

static void
parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len)
{
	memset(tb, 0, sizeof(*tb) * max);
	while (RTA_OK(rta, len)) {
		if (rta->rta_type <= max) {
			tb[rta->rta_type] = rta;
		}

		rta = RTA_NEXT(rta, len);
	}
}

static int addattr32(struct nlmsghdr *n, size_t maxlen, int type, __u32 data)
{
	int len = RTA_LENGTH(4);
	struct rtattr *rta;

	if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
		fprintf(stderr,
			"addattr32: Error! max allowed bound %zu exceeded\n",
			maxlen);
		return -1;
	}

	rta = NLMSG_TAIL(n);
	rta->rta_type = type;
	rta->rta_len = len;
	memcpy(RTA_DATA(rta), &data, 4);
	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;

	return 0;
}

static int addattr_l(struct nlmsghdr *n, size_t maxlen, int type,
		     const void *data, int alen)
{
	int len = RTA_LENGTH(alen);
	struct rtattr *rta;

	if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
		fprintf(stderr,
			"addattr_l ERROR: message exceeded bound of %zu\n",
			maxlen);
		return -1;
	}

	rta = NLMSG_TAIL(n);
	rta->rta_type = type;
	rta->rta_len = len;
	memcpy(RTA_DATA(rta), data, alen);
	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);

	return 0;
}

/**
 * @ingroup intern
 * @brief send_mod_request - send a linkinfo modification request
 *
 * @param fd decriptor to a priorly opened netlink socket
 * @param n netlink message containing the request
 *
 * sends a request to setup the the linkinfo to netlink layer and awaits the
 * status.
 *
 * @return 0 if success
 * @return negativ if failed
 */
static int send_mod_request(int fd, struct nlmsghdr *n)
{
	int status;
	struct sockaddr_nl nladdr;
	struct nlmsghdr *h;

	struct iovec iov = {
		.iov_base = (void *)n,
		.iov_len = n->nlmsg_len
	};
	struct msghdr msg = {
		.msg_name = &nladdr,
		.msg_namelen = sizeof(nladdr),
		.msg_iov = &iov,
		.msg_iovlen = 1,
	};
	char buf[16384];

	memset(&nladdr, 0, sizeof(nladdr));

	nladdr.nl_family = AF_NETLINK;
	nladdr.nl_pid = 0;
	nladdr.nl_groups = 0;

	n->nlmsg_seq = 0;
	n->nlmsg_flags |= NLM_F_ACK;

	status = sendmsg(fd, &msg, 0);

	if (status < 0) {
		perror("Cannot talk to rtnetlink");
		return -1;
	}

	iov.iov_base = buf;
	while (1) {
		iov.iov_len = sizeof(buf);
		status = recvmsg(fd, &msg, 0);
		for (h = (struct nlmsghdr *)buf; (size_t) status >= sizeof(*h);) {
			int len = h->nlmsg_len;
			int l = len - sizeof(*h);
			if (l < 0 || len > status) {
				if (msg.msg_flags & MSG_TRUNC) {
					fprintf(stderr, "Truncated message\n");
					return -1;
				}
				printf("!!!malformed message: len=%d\n", len);
				return -1;
			}

			if (h->nlmsg_type == NLMSG_ERROR) {
				struct nlmsgerr *err =
				    (struct nlmsgerr *)NLMSG_DATA(h);
				if ((size_t) l < sizeof(struct nlmsgerr)) {
					fprintf(stderr, "ERROR truncated\n");
				} else {
					errno = -err->error;
					if (errno == 0)
						return 0;

					perror("RTNETLINK answers");
				}
				return -1;
			}
			status -= NLMSG_ALIGN(len);
			h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
		}
	}

	return 0;
}

/**
 * @ingroup intern
 * @brief send_dump_request - send a dump linkinfo request
 *
 * @param fd decriptor to a priorly opened netlink socket
 * @param family rt_gen message family
 * @param type netlink message header type
 *
 * @return 0 if success
 * @return negativ if failed
 */
static int send_dump_request(int fd, int family, int type)
{
	struct get_req req;

	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = sizeof(req);
	req.n.nlmsg_type = type;
	req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH;
	req.n.nlmsg_pid = 0;
	req.n.nlmsg_seq = 0;

	req.g.rtgen_family = family;

	return send(fd, (void *)&req, sizeof(req), 0);
}



  
//extern int optind, opterr, optopt;

/**
 * @ingroup intern
 * @brief open_nl_sock - open a netlink socket
 *
 * opens a netlink socket and returns the socket descriptor
 *
 * @return 0 if success
 * @return negativ if failed
 */
static int open_nl_sock()
{
	int fd;
	int sndbuf = 32768;
	int rcvbuf = 32768;
	unsigned int addr_len;
	struct sockaddr_nl local;

	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
	if (fd < 0) {
		printf("Cannot open netlink socket");
		return -1;
	}

	setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *)&sndbuf, sizeof(sndbuf));

	setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf, sizeof(rcvbuf));

	memset(&local, 0, sizeof(local));
	local.nl_family = AF_NETLINK;
	local.nl_groups = 0;

	if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0) {
		printf("Cannot bind netlink socket");
		return -1;
	}

	addr_len = sizeof(local);
	if (getsockname(fd, (struct sockaddr *)&local, &addr_len) < 0) {
		printf("Cannot getsockname");
		return -1;
	}
	if (addr_len != sizeof(local)) {
		printf("Wrong address length %u\n", addr_len);
		return -1;
	}
	if (local.nl_family != AF_NETLINK) {
		printf("Wrong address family %d\n", local.nl_family);
		return -1;
	}
	return fd;
}

/**
 * @ingroup intern
 * @brief do_get_nl_link - get linkinfo
 *
 * @param fd socket file descriptor to a priorly opened netlink socket
 * @param acquire  which parameter we want to get
 * @param name name of the can device. This is the netdev name, as ifconfig -a
 * shows in your system. usually it contains prefix "can" and the numer of the
 * can line. e.g. "can0"
 * @param res pointer to store the result
 *
 * This callback send a dump request into the netlink layer, collect the packet
 * containing the linkinfo and fill the pointer res points to depending on the
 * acquire mode set in param acquire.
 *
 * @return 0 if success
 * @return -1 if failed
 */

static int do_get_nl_link(int fd, __u8 acquire, const char *name, void *res)
{
	struct sockaddr_nl peer;

	char cbuf[64];
	char nlbuf[1024 * 8];

	int ret = -1;
	int done = 0;

	struct iovec iov = {
		.iov_base = (void *)nlbuf,
		.iov_len = sizeof(nlbuf),
	};

	struct msghdr msg = {
		.msg_name = (void *)&peer,
		.msg_namelen = sizeof(peer),
		.msg_iov = &iov,
		.msg_iovlen = 1,
		.msg_control = &cbuf,
		.msg_controllen = sizeof(cbuf),
		.msg_flags = 0,
	};
	struct nlmsghdr *nl_msg;
	ssize_t msglen;

	struct rtattr *linkinfo[IFLA_INFO_MAX + 1];
	struct rtattr *can_attr[IFLA_CAN_MAX + 1];

	if (send_dump_request(fd, AF_PACKET, RTM_GETLINK) < 0) {
		perror("Cannot send dump request");
		return ret;
	}

	while (!done && (msglen = recvmsg(fd, &msg, 0)) > 0) {
		size_t u_msglen = (size_t) msglen;
		/* Check to see if the buffers in msg get truncated */
		if (msg.msg_namelen != sizeof(peer) ||
		    (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) {
			fprintf(stderr, "Uhoh... truncated message.\n");
			return -1;
		}

		for (nl_msg = (struct nlmsghdr *)nlbuf;
		     NLMSG_OK(nl_msg, u_msglen);
		     nl_msg = NLMSG_NEXT(nl_msg, u_msglen)) {
			int type = nl_msg->nlmsg_type;
			int len;

			if (type == NLMSG_DONE) {
				done++;
				continue;
			}
			if (type != RTM_NEWLINK)
				continue;

			struct ifinfomsg *ifi = NLMSG_DATA(nl_msg);
			struct rtattr *tb[IFLA_MAX + 1];

			len =
				nl_msg->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
			parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);

			if (strcmp
			    ((char *)RTA_DATA(tb[IFLA_IFNAME]), name) != 0)
				continue;

			if (tb[IFLA_LINKINFO])
				parse_rtattr_nested(linkinfo,
						    IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
			else
				continue;

			if (acquire == GET_XSTATS) {
				if (!linkinfo[IFLA_INFO_XSTATS])
					fprintf(stderr, "no can statistics found\n");
				else {
					memcpy(res, RTA_DATA(linkinfo[IFLA_INFO_XSTATS]),
					       sizeof(struct can_device_stats));
					ret = 0;
				}
				continue;
			}

			if (!linkinfo[IFLA_INFO_DATA]) {
				fprintf(stderr, "no link data found\n");
				return ret;
			}

			parse_rtattr_nested(can_attr, IFLA_CAN_MAX,
					    linkinfo[IFLA_INFO_DATA]);

			switch (acquire) {
			case GET_STATE:
				if (can_attr[IFLA_CAN_STATE]) {
					*((int *)res) = *((__u32 *)
							  RTA_DATA(can_attr
								   [IFLA_CAN_STATE]));
					ret = 0;
				} else {
					fprintf(stderr, "no state data found\n");
				}

				break;
			case GET_RESTART_MS:
				if (can_attr[IFLA_CAN_RESTART_MS]) {
					*((__u32 *) res) = *((__u32 *)
							     RTA_DATA(can_attr
								      [IFLA_CAN_RESTART_MS]));
					ret = 0;
				} else
					fprintf(stderr, "no restart_ms data found\n");

				break;
			case GET_BITTIMING:
				if (can_attr[IFLA_CAN_BITTIMING]) {
					memcpy(res,
					       RTA_DATA(can_attr[IFLA_CAN_BITTIMING]),
					       sizeof(struct can_bittiming));
					ret = 0;
				} else
					fprintf(stderr, "no bittiming data found\n");

				break;
			case GET_CTRLMODE:
				if (can_attr[IFLA_CAN_CTRLMODE]) {
					memcpy(res,
					       RTA_DATA(can_attr[IFLA_CAN_CTRLMODE]),
					       sizeof(struct can_ctrlmode));
					ret = 0;
				} else
					fprintf(stderr, "no ctrlmode data found\n");

				break;
			case GET_CLOCK:
				if (can_attr[IFLA_CAN_CLOCK]) {
					memcpy(res,
					       RTA_DATA(can_attr[IFLA_CAN_CLOCK]),
					       sizeof(struct can_clock));
					ret = 0;
				} else
					fprintf(stderr,
						"no clock parameter data found\n");

				break;
			case GET_BITTIMING_CONST:
				if (can_attr[IFLA_CAN_BITTIMING_CONST]) {
					memcpy(res,
					       RTA_DATA(can_attr[IFLA_CAN_BITTIMING_CONST]),
					       sizeof(struct can_bittiming_const));
					ret = 0;
				} else
					fprintf(stderr, "no bittiming_const data found\n");

				break;
			case GET_BERR_COUNTER:
				if (can_attr[IFLA_CAN_BERR_COUNTER]) {
					memcpy(res,
					       RTA_DATA(can_attr[IFLA_CAN_BERR_COUNTER]),
					       sizeof(struct can_berr_counter));
					ret = 0;
				} else
					fprintf(stderr, "no berr_counter data found\n");

				break;

			default:
				fprintf(stderr, "unknown acquire mode\n");
			}
		}
	}

	return ret;
}

/**
 * @ingroup intern
 * @brief get_link - get linkinfo
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param acquire which parameter we want to get
 * @param res pointer to store the result
 *
 * This is a wrapper for do_get_nl_link
 *
 * @return 0 if success
 * @return -1 if failed
 */
static int get_link(const char *name, __u8 acquire, void *res)
{
	int err, fd;

	fd = open_nl_sock();
	if (fd < 0)
		return -1;

	err = do_get_nl_link(fd, acquire, name, res);
	close(fd);

	return err;

}

/**
 * @ingroup intern
 * @brief do_set_nl_link - setup linkinfo
 *
 * @param fd socket file descriptor to a priorly opened netlink socket
 * @param if_state state of the interface we want to put the device into. this
 * parameter is only set if you want to use the callback to driver up/down the
 * device
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param req_info request parameters
 *
 * This callback can do two different tasks:
 * - bring up/down the interface
 * - set up a netlink packet with request, as set up in req_info
 * Which task this callback will do depends on which parameters are set.
 *
 * @return 0 if success
 * @return -1 if failed
 */
static int do_set_nl_link(int fd, __u8 if_state, const char *name,
			  struct req_info *req_info)
{
	struct set_req req;

	const char *type = "can";

	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
	req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
	req.n.nlmsg_type = RTM_NEWLINK;
	req.i.ifi_family = 0;

	req.i.ifi_index = if_nametoindex(name);
	if (req.i.ifi_index == 0) {
		fprintf(stderr, "Cannot find device \"%s\"\n", name);
		return -1;
	}

	if (if_state) {
		switch (if_state) {
		case IF_DOWN:
			req.i.ifi_change |= IFF_UP;
			req.i.ifi_flags &= ~IFF_UP;
			break;
		case IF_UP:
			req.i.ifi_change |= IFF_UP;
			req.i.ifi_flags |= IFF_UP;
			break;
		default:
			fprintf(stderr, "unknown state\n");
			return -1;
		}
	}

	if (req_info != NULL) {
		/* setup linkinfo section */
		struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
		addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
		addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type,
			  strlen(type));
		/* setup data section */
		struct rtattr *data = NLMSG_TAIL(&req.n);
		addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);

		if (req_info->restart_ms > 0 || req_info->disable_autorestart)
			addattr32(&req.n, 1024, IFLA_CAN_RESTART_MS,
				  req_info->restart_ms);

		if (req_info->restart)
			addattr32(&req.n, 1024, IFLA_CAN_RESTART, 1);

		if (req_info->bittiming != NULL) {
			addattr_l(&req.n, 1024, IFLA_CAN_BITTIMING,
				  req_info->bittiming,
				  sizeof(struct can_bittiming));
		}

		if (req_info->ctrlmode != NULL) {
			addattr_l(&req.n, 1024, IFLA_CAN_CTRLMODE,
				  req_info->ctrlmode,
				  sizeof(struct can_ctrlmode));
		}

		/* mark end of data section */
		data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;

		/* mark end of link info section */
		linkinfo->rta_len =
		    (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
	}

	return send_mod_request(fd, &req.n);
}

/**
 * @ingroup intern
 * @brief set_link - open a netlink socket and setup linkinfo
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a
 * shows in your system. usually it contains prefix "can" and the numer of the
 * can line. e.g. "can0"
 * @param if_state state of the interface we want to put the device into. this
 * parameter is only set if you want to use the callback to driver up/down the
 * device
 * @param req_info request parameters
 *
 * This is a wrapper for do_set_nl_link. It opens a netlink socket and sends
 * down the requests.
 *
 * @return 0 if success
 * @return -1 if failed
 */
static int set_link(const char *name, __u8 if_state, struct req_info *req_info)
{
	int err, fd;

	fd = open_nl_sock();
	if (fd < 0)
		return -1;

	err = do_set_nl_link(fd, if_state, name, req_info);
	close(fd);

	return err;
}

/**
 * @ingroup extern
 * can_do_start - start the can interface
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 *
 * This starts the can interface with the given name. It simply changes the if
 * state of the interface to up. All initialisation works will be done in
 * kernel. The if state can also be queried by a simple ifconfig.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_do_start(const char *name)
{
	return set_link(name, IF_UP, NULL);
}

/**
 * @ingroup extern
 * can_do_stop - stop the can interface
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 *
 * This stops the can interface with the given name. It simply changes the if
 * state of the interface to down. Any running communication would be stopped.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_do_stop(const char *name)
{
	return set_link(name, IF_DOWN, NULL);
}

/**
 * @ingroup extern
 * can_do_restart - restart the can interface
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 *
 * This triggers the start mode of the can device.
 *
 * NOTE:
 * - restart mode can only be triggerd if the device is in BUS_OFF and the auto
 * restart not turned on (restart_ms == 0)
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_do_restart(const char *name)
{
	int state;
	__u32 restart_ms;

	/* first we check if we can restart the device at all */
	if ((can_get_state(name, &state)) < 0) {
		fprintf(stderr, "cannot get bustate, "
			"something is seriously wrong\n");
		return -1;
	} else if (state != CAN_STATE_BUS_OFF) {
		fprintf(stderr,
			"Device is not in BUS_OFF," " no use to restart\n");
		return -1;
	}

	if ((can_get_restart_ms(name, &restart_ms)) < 0) {
		fprintf(stderr, "cannot get restart_ms, "
			"something is seriously wrong\n");
		return -1;
	} else if (restart_ms > 0) {
		fprintf(stderr,
			"auto restart with %ums interval is turned on,"
			" no use to restart\n", restart_ms);
		return -1;
	}

	struct req_info req_info = {
		.restart = 1,
	};

	return set_link(name, 0, &req_info);
}

/**
 * @ingroup extern
 * can_set_restart_ms - set interval of auto restart.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param restart_ms interval of auto restart in milliseconds
 *
 * This sets how often the device shall automatically restart the interface in
 * case that a bus_off is detected.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_set_restart_ms(const char *name, __u32 restart_ms)
{
	struct req_info req_info = {
		.restart_ms = restart_ms,
	};

	if (restart_ms == 0)
		req_info.disable_autorestart = 1;

	return set_link(name, 0, &req_info);
}

/**
 * @ingroup extern
 * can_set_ctrlmode - setup the control mode.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 *
 * @param cm pointer of a can_ctrlmode struct
 *
 * This sets the control mode of the can device. There're currently three
 * different control modes:
 * - LOOPBACK
 * - LISTEN_ONLY
 * - TRIPPLE_SAMPLING
 *
 * You have to define the control mode struct yourself. a can_ctrlmode struct
 * is declared as:
 *
 * @code
 * struct can_ctrlmode {
 *	__u32 mask;
 *	__u32 flags;
 * }
 * @endcode
 *
 * You can use mask to select modes you want to control and flags to determine
 * if you want to turn the selected mode(s) on or off. Every control mode is
 * mapped to an own macro
 *
 * @code
 * #define CAN_CTRLMODE_LOOPBACK   0x1
 * #define CAN_CTRLMODE_LISTENONLY 0x2
 * #define CAN_CTRLMODE_3_SAMPLES  0x4
 * @endcode
 *
 * e.g. the following pseudocode
 *
 * @code
 * struct can_ctrlmode cm;
 * memset(&cm, 0, sizeof(cm));
 * cm.mask = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
 * cm.flags = CAN_CTRLMODE_LOOPBACK;
 * can_set_ctrlmode(candev, &cm);
 * @endcode
 *
 * will turn the loopback mode on and listenonly mode off.
 *
 * @return 0 if success
 * @return -1 if failed
 */

int can_set_ctrlmode(const char *name, struct can_ctrlmode *cm)
{
	struct req_info req_info = {
		.ctrlmode = cm,
	};

	return set_link(name, 0, &req_info);
}

/**
 * @ingroup extern
 * can_set_bittiming - setup the bittiming.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param bt pointer to a can_bittiming struct
 *
 * This sets the bittiming of the can device. This is for advantage usage. In
 * normal cases you should use can_set_bitrate to simply define the bitrate and
 * let the driver automatically calculate the bittiming. You will only need this
 * function if you wish to define the bittiming in expert mode with fully
 * manually defined timing values.
 * You have to define the bittiming struct yourself. a can_bittiming struct
 * consists of:
 *
 * @code
 * struct can_bittiming {
 *	__u32 bitrate;
 *	__u32 sample_point;
 *	__u32 tq;
 *	__u32 prop_seg;
 *	__u32 phase_seg1;
 *	__u32 phase_seg2;
 *	__u32 sjw;
 *	__u32 brp;
 * }
 * @endcode
 *
 * to define a customized bittiming, you have to define tq, prop_seq,
 * phase_seg1, phase_seg2 and sjw. See http://www.can-cia.org/index.php?id=88
 * for more information about bittiming and synchronizations on can bus.
 *
 * @return 0 if success
 * @return -1 if failed
 */

int can_set_bittiming(const char *name, struct can_bittiming *bt)
{
	struct req_info req_info = {
		.bittiming = bt,
	};

	return set_link(name, 0, &req_info);
}

/**
 * @ingroup extern
 * can_set_bitrate - setup the bitrate.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param bitrate bitrate of the can bus
 *
 * This is the recommended way to setup the bus bit timing. You only have to
 * give a bitrate value here. The exact bit timing will be calculated
 * automatically. To use this function, make sure that CONFIG_CAN_CALC_BITTIMING
 * is set to y in your kernel configuration. bitrate can be a value between
 * 1000(1kbit/s) and 1000000(1000kbit/s).
 *
 * @return 0 if success
 * @return -1 if failed
 */

int can_set_bitrate(const char *name, __u32 bitrate)
{
	struct can_bittiming bt;

	memset(&bt, 0, sizeof(bt));
	bt.bitrate = bitrate;

	return can_set_bittiming(name, &bt);
}

/**
 * @ingroup extern
 * can_set_bitrate_samplepoint - setup the bitrate.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param bitrate bitrate of the can bus
 * @param sample_point sample point value
 *
 * This one is similar to can_set_bitrate, only you can additionally set up the
 * time point for sampling (sample point) customly instead of using the
 * CIA recommended value. sample_point can be a value between 0 and 999.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_set_bitrate_samplepoint(const char *name, __u32 bitrate,
				__u32 sample_point)
{
	struct can_bittiming bt;

	memset(&bt, 0, sizeof(bt));
	bt.bitrate = bitrate;
	bt.sample_point = sample_point;

	return can_set_bittiming(name, &bt);
}

/**
 * @ingroup extern
 * can_get_state - get the current state of the device
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param state pointer to store the state
 *
 * This one stores the current state of the can interface into the given
 * pointer. Valid states are:
 * - CAN_STATE_ERROR_ACTIVE
 * - CAN_STATE_ERROR_WARNING
 * - CAN_STATE_ERROR_PASSIVE
 * - CAN_STATE_BUS_OFF
 * - CAN_STATE_STOPPED
 * - CAN_STATE_SLEEPING
 *
 * The first four states is determined by the value of RX/TX error counter.
 * Please see relevant can specification for more information about this. A
 * device in STATE_STOPPED is an inactive device. STATE_SLEEPING is not
 * implemented on all devices.
 *
 * @return 0 if success
 * @return -1 if failed
 */

int can_get_state(const char *name, int *state)
{
	return get_link(name, GET_STATE, state);
}

/**
 * @ingroup extern
 * can_get_restart_ms - get the current interval of auto restarting.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param restart_ms pointer to store the value.
 *
 * This one stores the current interval of auto restarting into the given
 * pointer.
 *
 * The socketcan framework can automatically restart a device if it is in
 * bus_off in a given interval. This function gets this value in milliseconds.
 * restart_ms == 0 means that autorestarting is turned off.
 *
 * @return 0 if success
 * @return -1 if failed
 */

int can_get_restart_ms(const char *name, __u32 *restart_ms)
{
	return get_link(name, GET_RESTART_MS, restart_ms);
}

/**
 * @ingroup extern
 * can_get_bittiming - get the current bittimnig configuration.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param bt pointer to the bittiming struct.
 *
 * This one stores the current bittiming configuration.
 *
 * Please see can_set_bittiming for more information about bit timing.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_get_bittiming(const char *name, struct can_bittiming *bt)
{
	return get_link(name, GET_BITTIMING, bt);
}

/**
 * @ingroup extern
 * can_get_ctrlmode - get the current control mode.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param cm pointer to the ctrlmode struct.
 *
 * This one stores the current control mode configuration.
 *
 * Please see can_set_ctrlmode for more information about control modes.
 *
 * @return 0 if success
 * @return -1 if failed
 */

int can_get_ctrlmode(const char *name, struct can_ctrlmode *cm)
{
	return get_link(name, GET_CTRLMODE, cm);
}

/**
 * @ingroup extern
 * can_get_clock - get the current clock struct.
 *
 * @param name: name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param clock pointer to the clock struct.
 *
 * This one stores the current clock configuration. At the time of writing the
 * can_clock struct only contains information about the clock frequecy. This
 * information is e.g. essential while setting up the bit timing.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_get_clock(const char *name, struct can_clock *clock)
{
	return get_link(name, GET_CLOCK, clock);
}

/**
 * @ingroup extern
 * can_get_bittiming_const - get the current bittimnig constant.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param btc pointer to the bittiming constant struct.
 *
 * This one stores the hardware dependent bittiming constant. The
 * can_bittiming_const struct consists:
 *
 * @code
 * struct can_bittiming_const {
 *	char name[16];
 *	__u32 tseg1_min;
 *	__u32 tseg1_max;
 *	__u32 tseg2_min;
 *	__u32 tseg2_max;
 *	__u32 sjw_max;
 *	__u32 brp_min;
 *	__u32 brp_max;
 *	__u32 brp_inc;
 *	};
 * @endcode
 *
 * The information in this struct is used to calculate the bus bit timing
 * automatically.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_get_bittiming_const(const char *name, struct can_bittiming_const *btc)
{
	return get_link(name, GET_BITTIMING_CONST, btc);
}


/**
 * @ingroup extern
 * can_get_berr_counter - get the tx/rx error counter.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param bc pointer to the error counter struct..
 *
 * This one gets the current rx/tx error counter from the hardware.
 *
 * @code
 * struct can_berr_counter {
 *	__u16 txerr;
 *	__u16 rxerr;
 *	};
 * @endcode
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_get_berr_counter(const char *name, struct can_berr_counter *bc)
{
	return get_link(name, GET_BERR_COUNTER, bc);
}

/**
 * @ingroup extern
 * can_get_device_stats - get the can_device_stats.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param bc pointer to the error counter struct..
 *
 * This one gets the current can_device_stats.
 *
 * Please see struct can_device_stats for more information.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_get_device_stats(const char *name, struct can_device_stats *cds)
{
	return get_link(name, GET_XSTATS, cds);
}

void can_write_test(int arg)
{
	int s = (int) arg;
	struct can_frame frame;
	int dlc = 8;
	int i, rtr = 0, extended = 0;
	ssize_t len;
	int err;
	struct pollfd fds[] = {
		{
 			.fd = s,
			.events = POLLOUT,
		},
	};

	for(i = 0; i < dlc; i++) {
		frame.data[i] = 0x31 + i;
	}

	frame.can_id = 0x100;
	frame.can_dlc = dlc;

	if (extended) {
		frame.can_id &= CAN_EFF_MASK;
		frame.can_id |= CAN_EFF_FLAG;
	}
	else
		frame.can_id &= CAN_SFF_MASK;

	if (rtr)
		frame.can_id |= CAN_RTR_FLAG;

	printf("\n CAN0 transfer id: %d", frame.can_id);
	printf("\n CAN0 transfer dlc: %d", frame.can_dlc);
	printf("\n CAN0 transfer Data:\n");
	for (i = 0; i < frame.can_dlc; i++)
		printf(" 0x%02x", frame.data[i]);
	printf("\n");

again:
	while(1) {
		err = poll(fds, 1, 1000);

		if((err == -1) || (err == 0))
			printf("\n poll write error = %d \n", err);
		else
			break;
	}

	/* send frame */
	len = write(s, &frame, sizeof(frame));

	usleep(500);

	if(len != sizeof(frame))
		printf("\n write error %d \n", errno);

	if (len == -1) {
		switch (errno) {
			case ENOBUFS:
				usleep(1000);
				break;

			case EINTR: /* fallthrough */
				usleep(1000);
				goto again;
			default:
				usleep(1000);
				goto again;
		}
	}

	printf("\n CAN0 transfer end !!!\n");
}

void can_read_test(int arg)
{
	int s = (int) arg;
	struct can_frame Rx_frame;
	fd_set readfds;
	int i;
	ssize_t nbytes;
	int err;

	struct pollfd fds[] = {
		{
			.fd	= s,
			.events	= POLLIN,
		},
	};

	while(1) {
		err = poll(fds, 1, 10000);

		if((err == -1) || (err == 0))
			printf("\n poll read error =%d ", err);
		else
			break;
	}

	nbytes = read(s, &Rx_frame, sizeof(Rx_frame));

	printf("\n CAN1 receive id = %d", Rx_frame.can_id);
	printf("\n CAN1 receive dlc = %d", Rx_frame.can_dlc);
	printf("\n CAN1 receive Data:\n");
	for (i = 0; i < Rx_frame.can_dlc; i++)
		printf(" 0x%02x", Rx_frame.data[i]);

	printf("\n");
}

int main(int argc, char **argv)
{
	struct ifreq ifr;
	struct sockaddr_can addr;
	int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
	int s[2];
	int j;

	can_set_bitrate("can0", 500000);
	can_do_start("can0");
	can_set_bitrate("can1", 500000);
	can_do_start("can1");

	for(j = 0; j <= 1; j++)
	{
		if(j == 0)
		{
			strcpy(ifr.ifr_name, "can0");
		}
		else if(j == 1)
		{
			strcpy(ifr.ifr_name, "can1");
		}

		s[j] = socket(family, type, proto);
		if (s[j] < 0)
		{
			printf("ERROR");
			return 1;
		}

		addr.can_family = family;

		if (ioctl(s[j], SIOCGIFINDEX, &ifr) < 0)
		{
			printf("ERROR");
			return 1;
		}

		addr.can_ifindex = ifr.ifr_ifindex;
		if (bind(s[j], (struct sockaddr *)&addr, sizeof(addr)) < 0)
		{
			printf("ERROR");
			return 1;
		}

	}

	can_write_test(s[0]);
	can_read_test(s[1]);

	can_do_stop("can0");
	can_do_stop("can1");

	return 0;
}

参考官方,修改CAN0口测试收发,修改后代码如下

int main(int argc, char **argv)
{
	struct can_frame frame;
	struct can_frame Rx_frame;
	struct ifreq ifr;
	struct sockaddr_can addr;
	
	int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
	int dlc = 8;
	int can0_fd, ret, i, err,rtr = 0, extended = 0;
	int j;
	int ret1;
	int Tx_cnt = 0;
	ssize_t nbytes;

	can_set_bitrate("can0", 5000);
	can_do_start("can0");
    strcpy(ifr.ifr_name, "can0");
		
	can0_fd = socket(family, type, proto);
	if (can0_fd < 0)
	{
		printf("ERROR");
		return 1;
	}

	addr.can_family = family;

	if (ioctl(can0_fd, SIOCGIFINDEX, &ifr) < 0)
	{
		printf("ERROR");
		return 1;
	}

	addr.can_ifindex = ifr.ifr_ifindex;
	if (bind(can0_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
	{
		printf("ERROR");
		return 1;
	}
		
	
	
	for(i = 0; i < dlc; i++)
	{
		frame.data[i] = Tx_cnt%34 + i;
		Rx_frame.data[i] = 0;
	}

	frame.can_id = 0x100;
	frame.can_dlc = dlc;

	if (extended)
	{
		frame.can_id &= CAN_EFF_MASK;
		frame.can_id |= CAN_EFF_FLAG;
	} 
	else
	{
		frame.can_id &= CAN_SFF_MASK;
	}

	if (rtr)
		frame.can_id |= CAN_RTR_FLAG;
	
	printf("\n CAN0 transfer id: %d", frame.can_id);
	printf("\n CAN0 transfer dlc: %d", frame.can_dlc);
	printf("\n CAN0 transfer Data:\n");
	for (i = 0; i < frame.can_dlc; i++)
		printf(" 0x%02x", frame.data[i]);
	printf("\n");

	ret1 = 0;
	for(;;)
	{
		//send
		for(i = 0; i < dlc; i++)
		{
			frame.data[i] = Tx_cnt%34 + i;
			Rx_frame.data[i] = 0;
		}

		ret = write(can0_fd, &frame, sizeof(frame));
		if (ret == -1)
		{
			printf("write error !! \n");
		}
		printf("\n CAN0 transfer Data:\t");
		for (i = 0; i < frame.can_dlc; i++)
			printf(" 0x%02x", frame.data[i]);
		Tx_cnt++;
		printf("\t Tx: %d \n", Tx_cnt);

		//rx
		struct pollfd fds[] = {
			{
				.fd	= can0_fd,
				.events	= POLLIN,
			},
		};
		err = poll(fds, 1, 10000);
		switch(err)
		{
			case -1://出错
				printf("\n poll read error =%d ", err);
				break;
			case 0://超时
				printf("\n poll read error =%d ", err);
				break;
			default:
				nbytes = read(can0_fd, &Rx_frame, sizeof(Rx_frame));
				printf("\n CAN0 receive id = %d", Rx_frame.can_id);
				printf("\n CAN0 receive dlc = %d", Rx_frame.can_dlc);
				printf("\n CAN0 receive Data:\n");
				for (i = 0; i < Rx_frame.can_dlc; i++)
					printf(" 0x%02x", Rx_frame.data[i]);

				printf("\n");
				break;
		}
				
		sleep(10);
	}
	
	can_do_stop("can0"); 

        
	return 0;
}

三、测试结果

CAN0口连接周立功USBCAN-E-mini,连接电脑,测试收发。
在这里插入图片描述

在这里插入图片描述

参考
https://blog.csdn.net/wallace89/article/details/111303439

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/445487.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统安装及简单操作

目录 一、Linux系统安装 二、Linux系统启动 三、Linux系统本地登录 四、Linux系统操作方式 五、Linux的七种运行级别&#xff08;runlevel&#xff09; 六、shell 七、命令 一、Linux系统安装 场景1&#xff1a;直接通过光盘安装到硬件上&#xff08;方法和Windows安装…

1.初学docker

这是在centos7上的基本操作用法。 一、基本操作 # 安装yum源 yum install -y yum-utils # 配置yum源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 安装docker yum install -y docker-ce-cli containerd.io docker-buildx-plu…

计算机网络-数据链路层

一、认识以太网 "以太网" 不是⼀种具体的网络&#xff0c;而是一种技术标准; 既包含了数据链路层的内容, 也包含了⼀些物理 层的内容。 例如&#xff1a;规定了网络拓扑结构&#xff0c;访问控制方式&#xff0c;传输速率等; 例如&#xff1a;以太网中的网线必须使用…

mysql的trace追踪SQL工具,进行sql优化

trace是MySQL5.6版本后提供的SQL跟踪工具&#xff0c;通过使用trace可以让我们明白optimizer&#xff08;优化器&#xff09;如何选择执行计划。 注意&#xff1a;开启trace工具会影响mysql性能&#xff0c;所以只适合临时分析sql使用&#xff0c;用完之后请立即关闭。 测试数…

MQ高可用相关设置

文章目录 前言MQ如何保证消息不丢失RabbitMQRocketMQKafkaMQ MQ如何保证顺序消息RabbitMQRocketMQKafka MQ刷盘机制/集群同步RabbitMQRocketMQKafka 广播消息&集群消息RabbitMQRocketMQ MQ集群架构RabbitMQRocketMQKafka 消息重试RabbitMQRockeMqKafka 死信队列RocketMQKaf…

基于springboot实现中小企业财务管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现中小企业财务管理系统演示 摘要 自改革开放一来&#xff0c;我国的经济发展进入到了快速发展时期&#xff0c;大城市的经济水平不断提高&#xff0c;吸引了很多的人不愿千里来大城市奋斗。一个企业的发展离不开相关的规定流程。信息化到来的今天在我们的生活…

计算机网络(基础篇)复习笔记——体系结构/协议基础(持续更新中......)

目录 1 计算机网络基础相关技术Rip 路由更新操作 2 体系结构(OSI 7层, TCP/IP4层)应用层运输层网络层IPv4无分类域间路由选择 CIDRIPV6 数据链路层循环冗余校验CRC协议设备 物理层传输媒体信道复用技术宽带接入技术数据通信 3 网络局域网(以太网Ethernet) 4 通信过程编码:信道极…

uniapp让输入框保持聚焦状态,不会失去焦点

使用场景&#xff1a;当输入框还有发送按钮的时候&#xff0c;点击发送希望软键盘不消失&#xff0c;还可以继续输入&#xff0c;或者避免因输入图片标签造成的屏闪问题 多次尝试后发现一个很实用的方法&#xff0c;适用input输入框和editor输入框 解决办法&#xff1a;把cli…

operator-sdk入门(mac)

1. 安装operator-sdk brew install operator-sdk 2. 安装kubebuilder brew install kubebuilder 3.初始化一个operator脚手架 3.1 新建一个文件夹 redis-operator 3.2 执行初始化 operator-sdk init --domain lyl.com --repo github.com 参数介绍 可以通过operator-sdk --…

Windows下同一电脑配置多个Git公钥访问不同的账号

前言 产生这个问题的原因是我在Gitee码云上有两个账号,为了方便每次不用使用http模式推拉代码,于是我就使用了ssh的模式,起初呢我用两台电脑分别连接两个账号,用起来也相安无事,近段时时间台式机在家里,我在外地出差了,就想着把ssh公钥同时添加到不同的账号里,结果却发现不能用…

《探索自动驾驶技术的前景与挑战》

自动驾驶技术,作为现代科技的一大突破,正逐渐改变着我们的交通方式、生活方式以及整个社会结构。本文将围绕自动驾驶技术的现状、优势、局限性以及未来发展趋势展开探讨。 自动驾驶技术的现状概述 自动驾驶技术作为当今科技领域的一项前沿技术,已经取得了巨大的进展并在不同…

Python算法题集_在排序数组中查找元素的第一个和最后一个位置

Python算法题集_在排序数组中查找元素的第一个和最后一个位置 题34&#xff1a;在排序数组中查找元素的第一个和最后一个位置1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【二分法两次左边界】2) 改进版一【二分法左右边界】3) 改进版二【第三…

linux安装ngnix完整步骤(支持centos/银河麒麟操作系统)

linux安装ngnix&#xff08;支持centos/银河麒麟操作系统&#xff09; 本次操作系统安装ngnix采用离线或在线安装方式&#xff0c;离线就是不联网环境&#xff0c;在线则是联网环境&#xff1b;支持centos7或centos8或国产操作系统&#xff08;银河麒麟高级服务器操作系统&…

VUE3项目学习系列--项目基础配置(四)

一、环境变量配置 项目开发过程中会经历开发环境、测试环境、生产环境三种状态&#xff0c;对与环境变量的配置需求不同&#xff0c;因此需要在项目中进行环境变量的配置。 1.在项目根目录下添加如下3个文件 .env.development.env.production.env.test 文件中输入对应的配置…

Turbo C++编译并运行 C语言程序

Turbo C编译并运行 C语言程序 安装和下载Windows 版Turbo CTurbo C编译和运行 C 程序1.打开Turbo C2.新建C语言程序3.保存C语言程序4.命名C语言程序5.编译C语言程序6.运行C语言程序7.运行C语言程序成功 Turbo C是什么&#xff1f;什么是编译器&#xff1f;Turbo C/C 的超凡价值…

算法---双指针练习-4(盛水最多的容器)

题目 1. 题目解析2. 讲解算法原理3. 编写代码 1. 题目解析 题目地址&#xff1a;盛水最多的容器 2. 讲解算法原理 算法的主要思路是使用双指针的方法&#xff0c;通过不断调整指针的位置来计算面积&#xff0c;并更新最大面积。具体步骤如下&#xff1a; 初始化左指针x为数组…

Java二叉树 (2)

&#x1f435;本篇文章将对二叉树的一些基础操作进行梳理和讲解 一、操作简述 int size(Node root); // 获取树中节点的个数int getLeafNodeCount(Node root); // 获取叶子节点的个数int getKLevelNodeCount(Node root,int k); // 获取第K层节点的个数int getHeight(Node r…

基于springboot+vue实现早餐店点餐系统项目【项目源码+论文说明】计算机毕业设计

基于springbootvue实现早餐店点餐系统演示 摘要 多姿多彩的世界带来了美好的生活&#xff0c;行业的发展也是形形色色的离不开技术的发展。作为时代进步的发展方面&#xff0c;信息技术至始至终都是成就行业发展的重要秘密。不论何种行业&#xff0c;大到国家、企业&#xff0…

Python实例☞组织结构案例

实例一&#xff1a; ❶要求☞ 使用while循环模拟用户登录 ❷程序代码☞ i1 while i<4: nameinput("请输入您的姓名&#xff1a;") passwardinput("请输入你的密码&#xff1a;") if name"鯨殤" and passward"88888": print(&quo…

VLAN FAQ

如何快速查看所有接口的接口类型和缺省VLAN&#xff1f; 可通过命令display port vlan查看到设备上所有接口的接口类型和缺省VLAN。例如&#xff1a; V200R005及后续版本<HUAWEI> display port vlan Port Link Type PVID Trunk VLAN List --…