【LabVIEW FPGA图形化】IP集成节点:IIC通信实验

目录

  • 一、前情提要
  • 二、FPGA蔡氏定律
  • 三、LabVIEW FPGA IP集成节点网表文件的编写
  • 四、IIC时序仿真
  • 五、FPGA图形化程序编写
  • 总结

一、前情提要

上一节内容介绍了图形化FPGA的USB通信,USB通信主要用于FPGA与上位机之间的通信,对于器件(芯片)与器件之间的数据交互,往往采用串口、SPI、IIC、IIS等约定协议进行通信。IIC作为一种很常用的通信协议广泛用于ADC、EEPROM、陀螺仪、倾角传感器等各类传感器和存储芯片之间的通信,FPGA作为可编程的硬件电路,自然也可以用过硬件电路实现硬件IIC,硬件IIC相较于软件IIC有一定的优势,两者之间的关系网上资料很多本文不再赘述,想了解更多可以问ChatGPT,本节重点关注FPGA的IIC通信(常规250Mbps,快速400Mbps),本节内容将手把手带大家编写一个IIC通信实验的IP集成节点。

【LabVIEW FPGA图形化】 ngc、edf网表文件的编写:LED流水灯

【LabVIEW FPGA图形化】 IP集成节点:按键控制LED

【LabVIEW FPGA图形化】IP集成节点:串口通信

【LabVIEW FPGA图形化】IP集成节点:频率计

【LabVIEW FPGA图形化】IP集成节点:USB通信

二、FPGA蔡氏定律

FPGA有两条蔡氏定律:
1、FPGA不仅仅是FPGA。
2、FPGA的最终目的是做出可用的电路。

FPGA的学习脱离不了硬件电路,FPGA实现IIC通信也需要相应的目标器件,常见的IIC器件有24C02、PCF8591、OLED、PCF8574、MPU6050等。黑金AX516上提供了一片支持IIC通信的EEPROM,型号为24LC04,由2个block组成,每块容量为2K,用作一些关键参数的存储,掉电不丢失。这种芯片操作简单,具有极高性价比。

EEPROM原理图部分

EEPROM引脚与FPGA连接:SDA–>N5 SCL–>P6。

三、LabVIEW FPGA IP集成节点网表文件的编写

了解了EEPROM的硬件以及连接方式,接下来我们需要根据IIC的时序编写网表。在单片机上,常用软件模拟IIC的方式实现IIC的通信协议。

#include "iic.h"#define DELAY_TIME 5//I2C总线内部延时函数
void IIC_Delay(unsigned char i)
{do{_nop_();}while(i--);        
}//I2C总线启动信号
void IIC_Start(void)
{SDA = 1;SCL = 1;IIC_Delay(DELAY_TIME);SDA = 0;IIC_Delay(DELAY_TIME);SCL = 0;	
}//I2C总线停止信号
void IIC_Stop(void)
{SDA = 0;SCL = 1;IIC_Delay(DELAY_TIME);SDA = 1;IIC_Delay(DELAY_TIME);
}//发送应答或非应答信号
void IIC_SendAck(bit ackbit)
{SCL = 0;SDA = ackbit;  					IIC_Delay(DELAY_TIME);SCL = 1;IIC_Delay(DELAY_TIME);SCL = 0; SDA = 1;IIC_Delay(DELAY_TIME);
}//等待应答
bit IIC_WaitAck(void)
{bit ackbit;SCL  = 1;IIC_Delay(DELAY_TIME);ackbit = SDA;SCL = 0;IIC_Delay(DELAY_TIME);return ackbit;
}//I2C总线发送一个字节数据
void IIC_SendByte(unsigned char byt)
{unsigned char i;for(i=0; i<8; i++){SCL  = 0;IIC_Delay(DELAY_TIME);if(byt & 0x80) SDA  = 1;else SDA  = 0;IIC_Delay(DELAY_TIME);SCL = 1;byt <<= 1;IIC_Delay(DELAY_TIME);}SCL  = 0;  
}//I2C总线接收一个字节数据
unsigned char IIC_RecByte(void)
{unsigned char i, da;for(i=0; i<8; i++){   SCL = 1;IIC_Delay(DELAY_TIME);da <<= 1;if(SDA) da |= 1;SCL = 0;IIC_Delay(DELAY_TIME);}return da;    
}
void write_eeprom(unsigned char add,unsigned char dat)
{IIC_Start();IIC_SendByte(0xA0);IIC_WaitAck();IIC_SendByte(add);IIC_WaitAck();IIC_SendByte(dat);IIC_WaitAck();IIC_Stop();
}unsigned char read_eeprom(unsigned char add)
{unsigned char temp;IIC_Start();IIC_SendByte(0xA0);IIC_WaitAck();IIC_SendByte(add);IIC_WaitAck();IIC_Start();IIC_SendByte(0xA1);IIC_WaitAck();temp=IIC_RecByte();IIC_SendAck();IIC_Stop();
}

以上是软件模拟IIC的C语言代码,相较于底层verliog,C语言作为顶层更易于理解,如上面write_eeprom()、read_eeprom()两个函数,将IIC的通信逻辑体现得淋漓尽致,根据两个函数逻辑所设计出的状态转移图如下:

IIC通信状态转移图
根据状态转移图我们可以更简便的用有限状态机去实现我们的代码。当然,在编写代码之前,我们还需要设计模块的输入和输出,以下是RTL视图:

在这里插入图片描述

根据RTL视图我们可以确定模块的输入与输出,定义相关的寄存器,结合状态转移图就可以构建出我们的代码结构。

以下为IIC通信的Verliog代码

module IIC_Generate (input               clk,input               reset,input               sda_in,input               rw,input       [7:0]   device_addr,input       [7:0]   add,input       [7:0]   dat,input               input_vaild,output reg          scl_out,output reg          sda_ena,output reg          sda_out,    //SCL为低电平时,SDA数据才允许改变output reg  [7:0]   data_out,output reg          output_vaild, output reg          idle);parameter IDLE         =        8'd0;
parameter IIC_START    =        8'd1;
parameter IIC_Send_device_add = 8'd2;
parameter IIC_WaitAck0 =        8'd3;
parameter IIC_Send_add =        8'd4;
parameter IIC_WaitAck1 =        8'd5;
parameter IIC_Send_dat =        8'd6;
parameter IIC_WaitAck2 =        8'd7;
parameter IIC_stop     =        8'd8;
parameter IIC_START1   =        8'd9;
parameter IIC_Send_device_add1 =8'd10;
parameter IIC_WaitAck3 =        8'd11;
parameter IIC_rec_byte =        8'd12;reg [7:0]   State=0;
reg [7:0]   device_addr_d0;
reg [7:0]   device_addr1_d0;
reg [7:0]   add_d0;
reg [7:0]   dat_d0;
reg         rw_d0;
reg [15:0]  cnt;
reg [7:0]   i;
reg [7:0]   data_recive=0;
always @(posedge clk or posedge reset) begin  //缓存有效数据的状态if(reset) begindevice_addr_d0<=0;add_d0  <=0;dat_d0  <=0;rw_d0   <=0;endelse if(input_vaild==1'b1&&idle==1'b1) begin device_addr_d0<=device_addr;        //先把这些值寄存一下device_addr1_d0<=device_addr+1'b1;add_d0  <=add;dat_d0  <=dat;rw_d0   <=rw;endelse begindevice_addr_d0<=device_addr_d0;add_d0  <=add_d0;dat_d0  <=dat_d0;rw_d0   <=rw_d0;    end
end  always @(posedge clk ) begin   //准备好输入if(reset)idle<=0;else if(State==IDLE)idle<=1;else idle<=0;
endalways @(posedge clk or posedge reset) begin //状态转移图if(reset) beginscl_out<=1;   sda_ena<=1;sda_out<=1;data_out<=0;output_vaild<=0;State<=IDLE;cnt<=0;endelse begincase (State)IDLE: beginif (input_vaild==1) beginState<=IIC_START;cnt<=0;endelse beginState<=IDLE;  scl_out<=1;   sda_ena<=0;sda_out<=1;endendIIC_START: beginif (cnt==0) beginscl_out<=1'b1;sda_out<=1'b1;sda_ena<=1'b1;cnt<=cnt+1;endelse if(cnt==50) begin  //SDA先由高变低sda_out<=1'b0;cnt<=cnt+1;endelse if(cnt==200) beginscl_out<=1'b0;    //SCL后由高变低cnt<=cnt+1;endelse if(cnt==249)begincnt<=0;State<=IIC_Send_device_add;i<=7;endelse begincnt<=cnt+1;endendIIC_Send_device_add:beginif (cnt==0) beginscl_out<=1'b0;sda_out<=device_addr_d0[i]; cnt<=cnt+1;endelse if (cnt==50) beginscl_out<=1'b1;      //SCL为高电平,保持100时钟cnt<=cnt+1;endelse if(cnt==150) beginscl_out<=1'b0;  cnt<=cnt+1;  endelse if(cnt==199) begincnt<=0;if(i==0) beginState<=IIC_WaitAck0;cnt<=0;endelse begini<=i-1;  State<=State;  endendelsecnt<=cnt+1; endIIC_WaitAck0: beginsda_ena<=1'b0;sda_out<=1'b0;if(cnt==50) beginscl_out<=1'b1;cnt<=cnt+1;endelse if(cnt==150) beginscl_out<=1'b0;cnt<=cnt+1;endelse if(cnt==199) begincnt<=0;State<=IIC_Send_add;i<=7;endelse cnt<=cnt+1;endIIC_Send_add:beginif(cnt==0) beginsda_ena<=1'b1;sda_out<=add_d0[i];cnt<=cnt+1;endelse if (cnt==50) beginscl_out<=1'b1;      //SCL为高,保持100时钟cnt<=cnt+1;endelse if(cnt==150) beginscl_out<=1'b0;  cnt<=cnt+1;  endelse if(cnt==199) begincnt<=0;if(i==0) beginState<=IIC_WaitAck1;cnt<=0;endelsei<=i-1;endelsecnt<=cnt+1;endIIC_WaitAck1: beginsda_ena<=1'b0;sda_out<=1'b0;if(cnt==50) beginscl_out<=1'b1;cnt<=cnt+1;endelse if(cnt==150) beginscl_out<=1'b0;cnt<=cnt+1;endelse if(cnt==199) begincnt<=0;if (rw_d0==0) begin     //继续写入State<=IIC_Send_dat;sda_out<=1'b1;	//保证下一次开始的时序					i<=7;  endelseState<=IIC_START1;    //准备读取endelse cnt<=cnt+1;endIIC_Send_dat: beginif(cnt==0) beginsda_ena<=1'b1;sda_out<=dat_d0[i];cnt<=cnt+1;endelse if (cnt==50) beginscl_out<=1'b1;      //SCL为高,保持100时钟cnt<=cnt+1;endelse if(cnt==150) beginscl_out<=1'b0;  cnt<=cnt+1;  endelse if(cnt==199) begincnt<=0;if(i==0) beginState<=IIC_WaitAck2;cnt<=0;endelse beginState<=State;i<=i-1;  endendelse cnt<=cnt+1; endIIC_WaitAck2: beginsda_ena<=1'b0;sda_out<=1'b0;		//保证最后停止的时序output_vaild<=0;if(cnt==50) beginscl_out<=1'b1;cnt<=cnt+1;endelse if(cnt==150) beginscl_out<=1'b0;cnt<=cnt+1;endelse if(cnt==199) begincnt<=0;State<=IIC_stop;i<=7;endelse cnt<=cnt+1;            endIIC_stop:beginif(cnt==0) beginsda_ena<=1'b1; cnt<=cnt+1;  endelse if (cnt==50) beginscl_out<=1'b1;            //SCL先拉高cnt<=cnt+1;endelse if(cnt==150) beginsda_out<=1'b1;        //SDA再拉高cnt<=cnt+1;endelse if (cnt==199) begincnt<=0;State<=IDLE;endelsecnt<=cnt+1;endIIC_START1: beginif (cnt==50) beginscl_out<=1'b1;sda_out<=1'b1;sda_ena<=1'b1;cnt<=cnt+1;endelse if(cnt==100) begin  //SDA先由高变低 sda_out<=1'b0;cnt<=cnt+1;endelse if(cnt==200) beginscl_out<=1'b0;    //SCL后由高变低cnt<=cnt+1;endelse if(cnt==249)begincnt<=0;State<=IIC_Send_device_add1;i<=7;endelse begincnt<=cnt+1;end  endIIC_Send_device_add1: beginif (cnt==0) beginscl_out<=1'b0;sda_out<=device_addr1_d0[i]; cnt<=cnt+1;endelse if (cnt==50) beginscl_out<=1'b1;      //SCL为高,保持100时钟cnt<=cnt+1;endelse if(cnt==150) beginscl_out<=1'b0;  cnt<=cnt+1;  endelse if(cnt==199) begincnt<=0;if(i==0) beginState<=IIC_WaitAck3;cnt<=0;endelse begini<=i-1;  State<=State;  endendelse cnt<=cnt+1; endIIC_WaitAck3: beginsda_ena<=1'b0;sda_out<=1'b0;if(cnt==50) beginscl_out<=1'b1;cnt<=cnt+1;endelse if(cnt==150) beginscl_out<=1'b0;cnt<=cnt+1;endelse if(cnt==199) begincnt<=0;State<=IIC_rec_byte;i<=7;endelse cnt<=cnt+1;   endIIC_rec_byte: beginif (cnt==0) beginsda_ena<=1'b0;cnt<=cnt+1; endelse if (cnt==50) beginscl_out<=1'b1;cnt<=cnt+1; endelse if (cnt==100) begindata_recive[i]<=sda_in;cnt<=cnt+1; endelse if (cnt==150) beginscl_out<=1'b0;cnt<=cnt+1; endelse if (cnt==199) begincnt<=0;if (i==0) beginState<=IIC_WaitAck2;data_out<=data_recive;output_vaild<=1;endelse beginState<=State;i<=i-1;endendelsecnt<=cnt+1; enddefault: ;endcaseend
endendmodule 

上面的代码没有黑金代码简洁,也没有C语言代码简洁,原因就是保留了所有状态,没有将wait_ack,write_data状态合并导致相当多的代码重复,不过代码易于理解,文中cnt=199(50M/200=250k),若提高系统时钟为80M,IIC协议可以以快速模式运行(80M/200=400k),当然,也可以修改计数值实现速度调整。

编写好顶层文件后需要修改综合参数,在Xilinx Specific Options中去掉 Add I/O Buffer选项,不添加I/O buffer并综合。

四、IIC时序仿真

在仿真前我们先看一下IIC的表情包。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

以上表情包均是IIC时序描述,说明了当时序(应答)不正确的时候,数据传输无效。我在查找IIC资料时,发现网上鲜有一次通信完整的IIC时序,在数据手册里也只有起始位、停止位、单个字节数据的描述,现在我们通过仿真方式了解一下底层IIC通信的过程。
首先我们需要编写testbench仿真文件:

`timescale 1ns / 1ps
module IIC_General_tb();reg         clk             ;reg         reset           ;reg          rw             ;reg  [7:0]   device_addr    ;reg  [7:0]   add            ;reg  [7:0]    dat           ;reg      input_vaild        ;wire     scl_out            ;wire     sda_ena            ;wire     sda_out            ;wire     data_out           ;wire     output_vaild       ;wire     idle               ;   reg      sda_in             ;IIC_Generate IIC_Generate_tb (.clk               (clk         ),.reset             (reset       ),.sda_in            (sda_in      ),.rw                (rw          ),.device_addr       (device_addr ),.add               (add         ),.dat               (dat         ),.input_vaild       (input_vaild ),.scl_out           (scl_out     ),.sda_ena           (sda_ena     ),.sda_out           (sda_out     ),.data_out          (data_out    ),.output_vaild      (output_vaild),.idle              (idle        ));initial beginsda_in=1;clk=0;reset=1;rw=0;device_addr=0;add=0;dat=0;input_vaild=0;#100reset=0;#60device_addr=8'h90;add=8'h55;dat=8'haa;rw=0;input_vaild=1;#20input_vaild=0;rw=0;device_addr=0;add=0;dat=0;#119000device_addr=8'h90;add=8'h55;dat=0;rw=1;input_vaild=1;#20device_addr=0;add=0;dat=0;rw=0;input_vaild=0;endalways #10 clk = ~ clk;
endmodule

激励将器件地址设置为0x90,地址设置为0x55,数据设置为0xaa,分别进行读写操作。
在写数据阶段完整IIC时序如下图:
在这里插入图片描述
主要看sda上的数据随着scl的变化,注意在起始状态,等待应答状态和停止状态下sda和scl的变化顺序。
同样,我们观察在读数据阶段下sda和scl的变化顺序。
在这里插入图片描述
在读数据时,有两次起始的过程,要注意提前把信号线拉高才能满足开始的时序。

五、FPGA图形化程序编写

将上面程序生成的IIC_General.ngc 添加到vi所在的工程目录下,调用IP节点,对其各个端口进行连线。为了实现快速模式下的IIC通信(400kbit/s),FPGA通过锁相环生成一个80M的衍生时钟(并不是所有器件都支持快速模式的通信),进行单次读写的测试。

在上图中,时钟为80M,输入数据和读写操作都通过前面板人为控制发送,通过一个计数器显示数据有效次数以及读出的数据。

在这里插入图片描述

编译好程序后我们在前面板上进行了数据读取,一共是读取了3次,写入了2次,可以看到输出的显示数据得到的值与我们写入的值一致,单次数据读写成功。若后续有连续写入的需要,可以在数据输入和输出之间加FIFO,将该IP作为器件的数据交互线程,在其他线程中产生/读取数据。

总结

FPGA图形化编程其优势在于逻辑图形化,若不去考虑底层verliog,在顶层设计上FPGA的图形化编程是有优势的,在工程上,可以直接调用开源的网表文件,可以更有效率的完成FPGA的设计。如果后续需要进一步提高IIC的速率(取决于器件),采用更高速的IIC通信,可以通过修改底层cnt的值和IP节点的输入时钟改变SCL时钟线的跳变时间,从而实现任意速率下的IIC通信。本节实验的Verliog网表文件和LabVIEW的vi均开源在 我的资源 如有需要可以下载学习。

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

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

相关文章

人工智能前沿知识

本来想着初试完学习一下李沐大神的《动手学深度学习》这本书的&#xff0c;但是时间仓促&#xff0c;完全来不及。只能先自行了解一些知识&#xff0c;之后再深入了解。 这里为面试应答&#xff0c;问了chatgpt一些关于AI前沿的知识&#xff1a; 还需要再了解一番&#xff1a;…

Squid代理服务器应用及配置(图文详解)

Squid缓存代理 Squid代理服务器代理的工作机制代理的基本类型传统代理透明代理反向代理 使用代理的好处 实验环境部署squid代理安装关闭防护墙安装依赖环境编译安装Squid脚本解释创建软连接及用户&#xff0c;改组 修改Squid的配置文件squid检查启动 编写Squid服务脚本服务启动…

chatgpt赋能python:Python方法重写:提升代码复用性和性能优化

Python方法重写&#xff1a;提升代码复用性和性能优化 Python是一门简洁、易读易写的语言&#xff0c;但在实际的编程开发中&#xff0c;我们往往会遇到代码复用性不高、性能不够优化等问题。而方法重写是一种有效的方式来解决这些问题。 什么是方法重写&#xff1f; 方法重…

chatgpt如何联网?访问2021年之后的信息

介绍 一般来说&#xff0c;chatgpr稚嫩恶搞访问2021年之前的事。 chatgpt如何联网&#xff1f; 如何访问2021年之后的信息&#xff1f; 方法 打开edge浏览器啊&#xff0c;添加拓展 “webchatgpt” 举例子

白痴学日语系列之模拟题

题型一、单词 汉字对应的假名 1、小卖部 2、杂志 3、礼物 おみやげ 4、公司职员 5、老师 假名对应的汉字 6、社长&#xff0c;总经理 7、星期六 8、房间 9、迟到 10、下个月 选平假名对应的片假名 11、美国 12、足球 13、出租车 14、百货商场 15、便利店 题型二、选择题 1…

白痴学日语系列之初识日语(三)

每日记单词 足/脚[あし]2 a shi 脚&#xff1b;腿 【记】あ&#xff08;恶&#xff09;し&#xff08;像&#xff09;→身上脏的地方→腿&#xff1b;脚 联想记忆&#xff0c;阿西吧&#xff08;阿西吧&#xff0c;意思类似于我去&#xff0c;是表示对某一事件或者某一事物感…

chatgpt赋能python:PythonRPG游戏:带你进入主角的魔幻冒险世界

Python RPG游戏&#xff1a;带你进入主角的魔幻冒险世界 Python是一种广泛使用的高级编程语言&#xff0c;被用于开发各种应用程序和游戏。其中&#xff0c;RPG游戏是其中最受欢迎的游戏之一。Python的各种优点使其成为开发RPG游戏的一个理想选择。在这篇文章中&#xff0c;我…

游戏思考26:游戏服务器压力测试文档(新增linux相关命令,02/10未完待续)

文章目录 一、压力测试关注点二、计算最耗时的加载操作1&#xff09;从数据库读取数据&#xff0c;对加载的类型进一步划分各种类型&#xff0c;计算最耗时操作2&#xff09;查看CPU随着在线人数的变化所占百分比3&#xff09;查看内存变化4&#xff09;备注 三、MMORPG服务器对…

C语言——飞机游戏

目录 前言 一、飞机游戏的代码 二、代码解析 1、代码重构 1&#xff09;主函数 2&#xff09;其它函数 2、新的子弹 3、敌机 1&#xff09;静止的敌机 2&#xff09;敌机的移动 3&#xff09;击中敌机 4、清屏功能 总结 前言 代码参考了《C语言课程设计与游戏开发…

谈一谈游戏AI - 综述

成功者总是善于发现 “可学之处”&#xff0c;执着精进&#xff1b;失败者总是善于发现 “不可学之处”&#xff0c;怨天尤人。 郑重说明&#xff1a;本文适合对游戏开发感兴趣的小白初学者&#xff0c;本人力图将事物用简单的语言表达清楚&#xff0c;但水平有限&#xff0c;能…

安卓版ChatGPT要上线了!

Datawhale干货 最新&#xff1a;ChatGPT安卓版&#xff0c; 来源&#xff1a;机器之心 自发布以来&#xff0c;ChatGPT 一直受到高度关注&#xff0c;在全球范围内吸引了大量用户。有机构统计认为&#xff0c;早在今年 1 月&#xff0c;ChatGPT 的用户量就已经超过了一亿。彼时…

必看!大语言模型调研汇总!!

作者&#xff1a;guolipa 知乎 自从ChatGPT出现之后&#xff0c;各种大语言模型是彻底被解封了&#xff0c;每天见到的模型都能不重样&#xff0c;几乎分不清这些模型是哪个机构发布的、有什么功能特点、以及这些模型的关系。比如 GPT-3.0 和 GPT 3.5 就有一系列的模型版本…

一网打尽!国内外50多个大模型调研汇总

因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享 点击关注#互联网架构师公众号&#xff0c;领取架构师全套资料 都在这里 0、2T架构师学习资料干货分 上一篇&#xff1a;ChatGPT研究框架&#xff08;80页PPT&#xff0c;附下载&#xff09;…

大语言模型调研汇总

自从ChatGPT出现之后,各种大语言模型是彻底被解封了,每天见到的模型都能不重样,几乎分不清这些模型是哪个机构发布的、有什么功能特点、以及这些模型的关系。比如 GPT-3.0 和 GPT 3.5 就有一系列的模型版本和索引,还有羊驼、小羊驼、骆驼 ...... 于是浅浅的调研了一下比较有…

总结从T5、GPT-3、Chinchilla、PaLM、LLaMA、Alpaca等近30个最新模型

自从ChatGPT出现之后&#xff0c;各种大语言模型是彻底被解封了&#xff0c;每天见到的模型都能不重样&#xff0c;几乎分不清这些模型是哪个机构发布的、有什么功能特点、以及这些模型的关系。比如 GPT-3.0 和 GPT 3.5 就有一系列的模型版本和索引&#xff0c;还有羊驼、小羊驼…

一网打尽!国内外大模型调研汇总

作者 | guolipa 整理 | NewBeeNLP https://zhuanlan.zhihu.com/p/614766286 大家好&#xff0c;这里是 NewBeeNLP。 自从ChatGPT出现之后&#xff0c;各种大语言模型是彻底被解封了&#xff0c;每天见到的模型都能不重样&#xff0c;几乎分不清这些模型是哪个机构发布的、有什…

学习笔记借助chatGPT生成excel统计公式

要求&#xff1a;通过Excel公式提取ExcelB列表格中邮箱名称&#xff08;之前的字符&#xff09; 知道老板要求后&#xff0c;我们就需要写出对应的提取公式&#xff0c;可是对于Excel公式使用不熟练的人来说&#xff0c;这个公式如何写呢&#xff1f;这时候我们就需要借助chatG…

《辉煌优配》6G技术推进下,CPO引领光通信发展新方向

3月1日&#xff0c;中国工业和信息化部部长金壮龙在国务院新闻办新闻发布会上表明&#xff0c;工信部将研究制定未来产业开展行动计划&#xff0c;加快布局人形机器人、元宇宙、量子科技等前沿范畴&#xff0c;全面推动6G技能研制。2月27日&#xff0c;2023年世界移动通讯大会&…

动态销售看板图表 | 汇总不同部门数据,一键切换部门

背景&#xff1a;公司有五十多个子部门&#xff0c;每个sheet存储着每个部门的所有数据&#xff08;不sheet表格结构需要保持一致&#xff09;&#xff0c;如果想将每个部门月至今的销售数据做成图表&#xff0c;怎么办&#xff1f;50多个sheet逐一添加图表&#xff1f;当然不&…

12. Excel数据可视化看板--动态销售月报看板

文章目录 1可视化看板作用1.1 形象直观&#xff0c;有利于提高效率1.2 透明度高&#xff0c;便于配合和监督1.3 降低成本&#xff0c;缩短生产周期1.4 传递现场的生产信息&#xff0c;统一思想1.5 杜绝现场管理中的漏洞1.6 绩效考核的公平化、透明化1.7 保证生产现场作业秩序&a…