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 8struct 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      7static 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]);elsecontinue;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;} elsefprintf(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;} elsefprintf(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;} elsefprintf(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;} elsefprintf(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;} elsefprintf(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;} elsefprintf(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;}elseframe.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);elsebreak;}/* 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);elsebreak;}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(;;){//sendfor(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);//rxstruct 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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Tokeniser估算GPT和LLM服务的查询成本

将LLM集成到项目所花费的成本主要是我们通过API获取LLM返回结果的成本&#xff0c;而这些成本通常是根据处理的令牌数量计算的。我们如何预估我们的令牌数量呢&#xff1f;Tokeniser包可以有效地计算文本输入中的令牌来估算这些成本。本文将介绍如何使用Tokeniser有效地预测和管…

异步编程实战:使用C#实现FTP文件下载及超时控制

博客标题: 异步编程实战&#xff1a;使用C#实现FTP文件下载及超时控制 如果你的函数不是async&#xff0c;你仍然可以实现相同的超时功能&#xff0c;但你将不得不依赖更多的同步代码或使用.Result或.GetAwaiter().GetResult()来阻塞等待任务完成&#xff0c;这可能导致死锁的风…

verilog中的函数和for循环

在Verilog中&#xff0c;clogb2 的英文全称是 “ceiling&#xff08;天花板&#xff09; log base 2”&#xff0c;表示对输入参数取对数&#xff08;以2为底&#xff09;&#xff0c;并向上取整到最接近的整数值。这个函数通常用于计算内存地址宽度或状态数所需的位数12。 fun…

STM32---通用定时器(二)相关实验

写在前面&#xff1a;前面我们学习了基本定时器、通用定时器的相关理论部分&#xff0c;了解到通用定时器的结构框图&#xff0c;总共包含六大模块&#xff1a;时钟源、控制器、时基单元、输入捕获、公共部分以及输出捕获。对相关模块的使用也做详细的讲解。本节我们主要是对上…

Day33-计算机基础3

Day33-计算机基础3 1.根据TCP/IP进行Linux内核参数优化1.1 例1&#xff1a;调整访问服务端的【客户端】的动态端口范围 &#xff0c;LVS&#xff08;10-50万并发&#xff09;&#xff0c;NGINX负载&#xff0c;SQUID缓存服务,1.2 企业案例&#xff1a;DOS攻击的案例&#xff1a…

[备赛笔记]——5G大唐杯(5G考试等级考考试基础试题)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;Vir2021GKBS &#x1f43c;本文由…

redis缓存满了的话会发生什么?

线上问题 未及时加监控&#xff0c;导致线上redis被逐出&#xff0c;业务有损 示例&#xff1a; 一个key临时存储在redis等缓存中&#xff0c;如果该key在一段时间内有很大作用 比如一次业务请求&#xff0c;上游服务写入一个value&#xff0c;时长1小时&#xff0c;下游服务…

Matlab|考虑源荷两侧不确定性的含风电电力系统低碳调度

目录 1 主要内容 目标函数&#xff1a; 约束条件&#xff1a; 程序亮点总结&#xff1a; 2 代码问题与程序测试 设备出力运行结果&#xff1a; 3 下载链接 1 主要内容 本程序是对《考虑源荷两侧不确定性的含风电电力系统低碳调度》的方法复现&#xff0c;主要实现了基…

【QT+QGIS跨平台编译】之七十六:【QGIS_Native+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、QGIS_Native介绍二、QGIS下载三、文件分析四、pro文件五、编译实践一、QGIS_Native介绍 QGIS_Native模块是QGIS软件的核心部分,提供了许多基本功能和核心组件,主要用于处理与底层操作系统的关系。 二、QGIS下载 QGIS网址: QGIS Source Download 三、文件分析…

Django学习笔记

Django学习笔记 一、Django整体流程跑通 1.1安装 pip install django //安装 import django //在python环境中导入django django.get_version() //获取版本号&#xff0c;如果能获取到&#xff0c;说明安装成功Django目录结构 Python310-Scripts\django-admi…

前端框架的发展历程

文章目录 前言 一、静态页面时代 二、JavaScript的兴起 三、jQuery的出现 四、前端框架的崛起 1.AngularJS 2.React 3.Vue.js 五、面向组件化的发展趋势 总结 前言 前端框架的发展史就是一个不断进化的过程&#xff0c;它的发展和进化一定程度…

力扣刷题Days14第二题--80删除数组中重复元素||(js)

目录 1&#xff0c;题目-中等 2&#xff0c;代码 双指针 3&#xff0c;学习与总结 思路学习与整理 1&#xff0c;题目-中等 给你一个有序数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使得出现次数超过两次的元素只出现两次 &#xff0c;返回删除后数组…

区块链和人工智能的关系以及经典案例

目录 1.区块链与人工智能的关系 2.应用案例&#xff1a;基于区块链的医疗数据共享平台 2.1背景 2.2方案 2.3优势 2.4挑战 区块链技术和人工智能&#xff08;AI&#xff09;是两种不同的技术&#xff0c;但它们之间存在着互补关系。区块链技术提供了一种安全、透明、去中心…

Android Studio下载gradle超时问题解决

方法一 1. 配置根目录的setting.gradle.kts文件 pluginManagement {repositories {maven { urluri ("https://www.jitpack.io")}maven { urluri ("https://maven.aliyun.com/repository/releases")}maven { urluri ("https://maven.aliyun.com/repos…

Open-Sora:开源 Sora 复现方案,成本降低 46%

Colossal-AI 开源了完整的 Sora 复现架构方案 Open-Sora&#xff0c;声称可降低 46% 复现成本&#xff0c;并将模型训练输入序列长度扩充至 819K patches。 演示站点&#xff1a; https://ai.uaai.cn UAAI 官方论坛&#xff1a; www.jingyuai.com京娱AI Sora 算法复现方案 在 …

springboot256基于springboot+vue的游戏交易系统

游戏交易系统设计与实现 摘 要 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对游戏交…

[LeetCode][LCR143]树的子结构判断——递归

题目 LCR 143. 子结构判断 给定两棵二叉树 tree1 和 tree2&#xff0c;判断 tree2 是否以 tree1 的某个节点为根的子树具有相同的结构和节点值。注意&#xff0c;空树不会是以 tree1 的某个节点为根的子树具有相同的结构和节点值。 示例&#xff1a; 输入&#xff1a;tree1 …

3.9Code

基于顺序存储结构的图书信息表的图书去重 #include<iostream> #include<stdlib.h> #include<string.h>typedef int status;#define OK 1using namespace std;typedef struct{char no[50];char name[50];float price; }Book;typedef struct{Book* elem;int …

鸿蒙App动画、弹窗

动画 属性动画 https://developer.harmonyos.com/cn/docs/documentation/doc-references-V3/ts-animatorproperty-0000001478181445-V3 组件的某些通用属性变化时&#xff0c;可以通过属性动画实现渐变过渡效果&#xff0c;提升用户体验。支持的属性包括width、height、backg…

【软件工程】软件工程定义、软件危机以及软件生命周期

&#x1f338;博主主页&#xff1a;釉色清风&#x1f338;文章专栏&#xff1a;软件工程&#x1f338; 今日语录&#xff1a;What matters isn’t how others think of your ambitions but how fervently you cling to them. 软件工程系列&#xff0c;主要根据老师上课所讲提及…