你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32 dds

[复制链接]
gujiamao 发布时间:2015-5-3 10:39
本帖最后由 gujiamao 于 2015-5-3 10:41 编辑 & k, w, n9 ~& W- Y& ?) C  \

: K2 o6 d/ H1 H+ d* b/ c
( v% V" P! Q2 S1 w4 Q
最近要用到正弦波,就用STM32内部的DAC产生。' R$ p0 d3 M! B+ b" k0 \
思路主要有以下三个:8 E: ?5 z: u! j  O
1.用matlab或者excel产生一个N长度的正弦码表,如果要产生频率为f的正弦波,则每隔fclk / (N * f)个定时器中断给DAC的数据寄存器赋值一次(fclk是定时器中断频率);# m2 j: X, g  M9 g: G* L2 U
2.根据定时器频率fclk和信号频率f计算出一个周期内点的个数N = fclk / f,动态生成正弦码表,则每个定时器中断给DAC的数据寄存器赋值一次;1 R9 [$ f+ l6 Z* ^% r+ A
先总结下,思路1和思路2的方法差不多,在频率的范围上,f = fclk / (N * M)(M是多少个中断赋值DAC),思路2的M为1,频率范围应该更大些;
% \$ G  O. z6 f0 N& c; P% U# y& k+ i                                                       在波形的美观上,思路1更好些,因为频率大的时候,2中的点数会少,导致波形中高频能量比较大;
' o( B; @. k7 g' ~7 c7 g" v但是,都是时钟的分频,比如说fclk / 8, fclk / 16,两者之间的频率是肯定产生不了的。
4 C5 |5 z" m( g& v, V8 O9 s以上的方法都不尽如人意。5 ?4 @% a7 l% }
想到在学校里参加电子设计比赛时,用过AD9850产生过正弦波,为何不用DDS的原理实现呢?5 h% t3 [8 Y5 b8 V; r
1.高速dac; 2.正弦码表;3.相位累加器;4.低通滤波器,STM32都有,试一试呗。. v5 }6 d6 l; I4 g6 k+ B- k, h% D% K7 j
) _: c) w" S/ N, s
3.DDS的方法:以下是个人的理解,不知道对不对。sin(ΔΦ) = sin(w*t) = sin(2*pi*f*Ts),其中f是要得的信号频率,Ts = 1 / fclk, fclk是定时器中断频率,相位Φ就是ΔΦ的不断累积。
7 D; ^& e8 _: L8 s程序里是这么做的,当串口输入f时,计算出delta_phase_temp = 2.0 * f / fclk,显然这是一个浮点数,总不能在中断内部计算浮点数吧,听同事说有一个Q15的数据格式,将浮点数
/ I$ m- X/ P9 _3 [" ]转化成short类型的方法,网上查了下,发现STM32的DSP库里有这样的东西,能够快速计算出某相位的正弦值(下面会介绍),接下来把delta_phase_temp 转换成Q15格式,
/ y4 B' P! d8 N9 {. v- pdelta_phase = float_to_Q15(delta_phase_temp),这样基本工作就OK了,接下来打开定时器中断,写中断服务程序,主要就是相位累加和计算出给DAC赋值的数字量,: k+ k! R2 p* S3 M0 t" m8 y; ~  o- d
phase +=  delta_phase,相位累加够简单吧,给DAC赋值的数字量就是此相位对应的正弦值啦,这就用到了CMSIS的DSP库里面的东东了,第一次接触,感慨,聪明人真的太多了,) @5 o" L% j& p2 J& w$ ]2 a
Q15的格式不说了,避免浮点运算,选用查表法,自己怎么想不出来呢。' \8 D* N5 b1 O' l
下面的函数就是把Q15格式的theta算成Q15格式的正弦值,函数我就不分析了,论坛里大大们一看就懂。: Q( D3 ^4 l1 L- x' t' I; n
void arm_sin_q15(q15_t theta, q15_t* pSinVal)* \* d( [9 q& H, F
{% H6 U. R) N+ v* l" C
        q15_t x0;
/ U+ E; S$ B8 n4 e: m* u+ ~+ E7 P        q15_t y0,y1;* s' }* a) G/ T/ y9 W
        q15_t xSpacing = 0xB6;& }( K, s) ^& p. {: I+ K7 o8 r1 F
        unsigned int i = 0;
0 U. _  h+ k. R" r& r        q15_t oneByXSpacing;
7 w8 o9 `1 p; t7 l$ |9 S+ p        q15_t out;$ R4 B4 ^" W- d1 c  c
        unsigned int sign_bits;
* `$ k# I' E3 h        short firstX = 0x8000;
; g( b+ j0 j3 X) t4 M        i = (unsigned int)(theta - firstX) / (unsigned int)xSpacing;. f% |0 |( n1 z1 k8 d
        if(i < 0){
$ u5 p. k9 U' x: Z) e4 I$ A- H- g                i = 0;$ v7 ~( O/ O) q3 Y8 d3 y4 G( a
        }
1 P" ^' Y* {) P' G: P( F        else if(i >= 358){
9 F$ K! ]- r0 v$ ]/ c                i = 358;1 A1 j2 M1 e" W
        }3 z& E% Z% v% W" J7 O! R4 |
        x0 = (q15_t)firstX + ((q15_t)i * xSpacing);
5 ?; q) P3 `% d2 t# E9 e        y0 = SinTabQ15;
* h3 t5 G) V! B0 J. B) F        y1 = SinTabQ15[i + 1u];- O, \9 n" a8 S  B
        sign_bits = 8u;
7 y1 v: _3 N9 }( X% q; G9 o* j        oneByXSpacing = 0x5A00;( g  d7 `; N. K# z
        out =(((q15_t) (((int) (theta - x0) * oneByXSpacing) >> 16)) << sign_bits);
1 B5 |7 ~" ~, H: L        *pSinVal = y0 + ((q15_t) (((int) (y1 - y0) * out) >> 15));
1 S8 `! r/ x" M" {  S" E* l0 M}$ `5 {: F  w0 T. x  H' W
算出Q15格式的正弦值之后,当然还是转成0~1之间的浮点数啦,之后再进行DAC赋值,dac_ch2.write((int)(Q15_to_float(sin) * 4095));- b+ `! M* n) l1 j+ m# w) W/ ^
下午看了下效果还不错,当然没有AD9850产生的波形准而好看了。等去公司了,上点图看看。
6 I' R$ D6 H1 w* T% b相比思路1和2,思路3的明显方法好多了。
: l2 I2 l$ b: j  @8 G, T: _
赞 1 收藏 1 评论2 发布时间:2015-5-3 10:39

举报

2个回答
stary666 回答时间:2015-5-3 15:10:48
沙发,支持原创
moyanming2013 回答时间:2015-5-4 14:11:23
路过看看。。。。。。。
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版