OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6331|回复: 15

DAC输出梯形波

[复制链接]

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
125
金钱
125
注册时间
2016-2-21
在线时间
32 小时
发表于 2016-4-11 12:53:45 | 显示全部楼层 |阅读模式
1金钱
原子哥,各位大神,我想要用TIM+DAC+DMA输出一个梯形波形,总共时长是30min(1800s),上升和下降阶段各是30s,幅值是3V,如下图所示:

目前打算用TIM+DAC+DMA实现,但是DMA里面内存的数组应该怎么写呀?感觉应该不会是要把所有点都写进数组吧,但是我也不知道有啥其他的办法,请各位指点迷津!

最佳答案

查看完整内容[请看2#楼]

道理就是这样, 建立一个数组,定时发送一个点数据,到DA。 提前就要规划数组存储的问题,或者用内部RAM,或者外扩芯片,各有各的处理方法。 如果存储空间不够,只好增大时间间隔, 比如1ms一个点,增大到2ms、5ms,都可以降低对RAM的需求量。 但又会牵扯到曲线精细程度的问题。 所以要规划、核算、再规划、再核算。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

58

主题

6293

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11475
金钱
11475
注册时间
2014-4-1
在线时间
1297 小时
发表于 2016-4-11 12:53:46 | 显示全部楼层
王木土哈哈哈 发表于 2016-4-11 15:49
我现在的困惑是不知道中断那里改怎么处理,新手中断学的迷迷糊糊的。比如我现在打算使用定时器每隔1ms产 ...


道理就是这样,
建立一个数组,定时发送一个点数据,到DA。

提前就要规划数组存储的问题,或者用内部RAM,或者外扩芯片,各有各的处理方法。

如果存储空间不够,只好增大时间间隔,
比如1ms一个点,增大到2ms、5ms,都可以降低对RAM的需求量。
但又会牵扯到曲线精细程度的问题。
所以要规划、核算、再规划、再核算。

回复

使用道具 举报

58

主题

6293

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11475
金钱
11475
注册时间
2014-4-1
在线时间
1297 小时
发表于 2016-4-11 13:59:57 | 显示全部楼层

两段斜线占据多数存储空间,

中间平线可以采用输出一次、然后保持的方式,
或者有限个点,反复DMA。

回复

使用道具 举报

2

主题

686

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
10569
金钱
10569
注册时间
2014-6-12
在线时间
1022 小时
发表于 2016-4-11 14:51:53 | 显示全部楼层
梯形两边算出速率按时间来输出不同的电平,顶部同样用时间来判断输出电平数值。
回复

使用道具 举报

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
125
金钱
125
注册时间
2016-2-21
在线时间
32 小时
 楼主| 发表于 2016-4-11 15:49:51 | 显示全部楼层
xuande 发表于 2016-4-11 13:59
两段斜线占据多数存储空间,

中间平线可以采用输出一次、然后保持的方式,

我现在的困惑是不知道中断那里改怎么处理,新手中断学的迷迷糊糊的。比如我现在打算使用定时器每隔1ms产生一个中断触发DMA,DMA发送一个数据给DAC输出,以上升阶段的30s为例,这样的话我就需要在DMA内存中输入一个30*1000的数组(实在是太多了),这个应该不是正确的做法吧?但是我又不大清楚应该怎么做
回复

使用道具 举报

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
125
金钱
125
注册时间
2016-2-21
在线时间
32 小时
 楼主| 发表于 2016-4-11 15:53:43 | 显示全部楼层
xuyaqi 发表于 2016-4-11 14:51
梯形两边算出速率按时间来输出不同的电平,顶部同样用时间来判断输出电平数值。

梯形两边的速率是知道的,时间我打算1ms进一次中断,但是产生中断之后DMA的内存空间里我是应该设置内存地址自增,然后内存里面存y=k*t(t每次加1ms)吗?
回复

使用道具 举报

2

主题

686

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
10569
金钱
10569
注册时间
2014-6-12
在线时间
1022 小时
发表于 2016-4-11 18:03:41 | 显示全部楼层
只要你有算法用不着存数组,中断来时算一下该输出啥电平直接输出不用预先存起来。
回复

使用道具 举报

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
125
金钱
125
注册时间
2016-2-21
在线时间
32 小时
 楼主| 发表于 2016-4-11 20:01:32 | 显示全部楼层
xuande 发表于 2016-4-11 17:02
道理就是这样,
建立一个数组,定时发送一个点数据,到DA。

我觉得差不多也是这个意思,谢啦
回复

使用道具 举报

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
125
金钱
125
注册时间
2016-2-21
在线时间
32 小时
 楼主| 发表于 2016-4-11 20:04:43 | 显示全部楼层
xuyaqi 发表于 2016-4-11 18:03
只要你有算法用不着存数组,中断来时算一下该输出啥电平直接输出不用预先存起来。

其实这一段斜线的算法应该很简单的吧,y=k*t这种形式的,但是如果不先存好数据而是直接输出的话应该怎么做呢?我是用DMA从内存发送数据到DA,内存里预先存好数据,这个方法不大好,你说的直接输出大概是要如何实现呢?
回复

使用道具 举报

58

主题

6293

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11475
金钱
11475
注册时间
2014-4-1
在线时间
1297 小时
发表于 2016-4-11 20:36:37 | 显示全部楼层

斜线有斜率的要求。


回复

使用道具 举报

2

主题

686

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
10569
金钱
10569
注册时间
2014-6-12
在线时间
1022 小时
发表于 2016-4-11 21:27:19 | 显示全部楼层
王木土哈哈哈 发表于 2016-4-11 20:04
其实这一段斜线的算法应该很简单的吧,y=k*t这种形式的,但是如果不先存好数据而是直接输出的话应该怎么 ...

这个不需要DMA,你算好后直接放到DAC数据保持寄存器就可以输出了。
回复

使用道具 举报

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
125
金钱
125
注册时间
2016-2-21
在线时间
32 小时
 楼主| 发表于 2016-4-11 21:45:47 | 显示全部楼层
xuyaqi 发表于 2016-4-11 21:27
这个不需要DMA,你算好后直接放到DAC数据保持寄存器就可以输出了。

我明白了,谢啦!
回复

使用道具 举报

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
125
金钱
125
注册时间
2016-2-21
在线时间
32 小时
 楼主| 发表于 2016-4-13 14:23:55 | 显示全部楼层
xuande 发表于 2016-4-11 12:53
道理就是这样,
建立一个数组,定时发送一个点数据,到DA。

大神,我用TIM+DAC+DMA写这个程序,编译的没问题,但是示波器上没有信号,同样的程序架构,我输出周期的正弦波和方波都有波形输出,这个梯形波我用了一个60000的数组,每隔30ms进一次中断,发送一个数据,总共发送60000个数据,1800s,但是示波器检测不到信号,代码如下:能帮我看看吗?

#include "dac.h"
#include "sys.h"
#include "math.h"

#define DAC_DHR12R1  0x40007420 //DAC通道1输出寄存器地址

/********生成梯形波形输出表***********/
void Fade_Data( u16 cycle ,u16 *D )
{
        u16 i;
        for( i=0;i<cycle;i++)
        {
                if(i<(cycle/60))  D= (u16)((Vref*60/cycle*i)*4095/3.3);
                else if(i>(cycle/60)&&i<(cycle*59/60)) D= (u16)(Vref*4095/3.3);
                else if (i>(cycle*59/60)&&i<cycle) D = (u16)((60*Vref-60*Vref/cycle*i)*4095/3.3);
        }
}
  u16 Fade_Value[N];

static void DAC_Config(void)//使能DAC时钟,初始化GPIO
{
                GPIO_InitTypeDef GPIO_InitStruct;
                DAC_InitTypeDef   DAC_InitStruct;
               
                RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
                RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);
               
                GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AN;//模拟输入
                GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4;
                GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;
                GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化GPIO
               
                DAC_InitStruct.DAC_OutputBuffer=DAC_OutputBuffer_Disable;//不使用DAC输出缓存
                DAC_InitStruct.DAC_Trigger=DAC_Trigger_T2_TRGO;//使用定时器2作为触发源
                DAC_InitStruct.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生器
                DAC_Init(DAC_Channel_1,&DAC_InitStruct);//初始化DAC1
               
                DAC_Cmd(DAC_Channel_1,ENABLE);//使能DAC通道1
               
                DAC_DMACmd(DAC_Channel_1,ENABLE);//使能DAC的DMA请求
}

static void DAC_TIM_Config(void)//配置定时器
{
                TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
               
                RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
               
                TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
                TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
                TIM_TimeBaseInitStruct.TIM_Period=299;//自动重装载值299,定时周期300
                TIM_TimeBaseInitStruct.TIM_Prescaler=8399;//预分频,分频84M/(8399+1)=10kHz
                TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);//定时器初始化配置
               
                TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_Update);//配置TIM2触发源
               
                TIM_Cmd(TIM2,ENABLE);//使能TIM2时钟

}

static void DAC_DMA_Config(void)//配置DMA
{
                DMA_InitTypeDef DMA_InitStruct;
                RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
               
                DMA_InitStruct.DMA_BufferSize=32;//缓存大小为32字节
                DMA_InitStruct.DMA_Channel=DMA_Channel_7;//DMA通道4
                DMA_InitStruct.DMA_DIR=DMA_DIR_MemoryToPeripheral;//方向为存储器到外设
                DMA_InitStruct.DMA_FIFOMode=DMA_FIFOMode_Disable;//关闭双缓冲模式
                DMA_InitStruct.DMA_Memory0BaseAddr=(uint32_t)Fade_Value;//存储器数据地址Fade_Value
                DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_Word;//存储器数据以字为单位
                DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable;//存储器地址自增
                DMA_InitStruct.DMA_Mode=DMA_Mode_Normal;//DMA正常模式
                DMA_InitStruct.DMA_PeripheralBaseAddr=DAC_DHR12R1;//外设地址基地址
                DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Word;//外设数据单位
                DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设地址不自增
                DMA_InitStruct.DMA_Priority=DMA_Priority_High;//高DMA通道优先级
                DMA_InitStruct.DMA_FIFOThreshold=DMA_FIFOThreshold_Full;
                DMA_InitStruct.DMA_MemoryBurst=DMA_MemoryBurst_Single;
                DMA_InitStruct.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
                DMA_Init(DMA1_Stream5,&DMA_InitStruct);//初始化DMA1-5
               
                DMA_Cmd(DMA1_Stream5,ENABLE);//使能DMA数据流5

}
void MYDAC_Init(void)
{               
                Fade_Data( N ,Fade_Value);
                DAC_Config();
                DAC_TIM_Config();
                DAC_DMA_Config();
       

}



回复

使用道具 举报

58

主题

6293

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11475
金钱
11475
注册时间
2014-4-1
在线时间
1297 小时
发表于 2016-4-13 15:32:25 | 显示全部楼层

同样的程序架构,我输出周期的正弦波和方波都有波形输出
难道只是输出表的问题?

没有信号,是指测到0?

回复

使用道具 举报

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
125
金钱
125
注册时间
2016-2-21
在线时间
32 小时
 楼主| 发表于 2016-4-13 16:47:10 | 显示全部楼层
xuande 发表于 2016-4-13 15:32
同样的程序架构,我输出周期的正弦波和方波都有波形输出
难道只是输出表的问题?

示波器提示 通道1检测到未知信号
好像是我存储数据的函数有问题。。。另外,DMA可传输60000个数据,DAC的寄存器可以接受这么多数据吗?
回复

使用道具 举报

58

主题

6293

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11475
金钱
11475
注册时间
2014-4-1
在线时间
1297 小时
发表于 2016-4-13 17:12:18 | 显示全部楼层
王木土哈哈哈 发表于 2016-4-13 16:47
示波器提示 通道1检测到未知信号
好像是我存储数据的函数有问题。。。另外,DMA可传输60000个数据,DAC ...


DMA受定时器触发,
在下次触发前,必须保证DAC已经把前一个值输出。

所以,和数据多少无关。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 22:20

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表