网络高级(学习)2024.9.11

news2024/9/26 1:28:21

目录

Modbus库函数

1.初始化和释放函数

2.功能函数

3.功能案例

Modbus RTU

1.特点

2.协议格式

3.编程思路


Modbus库函数

1.初始化和释放函数

modbus_t*   modbus_new_tcp(const char *ip, int port)
功能:以TCP方式创建Modbus实例,并初始化
参数:
        ip:ip地址
        port:端口号
返回值:

        成功:Modbus实例
        失败:NULL

int modbus_set_slave(modbus_t *ctx, int slave)
功能:设置从机ID
参数:
        ctx:Modbus实例
        slave:从机ID
返回值:

        成功:0
        失败:-1

int   modbus_connect(modbus_t *ctx)
功能:和从机(slave)建立连接
参数:
        ctx:Modbus实例
返回值:

        成功:0
        失败:-1

void   modbus_free(modbus_t *ctx)
功能:释放Modbus实例
参数:
        ctx:Modbus实例

void   modbus_close(modbus_t *ctx)
功能:关闭套接字
参数:
        ctx:Modbus实例


2.功能函数

int   modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
功能:读取线圈状态,可读取多个连续线圈的状态(对应功能码为0x01
参数:
        ctx :Modbus实例
        addr :寄存器起始地址
        nb:寄存器个数
        dest:得到的状态值

int  modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
功能:读取输入状态,可读取多个连续输入的状态(对应功能码为0x02
参数:
        ctx:Modbus实例
        addr :寄存器起始地址
        nb:寄存器个数
        dest :得到的状态值
返回值:成功:返回nb的值

int  modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
功能:读取保持寄存器的值,可读取多个连续保持寄存器的值(对应功能码为0x03
参数:
        ctx:Modbus实例
        addr :寄存器起始地址
        nb:寄存器个数
        dest:得到的寄存器的值
返回值:

        成功:读到寄存器的个数
        失败:-1

int   modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
功能:读输入寄存器的值,可读取多个连续输入寄存器的值(对应功能码为0x04
参数:
        ctx:Modbus实例
        addr :寄存器起始地址
        nb:寄存器个数
        dest :得到的寄存器的值
返回值:

        成功:读到寄存器的个数
        失败:-1

int  modbus_write_bit(modbus_t *ctx, int addr, int status);
功能:写入单个线圈的状态(对应功能码为0x05
参数:
    ctx :Modbus实例
    addr:线圈地址
    status:线圈状态
返回值:

        成功:0
        失败:-1

int  modbus_write_register(modbus_t *ctx, int addr, int value);
功能:  写入单个寄存器(对应功能码为0x06
参数: 
    ctx:Modbus实例
    addr:寄存器地址
    value:寄存器的值 
返回值:

        成功:0
        失败:-1

int  modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src);
功能:写入多个连续线圈的状态(对应功能码为15
参数:
        ctx:Modbus实例
        addr:线圈地址
        nb:线圈个数
        src:多个线圈状态
返回值:

        成功:0
        失败:-1

int  modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src);
功能:写入多个连续寄存器(对应功能码为16
参数:
        ctx:Modbus实例
        addr:寄存器地址
        nb:寄存器的个数
        src:多个寄存器的值 
返回值:

        成功:0
        失败:-1


3.功能案例

读取保持寄存器的值03功能:

#include <stdio.h>
#include "modbus-tcp.h"
#include "modbus.h"

int main(int argc, char const *argv[])
{
    // 创建modbus实例
    modbus_t *ctx;
    ctx = modbus_new_tcp(argv[1], 502);
    if (ctx == NULL)
    {
        perror("modbus new tcp失败");
        return -1;
    }

    // 设置从机ID
    modbus_set_slave(ctx, 1);

    // 建立连接
    if (modbus_connect(ctx) < 0)
    {
        printf("modbus connect err\n");
        modbus_free(ctx);
        return -1;
    }
    printf("connect ok\n");
    uint16_t dest[32];
    int addr, nb;
    printf("请输入寄存器起始地址,寄存器个数:");
    scanf("%d %d", &addr, &nb);
    getchar();
    int mrr = modbus_read_registers(ctx, addr, nb, dest);
    if (mrr <= 0)
    {
        perror("读保持寄存器的值失败");
        return -1;
    }
    else
    {
        for (int i = 0; i < mrr; i++)
        {
            printf("寄存器的值为:%d\n", dest[i]);
        }
    }

    // 释放
    modbus_free(ctx);
    modbus_close(ctx);

    return 0;
}

写入单个线圈的状态05功能:

#include <stdio.h>
#include "modbus-tcp.h"
#include "modbus.h"

int main(int argc, char const *argv[])
{
    // 创建modbus实例
    modbus_t *ctx;
    ctx = modbus_new_tcp(argv[1], 502);
    if (ctx == NULL)
    {
        perror("modbus new tcp失败");
        return -1;
    }

    // 设置从机ID
    modbus_set_slave(ctx, 1);

    // 建立连接
    if (modbus_connect(ctx) < 0)
    {
        printf("modbus connect err\n");
        modbus_free(ctx);
        return -1;
    }
    printf("connect ok\n");
    uint16_t dest[32];
    int addr, status;
    printf("请输入线圈地址,线圈状态:");
    scanf("%d %d", &addr, &status);
    getchar();
    int mrr = modbus_write_bit(ctx, addr, status);
    if (mrr <= 0)
    {
        perror("写入单个线圈的状态失败");
        return -1;
    }
    else
    {
        printf("写入单个线圈的状态成功\n");
    }

    // 释放
    modbus_free(ctx);
    modbus_close(ctx);

    return 0;
}

Modbus RTU

1.特点

(1)Modbus RTU和Modbus ASCII协议是基于串口进行通信的协议,在一般工业场景使用modbus RTU的场景还是更多一些
(2)与modbus TCP不同的是RTU没有报文头MBAP字段,但是在尾部增加了两个CRC检验字节(CRC16),因为网络协议中自带校验,所以在TCP协议中不需要使用CRC校验码


2.协议格式

ModbusRTU数据帧包含地址码、功能码、数据、校验码四部分

地址码:1个字节的从机地址码,=0:广播地址,=1-247:从机地址,=248-255:保留
功能码:与Modbus TCP相同
数据区:数据区包含这么几部分:起始地址、数量、数据,这三项是大端模式
CRC校验:两个字节,校验的数据范围为:地址码+功能码+数据区,校验码的产生可以通过函数自动生成。


3.编程思路

com1在虚拟机识别的是一个设备文件: /dev/ttyS1就是对这个文件进行操作--文件IO
(1)打开设备文件        //open
(2)对设备文件进行配置:对com1设置,波特率、数据位、停止位等
(3)写文件
        write
(4)读文件
        read

4.代码

Crc_Calc.h:


#ifndef _CRC_CALC_H_
#define _CRC_CALC_H_

#include "stdint.h"

#ifdef _CRC_CALC_C_
#define CRC_CALC_EXT
#else
#define CRC_CALC_EXT extern
#endif


unsigned short GetCRC16(unsigned char *ptr,  unsigned char len);

#endif 

Crc_Calc.c:

#define _CRC_CALC_C_
#include "stdint.h"
#include "stdio.h"

unsigned char const TabH[] = {  //CRC高位字节值表
                                0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
                                0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
                                0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
                                0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
                                0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
                                0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
                                0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
                                0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
                                0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
                                0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
                                0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
                                0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
                                0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
                                0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
                                0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
                                0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
                                0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
                                0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
                                0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
                                0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
                                0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
                                0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
                                0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
                                0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
                                0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
                                0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
                             } ;
unsigned char const TabL[] = {  //CRC低位字节值表
                                0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
                                0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
                                0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
                                0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
                                0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
                                0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
                                0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
                                0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
                                0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
                                0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
                                0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
                                0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
                                0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
                                0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
                                0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
                                0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
                                0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
                                0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
                                0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
                                0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
                                0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
                                0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
                                0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
                                0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
                                0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
                                0x43, 0x83, 0x41, 0x81, 0x80, 0x40
                             } ;

/*******************************************************************************
** 函数名称: crc
** 功能描述: CRC校验函数
** 参    数: *puchMsg-要校验数据的指针
             usDataLen-要校验数据的长度
** 返 回 值: crc-16位的CRC校验值      
*******************************************************************************/
unsigned short GetCRC16(unsigned char *ptr,  unsigned char len)
{ 
    unsigned int index;
    unsigned char crch = 0xFF;  //高CRC字节
    unsigned char crcl = 0xFF;  //低CRC字节


    while (len--)  //计算指定长度的CRC
    {
        index = crch ^ *ptr++;
        crch = crcl ^ TabH[index];
        crcl = TabL[index];
    }
    
    return ((crch<<8) | crcl);
} 

serial_init.c:

#include <termios.h>

void uart_init(int fd)
{
    struct termios options;
    //设置串口属性
	//获取串口原有属性
    tcgetattr(fd, &options);
	//激活选项CLOCAL(本地连接)和CREAD(接受使能)
    options.c_cflag |= ( CLOCAL | CREAD );
	//设置字符大小
    options.c_cflag &= ~CSIZE;
    //设置流控
    options.c_cflag &= ~CRTSCTS;
	//设置8位数据位
    options.c_cflag |= CS8;
	//设置停止位
    options.c_cflag &= ~CSTOPB;
    //忽略奇偶错字符
    options.c_iflag |= IGNPAR;
    //将输入的CR转换为NL和停止输出控制流起作用
    options.c_iflag &= ~(ICRNL | IXON);
    options.c_oflag = 0;
    options.c_lflag = 0;
	//设置波特率(输入和输出的波特率)
    cfsetispeed(&options, B9600);
    cfsetospeed(&options, B9600);
	//激活配置
    tcsetattr(fd, TCSANOW, &options);
}

modbus_rtu.c:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "stdint.h"
#include <termios.h>
#include "Crc_Calc.h"

void uart_init(int fd);

int main(int argc, char const *argv[])
{
    int fd;
    fd = open("/dev/ttyS1", O_RDWR);
    if (fd < 0)
    {
        perror("open失败");
        return -1;
    }
    // 对串口进行初始化
    uart_init(fd);

    // 写一个线圈的状态
    uint8_t buf[16] = {0x01, 0x05, 0x00, 0x00, 0xFF, 0x00};
    unsigned short crc;
    crc = GetCRC16(buf, 6);
    buf[6] = crc >> 8;
    buf[7] = crc & 0xff;
    write(fd, buf, sizeof(buf));
    printf("发送成功\n");

    uint8_t buf1[16] = {0};

    int ret = read(fd, buf1, sizeof(buf1));

    for (int i = 0; i < ret; i++)
    {
        printf("%#x ", buf1[i]);
    }
    printf("\n");

    close(fd);
    return 0;
}

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

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

相关文章

坐牢第三十八天(Qt)

1、使用Qt绘画事件处理画一个闹钟 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> #include <QPaintEvent>//画画处理事件 #include <QPainter>//画画 #include <QTime> //时间类 #include <QTimer>…

NVIDIA AI Workbench 让 Windows 上的 GPU 使用更加简便

NVIDIA AI Workbench 是一款免费的、用户友好型开发环境管理器&#xff0c;可在您选择的系统&#xff08;PC、工作站、数据中心或云&#xff09;上简化数据科学、ML 和 AI 项目。在 Windows、macOS 和 Ubuntu 上&#xff0c;您可以本地开发、测试项目和构建项目原型&#xff0c…

初识Maven:Java项目管理工具

实际开发中&#xff0c;伴随着项目规模的增长&#xff0c;依赖管理和构建自动化变得至关重要&#xff0c;一套标准化的项目结构有助于更好的开发项目、简化这项任务&#xff08;真的不是强迫症&#xff09; Maven&#xff0c;作为 Apache Software Foundation 维护的项目管理工…

如何获取MySQL数据表的列信息

在数据库管理中&#xff0c;了解表的结构是至关重要的。在MySQL中&#xff0c;我们可以通过几种方式来获取数据表的列信息。这不仅可以帮助我们更好地理解表的结构&#xff0c;还可以在编写查询时提供便利。以下是三种常用的方法来获取MySQL数据表的列信息。 使用 SHOW COLUMN…

HDMI彩条显示——FPGA学习笔记12

素材来自原子哥 一、HDMI简介 英文全称是High-Definition Multimedia Interface&#xff0c;即高清多媒体接口。 HDMI引脚解析&#xff08;A型&#xff09; HDMI工作连接图 HDMI工作原理 DVI编码输出示意图 二、TMDS编码&#xff08;最小化差分传输&#xff09; TMDS编码框图…

pip 阿里云镜像报错 certificate verify failed: unable to get local issuer certificate

在没有管理员身份&#xff0c;且有防火墙限制的电脑上&#xff0c;pip安装​python库包失败。​但是在普通的电脑上安装正常。​​报错内容如下&#xff1a; (SSS_web) C:\Users\HXAIYVQ>pip install flask -i https://mirrors.aliyun.com/pypi/simple/ Looking in indexes…

302.AI学术论文搜索工具的智能体验

Hey朋友们&#xff0c; 你是否曾在学术的海洋里迷失方向&#xff0c;为了找到一篇论文而苦苦挣扎&#xff1f; 就像在茫茫大海中寻找灯塔&#xff0c;我们渴望一盏明灯&#xff0c;指引我们前行。 别担心&#xff0c;今天我来给你介绍一个超级给力的工具——302.AI学术论文…

求教0基础入门大模型的学习路线?

0基础入门大模型&#xff0c;transformer、bert这些是要学的&#xff0c;但是你的第一口不一定从这里咬下去。真的没有必要一上来就把时间精力全部投入到复杂的理论、各种晦涩的数学公式还有编程语言上&#xff0c;这样不仅容易让你气馁&#xff0c;而且特别容易磨光热情。当我…

如何系统的入门大模型?

对于刚开始接触大模型&#xff08;LLM&#xff09;的研究者来说&#xff0c;系统地学习和探索是非常重要的。以下是一个循序渐进的学习路径&#xff0c;帮助你高效地入门大模型的领域。 1、浏览基础资源与课程 首先&#xff0c;你可以通过阅读几篇公众号或知乎上的文章来了解大…

动态数字时钟屏保 提升桌面美化 电脑屏幕屏保软件

时钟屏保软件可以让你的电脑更有特色&#xff0c;当你离开电脑时候&#xff0c;屏保可以保护你的桌面隐私&#xff0c;还是比较有用的一款小软件&#xff0c;今天小编给大家推荐的这款可以实现动态数字时钟的屏保软件&#xff1a;芝麻时钟 &#xff08;下载地址&#xff1a;htt…

终端显示字体背景和字体颜色

【终端显示字体背景和字体颜色等使用用法】 在命令行下想要产生五颜六色的字体和背景&#xff0c;只需要加上一些颜色代码即可。 ANSI 标准规定了一种所有终端共享的指令集&#xff0c;并要求用 ASCII 的数字字符传递所有数值信息&#xff0c;用于控制 Linux 终端上的光标位置…

抓包分析ARP协议工作原理

目录 1. ARP 协议 2. 工作原理 3. ARP 协议报文格式 4. ARP 缓存的查看和修改 5. tcpdump 抓包分析 ARP 协议工作原理 5.1 搭建 2 台虚拟机 5.2 在主机 192.168.0.155 打开一个shell命令行开启抓包监听 5.3 在主机 192.168.0.155 打开另一个shell命令行 telnet 192.168.…

恢复二叉搜索树

题目 给你二叉搜索树的根节点 root &#xff0c;该树中的两个节点被错误地交换。请在不改变其结构的情况下&#xff0c;恢复这棵树。 进阶&#xff1a;使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用常数空间的解决方案吗&#xff1f; 示例 1&#xff1a; 输入&…

超声眼镜波清洗机有用吗?真正好用的超声波清洗机推荐

随着时代的进步&#xff0c;人们对家居生活质量的追求也日益提高。尤其是对于珠宝、饰品、眼镜等小物件&#xff0c;长时间不使用后往往会积累灰尘和细菌&#xff0c;这些细菌隐藏在肉眼看不到的地方&#xff0c;它们对健康的影响不容忽视。幸运的是&#xff0c;超声波清洗机能…

Nginx怎么重新编译添加模块

转自 https://www.php.cn/faq/547300.html

【机器人建模和控制】读书笔记

机器人建模和控制——马克斯庞 A. x 1 0 x 1 ∙ x 0 x^0_1x_1\bullet x_0 x10​x1​∙x0​&#xff0c;其实就是&#xff1a; 1&#xff09; x 1 x_1 x1​轴向量在 O 0 O_0 O0​系下的坐标 2&#xff09;在 x 0 x_0 x0​轴上的投影 3&#xff09;坐标变换矩阵的 R 1 0 R_1…

基于vue框架的城市智慧地铁管理系统73c2d(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,站点查询,车次线路,站点周边 开题报告内容 基于Vue框架的城市智慧地铁管理系统开题报告 一、研究背景与意义 1.1 研究背景 随着城市化进程的加速和人口的不断增长&#xff0c;城市交通压力日益增大。地铁作为城市公共交通的重要…

利用AI驱动智能BI数据可视化-深度评测Amazon Quicksight(一)

项目简介 随着生成式人工智能的兴起&#xff0c;传统的 BI 报表功能已经无法满足用户对于自动化和智能化的需求&#xff0c;今天我们将介绍亚马逊云科技平台上的AI驱动数据可视化神器 – Quicksight&#xff0c;利用生成式AI的能力来加速业务决策&#xff0c;从而提高业务生产…

设置广告活动目标和数字广告关键绩效指标的3个步骤

在微调广告预算、优化广告、分析数字广告关键绩效指标&#xff08;KPI&#xff09;和个性化着陆页面的同时&#xff0c;有一件事是在启动广告活动之前必须做的&#xff1a;确定哪些因素能使广告活动有效。 广告商很容易迷失在构成成功活动的各种指标中&#xff0c;但事实是&am…

20240912 每日AI必读资讯

OpenAI计划在接下来的两周内发布Strawberry - 独立产品&#xff1a;尽管草莓是ChatGPT的一部分&#xff0c;但它将作为一个独立的产品发布&#xff0c;具体如何提供尚不清楚。它可能会出现在用户选择的AI模型下拉菜单中&#xff0c;与现有服务有所不同。 - 推理功能&#xff…