【S32K3 RTD LLD篇7】K344中心对齐PWM中心点触发ADC BCTU采样

news2025/1/27 10:40:59

【S32K3 RTD LLD篇7】K344中心对齐PWM中心点触发ADC BCTU采样

  • 一,文档简介
  • 二,中心对齐PWM中心点触发ADC原理
    • 2.1 如何生成中心对齐的PWM
    • 2.2 如何生成PWM中心点触发标志
  • 三, 软件配置与实现
    • 3.1 Demo CT 模块配置
      • 3.1.1 引脚配置
      • 3.1.2 时钟配置
      • 3.1.3 外设配置
    • 3.2 主程序调用情况
    • 3.3 测试结果
  • 四,总结与坑位描述

一,文档简介

手里还有好几个典型的案子没来得及写,春节前就先上一个吧。前不久,有客户实际项目需要在S32K3XX 上实现中心对齐PWM的高电平中心点去触发ADC BCTU多通道采样。这个功能需要使用EMIOS,ADC,BCTU的相互配合,开始的时候客户总是无法实现在PWM中心点位置的触发,触发位置不对,后续给与客户K3相关模块原理的讲解分析,以及实际代码配置测试的引导,客户也实现了需要的功能。这里为了测试方便,还额外添加了PIT以及UART printf功能。所以在此总结下该功能的具体情况,便于后续有其他客户遇到类似功能需求,有参考且能够快速构建起来。
需求如下图,在向上向下计数的模式下,输出中心对齐的PWM,并且在高电平的中心点实现ADC BTCU LIST的触发采样。本文将在官方S32K344-EVB板子上实现1KHZ的中心对齐PWM,50%占空比,高电平中心点实现ADC BTCU LIST采样,基于RTD400 LLD版本。
在这里插入图片描述

图 1

二,中心对齐PWM中心点触发ADC原理

关于原理,ADC这块是没有什么悬念,可以直接参考之前的ADC软硬件触发的文章即可:

【S32K3 RTD LLD篇5】K344 ADC SW+HW trigger
就是图2这种结构,配置ADC之后,再配置BCTU,选择触发的EMIOS通道,当EMIOS的相关标志产生时候,就会触发BCTU,在watermark达到之后,产生通知去存储所有的LIST ADC值到buffer,然后再根据情况可以打印出ADC值便于查看。
在这里插入图片描述

图 2

当前工况,需要关心的逻辑主要是:如何生成中心对齐的PWM,如何实现在高电平中心点去产生一个标志,并用这个标志去触发BTCU采样。

2.1 如何生成中心对齐的PWM

首先来看看EMIOS的通道情况,支持中心对齐PWM的通道情况。
在这里插入图片描述

图 3

中心对齐的PWM模式是:OPWMCB
正如图1所示的情况,可以看到,这种模式下的计数器计数模式是向上向下的。下面再看看支持OPWMCB的通道类型有哪些,可以看到,只有type G。
在这里插入图片描述

图 4

那么,Type G支持的通道又有哪些呢?请看下图:
在这里插入图片描述

图 5

谜团揭开,只有eMIOS的CH1-CH7支持中心对齐的PWM。
好,那么又引出新的问题,该模式是否能够直接产生PWM高电平中心点的触发信号去触发ADC BCTU采样?回答:不能!
原因可以从图1看出,这种PWM模式下,产生的触发标志有两个,分别是向上向下计数对比完成的时候。所以,如果用这种模式通道直接去触发ADC采样,一个周期里面会产生两次触发,并且都在PWM的边沿上。
既然OPWMCB无法直接产生PWM中心点的触发,那么如何实现呢?
另外再开一个专门的通道,并且时钟源和OPWMCB同时钟源,只是那个通道只做计数产生触发标志,并不输出任何的波形。

2.2 如何生成PWM中心点触发标志

关键信息:OPWMCB同时钟源,只有计数模式,还是向上向下MCB模式,满足的情况只有一个通道:ADC CH0,counter bus类型还需要选择为counter_bus_B
在这里插入图片描述

图 6

来看看MCB的触发标志情况:
在这里插入图片描述

图 7

可以看到,非常完美,触发标志就在向上向下计数的顶点,该点正好就是同源PWM高电平中心点。
所以,到这里,原理上已经确定了具体的通道安排,两个通道:EMIOS0_CH0 MCB模式纯计数并触产生标志触发ADC采样; EMIOS0_CH1-CH7为OPWMCB模式,单纯输出中心对齐PWM。

三, 软件配置与实现

软件使用的是S32K3 RTD400版本,其他的版本配置类同!

3.1 Demo CT 模块配置

首先需要准备一个K344的demo,然后再去配置引脚,时钟,和外设模块。下面分别从几种配置来讲解。对于使用的模块主要有:2个GPIO, ADC,BCTU, EMIOS时钟,EMIOS PWM, LPUART用于打印log,PIT用来做定时打印, Trgmux配置了但是本文并没用,不讲!

3.1.1 引脚配置

用到的引脚有如下情况:
在这里插入图片描述

图 8

两个GPIO的用处是分别在BCTU触发通知和BCTU watermark通知中翻转,用来测试波形定位情况。ADC1_s10引脚用于ADC1,但是本文主要是BCTU用来结合ADC0,ADC0并没有添加特定外部引脚,用的是内部信号。LPUART是用来做打印用,EMIOS0_CH1是用来产生中心对其的PWM波形。

3.1.2 时钟配置

时钟这里需要关注的是:ADC时钟,EMIOS时钟,UART时钟,PIT时钟。
在这里插入图片描述

图9

这些时钟后续在配置具体的定时周期,波特率的时候需要用到。

3.1.3 外设配置

用到的外设主要有如下模块:
在这里插入图片描述

图 10

(1)Adc_Sar_Ip
ADC0模块的配置使用是one shot 模式,也就是一次触发就产生一次转换,这样就可以使用定时器EMIOS通道产生触发条件去触发产生一次转换,使能预采样是为了防止上一个通道的采样值电荷的残存导致对当前通道结果的影响,引起ADC值的偏差,触发模式使用BCTU,对于Adc prescaler value和calibration prescale的配置,需要满足RM中分频要求,最终的配置如下:
在这里插入图片描述

图 11

在这里插入图片描述

图 12

(2)Bctu_Ip
Bctu_Ip这边配置需要选对使用的EMIOS通道,从上述原理中可以知道,使用的是EMIOS0_CH0, 然后采用LIST模式,针对ADC0,LIST里面,当前添加了三个内部通道:BANDGAP,VREFL,VREFH. 具体配置如下:
在这里插入图片描述

图 13

在这里插入图片描述

图 14

(3)Emios_Mcl_Ip
这里就需要考虑需要产生的PWM周期的问题了,目标是产生1Khz的中心对其PWM,所以EMIOS模式是MCB向上向下计数模式。
对于MCB的时钟周期公式是:(2 x AS1) – 2.
那么对于EMIOS0时钟源是160Mhz,对应的1KHZ counter情况是如何的呢?先做160分配,得到1Mhz,然后再去按照(2 x AS1) – 2计算:
(2 x AS1) – 2=1Mhz/1KHZ=>AS1=1000/2 +1= 501.
配置如下:
在这里插入图片描述

图 15

(3)Emios_Pwm
前面原理分析是PWM采用的是OPWMCB中心对齐模式的PWM,时钟是来自EMIOS CH0的counter bus是B,然后周期是1khz,占空比是50%,具体配置如下:
在这里插入图片描述

图 16

(4)Lpuart_Uart
配置UART6时钟波特率为115200.
在这里插入图片描述

图 17

(5)Pit
在这里插入图片描述

图 18

(6)IntCtrl_Ip
中断配置如下,实际上也可以通过代码方式去配置。
在这里插入图片描述

图 19

3.2 主程序调用情况

配置完成之后,可以通过在main中调用如下代码实现中心PWM的输出以及ADC BCTU的采样。

#include "Clock_Ip.h"
#include "IntCtrl_Ip.h"
#include "Adc_Sar_Ip.h"
#include "Bctu_Ip.h"
#include "Siul2_Port_Ip.h"
#include "Pit_Ip.h"
#include "Siul2_Dio_Ip.h"
#include "Trgmux_Ip.h"
#include "Lpuart_Uart_Ip.h"
#include "Lpuart_Uart_Ip_Irq.h"
#include "string.h"
#include "stdio.h"
#include "retarget.h"
#include "Emios_Mcl_Ip.h"
#include "Emios_Pwm_Ip.h"

/* PIT instance used - 0 */
#define PIT_INST_0 0U
/* PIT Channel used - 0 */
#define CH_0 0U
/* PIT time-out period - equivalent to 1s */
#define PIT_PERIOD 40000000
static volatile uint8 toggleLed = 0U;
#ifdef ADC_3V3_VREF_SELECTED
#define ADC_BANDGAP         5980U /* Vbandgap ~ 1.2V on 14 bits resolution, 3.3V VrefH */
#else
#define ADC_BANDGAP         3932U /* Vbandgap ~ 1.2V on 14 bits resolution, 5V VrefH */
#endif

#define ADC_SAR_USED_CH                 48U /* Internal Bandgap Channel */
#define BCTU_USED_SINGLE_TRIG_IDX       0U
#define BCTU_USED_FIFO_IDX              0U
#define BCTU_FIFO_WATERMARK             3U
#define ADC_TOLERANCE(x,y)              (((x > y) ? (x - y) : (y - x)) > 200U) /* Check that the data is within tolerated range */

#define LED_Q172_PIN            13u
#define LED_Q172_PORT           PTA_H_HALF

#define GPIO_PTA2_PIN           2u
#define GPIO_PTA2_PORT         PTA_L_HALF
#define EMIOS_INST0                  0U

volatile int exit_code = 0;
volatile boolean notif_triggered = FALSE;
volatile boolean notif_triggered1 = FALSE;

volatile uint16 data;
volatile uint16 data1;
volatile uint16 data_bctu[3];

#define UART_LPUART_INTERNAL_CHANNEL  6
#define WELCOME_MSG_1 "Hello, This message is sent via Uart!\r\n"
volatile Lpuart_Uart_Ip_StatusType lpuartStatus = LPUART_UART_IP_STATUS_ERROR;
uint32 remainingBytes;
uint32 T_timeout = 0xFFFFFF;
uint8* pBuffer;

extern void Adc_Sar_0_Isr(void);
extern void Bctu_0_Isr(void);
extern void Adc_Sar_1_Isr(void);

void AdcEndOfChainNotif(void)
{
    notif_triggered = TRUE;
    data = Adc_Sar_Ip_GetConvData(ADCHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, ADC_SAR_USED_CH);
    /* Checks the measured ADC data conversion */
}
void AdcEndOfChainNotif1(void)
{
    notif_triggered1 = TRUE;
    data1 = Adc_Sar_Ip_GetConvData(ADCHWUNIT_1_BOARD_INITPERIPHERALS_INSTANCE, 34);
    /* Checks the measured ADC data conversion */
}
void Pit0ch0Notification(void)
{
    toggleLed = 1U;
}

void BctuWatermarkNotif(void)
{
    uint8 idx;
    Siul2_Dio_Ip_WritePin(GPIO_PTA2_PORT, GPIO_PTA2_PIN, 1U);
    notif_triggered = TRUE;
    for (idx = 0u; idx < BCTU_FIFO_WATERMARK; idx++)
    {
    	data_bctu[idx] = Bctu_Ip_GetFifoData(BCTUHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, BCTU_USED_FIFO_IDX);
    }
    Siul2_Dio_Ip_WritePin(GPIO_PTA2_PORT, GPIO_PTA2_PIN, 0U);
}

void BcutTriggerNotif()
{
	Siul2_Dio_Ip_WritePin(LED_Q172_PORT, LED_Q172_PIN, 1U);
	Siul2_Dio_Ip_WritePin(LED_Q172_PORT, LED_Q172_PIN, 0U);
}
void TestDelay(uint32 delay);
void TestDelay(uint32 delay)
{
    static volatile uint32 DelayTimer = 0;
    while(DelayTimer < delay)
    {
        DelayTimer++;
    }
    DelayTimer = 0;
}
int main(void)
{
    StatusType status;
    uint8 Index;
    Clock_Ip_StatusType clockStatus;

    /* Initialize and configure drivers */
    clockStatus = Clock_Ip_Init(&Clock_Ip_aClockConfig[0]);
    while (clockStatus != CLOCK_IP_SUCCESS)
    {
        clockStatus = Clock_Ip_Init(&Clock_Ip_aClockConfig[0]);
    }
    Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS_PortContainer_0_BOARD_InitPeripherals, g_pin_mux_InitConfigArr_PortContainer_0_BOARD_InitPeripherals);

#if 1
    Bctu_Ip_Init(BCTUHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, &BctuHwUnit_0_BOARD_INITPERIPHERALS);

    status = (StatusType) Adc_Sar_Ip_Init(ADCHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, &AdcHwUnit_0_BOARD_InitPeripherals);
    while (status != E_OK);
    status = (StatusType) Adc_Sar_Ip_Init(ADCHWUNIT_1_BOARD_INITPERIPHERALS_INSTANCE, &AdcHwUnit_1_BOARD_InitPeripherals);
    while (status != E_OK);

    /* set PIT 0 interrupt */
    IntCtrl_Ip_Init(&IntCtrlConfig_0);
    IntCtrl_Ip_EnableIrq(PIT0_IRQn);
    /* Install and enable interrupt handlers */
    IntCtrl_Ip_InstallHandler(ADC0_IRQn, Adc_Sar_0_Isr, NULL_PTR);
    IntCtrl_Ip_InstallHandler(BCTU_IRQn, Bctu_0_Isr, NULL_PTR);
    IntCtrl_Ip_InstallHandler(ADC1_IRQn, Adc_Sar_1_Isr, NULL_PTR);

    IntCtrl_Ip_EnableIrq(ADC0_IRQn);
    IntCtrl_Ip_EnableIrq(BCTU_IRQn);
    IntCtrl_Ip_EnableIrq(ADC1_IRQn);

   // IntCtrl_Ip_EnableIrq(EMIOS0_5_IRQn);

    /* Call Calibration function multiple times, to mitigate instability of board source */
    for(Index = 0; Index <= 5; Index++)
    {
        status = (StatusType) Adc_Sar_Ip_DoCalibration(ADCHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE);
        if(status == E_OK)
        {
            break;
        }
    }
    for(Index = 0; Index <= 5; Index++)
    {
        status = (StatusType) Adc_Sar_Ip_DoCalibration(ADCHWUNIT_1_BOARD_INITPERIPHERALS_INSTANCE);
        if(status == E_OK)
        {
            break;
        }
    }

    Adc_Sar_Ip_EnableNotifications(ADCHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, ADC_SAR_IP_NOTIF_FLAG_NORMAL_ENDCHAIN | ADC_SAR_IP_NOTIF_FLAG_INJECTED_ENDCHAIN);
    Adc_Sar_Ip_EnableNotifications(ADCHWUNIT_1_BOARD_INITPERIPHERALS_INSTANCE, ADC_SAR_IP_NOTIF_FLAG_NORMAL_ENDCHAIN | ADC_SAR_IP_NOTIF_FLAG_INJECTED_ENDCHAIN);
    /* Start a SW triggered normal conversion on ADC_SAR */

    Adc_Sar_Ip_StartConversion(ADCHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, ADC_SAR_IP_CONV_CHAIN_NORMAL);

    /* Wait for the notification to be triggered and read the data */
    while (notif_triggered != TRUE);
    notif_triggered = FALSE;

    /* Start a SW triggered injected conversion on ADC_SAR */
    Adc_Sar_Ip_StartConversion(ADCHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, ADC_SAR_IP_CONV_CHAIN_INJECTED);

    /* Wait for the notification to be triggered and read the data */
    while (notif_triggered != TRUE);
    notif_triggered = FALSE;
#endif
    /* Initialize PIT instance 0 - Channel 0 */
    Pit_Ip_Init(PIT_INST_0, &PIT_0_InitConfig_PB_BOARD_InitPeripherals);
    /* Initialize channel 0 */
    Pit_Ip_InitChannel(PIT_INST_0, PIT_0_CH_0);
    /* Enable channel interrupt PIT_0 - CH_0 */
    Pit_Ip_EnableChannelInterrupt(PIT_INST_0, CH_0);
    /* Start channel CH_0 */
    Pit_Ip_StartChannel(PIT_INST_0, CH_0, PIT_PERIOD);

   // Trgmux_Ip_Init(&Trgmux_Ip_xTrgmuxInitPB);//
    Lpuart_Uart_Ip_Init(UART_LPUART_INTERNAL_CHANNEL, &Lpuart_Uart_Ip_xHwConfigPB_6_BOARD_INITPERIPHERALS);

    Emios_Mcl_Ip_Init(EMIOS_INST0, &Emios_Mcl_Ip_0_Config_BOARD_INITPERIPHERALS);

    Emios_Pwm_Ip_InitChannel(EMIOS_PWM_IP_BOARD_INITPERIPHERALS_I0_CH1_CFG, &Emios_Pwm_Ip_BOARD_InitPeripherals_I0_Ch1);

    printf("S32K344 PIT TRIGMUX ADC demo RTD400.\r\n");

    /* Uart_AsyncSend transmit data */
    lpuartStatus = Lpuart_Uart_Ip_AsyncSend(UART_LPUART_INTERNAL_CHANNEL, (const uint8 *) WELCOME_MSG_1, strlen(WELCOME_MSG_1));
    /* Check for no on-going transmission */
    do
    {
        lpuartStatus = Lpuart_Uart_Ip_GetTransmitStatus(UART_LPUART_INTERNAL_CHANNEL, &remainingBytes);
    } while (LPUART_UART_IP_STATUS_BUSY == lpuartStatus && 0 < T_timeout--);

    Siul2_Dio_Ip_WritePin(GPIO_PTA2_PORT, GPIO_PTA2_PIN, 0U);

    while(1)
    {
#if 1
        if( toggleLed == 1)
        {
      	  toggleLed = 0;
  
      	  printf("ADC0_bandgap    ch48 data_bctu = %d .\r\n", data_bctu[0]);
      	  printf("ADC0_vrefl       ch54 data_bctu = %d .\r\n", data_bctu[1]);
      	  printf("ADC0_vrefh       ch55 data_bctu = %d .\r\n", data_bctu[2]);


        }
#endif
    }
    return exit_code;
}

3.3 测试结果

测试结果包括两部分:打印结果看ADC采样值情况,以及PWM输出和BCTU触发位置的关系情况。打印结果如下,可以看到内部三个不同ADC通道的值是正确的:
在这里插入图片描述

图 20

PWM波形测试情况如下:
Ch1:PTB13 PWM
Ch2:PTA29 BCTU trigger notification
Ch3: PTA2 BCTU watermark notification
在这里插入图片描述

图 21

从图中,可以看到BCTU第一次触发是在PWM高电平的中心点位置,BCTU watermark notification是在三次触发ADC采样之后用来存储数据的。
下面再来一张查看PWM的周期的波形:
在这里插入图片描述

图 22
可以看到,PWM周期位1Khz,占空比是50%,并且BCTU第一次触发是在PWM高脉冲的中心位置。

四,总结与坑位描述

通过上述的配置,最终在S32K344-EVB上使用RTD400 LLD方式实现了1Khz,50%占空比的中心对齐PWM,高脉冲中心位置触发ADC BCTU LIST采集。
遇到的坑位属于自己配置的问题,开始的时候误认为watermark配置的值和LIST通道数保持一致,实际上是watermark触发是在 超过watermark值才会触发。所以,如果是3个通道的LIST,那么watermark需要配置的是2,而不是3,如果是3的情况,测试波形如下:
在这里插入图片描述

图23

可以看到,实际上是触发了4次之后,才会产生watermark通知。
所以,切记要配对watermark的FIFO数。

文章源码链接:
https://community.nxp.com/t5/S32K-Knowledge-Base/RTD400-K344-Center-Aligned-PWM-Trigger-ADC-BCTU/ta-p/2034211

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

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

相关文章

14-6-3C++STL的list

&#xff08;一&#xff09;list的插入 1.list.insert(pos,elem);//在pos位置插入一个elem元素的拷贝&#xff0c;返回新数据的位置 #include <iostream> #include <list> using namespace std; int main() { list<int> lst; lst.push_back(10); l…

unity学习20:time相关基础 Time.time 和 Time.deltaTime

目录 1 unity里的几种基本时间 1.1 time 相关测试脚本 1.2 游戏开始到现在所用的时间 Time.time 1.3 时间缩放值 Time.timeScale 1.4 固定时间间隔 Time.fixedDeltaTime 1.5 两次响应时间之间的间隔&#xff1a;Time.deltaTime 1.6 对应测试代码 1.7 需要关注的2个基本…

HarmonyOS:创建应用静态快捷方式

一、前言 静态快捷方式是一种在系统中创建的可以快速访问应用程序或特定功能的链接。它通常可以在长按应用图标&#xff0c;以图标和相应的文字出现在应用图标的上方&#xff0c;用户可以迅速启动对应应用程序的组件。使用快捷方式&#xff0c;可以提高效率&#xff0c;节省了查…

mysql 学习6 DQL语句,对数据库中的表进行 查询 操作

前期准备数据 重新create 一张表 create table emp(id int comment 编号,workno varchar(10) comment 工号,name varchar(10) comment 姓名,gender char comment 性别,ager tinyint unsigned comment 年龄,idcard char(18) comment 身份证号,workaddress varchar(10) c…

【ES实战】治理项之索引模板相关治理

索引模板治理 文章目录 索引模板治理问题现象分析思路操作步骤问题程序化方案索引与索引模板增加分片数校验管理 彩蛋如何查询Flink on Yarn 模式下的Task Manager日志相关配置查询已停止的Flink任务查询未停止的Flink任务 问题现象 在集群索引新建时&#xff0c;索引的分片比…

springboot3 集成 knife4j(接口文档)

提示&#xff1a;文章是集成 knife4j&#xff0c;而非 swagger2 或者 swagger3&#xff0c;效果如图 文章目录 前言一、添加依赖二、如何集成1.配置文件2.注解部分1.Tag2.Operation3.Parameter4.Schema 3.使用 总结 前言 提示&#xff1a;&#xff1a;大家在开发阶段&#xff…

51单片机开发:独立键盘实验

实验目的&#xff1a;按下键盘1时&#xff0c;点亮LED灯1。 键盘原理图如下图所示&#xff0c;可见&#xff0c;由于接GND&#xff0c;当键盘按下时&#xff0c;P3相应的端口为低电平。 键盘按下时会出现抖动&#xff0c;时间通常为5-10ms&#xff0c;代码中通过延时函数delay…

Flutter_学习记录_Tab的简单Demo~真的很简单

1. Tab的简单使用了解 要实现tab(选项卡或者标签视图)需要用到三个组件&#xff1a; TabBarTabBarViewTabController 这一块&#xff0c;我也不知道怎么整理了&#xff0c;直接提供代码吧&#xff1a; import package:flutter/material.dart;void main() {runApp(MyApp());…

GESP2024年3月认证C++六级( 第三部分编程题(1)游戏)

参考程序&#xff1a; #include <cstdio> using namespace std; const int N 2e5 5; const int mod 1e9 7; int n, a, b, c; int f[N << 1]; int ans; int main() {scanf("%d%d%d%d", &n, &a, &b, &c);f[N n] 1;for (int i n; i…

数据结构测试题2

一、单选题&#xff08;每题 2 分&#xff0c;共20分&#xff09; 1. 栈和队列的共同特点是( A )。 A.只允许在端点处插入和删除元素 B.都是先进后出 C.都是先进先出 D.没有共同点 2. 用链接方式存储的队列&#xff0c;在进行插入运算时( C ) A. 仅修改头指针 B. 头…

项目概述与规划 (I)

项目概述与规划 (I) JavaScript的学习已经接近尾声了&#xff0c;最后我们将通过一个项目来讲我们在JavaScript中学习到的所有都在这个项目中展现出来&#xff0c;这个项目的DEMO来自于Udemy中的课程&#xff0c;作者是Jonas Schmedtmann&#xff1b; 项目规划 项目步骤 用户…

【WebRTC - STUN/TURN服务 - COTURN配置】

在WebRTC中&#xff0c;对于通信的两端不在同一个局域网的情况下&#xff0c;通信两端往往无法P2P直接连接&#xff0c;需要一个TURN中继服务&#xff0c;而中继服务可以选用 COTURN 构建。 注&#xff1a;COTURN 是一个开源的 TURN&#xff08;Traversal Using Relays around…

【HuggingFace项目】:Open-R1 - DeepSeek-R1 大模型开源复现计划

项目链接&#xff1a;https://github.com/huggingface/open-r1 概述 Open-R1 是由 HuggingFace 发布的一个完全开放的项目&#xff0c;旨在通过三个主要步骤复现 DeepSeek-R1 的完整训练流程。这个项目的目标是让更多人能够理解和使用 DeepSeek-R1 的技术方案&#xff0c;从而…

On to OpenGL and 3D computer graphics

2. On to OpenGL and 3D computer graphics 声明&#xff1a;该代码来自&#xff1a;Computer Graphics Through OpenGL From Theory to Experiments&#xff0c;仅用作学习参考 2.1 First Program Square.cpp完整代码 /// // square.cpp // // OpenGL program to draw a squ…

【数据分享】2014-2025年我国水系数据(免费获取/全国/分省)

水系数据是我们在各项研究中经常使用的数据&#xff01;水系数据虽然很常用&#xff0c;但是却基本没有能下载最近年份水系数据的网站&#xff0c;所以很多人不知道如何获得水系数据。 本次我们给大家分享的是2014-2025年的全国范围的水系数据&#xff0c;包括水系线数据和水系…

学习数据结构(2)算法复杂度+顺序表

1.空间复杂度 &#xff08;1&#xff09;概念 空间复杂度也是一个数学表达式&#xff0c;表示一个算法在运行过程中根据算法的需要额外临时开辟的空间。 空间复杂度不是指程序占用了多少bytes的空间&#xff0c;因为常规情况每个对象大小差异不会很大&#xff0c;所以空间复杂…

MyBatis和JPA区别详解

文章目录 MyBatis和JPA区别详解一、引言二、设计理念与使用方式1、MyBatis&#xff1a;半自动化的ORM框架1.1、代码示例 2、JPA&#xff1a;全自动的ORM框架2.1、代码示例 三、性能优化与适用场景1、MyBatis&#xff1a;灵活的SQL控制1.1、适用场景 2、JPA&#xff1a;开发效率…

DeepSeek明确学术研究方向效果如何?

明确学术研究方向 在学术写作中&#xff0c;选择一个出色的研究主题至关重要&#xff0c;因为它直接关系到论文是否能登上高级别的学术期刊。不少学者在这个过程中走入了误区&#xff0c;他们往往将大把的时间花在写作本身&#xff0c;而忽略了对选题的深入思考&#xff0c;这…

牛客周赛round78 B,C

B.一起做很甜的梦 题意&#xff1a;就是输出n个数&#xff08;1-n&#xff09;&#xff0c;使输出的序列中任意选连续的小序列&#xff08;小序列长度>2&&<n-1&#xff09;不符合排列&#xff08;例如如果所选长度为2&#xff0c;在所有长度为2 的小序列里不能出…

基于语义-拓扑-度量表征引导的大语言模型推理的空中视觉语言导航

1. 摘要翻译及主要贡献点 摘要&#xff1a; 空中视觉语言导航&#xff08;VLN&#xff09;是一项新兴任务&#xff0c;它使无人机能够通过自然语言指令和视觉线索在户外环境中导航。由于户外空中场景中复杂的空间关系&#xff0c;这项任务仍然具有挑战性。本文提出了一种端到…