AXI CANFD MicroBlaze 测试笔记

news2024/11/20 4:43:40

文章目录

    • 前言
    • 测试用的硬件连接
    • Vivado 配置
    • Vitis MicroBlaze CANFD 代码
    • 测试代码
    • 测试截图
    • Github Link

前言

官网: CAN with Flexible Data Rate (CAN FD) (xilinx.com)

特征:

  • 支持8Mb/s的CANFD
  • 多达 3 个数据位发送器延迟补偿(TDC, transmitter delay compensation)
  • 32-deep TX FIFO, 2 * 64-deep RX FIFO, 32 ID Filter
  • 接收支持 顺序(Sequential)模式 和 邮箱(Mailbox)模式
  • Bus-Off 恢复模式: 自动恢复 或 用户干预的自动恢复

参考:

  • How to configure CAN/CANFD clocks and identify the CAN nodes (xilinx.com)
  • canfd 默认文档和示例路径: C:\Xilinx\Vitis\2023.2\data\embeddedsw\XilinxProcessorIPLib\drivers\canfd_v2_8

本文仅作学习交流使用.

测试用的硬件连接

硬件:

  • FPGA: xc7a35tfgg484-2
  • 时钟: 50MHz, 有源, 单端, 3V3, 引脚Y18
  • 复位: 低电平复位, 3V3, 引脚F20
  • UART: TX G16, RX G15
  • CANFD: TX F16, RX E17

Vivado 配置

如图:

请添加图片描述

时钟:

  • clk_out1, 160MHz, can_clk_x2, 也是其它组件的时钟
  • clk_out2, 80MHz, can_clk, 是CAN和CANFD配置的主时钟
  • 低电平复位

调试串口:

  • 9600 or 115200 bps

时钟的配置截图

在这里插入图片描述

CANFD的配置, 收发FIFO Depth都是32, 接收使用顺序模式, 不用FIFO1

在这里插入图片描述

可适当减少RX FIFO-0 Depth以减少RAM消耗. 含MicroBlaze 64K, 一路CANFD, 没有使用任何外部RAM的消耗如下(xc7a35tfgg484-2):

在这里插入图片描述

Vitis MicroBlaze CANFD 代码

初始化:

  • 查找并初始化已有CANFD配置
  • 进入配置模式, 配置位速率, 采样点, TDC, 滤波器, 关闭BRS
  • 设置收发错误事件回调, 使能中断
  • 进入正常模式
  • 注意在C文件中编译, 不然Cpp中 XSetupInterruptSystem 会报错 error: invalid conversion from 'void (*)(void*)' to 'void*' [-fpermissive]

参考代码如下:

int bsp_canfd_init(XCanFd *InstancePtr, uint32_t BaseAddress, uint32_t BaudRate,
                   float SamplePoint, uint32_t FastBaudRate,
                   float FastSamplePoint) {
  XCanFd_Config *ConfigPtr = XCanFd_LookupConfig(BaseAddress);
  if (ConfigPtr == NULL) {
    bsp_canfd_debug_printf("Error: XCanFd_LookupConfig returned NULL\n");
    return -1;
  } else {
    bsp_canfd_debug_printf("XCanFd_Config:\n");
    bsp_canfd_debug_printf("  BaseAddress: 0x%08X\n", ConfigPtr->BaseAddress);
    bsp_canfd_debug_printf("  Rx_Mode: %s\n",
                           ConfigPtr->Rx_Mode ? "Mailbox" : "Sequential");
    bsp_canfd_debug_printf("  NumofRxMbBuf: %d\n", ConfigPtr->NumofRxMbBuf);
    bsp_canfd_debug_printf("  NumofTxBuf: %d\n", ConfigPtr->NumofTxBuf);
    bsp_canfd_debug_printf("  IntrId: %d\n", ConfigPtr->IntrId);
    bsp_canfd_debug_printf("  IntrParent: 0x%08X\n", ConfigPtr->IntrParent);
  }
  int Status =
      XCanFd_CfgInitialize(InstancePtr, ConfigPtr, ConfigPtr->BaseAddress);
  if (Status != XST_SUCCESS) {
    bsp_canfd_debug_printf("Error: XCanFd_CfgInitialize returned %d\n", Status);
    return -2;
  } else {
    bsp_canfd_debug_printf("XCanFd_CfgInitialize: Success\n");
  }

  // config mode
  XCanFd_EnterMode(InstancePtr, XCANFD_MODE_CONFIG);
  while (XCanFd_GetMode(InstancePtr) != XCANFD_MODE_CONFIG)
    ;
  bsp_canfd_debug_printf("XCanFd_EnterMode: XCANFD_MODE_CONFIG\n");

  // 80MHz / (3 + 1) = 20MHz, 20MHz / (1 + (30 + 1) + (7 + 1)) = 500KHz
  // XCanFd_SetBitTiming(InstancePtr, 8, 7, 30);
  XCanFd_SetBaudRatePrescaler(InstancePtr, 0x3);
  u16 total_tq = 20000000 / BaudRate;
  u16 tseg1 = (u16)(SamplePoint * total_tq) - 2;
  u8 tseg2 = (u8)(total_tq - tseg1 - 3);
  u8 sjw = tseg2 + 1;
  XCanFd_SetBitTiming(InstancePtr, sjw, tseg2, tseg1);

  // 80MHz, 80 / (1 + (30 + 1) + (7 + 1)) = 2MHz
  // XCanFd_SetFBitTiming(InstancePtr, 8, 7, 30);
  XCanFd_SetFBaudRatePrescaler(InstancePtr, 0x0);
  u16 ftotal_tq = 80000000 / FastBaudRate;
  u8 ftseg1 = (u8)(FastSamplePoint * ftotal_tq) - 2;
  u8 ftseg2 = (u8)(ftotal_tq - ftseg1 - 3);
  u8 fsjw = ftseg2 + 1;
  XCanFd_SetFBitTiming(InstancePtr, fsjw, ftseg2, ftseg1);

  // TDC, 0~31
  // XCanFd_Set_Tranceiver_Delay_Compensation(InstancePtr, 0x3);

  XCanFd_SetBitRateSwitch_DisableNominal(InstancePtr);
  bsp_canfd_debug_printf("XCanFd: %d@0.%d, %d@0.%d\n", BaudRate,
                         (int)(SamplePoint * 1000), FastBaudRate,
                         (int)(FastSamplePoint * 1000));

  if (XCANFD_GET_RX_MODE(InstancePtr) == 0) {
    bsp_canfd_debug_printf(
        "RX_MODE Sequential Filter: XCANFD_AFR_UAF_ALL_MASK\n");
    XCanFd_AcceptFilterDisable(InstancePtr, XCANFD_AFR_UAF_ALL_MASK);
    XCanFd_AcceptFilterEnable(InstancePtr, XCANFD_AFR_UAF_ALL_MASK);
  } else {
    bsp_canfd_debug_printf("RX_MODE Mailbox Filter: Need to be implemented\n");
  }

  XCanFd_SetHandler(InstancePtr, XCANFD_HANDLER_SEND, (void *)SendHandler,
                    (void *)InstancePtr);
  XCanFd_SetHandler(InstancePtr, XCANFD_HANDLER_RECV, (void *)RecvHandler,
                    (void *)InstancePtr);
  XCanFd_SetHandler(InstancePtr, XCANFD_HANDLER_ERROR, (void *)ErrorHandler,
                    (void *)InstancePtr);
  XCanFd_SetHandler(InstancePtr, XCANFD_HANDLER_EVENT, (void *)EventHandler,
                    (void *)InstancePtr);
  Status =
      XSetupInterruptSystem(InstancePtr, &XCanFd_IntrHandler, ConfigPtr->IntrId,
                            ConfigPtr->IntrParent, XINTERRUPT_DEFAULT_PRIORITY);
  if (Status != XST_SUCCESS) {
    bsp_canfd_debug_printf("Error: XSetupInterruptSystem returned %d\n",
                           Status);
    return 1;
  } else {
    bsp_canfd_debug_printf("XSetupInterruptSystem: Success\n");
  }
  XCanFd_InterruptEnable(InstancePtr, XCANFD_IXR_ALL);
  XCanFd_EnterMode(InstancePtr, XCANFD_MODE_NORMAL);
  while (XCanFd_GetMode(InstancePtr) != XCANFD_MODE_NORMAL)
    ;
  bsp_canfd_debug_printf("XCanFd_EnterMode: XCANFD_MODE_NORMAL\n");

  return 0;
}

发送套用Linux SocketCAN接口, 毕竟这个用的人多, 易于理解. 因为发送FIFO深度为32, 所以, 正常情况下连发32帧无需插入延时, 也无需自己处理发送队列, 这已经够大部分情况使用了.

int bsp_canfd_send(XCanFd *InstancePtr, struct canfd_frame *frame) {
  bool is_extended = frame->can_id & CAN_EFF_FLAG ? true : false;
  bool is_remote = frame->can_id & CAN_RTR_FLAG ? true : false;
  bool is_fd = frame->flags & CANFD_FDF ? true : false;
  bool is_brs = frame->flags & CANFD_BRS ? true : false;
  bool is_esi = frame->flags & CANFD_ESI ? true : false;
  u32 TxFrame[CANFD_MTU];
  TxFrame[0] = XCanFd_CreateIdValue(
      CAN_SFF_MASK & (is_extended ? ((frame->can_id & CAN_EFF_MASK) >> 18)
                                  : frame->can_id),
      is_extended ? 1 : (u32)is_remote, (u32)is_extended,
      (u32)is_extended ? (frame->can_id & 0x3FFFF) : 0,
      is_extended ? (u32)is_remote : 0);
  if ((!is_fd) && (!is_brs)) {
    TxFrame[1] = XCanFd_CreateDlcValue(frame->len);
  } else {
    if (is_brs) {
      TxFrame[1] =
          XCanFd_Create_CanFD_Dlc_BrsValue(XCanFd_GetLen2Dlc(frame->len));
    } else {
      TxFrame[1] = XCanFd_Create_CanFD_DlcValue(XCanFd_GetLen2Dlc(frame->len));
    }
  }
  u8 *FramePtr = (u8 *)(&TxFrame[2]);
  for (int i = 0; i < frame->len; i++) {
    FramePtr[i] = frame->data[i];
  }
  u32 TxBufferNumber;
  int status = XCanFd_Send(InstancePtr, TxFrame, &TxBufferNumber);
  if (status == XST_FIFO_NO_ROOM) {
    bsp_canfd_debug_printf("Error: XCanFd_Send returned XST_FIFO_NO_ROOM\n");
    return -1;
  }
  if (status != XST_SUCCESS) {
    bsp_canfd_debug_printf("Error: XCanFd_Send returned %d\n", status);
    return -2;
  }
  return 0;
}

接收的示例, 类似 candump:

  • 标准帧是%03X打印, 扩展帧是%08X打印.
  • 远程帧打R, 数据帧打D
  • CANFD打F且长度为[%02d], Classic CAN打-且数据长度为[%d]
  • 开启了BRS打B, 否则打-
  • ESI 暂不关心
  • 当然这里打印接收只是用于测试, 实际不要在中断中阻塞打印
static void RecvHandler(void *CallBackRef) {
  XCanFd *CanPtr = (XCanFd *)CallBackRef;
  int Status;
  u32 RxFrame[CANFD_MTU];

  /* Check for the design 1 - MailBox 0 - Sequential */
  if (XCANFD_GET_RX_MODE(CanPtr) == 1) {
    Status = XCanFd_Recv_Mailbox(CanPtr, RxFrame);
  } else {
    Status = XCanFd_Recv_Sequential(CanPtr, RxFrame);
  }

  u32 id1 = (RxFrame[0] >> (u32)XCANFD_IDR_ID1_SHIFT) & (u32)0x7FF;
  u32 is_extended = (RxFrame[0] >> (u32)XCANFD_IDR_IDE_SHIFT) & (u32)0x1;
  u32 id2 = (RxFrame[0] >> (u32)XCANFD_IDR_ID2_SHIFT) & (u32)0x3FFFF;
  u32 is_remote = is_extended
                      ? (RxFrame[0] & 0x01)
                      : ((RxFrame[0] >> (u32)XCANFD_IDR_SRR_SHIFT) & (u32)0x1);

  /* Get the Dlc inthe form of bytes */
  u32 len = XCanFd_GetDlc2len(RxFrame[1] & XCANFD_DLCR_DLC_MASK, EDL_CANFD);
  if (Status != XST_SUCCESS) {
    bsp_canfd_debug_printf("Error: XCanFd_Recv returned %d\n", Status);
    return;
  }
  u32 is_brs = RxFrame[1] & XCANFD_DLCR_BRS_MASK ? 1 : 0;
  u32 is_fdf = RxFrame[1] & XCANFD_DLCR_EDL_MASK ? 1 : 0;
  // bsp_canfd_debug_printf("%08X ", RxFrame[0]);
  u8 *FramePtr = (u8 *)(&RxFrame[2]);
  if (is_extended) {
    bsp_canfd_debug_printf("%08X ", id1 << 18 | id2);
  } else {
    bsp_canfd_debug_printf("%03X ", id1);
  }
  if (is_remote) {
    bsp_canfd_debug_printf("R [%d]", len);
  } else {
    bsp_canfd_debug_printf("D ");
    if (is_fdf) {
      bsp_canfd_debug_printf("F ");
    } else {
      bsp_canfd_debug_printf("- ");
    }
    if (is_brs) {
      bsp_canfd_debug_printf("B ");
    } else {
      bsp_canfd_debug_printf("- ");
    }
    if ((!is_fdf) && (!is_brs)) {
      bsp_canfd_debug_printf("[%d] ", len);
    } else {
      bsp_canfd_debug_printf("[%02d] ", len);
    }
    for (int i = 0; i < len; i++) {
      bsp_canfd_debug_printf("%02X ", FramePtr[i]);
    }
  }
  bsp_canfd_debug_printf("\n");
}

测试代码

如下:

  • 位速率 500K@80%, 4M@80%, 如果出现收发不正常, 可能需要微调初始化中的TDC, 检查CAN收发器以及终端电阻
  • 对数据帧远程帧, CAN或CANFD或CANFD BRS都做了测试
  • 连续发送32帧
int main() {
  xil_printf("============================================\n");

  XCanFd CanFd0;
  int Status =
      bsp_canfd_init(&CanFd0, XPAR_CANFD_0_BASEADDR, 500000, 0.8, 4000000, 0.8);
  if (Status != 0) {
    xil_printf("Error: bsp_canfd_init returned %d\n", Status);
    return -1;
  }

  for (int i = 0; i < 4; i++) {
    struct canfd_frame frame = {
        .can_id = 0x123,
        .len = 8,
        .flags = 0,
        .__res0 = 0,
        .__res1 = 0,
        .data = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
                 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
                 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
                 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
                 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31,
                 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
                 0x3C, 0x3D, 0x3E, 0x3F},
    };
    // std can
    frame.can_id = 0x123;
    frame.len = 8;
    frame.flags = 0;
    int Status = bsp_canfd_send(&CanFd0, &frame);
    // std can remote
    frame.can_id = 0x124 | CAN_RTR_FLAG;
    frame.len = 8;
    frame.flags = 0;
    Status |= bsp_canfd_send(&CanFd0, &frame);
    // std can fd
    frame.can_id = 0x125;
    frame.len = 64;
    frame.flags = CANFD_FDF;
    Status |= bsp_canfd_send(&CanFd0, &frame);
    // std can fd brs
    frame.can_id = 0x126;
    frame.len = 64;
    frame.flags = CANFD_FDF | CANFD_BRS;
    Status |= bsp_canfd_send(&CanFd0, &frame);

    // ext can
    frame.can_id = 0x12345678 | CAN_EFF_FLAG;
    frame.len = 8;
    frame.flags = 0;
    Status |= bsp_canfd_send(&CanFd0, &frame);
    // ext can remote
    frame.can_id = 0x12345679 | CAN_EFF_FLAG | CAN_RTR_FLAG;
    frame.len = 8;
    frame.flags = 0;
    Status |= bsp_canfd_send(&CanFd0, &frame);
    // ext can fd
    frame.can_id = 0x1234567A | CAN_EFF_FLAG;
    frame.len = 64;
    frame.flags = CANFD_FDF;
    Status |= bsp_canfd_send(&CanFd0, &frame);
    // ext can fd brs
    frame.can_id = 0x1234567B | CAN_EFF_FLAG;
    frame.len = 64;
    frame.flags = CANFD_FDF | CANFD_BRS;
    Status |= bsp_canfd_send(&CanFd0, &frame);

    if (Status != 0) {
      xil_printf("Error: bsp_canfd_send %d returned %d\n", i, Status);
      return -1;
    }
  }

  while (1) {
  }

  return 0;
}

测试截图

设置:

在这里插入图片描述

MCU连续发出的32帧报文:

在这里插入图片描述

逻辑分析仪上可以看出来两帧之间卡着标准的3 ITM来的

在这里插入图片描述

出现BRS时的情况, 左边500K, 右边4M

在这里插入图片描述

CAN分析仪向FPGA发送测试:

在这里插入图片描述

Github Link

domain_controller_orin_x2_tc397/axi_canfd_microblaze at main · weifengdq/domain_controller_orin_x2_tc397 (github.com)

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

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

相关文章

VS Code上,QT基于cmake,qmake的构建方法(非常详细)

VS Code上,QT基于cmake&#xff0c;qmake的构建方法 1 前言2 QT基于cmake的构建方法2.1 VS Code关键插件安装2.2 系统环境变量配置2.3 VS Code中&#xff0c;环境变量配置2.4 Cmake新建一个新的Porject 3 QT基于qmake的构建方法 1 前言 最近&#xff0c;由于认证了github的学生…

RabbitMQ学习总结-延迟消息

1.死信交换机 一致不被消费的信息/过期的信息/被标记nack/reject的信息&#xff0c;这些消息都可以进入死信交换机&#xff0c;但是首先要配置的有私信交换机。私信交换机可以再RabbitMQ的客户端上选定配置-dead-letter-exchange。 2.延迟消息 像我们买车票&#xff0c;外卖…

PHP 生成图片

1.先确认是否有GD库 echo phpinfo(); // 创建一个真彩色图像 $image imagecreatetruecolor(120, 50);// 分配颜色 $bgColor imagecolorallocate($image, 255, 255, 255); // 白色背景 $textColor imagecolorallocate($image, 230, 230, 230); // 黑色文字// 填充背景 image…

MyFileServer

靶场下载地址 https://download.vulnhub.com/myfileserver/My_file_server_1.ova 信息收集 # nmap -sn 192.168.56.0/24 -oN live.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-24 22:07 CST Nmap scan report for 192.168.56.2 (192.168.56.2) Host is up (0.…

Java学习笔记(13)

阶段项目 拼图小游戏 JFrame JMenuBar JMenu JMenuItem 用add方法添加到不同的对象中 添加图片 先创建一个图片ImageIcon的对象&#xff0c;写入图片的路径 再创建JLabel管理容器对象&#xff0c;把图片放到这个容器中&#xff0c;再把容器添加到界面 界面坐标位置 改变图…

nmcli --help(nmcli -h)nmcli文档、nmcli手册

文章目录 nmcli --helpOPTION解释OBJECT解释1. g[eneral]&#xff1a;查看NetworkManager的状态2. n[etworking]&#xff1a;启用或禁用网络3. r[adio]&#xff1a;查看无线电状态&#xff08;例如&#xff0c;Wi-Fi&#xff09;4. c[onnection]&#xff1a;列出所有的网络连接…

openwrt下部署clouddrive2

在启动项上增加启动参数 在exit 0前面增加 mount --make-shared /mnt/data480g注意&#xff0c;后面的/mnt/data480g要替换成你设置的共享映射券。 拉取镜像 docker pull cloudnas/clouddrive2启动镜像 一定要用ssh在后台用docker run命令启动&#xff0c;因为openwrt前台…

AI技术崛起:数据可视化之路更近

在当今AI技术蓬勃发展的时代&#xff0c;数据可视化作为信息传达的重要手段&#xff0c;其门槛逐渐降低。然而&#xff0c;这并不意味着我们可以忽视学习数据可视化的重要性。即使不需要深入专业技术&#xff0c;对数据可视化的基础知识的了解也是至关重要的。那么&#xff0c;…

恢复u盘数据时可以关机吗?深入解析与操作建议

随着科技的飞速发展&#xff0c;U盘已成为我们日常生活中不可或缺的数据存储设备。然而&#xff0c;当U盘中的数据遭遇丢失或损坏时&#xff0c;如何安全有效地恢复数据成为了一个重要的问题。在这个过程中&#xff0c;许多用户可能会疑惑&#xff1a;恢复u盘数据时可以关机吗&…

基于matlab使用 fmincon 函数来进行有约束条件的最小化问题求解

一、一般步骤 生成带有噪声的正态分布数据&#xff1b;定义拟合模型。 model (params, x) normpdf(x, params(1), params(2)); 初始参数猜测 initial_guess [mu, sigma]; 设置约束条件 lb [0, 0]; % 参数的最小值 ub [10, 10]; % 参数的最大值 定义优化问题 opts …

Android studio SDK Manager显示不全的问题解决

发现SDK Manager中只显示已下载的SDK版本&#xff0c;想下载其他版本下载不到&#xff0c;尝试翻墙也没用&#xff0c;修改host文件成功 在多个地点Ping服务器,网站测速 - 站长工具 输入dl.google.com&#xff0c;进行ping检测。 选择一个地址&#xff0c;比如180.163.150.1…

Docker使用(三)Docker底层分析

Docker使用(三)Docker底层分析 四、底层分析 1、Docker镜像原理 1.1 commit镜像 docker commit 提交容器成为一个新的副本 # 命令和git原理类似 docker commit -m“提交的描述信息” -a“作者” 容器id 目标镜像名:[TAG] 实操&#xff1a; # 1、启动一个默认tomcat # …

【并查集】模版

【模板】并查集 - 洛谷 #include <bits/stdc.h> using namespace std; const int N2e59; int a[N]; int Find(int x) {if(xa[x]){return x;}else{a[x]Find(a[x]);return a[x];} } void push(int x,int y) {a[Find(x)]Find(y);return ; } int main() {int n,m; cin>>…

kubernetes部署集群

kubernetes部署集群 集群部署获取镜像安装docker[集群]阿里仓库下载[集群]集群部署[集群]集群环境配置[集群]关闭系统Swap[集群]安装Kubeadm包[集群]配置启动kubelet[集群]配置master节点[master]配置使用网络插件[master]node加入集群[node]后续检查[master]测试集群 集群部署…

【C语言进阶篇】数据在内存中的存储

目录 1.大小端字节序和字节序判断 2.浮点数在内存中的存储与读取 2.1 浮点数在内存中的存储 2.2 浮点数在内存中的读取 在前面的学习中&#xff0c;我们知道内存被划分为一个个小的内存单元&#xff0c;数据就是存储在这些内存单元中的。那么&#xff0c;具体是如何存储的&am…

ADC 架构 IV :Σ-Δ 型 ADC 高级概念和应用

目录 简介 高阶环路考量 数字滤波器对多路复用应用的意义 多级噪声整形 (MASH) Σ-Δ 转换器 总结 简介 上节已论述了 Σ-Δ 型 ADC 的基本原理。本教程将介绍一些更高级的概念&#xff0c;包括 空闲音、多位 Σ-Δ、MASH、带通 Σ-Δ&#xff0c;并提出一些示例应用。 简…

HarmonyOS NEXT星河版——还是Android上套个壳吗?

这真的是我2024年听过最搞笑的话,就在前几天&#xff0c;居然还有人说鸿蒙OS就是安卓套个壳&#xff0c;简直无语&#xff01; 你敢相信&#xff1f;就在前几天&#xff0c;我还听到有人说&#xff1a;鸿蒙os就是安卓上套一个壳。唉&#xff0c;我真是无语了。 哎&#xff0c…

<机器学习初识>——《机器学习》

目录 一、人工智能概述 1 人工智能应用场景 2 人工智能发展必备三要素 3 人工智能、机器学习和深度学习 二、人工智能发展历程 1 人工智能的起源 1.1 图灵测试 1.2 达特茅斯会议 2 发展历程 三、 人工智能主要分支 1 主要分支介绍 1.1 分支一&#xff1a;计算机视觉…

SRPC快速入门 - Sogou基于Workflow的自研RPC框架

什么是rpc RPC&#xff08;Remote Procedure Call&#xff09;&#xff0c;远程过程调用&#xff0c;它把网络交互类比为client调用server上的函数。RPC 的主要功能目标是让构建分布式计算&#xff08;应用&#xff09;更容易&#xff0c;在提供强大的远程调用能力时不损失本地…

【SQL Server】实验八 综合设计

1 实验目的 了解和掌握数据库设计的有关理论和方法。可以灵活运用数据库设计方法设计一个中小型规模的数据库。 2 实验内容 2.1 数据库概念模型设计 进行需求分析。设计数据库概念模型&#xff0c;画出E-R图。 2.2 数据库逻辑模型设计 根据数据库概念模型设计数据库的逻…