STM32 DAC + DMA + TIM 输出正弦波,三角波,方波信号

2023-11-05

硬件平台:STM32F4
库类型:标准库。
参考:【二代示波器教程】第12章 示波器设计—DAC信号发生器的实现

DAC框图如下:

在这里插入图片描述
通过TIM触发DAC转换,转换完成后通过DMA输出。

DMA通道框图

在这里插入图片描述

DAC输出阻抗的问题:

DAC集成了2个输出缓存,可以用来减少输出阻抗,无须外部运放即可直接驱动外部负载。每个DAC通道输出缓存可以通过设置DAC_CR寄存器的BOFFx位来使能或者关闭,如果带载能力还不行,后面就需要接一个电压跟随器,选择运放一定要选择电流大的型号。

DAC使能输出缓冲后,DAC的最小输出电压为0.2V。最大电压为Vref±0.2(会造成削顶问题)。而未使能输出缓冲则可达到0V。
在这里插入图片描述
输出缓冲和外接负载时的框图。
在这里插入图片描述

DAC驱动实现

我们这里使用了DAC1,驱动中还需要用到TIM6和DMA,方便我们配置不同的的频率,占空比和幅值。

1. 引脚配置和DAC配置

/*
*********************************************************************************************************
*	函 数 名: bsp_InitDAC1
*	功能说明: 配置PA4/DAC1
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitDAC1(void)
{	
	/* 配置GPIO */
	{
		GPIO_InitTypeDef GPIO_InitStructure;
		
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
		
		/* 配置DAC引脚为模拟模式  PA4 / DAC_OUT1 */
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
		GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
		GPIO_Init(GPIOA, &GPIO_InitStructure);
	}	

	/* DAC通道1配置 */
	{
		DAC_InitTypeDef DAC_InitStructure;
		
		/* 使能DAC时钟 */
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);		

		DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;	/* 选择软件触发, 软件修改DAC数据寄存器 */
		DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
		DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
		//DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
		DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
		DAC_Init(DAC_Channel_1, &DAC_InitStructure);
		DAC_Cmd(DAC_Channel_1, ENABLE);
	}
}

特别注意。程序中关闭了DAC输出缓冲,即DAC参数成员DAC_InitStructure.DAC_OutputBuffer。

2. DAC的定时器触发和DMA配置:

/*
*********************************************************************************************************
*	函 数 名: dac1_InitForDMA
*	功能说明: 配置PA4 为DAC_OUT1, 启用DMA2
*	形    参: _BufAddr : DMA数据缓冲区地址
*			  _Count   : 缓冲区样本个数
*			 _DacFreq  : DAC样本更新频率
*	返 回 值: 无
*********************************************************************************************************
*/
void dac1_InitForDMA(uint32_t _BufAddr, uint32_t _Count, uint32_t _DacFreq)
{	
	uint16_t usPeriod;
	uint16_t usPrescaler;
	uint32_t uiTIMxCLK;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	
	DMA_Cmd(DMA1_Stream5, DISABLE);
	DAC_DMACmd(DAC_Channel_1, DISABLE);
	TIM_Cmd(TIM6, DISABLE);
	

	/* TIM6配置 */
	{
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);

		uiTIMxCLK = SystemCoreClock / 2;
		
		if (_DacFreq < 100)
		{
			usPrescaler = 10000 - 1;						 /* 分频比 = 10000 */
			usPeriod =  (uiTIMxCLK / 10000) / _DacFreq  - 1; /* 自动重装的值 */
		}
		else if (_DacFreq < 3000)
		{
			usPrescaler = 100 - 1;							/* 分频比 = 100 */
			usPeriod =  (uiTIMxCLK / 100) / _DacFreq  - 1;	/* 自动重装的值 */
		}
		else	/* 大于4K的频率,无需分频 */
		{
			usPrescaler = 0;						/* 分频比 = 1 */
			usPeriod = uiTIMxCLK / _DacFreq - 1;	/* 自动重装的值 */
		}

		TIM_TimeBaseStructure.TIM_Period = usPeriod;
		TIM_TimeBaseStructure.TIM_Prescaler = usPrescaler;
		TIM_TimeBaseStructure.TIM_ClockDivision = 0;
		TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
		TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000;		/* TIM1 和 TIM8 必须设置 */	

		TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);

		/* 选择TIM6做DAC的触发时钟 */
		TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
	}

	/* DAC通道1配置 */
	{
		DAC_InitTypeDef DAC_InitStructure;
		
		/* 使能DAC时钟 */
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);		

		DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
		DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
		DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
		//DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
		DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
		DAC_Init(DAC_Channel_1, &DAC_InitStructure);
		DAC_Cmd(DAC_Channel_1, ENABLE);
	}

	/* DMA1_Stream5配置 */
	{
		DMA_InitTypeDef DMA_InitStructure;

		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

		/* 配置DMA1 Stream 5 channel 7用于DAC1 */
		DMA_InitStructure.DMA_Channel = DMA_Channel_7;
		DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&DAC->DHR12R1; 
		DMA_InitStructure.DMA_Memory0BaseAddr = _BufAddr;	
		DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;		
		DMA_InitStructure.DMA_BufferSize = _Count;
		DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
		DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
		DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
		DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
		DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;								//循环模式
		DMA_InitStructure.DMA_Priority = DMA_Priority_High;
		DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
		DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
		DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
		DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
		DMA_Init(DMA1_Stream5, &DMA_InitStructure);
		DMA_Cmd(DMA1_Stream5, ENABLE);

		/* 使能DAC通道1的DMA */
		DAC_DMACmd(DAC_Channel_1, ENABLE);
	}

	/* 使能定时器 */
	TIM_Cmd(TIM6, ENABLE);
}

通过这个函数可以方便的计算DAC的输出波形频率。 计算方法如下:

输出波形频率 = 配置的定时器触发频率 / DMA的缓冲个数 。

其中,DMA缓冲数据的个数就是输出波形一个周期的采样点数。程序中统一将其配置为128个点代表一个周期的波形。实际应用中,配置的点数不要太少, 否则波形不够漂亮。

比如,我们需要输出 10KHz的波形,这个函数的配置就是:

dac1_InitForDMA((uint32_t)&g_Wave1,128, 10000 * 128)

数组g_Wave1里面是128个波形采样点。通过修改触发频率来实现波形频率。

关于这个驱动代码,要注意TIM6的配置。F4的定时器从TIM1到TIM14的主频如下:

/*
 
********************************************************************************
 
system_stm32f4xx.c 文件中 voidSetSysClock(void) 函数对时钟的配置如下:

HCLK = SYSCLK / 1     (AHB1Periph)
 
PCLK2 = HCLK / 2      (APB2Periph)
 
PCLK1 = HCLK / 4      (APB1Periph)
 
因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock/ 2;
 
因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 =SystemCoreClock;
 
APB1 定时器有 TIM2, TIM3,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14
 
APB2 定时器有 TIM1, TIM8,TIM9, TIM10, TIM11
 
TIM 更新周期是 = TIMCLK / (TIM_Period + 1)/(TIM_Prescaler+ 1)
********************************************************************************
*/

由此可知,TIM6的主频是SystemCoreClock / 2。当主频是168MHz时,TIM6的时钟就是84MHz,TIM6更新周期 = TIM6CLK / (TIM_Period + 1)/(TIM_Prescaler+ 1),其中

TIM_Period就是定时器结构体成员TIM_TimeBaseStructure.TIM_Period。

TIM_Prescaler就是定时器结构体成员TIM_TimeBaseStructure.TIM_Prescaler。

另外还有非常重要的一点,TIM6是16位定时器,这两个参范围是0-65535,切不要超过65535。正是因为这个原因,程序中对不同的输出频率做了范围区分。

3. 正弦波输出配置:

/*
*********************************************************************************************************
*	函 数 名: dac1_SetSinWave
*	功能说明: DAC1输出正弦波
*	形    参: _vpp : 幅度 0-4095;
*			  _freq : 频率
*	返 回 值: 无
*********************************************************************************************************
*/
void dac1_SetSinWave(uint16_t _vpp, uint32_t _freq)
{	
	uint32_t i;
	uint32_t dac;
	
	TIM_Cmd(TIM6, DISABLE);
		
	/* 调整正弦波幅度 */		
	for (i = 0; i < 128; i++)
	{
		dac = (g_SineWave128[i] * _vpp) / 4095;
		if (dac > 4095)
		{
			dac = 4095;	
		}
		g_Wave1[i] = dac;
	}
	
	dac1_InitForDMA((uint32_t)&g_Wave1, 128, _freq * 128);
}

正弦波输出128个采样点代表一个周期,同时程序里面增加了一个幅值设置功能,范围0到4095。实际DAC输出的波形频率由前面第2步函数 dac1_InitForDMA实现。比如我们要实现频率10KHz,幅值4095正弦波,那么配置就是:dac1_SetSinWave(4095, 10000)

生成正弦波数据表

要输出正弦波,实质是要控制 DAC 以 v=sin(t)的正弦函数关系输出电压,其中 v 为电压输出,t 为时间。 而由于模拟信号连续而数字信号是离散的,所以使用 DAC 产生正弦波时,只能按一定时间间隔输出正弦曲线上的点,在该时间段内输出相同的电压值,若缩短时间间隔,提高单个周期内的输出点数,可以得到逼近连续正弦波的图形,见下图 37-3,若在外部电路加上适当的电容滤波,可得到更完美的图形。
在这里插入图片描述
由于正弦曲线是周期函数,所以只需要得到单个周期内的数据后按周期重复即可,而单个周期内取样输出的点数又是有限的,所以为了得到呈 v=sin(t)函数关系电压值的数据通常不会实时计算获取,而是预先计算好函数单个周期内的电压数据表,并且转化成以 DAC 寄存器表示的值。 如 sin 函数值的范围为[-1: +1],而 STM32 的 DAC 输出电压范围为[0~3.3]V,按 12 位 DAC 分辨率表示的方法,可写入寄存器的最大值为 212 = 4096,即范围为[0:4096]。所以,实际输出时,会进行如下处理:

  1. 抬升 sin 函数的输出为正值:v = sin(t)+1 ,此时,v 的输出范围为[0:2];
  2. 扩展输出至 DAC 的全电压范围: v = 3.3*(sin(t)+1)/2 ,此时,v 的输出范围为[0:3.3], 正是 DAC 的电压输出范围,扩展至全电压范围可以充分利用 DAC 的分辨率;
  3. 把电压值以 DAC 寄存器的形式表示:Reg_val = 212/3.3 * v = 211*(sin(t)+1),此时,存储到 DAC 寄存器的值范围为[0:4096];
  4. 实践证明,在 sin(t)的单个周期内,取 32 个点进行电压输出已经能较好地还原正弦波形,所以在 t∈[0:2π]区间内等间距根据上述 Reg_val 公式运算得到 32 个寄存器值,即可得到正弦波表;
  5. 控制 DAC 输出时,每隔一段相同的时间从上述正弦波表中取出一个新数据进行输出,即可输出正弦波。改变间隔时间的单位长度,可以改变正弦波曲线的周期。

生成的正弦波数据表:

/*  正弦波数据,12bit,1个周期128个点, 0-4095之间变化 */
const uint16_t g_SineWave128[] = {
	2047 ,  2147 ,	2248 ,	2347 ,	2446 ,	2544 ,	2641 ,	2737 ,
	2830 ,  2922 ,	3012 ,	3099 ,	3184 ,	3266 ,	3346 ,	3422 ,
	3494 ,  3564 ,	3629 ,	3691 ,	3749 ,	3803 ,	3852 ,	3897 ,
	3938 ,	3974 ,	4006 ,	4033 ,	4055 ,	4072 ,	4084 ,	4092 ,
	4094 ,	4092 ,	4084 ,	4072 ,	4055 ,	4033 ,	4006 ,	3974 ,
	3938 ,	3897 ,	3852 ,	3803 ,	3749 ,	3691 ,	3629 ,	3564 ,
	3494 ,	3422 ,	3346 ,	3266 ,	3184 ,	3099 ,	3012 ,	2922 ,
	2830 ,	2737 ,	2641 ,	2544 ,	2446 ,	2347 ,	2248 ,	2147 ,
	2047 ,	1947 ,	1846 ,	1747 ,	1648 ,	1550 ,	1453 ,	1357 ,
	1264 ,	1172 ,	1082 ,	995  ,	910  ,	828  ,	748  ,	672  ,
	600  ,	530  ,	465  ,	403  ,	345  ,	291  ,	242  ,	197  ,
	156  ,	120  ,	88   ,	61   ,	39   ,	22   ,	10   ,	2    ,
	0    ,	2    ,	10   ,	22   ,	39   ,	61   ,	88   ,	120  ,
	156  ,	197  ,	242  ,	291  ,	345  ,	403  ,  465  ,	530  ,
	600  ,	672  ,	748  ,	828  ,	910  ,	995  ,	1082 ,	1172 ,
	1264 ,	1357 ,	1453 ,	1550 ,	1648 ,	1747 ,	1846 ,	1947
};

4. 方波输出配置:

/*
*********************************************************************************************************
*	函 数 名: dac1_SetRectWave
*	功能说明: DAC1输出方波
*	形    参: _low  : 低电平时DAC, 
*			  _high : 高电平时DAC
*			  _freq : 频率 Hz
*			  _duty : 占空比 2% - 98%, 调节步数 1%
*	返 回 值: 无
*********************************************************************************************************
*/
void dac1_SetRectWave(uint16_t _low, uint16_t _high, uint32_t _freq, uint16_t _duty)
{	
	uint16_t i;
	TIM_Cmd(TIM6, DISABLE);
	
	for (i = 0; i < (_duty * 128) / 100; i++)
	{
		g_Wave1[i] = _high;
	}
	for (; i < 128; i++)
	{
		g_Wave1[i] = _low;
	}
	
	dac1_InitForDMA((uint32_t)&g_Wave1, 128, _freq * 128);
}

方波也是输出128个采样点代表一个周期,同时支持幅值和占空比的配置,其中占空比可以配置2%到98%,直接填数值2到98就可以了。实际DAC输出的波形频率由前面第2步函数dac1_InitForDMA实现。比如我们要实现频率10KHz,幅值4095,占空比50%的方波,那么配置就是:dac1_SetRectWave(0, 4095, 10000, 50)。

5. 三角波输出配置:

/*
*********************************************************************************************************
*	函 数 名: dac1_SetTriWave
*	功能说明: DAC1输出三角波
*	形    参: _low : 低电平时DAC, 
*			  _high : 高电平时DAC
*			  _freq : 频率 Hz
*			  _duty : 占空比
*	返 回 值: 无
*********************************************************************************************************
*/
void dac1_SetTriWave(uint16_t _low, uint16_t _high, uint32_t _freq, uint16_t _duty)
{	
	uint32_t i;
	uint16_t dac;
	uint16_t m;
	
	TIM_Cmd(TIM6, DISABLE);
		
	/* 构造三角波数组,128个样本,从 _low 到 _high */		
	m = (_duty * 128) / 100;
	
	if (m == 0)
	{
		m = 1;
	}
	
	if (m > 127)
	{
		m = 127;
	}
	for (i = 0; i < m; i++)
	{
		dac = _low + ((_high - _low) * i) / m;
		g_Wave1[i] = dac;
	}
	for (; i < 128; i++)
	{
		dac = _high - ((_high - _low) * (i - m)) / (128 - m);
		g_Wave1[i] = dac;
	}	
	
	dac1_InitForDMA((uint32_t)&g_Wave1, 128, _freq * 128);
}

三角波也是输出128个采样点代表一个周期,同时支持幅值和占空比的配置,其中占空比可以配置0%到100%,不过程序中对0%和100%做了一个特殊处理。实际DAC输出的波形频率由前面第2步函数dac1_InitForDMA实现。比如我们要实现频率10KHz,幅值4095,占空比50%的三角波,那么配置就是:dac1_SetTriWave (0, 4095, 10000, 50)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32 DAC + DMA + TIM 输出正弦波,三角波,方波信号 的相关文章

随机推荐

  • java创建request_java ->HttpServletRequest

    HttpServletRequest HttpServletRequest概述 我们在创建Servlet时会覆盖service 方法 或doGet doPost 这些方法都有两个参数 一个为代表请求的request和代表响应response
  • [JSP暑假实训] 三.MySQL数据库基本操作及Servlet网站连接显示数据库信息

    本系列文章是作者暑假给学生进行实训分享的笔记 主要介绍MyEclipse环境下JSP网站开发 包括JAVA基础 网页布局 数据库基础 Servlet 前端后台数据库交互 DAO等知识 前一篇文章讲解了MyEclipse环境下创建JSP注册表
  • Java锁性能提高(锁升级)机制总结

    锁的使用很难避免 如何尽量提高锁的性能就显得比较重要了 锁偏向 所谓的偏向锁是指在对象实例的Mark Word 说白了就是对象内存中的开头几个字节保留的信息 如果把一个对象序列化后明显可以看见开头的这些信息 为了在线程竞争不激烈的情况下 减
  • 机器学习极好的入门学习视频推荐

    首先说明本人最早看的机器学习视频是吴恩达的机器学习后来发现并不适合我 如果你以前了解过一些算法 不妨看看我以下推荐的视频 对于一点都不了解机器学习的小白 那就更要看我推荐的视频了 当然吴恩达的机器学习也很好 但是相信我 看下面我推荐的视频是
  • wikiextractor 提取维基百科语料报错的解决办法

    我提取维基百科语料的时候 刚开始使用的wikiextractor 后来发现总是报错 于是就没有用了 由于很多人都在问我是怎么提取的 现在把代码公布下 代码不是我写的 是从一个网站找到的 由于太久了 忘记了网站的地址 就没办法贴原网址了 如果
  • 登录验证码由servlet实现

    简单的登录验证码由servlet实现 创建包util 类ImageServlet package util import javax imageio ImageIO import javax servlet ServletException
  • 程序员如何优雅地解决线上问题?

    身为一个程序员 遇到线上问题那都是家常便饭的事儿 如果你在深夜看到一群同事围在一起 他们是在共同探讨什么哲学问题么 非也 他们一定是遇到了线上BUG 线上问题只要影响到了核心业务流程那便是事故 所以一旦事故发生 无论你在约会 还是周末打游戏
  • 练习- Java类和对象之构造方法与对象创建之计算数学中的分数值

    任务描述 本关任务 跟据键盘输入的分子和分母求出该分数的值 其中第一次输入的值为分子的值 第二次输入的值为分母的值 两次的值均为 int 型 任务 跟据键盘输入的分子和分母求出该分数的值 其中第一次输入的值为分子的值 第二次输入的值为分母的
  • C++ map (不影响map结构) 按照 插入顺序排序 (**)

    C map 不影响map结构 按照 插入顺序排序 C 实现的支持插入顺序的高效map 第三方的库 要点 1 Qt 设计的初期 只是一个自成系统的图形框架 它的功能只是为了满足设计 ui之用 虽然后来不断地扩大了使用的范围 使其有向 全功能的
  • centos7 x11vnc配置

    shishi将文件夹放入 opt目录下面 安装x11vnc cd opt x11vnc1 rpm ivh rpm 配置x11vnc cp opt x11vnc1 x11vnc service etc systemd system 文件内容如
  • Fiddler手机抓包

    本文转载自 Fiddler手机抓包 机智的老猫咪 博客园 Fiddler是一款安装在PC上的抓包软件 它不仅可以对pc上的程序进行抓包 也可以对手机上的程序进行抓包 下面说下抓取手机程序的步骤 一 PC端设置 1 PC上Fiddler抓取H
  • 【放苹果】m个苹果放到n个盘子中

    m个相同的苹果 放在n个相同的盘子中 由于相同 使用排列组合的方法不好处理 这里选用递归调用的方式解决问题 8个苹果 放在3个盘子里 8个苹果 放在2个盘子 5个苹果 放在2个盘子 每盘已经放入1个苹果 2个苹果 放在2个盘子里 每盘已经放
  • 设置linux防火墙的的脚本,Linux开启防火墙并设置策略脚本

    bash bash 现有规则全部注销 iptables P INPUT ACCEPT iptables F 全部进入端口禁止 iptables P INPUT DROP 开启ping和snmp iptables A INPUT i lo j
  • uniapp封装promise接口

    uniapp封装promise接口 uni app题拱了uni requet 方法 发起网络请求 首先在根目录里创建一个request文件夹 在里面创建request js文件 在文件里编写发起网络请求的代码 在全局main js中配置 在
  • vue项目使用vue-quill-editor,光标位置控制(已解决)

    查了网上很多资料使用 都没有解决 故记录在此 全局引入 import Vue from vue import VueQuillEditor from vue quill editor require styles import quill
  • [重点]call、apply和bind的区别以及源码解析

    前言 在前端面试中 最常见的面试题 this的指向问题 如何改变this指向 call apply和bind的区别以及源码解析 如果面试官问到this的指向问题 那么你去引导面试官 让他问你如何改变this指向 call apply和bin
  • Wazuh检测反弹shell

    Wazuh通过在agent服务器上执行指定的命令 并收集命令结果 可以在一定程度上发现反弹shell的入侵行为 目前有2中常见的检测方法 一种是通过netstat输出网络连接中的shell进程来识别 另一种是通过ps输出进程信息中的反弹sh
  • 光纤中的多种光学模式芯径_「涨知识」你想知道的光纤常识都在这里了,看不看随你...

    光纤已经成为远距离有线信号传输的主要手段 安装 维护光纤也是弱电人的基本功 光纤中涉及的理论知识 组件和铺设要点都很多 我们在这里作了一些梳理 三种光 不是所有的光都能用于光纤中信号传播 光线中主要使用三种波长的光 850 nm 1300
  • Zotero文献导入到Endnote

    1 2 导入的时候 请选择
  • STM32 DAC + DMA + TIM 输出正弦波,三角波,方波信号

    硬件平台 STM32F4 库类型 标准库 参考 二代示波器教程 第12章 示波器设计 DAC信号发生器的实现 DAC框图如下 通过TIM触发DAC转换 转换完成后通过DMA输出 DMA通道框图 DAC输出阻抗的问题 DAC集成了2个输出缓存