搜索
bottom↓
回复: 30

[原创] 用GD32做了个迷你DDS信号发生器

[复制链接]

出0入362汤圆

发表于 2022-6-21 23:58:25 | 显示全部楼层 |阅读模式
本帖最后由 tomzbj 于 2022-6-22 10:43 编辑

大约10年前, 某次看到一个用AVR做的DDS信号源, 记得作者是Jasper Hansen, 感觉挺不错.
搜了一下, 链接居然还在:
http://www.radanpro.com/Radan2400/mikrokontroleri/Jesper's%20AVR%20pages%20-%20MiniDDS.htm

大概的原理:
用单片机的一组8位GPIO搭成R-2R DAC
建立一个256点的正弦波形表
执行这个累加器循环, 就可以输出任意频率的正弦波了.
  1. void cloop(uint16_t step)
  2. {
  3.     registeruint16_t counter = 0;
  4.     while(1){
  5.        counter += step;
  6.        PORTC = waveform[counter >> 8];
  7.     }
  8.     return;
  9. }
复制代码

这个循环大概需要11个时钟周期, 用20M主频的ATTiny2313可以做到的最高DDS时钟是是20M/11=1.82MHz左右, 最高输出频率要再除以2, 不到0.91MHz. 把这个循环写成汇编的话可以优化到7个时钟周期, 最高能输出1.43MHz左右.
缺点么, 也很明显, CPU占用率是100%, 完全干不了别的了, 想加个屏幕加个按键什么的, 基本不可能.
从那之后我陆续用AVR和STM32各做了几次, STM32虽然比AVR快得多, 但在这个场合也没有太大优势, 循环体需要12个时钟周期, 72M的STM32F103也只能做到6M的DDS时钟.
某天突然想到, GD32F30x/F3x0能超频到280MHz, 用来做DDS岂不是很有优势? 最好不要用死循环的形式, 这样可以把屏幕按键都加上了.
先试试GPIO输出到底能有多快, 在开发板上用DMA按M2M方式直接写GPIO, 实测可以做到大约6.5个时钟周期更新一次, 果然不错. 不过更新周期不确定, 大概是因为DMA用M2M方式需要竞争总线, 能不能抢到要看运气. 看来得另想办法.
先画个小板, 原理图如下, GD32F350G8U6的PA0-PA7接成R2R DAC, 用高速运放GS8092缓冲输出(输出端忘了串50欧电阻了). 电荷泵SGM3204用于给运放提供负压. 此外就是128*32的OLED屏和两个按键, 没了.
支持国货, 除了不重要的AMS1117-3.3, 其他都是国产.


这个累加器循环怎么改呢? 先用定时器中断试试, 在中断服务程序里更新DAC. 结果呢, 不太理想, 中断服务程序需要37个时钟周期, 如果还要屏幕/按键/串口能响应,即使超频到240M,DDS时钟只能做到240M/50=4.8M左右, 不太实用.

另一个办法就是用DMA了, 用定时器触发DMA写GPIOA, 在DMA的半满和全满中断里重写波形数据表. 实测了一下, 刷新半张表也就是128个点, 需要1000个时钟周期多点, 这样可以做到每10个时钟周期输出一次, 同样超频240M, 可以做到24M的DDS时钟.

不过实测发现剩余200多个时钟周期不太够, 处理串口屏幕按键还是卡顿, 怎么办呢? 把中断这里的循环展开试试, 再测, 只需要700多个时钟周期, 这次操作比较流畅了.

操作么, 就俩按键, 短按上键切换输出幅度, 长按上键切换波形, 短按下键切换频率(可以预设4个频率), 长按下键进入设置菜单.

实测输出2M/3.58M/7.023M的频谱, 还可以吧? 7M时能看到右边17M的镜像峰了, sunzx给了个好办法, 后面缓冲级用自带6阶10M LPF的视频放大器即可.


原理图及程序见github链接:
https://github.com/tomzbj/diy/tree/master/2022/gd32_dds

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入362汤圆

 楼主| 发表于 2022-6-22 00:00:16 | 显示全部楼层
操作视频

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出3670入191汤圆

发表于 2022-6-22 00:07:07 来自手机 | 显示全部楼层
本帖最后由 Rabbitoose 于 2022-6-22 00:22 编辑

所以说你的工作经常要用到信号发生器吗?我一直想买一个信号发生器但是一直没有认真了解过。

以前翻帖子就看到过R2R,这次趁机学习一下

出330入1925汤圆

发表于 2022-6-22 01:30:13 | 显示全部楼层
这是超了2.6倍吗。。有点狠啊。。不过24M的话很有诱惑力了,差不多五百块机器的频率了

出0入362汤圆

 楼主| 发表于 2022-6-22 09:42:18 | 显示全部楼层
cne53102 发表于 2022-6-22 01:30
这是超了2.6倍吗。。有点狠啊。。不过24M的话很有诱惑力了,差不多五百块机器的频率了 ...
(引用自4楼)

以前测试的极限, GD32F350, F303, FFPR都是336M左右, 不太稳定, 280M就很稳了.
GD32F103可以超到192M.
GD32F450ZET6可以超到400M.

见我的测试 https://github.com/tomzbj/dhrystone_score

上面这几个, 除了F450, 超频后性能基本都是STC8的100倍以上, 价格也就是10元上下, 真不知道STC那伙人有什么好吹的

出30入54汤圆

发表于 2022-6-22 10:00:01 | 显示全部楼层
GD的flash是有一块SRAM模拟区的,这一点确实非常有利于超频

出0入1209汤圆

发表于 2022-6-22 10:03:24 | 显示全部楼层
tomzbj 发表于 2022-6-22 09:42
以前测试的极限, GD32F350, F303, FFPR都是336M左右, 不太稳定, 280M就很稳了.
GD32F103可以超到192M.
GD ...
(引用自5楼)

都是国货,人家有大火炉加持,你这个没有。

出0入362汤圆

 楼主| 发表于 2022-6-22 10:05:31 | 显示全部楼层
cne53102 发表于 2022-6-22 01:30
这是超了2.6倍吗。。有点狠啊。。不过24M的话很有诱惑力了,差不多五百块机器的频率了 ...
(引用自4楼)

DDS时钟24M, 实际输出频率能到10M左右吧... 不加LPF的话, 频谱看着还好, 用示波器看波形已经很杂乱了.

出0入42汤圆

发表于 2022-6-22 10:36:17 | 显示全部楼层
楼主位第一个链接需要爱国吗?我点开就是404

出0入362汤圆

 楼主| 发表于 2022-6-22 10:43:44 | 显示全部楼层
liyang121316 发表于 2022-6-22 10:36
楼主位第一个链接需要爱国吗?我点开就是404
(引用自9楼)

奇怪, 我再粘贴一个

http://www.radanpro.com/Radan2400/mikrokontroleri/Jesper's%20AVR%20pages%20-%20MiniDDS.htm

出0入362汤圆

 楼主| 发表于 2022-6-22 10:44:27 | 显示全部楼层
tomzbj 发表于 2022-6-22 10:43
奇怪, 我再粘贴一个

http://www.radanpro.com/Radan2400/mikrokontroleri/Jesper's%20AVR%20pages%20-%2 ...
(引用自10楼)

点开不行, 复制粘贴到地址栏可以...是老莫的bug么

出0入0汤圆

发表于 2022-6-22 10:47:12 | 显示全部楼层
网址没错, 应该是论坛的问题, 帖子外连断在 ' 符号, 可以手动复制去看

出10入12汤圆

发表于 2022-6-22 11:57:35 | 显示全部楼层
用DMA是最好的  竞争总线的问题如何解决或者降低影响呢

出0入4汤圆

发表于 2022-6-22 12:03:20 | 显示全部楼层
用FSMC来实现会不会快很多?

出0入362汤圆

 楼主| 发表于 2022-6-22 12:07:10 | 显示全部楼层
wowangru 发表于 2022-6-22 11:57
用DMA是最好的  竞争总线的问题如何解决或者降低影响呢
(引用自13楼)

不用M2M呗
其实是移花接木了一下, 用TIMER触发DMA写DAC, 但是没有真的写到DAC, 而是写到了GPIOA
不然没法实现用TIMER触发写GPIO

GD32本身的DAC虽然比STM32快, 但和GPIO+R2R比还是太慢了

出0入362汤圆

 楼主| 发表于 2022-6-22 12:08:01 | 显示全部楼层
pspice 发表于 2022-6-22 12:03
用FSMC来实现会不会快很多?
(引用自14楼)

FSMC应该也是6个周期输出一次吧? 我忘了
关键是重写查找表,  这个时间没法省

出10入12汤圆

发表于 2022-6-22 12:44:30 | 显示全部楼层
tomzbj 发表于 2022-6-22 12:07
不用M2M呗
其实是移花接木了一下, 用TIMER触发DMA写DAC, 但是没有真的写到DAC, 而是写到了GPIOA
不然没法 ...
(引用自15楼)

我就是用的APB2的tim1触发 DMA输出GPIO   但是也不是很稳定, IO时间精度不稳定

        DMA_InitTypeDef  DMA_InitStructure;   
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2ʱÖÓʹÄÜ
        DMA_DeInit(DMA2_Stream5);
        while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE){}
        DMA_InitStructure.DMA_Channel = DMA_Channel_6;
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(GPIOC->ODR);
        DMA_InitStructure.DMA_Memory0BaseAddr = (u32)g_EXC_DATA;
        DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
        DMA_InitStructure.DMA_BufferSize = POINT_NUM2;
        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_VeryHigh;
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//
        DMA_Init(DMA2_Stream5, &DMA_InitStructure);//³õʼ»¯DMA Stream
        DMA_Cmd(DMA2_Stream5, ENABLE);

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
        TIM_TimeBaseInitStructure.TIM_Period=6;   //
        TIM_TimeBaseInitStructure.TIM_Prescaler=1;
        TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
        TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);
        TIM_DMACmd(TIM1,TIM_DMA_Update,ENABLE);
  TIM_Cmd(TIM1, ENABLE);

出0入0汤圆

发表于 2022-6-22 15:07:20 | 显示全部楼层
正弦波的最大输出频率是不是DDS时钟除以256?

出0入362汤圆

 楼主| 发表于 2022-6-22 15:35:37 | 显示全部楼层
koon 发表于 2022-6-22 15:07
正弦波的最大输出频率是不是DDS时钟除以256?
(引用自18楼)

不是, DDS时钟除以2
不过这时波形基本没法看了

出0入0汤圆

发表于 2022-6-22 16:44:23 | 显示全部楼层
tomzbj 发表于 2022-6-22 15:35
不是, DDS时钟除以2
不过这时波形基本没法看了
(引用自19楼)

DDS时钟除以2,又没有滤波网络,这不是方波吗,这个正弦波不是256个点吗

出20入25汤圆

发表于 2022-6-22 16:53:57 | 显示全部楼层
tomzbj 发表于 2022-6-22 12:07
不用M2M呗
其实是移花接木了一下, 用TIMER触发DMA写DAC, 但是没有真的写到DAC, 而是写到了GPIOA
不然没法 ...
(引用自15楼)

那不还是存在DMA竞争总线吗

出0入0汤圆

发表于 2022-6-22 17:10:41 | 显示全部楼层
楼主厉害耶 thank you

出0入362汤圆

 楼主| 发表于 2022-6-22 19:03:49 来自手机 | 显示全部楼层
chenchaoting 发表于 2022-6-22 16:53
那不还是存在DMA竞争总线吗
(引用自21楼)

m2m的总线利用率低啊

不是m2m的话,别把总线全占完就行,输出频率是准的

出0入0汤圆

发表于 2022-6-22 19:48:46 来自手机 | 显示全部楼层
直接十块钱dds芯片不香?

出0入362汤圆

 楼主| 发表于 2022-6-22 19:52:43 | 显示全部楼层
NJ8888 发表于 2022-6-22 19:48
直接十块钱dds芯片不香?
(引用自24楼)

AD9833? 现在10元也只能买拆机件了吧, 新的起码30+了吧...
不知道有没有国内厂家克隆?

出0入362汤圆

 楼主| 发表于 2022-6-22 20:02:06 | 显示全部楼层
koon 发表于 2022-6-22 16:44
DDS时钟除以2,又没有滤波网络,这不是方波吗,这个正弦波不是256个点吗
(引用自20楼)

是啊, 不能刚好到2, 得稍微低点.
你看7M多的频谱不是还可以么, 右边17M的镜像也好办, 弄个12M左右的LPF就滤掉了.
用MS1651之类的视频放大器, 内置10M的6阶LPF, 刚合适.

出40入45汤圆

发表于 2022-6-22 20:02:58 | 显示全部楼层
koon 发表于 2022-6-22 16:44
DDS时钟除以2,又没有滤波网络,这不是方波吗,这个正弦波不是256个点吗
(引用自20楼)

三角波,就波峰波谷两个点

出0入0汤圆

发表于 2022-6-23 02:17:28 | 显示全部楼层
还是用FPGA来做最好。

出0入8汤圆

发表于 2022-6-23 18:26:11 | 显示全部楼层
厉害,膜拜一下

出0入0汤圆

发表于 2022-6-27 09:31:01 | 显示全部楼层
lyl520719 发表于 2022-6-23 02:17
还是用FPGA来做最好。
(引用自28楼)

有个国产DAC模块就是FPGA外加R2R电阻网络来实现的;

出0入4汤圆

发表于 2022-6-27 18:15:29 | 显示全部楼层
打不开 github了,以前在早上这个时间段还可以打开的。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-16 16:57

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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