详解CKS32F4xx系列DAC功能
eetrendMcu 2023-11-29

DAC模块作为CKS32F4xx系列的一个常用外设,可以将数字信号转换成模拟信号,最高分辨率可达12位,且两个独立DAC输出通道转换互不影响,各个通道均能使用DMA功能,可由软硬件触发。因此,为了实现DAC输出正弦波,拟采用一定的时间向DAC的数据寄存器写入数据,随后进行数模转换输出不同的电压,最后在时间轴上显示出波形。同时为了不占用CPU资源,配置DMA建立传输通道,以便数据快速的从内存搬移到外设。且在DAC初始化时,可以设置成定时器触发,待定时器溢出就会触发DAC工作,所以只要修改定时器的定时时间,就可改变正弦波周期。

DAC简述

1.png

①:DAC将VREF+引脚作为参考电压,在实际使用时将VSSA接地,同时把VREF+和VDDA接3.3V,DAC即可获得0~3.3V的输出电压。

②:数模转换器以VREF+作为参考电源,将DAC的数据寄存器“DORx”的数字编码转换成模拟信号并由右侧的“DAC_OUTx”通道输出。在CKS32有2个这样的DAC部件,其中PA4对应通道1,PA5对应通道2。

③:控制逻辑可以控制数据寄存器“DORx”加入一些伪噪声信号或配置产生三角波信号。

④:使用DAC时,数据会被先写入到DHRx寄存器,随后DAC会根据触发配置进行处理,最后将数据传输至DORx。DAC的触发源有三种,分别为:外部中断源触发、定时器触发和软件控制触发。

对于单DAC通道x的三种数据格式

8位数据右对齐:

用户须将数据写入寄存器DAC_DHR8Rx[7:0]位(实际是存入寄存器DHRx[11:4]位)。

12位数据左对齐:

用户须将数据写入寄存器DAC_DHR12Lx[15:4]位(实际是存入寄存器DHRx[11:0]位)。

12位数据右对齐:

用户须将数据写入寄存器DAC_DHR12Rx[11:0]位(实际是存入寄存器DHRx[11:0]位)。

数字输入经过DAC被线性地转换为模拟电压输出,任一DAC通道引脚上的输出电压满足下面的关系:

本案例中选择DAC的通道1,并采用12位的右对齐方式,通过查阅《CKS32F4xx参考手册》DAC和DMA章节可知,DAC1对应DMA1控制器通道7数据流5。

总的来说,DAC的输出是由DORx寄存器直接控制的,而用户写的数据是要写入DHRx寄存器,然后通过DHRx间接操作DORx,最终实现DAC的输出。

DAC输出正弦波配置

本文采用DAC1+TIM2+DMA1的方式,通过TIM2触发DAC1转换,转换完成后通过DMA1输出,主要步骤如下:

①由Matlab计算一个周期的正弦波数组;

②根据一个正弦波周期内点数和所需正弦波频率确定定时器触发间隔;

③初始化DAC1输出管脚和工作模式;

④配置触发DAC1用的定时器2;

⑤配置DMA1自主搬运正弦波数组。

待上述配置完成后,将PA4引脚接到示波器上,即可显示正弦波。以下是DAC的详细配置。

(1)正弦波数组生成

以下代码用于生成正弦波波形表:

for(i=0;i<100;i++) { Sine12bit[i]=2048*sin(1.0*i/(100- 1)*2*PI)+2048; }

从上述函数可以看出,正弦波的幅度被控制在0~4096之间,一个周期被平均分成100份,即100个点代表一个周期的波形,数组Sine12bit里面是100个采样点。

const uint16_t Sine12bit[100] = {

0x0800,0x0881,0x0901,0x0980,0x09FD,0x0A79,0x0AF2,0x0B68,0x0BDA,0x0C49,0x0CB3,0x0D19,0x0D79,0x0DD4,0x0E29,0x0E78,0x0EC0,0x0F02,0x0F3C,0x0F6F,0x0F9B,0x0FBF,0x0FDB,0x0FEF,0x0FFB,0x0FFF,0x0FFB,0x0FEF,0x0FDB,0x0FBF,0x0F9B,0x0F6F,0x0F3C,0x0F02,0x0EC0,0x0E78,0x0E29,0x0DD4,0x0D79,0x0D19,0x0CB3,0x0C49,0x0BDA,0x0B68,0x0AF2,0x0A79,0x09FD,0x0980,0x0901,0x0881,0x0800,0x077F,0x06FF,0x0680,0x0603,0x0587,0x050E,0x0498,0x0426,0x03B7,0x034D,0x02E7,0x0287,0x022C,0x01D7,0x0188,0x0140,0x00FE,0x00C4,0x0091,0x0065,0x0041,0x0025,0x0011,0x0005,0x0001,0x0005,0x0011,0x0025,0x0041,0x0065,0x0091,0x00C4,0x00FE,0x0140,0x0188,0x01D7,0x022C,0x0287,0x02E7,0x034D,0x03B7,0x0426,0x0498,0x050E,0x0587,0x0603,0x0680,0x06FF,0x077F};

(2)GPIO和DAC模式配置

该部分为输出引脚配置和DAC通道1配置,代码如下:

void DAC1_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    DAC_InitTypeDef DAC_InitStructure;
    /*  Enable GPIOA clock  */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);/*  Enable DAC clock  */RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);/*  Configure the DAC Pin to Analog mode: DAC_OUT1 -- PA4  */GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_PuPd= GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Speed= GPIO_Speed_100MHz;  
    GPIO_InitStructure.GPIO_OType= GPIO_OType_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    /*  Configure DAC Channel_1  */
    DAC_InitStructure.DAC_Trigger= DAC_Trigger_T2_TRGO;
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;DAC_Init(DAC_Channel_1, &DAC_InitStructure);
    DAC_Cmd(DAC_Channel_1, ENABLE);//Enable DAC Channel_1.
    DAC_DMACmd(DAC_Channel_1, ENABLE);//Enable DAC channel_1 DMA request.
}

在DAC1_GPIO_Init函数中,实现了相应GPIO引脚(PA4)的初始化和DAC工作模式配置。其中为了避免寄生的干扰和额外的功耗,应将PA4引脚设置成模拟输入模式(AIN),如此方可正常工作。

而对DAC工作模式进行配置时,可查看CKS官方提供的DAC_InitTypeDef结构体,该结构体中主要包含了DAC_CR寄存器的各寄存器配置。如下是DAC_InitTypeDef结构体成员简述:

(a)DAC_Trigger

该成员用于DAC的触发模式配置,由上文DAC通道框图可知,共有三种触发模式,分别是定时器触发(DAC_Trigger_T2/4/5/6/7/8_TRGO)、软件触发(DAC_Trigger_Software)和EXTI_9触发方式(DAC_Trigger_Ext_IT9)。

(b)DAC_WaveGeneration

该成员可配置输出伪噪声和三角波输出(DAC_WaveGeneration_Noise/Triangle),若使用自定义输出,应配置为DAC_WaveGeneration_None。

(c)DAC_OutputBuffer

该成员用于控制是否使能DAC的输出缓冲(DAC_OutputBuffer_Enable/Disable)。若需要直接驱动外部负载,可以使能该成员以减小输出阻抗。

(d)DAC_LFSRUnmask_TriangleAmplitude

该成员通过控制DAC_CR的MAMP2位设置LFSR寄存器位的数据,即当使用伪噪声或三角波输出时要叠加到DHRx的值。若使用伪噪声输出时LFSR=0xAAA,这时该结构体成员可赋值为DAC_LFSRUnmask_Bit0~DAC_LFSRUnmask_Bit11_0;若使用三角波输出时,这时该结构体成员可赋值为DAC_TriangleAmplitude_1~DAC_TriangleAmplitude_4096,可用于设置三角波的最大幅值。

本例中,将DAC通道1配置成定时器TIM2触发,不使用波形发生器和不使用输出缓存,不使用输出缓存是因为CKS32的DAC无需外部运放就可以直接驱动负载,三角波振幅一项虽然本案例没有用到,可以配置成任意,但此项不可缺,最后调用DAC_Cmd、DAC_DMACmd函数使能DAC通道1和DMA的请求。

(3)定时器配置

该部分是配置触发DAC的定时器TIM2,通过设定触发的间隔,从而间接控制正弦波周期,TIM2的工作决定DMA与DAC的工作频率,代码如下:

void TIM2_Init(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    /*  Enable Timer2 clock.  */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);/*  Configure Timer2 --Clock Frequency is 84MHz  */
    TIM_TimeBaseStructure.TIM_Period=83; TIM_TimeBaseStructure.TIM_Prescaler= 0x0;       
    TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;    
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  /*  Configure the trigger source for Timer2.  */TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
    TIM_Cmd(TIM2, ENABLE);//Enable Timer2.
}

前文的DAC已选用TIM2当触发源,此处TIM2的定时周期被配置为83,向上计数,不分频。CKS32F4xx系列的主频是168MHz,TIM2的时钟是84MHz,所以TIM2的更新频率是84M/(TIM_Period+1)/(TIM_Prescaler+1),即TIM2每隔1us触发一次DAC事件,不需要设置中断,当定时器向上计数至指定值时,产生Update事件,同时触发DAC把DHRx寄存器的数据转移到DORx,开始进行转换。由于正弦波数组是100个采样点,可得正弦波的输出频率为:

(4)DMA配置

该部分主要完成数据的传输,代码如下:

void DMA_InitForDAC(void)
{
    DMA_InitTypeDef  DMA_InitStructure;
    /*  Enable DMA1 clock.  */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);/*  Configure DMA1 Stream5 Channel_7 For DAC1  */
    DMA_InitStructure.DMA_Channel = DMA_Channel_7;  DMA_InitStructure.DMA_PeripheralBaseAdDMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Sine12bit ;DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_BufferSize = 100;
    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_MemoryDataSize_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); //Enable DMA1 Stream5.
}

需要注意的是,DAC->DHR12R1对应数据寄存器的地址,正弦波数组Sine12bit对应数据输入地址,DMA缓存的个数是单个正弦波周期对应的点数,DMA需工作在循环模式,由于正弦波数组Sine12bit定义为16位,那么涉及数据传输的变量都要配置成半字16位。经过上述的配置后,定时器TIM2每隔1us就会触发DMA搬运正弦波数组的一个数据到DAC通道1寄存器进行转换,每搬运100个数据即一个完整周期后,DMA开始循环,最终循环输出正弦波。

(5)主函数配置

本例程主函数主要对前文所述函数依次调用,程序编译下载至开发板,使用示波器测量PA4引脚即可查看输出10kHz的正弦波形,代码如下:

int main(void)   
{
    DAC1_GPIO_Init();
    TIM2_Init();
    DMA_InitForDAC();
    while (1);
}


声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 对话周祖成教授 - 清华大学与西门子EDA的合作之旅


  • 相关技术文库
  • 模拟
  • 模电
  • 运放
  • 放大
  • 信号继电器有哪些作用?

    继电器是一种电控制器件,在很多电路中都有继电器的使用。为增进大家对继电器的认识,本文将对继电器的原理、作用,以及信号继电器的分类予以介绍。如果你对继电器、信号继电器具有兴趣,不妨和小编一起继续往下阅...

    昨天
  • 电容界的强强联手:电解与薄膜的完美搭配

    电容是常用电子器件之一,针对不同用途,市场上推出了各式电容。为增进大家对电容的了解,本文将对电解电容和薄膜电容的搭配问题予以介绍。如果你对电容相关知识具有兴趣,不妨继续往下阅读哦。 在一个电器...

    昨天
  • IMX386揭秘:让您的照片跃出屏幕,惊艳世界!

    IMX386是一个对角线6.294毫米(1/2.86型)12兆像素CMOS有源像素型叠加型图像传感器与方形像素阵列。采用Exmor RS技术实现高速图像采集。通过柱状并行A/D转换电路和高灵敏度低噪声图像(与传统CMOS图像传感器相比),...

    昨天
  • 收藏!19个常用的5V转3.3V技巧

    必看的19个5V转3.3V技巧

    昨天
  • 低端运放电流检测方法

    低端运放电流检测方法分析下原理:运用运放的虚短特性,既得到了:V+ = V-; 运用运放的虚断特性,既

    昨天
  • 解锁电子世界的秘密武器:揭秘运算放大器的魔力

    什么是运算放大器?运算放大器是具有很高放大倍数的电路单元,具有带载能力强、低输出电阻特点。运算放大器的种类繁多,应用非常广泛。接下来简单给大家介绍一下运算放大器的应用及种类。 运算放大器的应用 1.电流源...

    昨天
  • 运算放大器端口名称

    基本简介运算放大器(简称"运放")是具有很高放大倍数的电路单元。在实际电路中,通常结合反馈网络共同组成某种功能模块。它是一种带有特殊耦合电路及反馈的放大器。其输出信号可以是输入信号加、减或微分、积分等数...

    昨天
  • 揭秘阻抗的魔力:如何用它释放电子信号的全部潜力

    输入阻抗跟一个普通的电抗元件没什么两样,它反映了对电流阻碍作用的大小。对于电压驱动的电路,输入阻抗越大,则对电压源的负载就越轻,因而就越容易驱动,也不会对信号源有影响;而对于电流驱动型的电路,输入阻抗...

    昨天
  • 运算放大器的大变身:从反向到同向,随心放大!

    运算放大器(OPAMP) 2 虚短和虚断 3 反向放大器 3.1 典型电路 3.2 放大倍数 3.3 仿真结果 4 同向放大器 4.1 双电源 4.2 双电源同向放大器仿真结果 4.3 单电源 4.4 双电源同向放大器仿真结果 5 总结 1 运算放大器(OPA...

    昨天
  • 运算放大器的神秘公式:用虚短虚断

    “虚短”是指在分析运算放大器处于线性状态时,可把两输入端视为等电位,这一特性称为虚假短路,简称虚短。显然不能将两输入端真正短路。 “虚断”是指在分析运放处于线性状态时,可以把两输入端视为等效开路,这一特性...

    昨天
  • 揭秘AD运输的秘密藏宝图:原理图库大揭秘!

    1、这里我们新建一个.sch(原理图)的文件,双击打开,如图所示。 2、进入后,单击“Add/Remove”选项,按键位置,如图所示。 3、开启后,如图所示,我们把界面保留在此,打开我们刚刚下载好的那个软件。 4、软件打...

    昨天
  • 七大运放应用电路设计(附运放的应用要点)

    运放的基本分析方法:虚断,虚短。对于不熟悉的运放应用电路,就使用该基本分析方法。

    昨天
下载排行榜
更多
评测报告
更多
广告