[原创] 用SPI_MOSI输出任意频率方波
本帖最后由 tomzbj 于 2022-6-26 16:20 编辑前两天试了一下用GD32的一组8位GPIO接成R2R DAC做DDS
https://www.amobbs.com/thread-5767262-1-1.html
之后想到如果只需要方波的话, 用SPI的MOSI就可以了. 256字节的波形表不需要了,只需要32字节的输出缓冲区, DMA循环输出, 正好是256比特.
DMA的半满和全满中断改成这样, 循环展开是必须的, 否则实在太慢.
void DS_DMA_FTF(void)
{
for(register int i = 0; i < 16; i++) {
dma_tab = 0;
counter += step;
dma_tab |= ((counter >> 31) << 7);
counter += step;
dma_tab |= ((counter >> 31) << 6);
counter += step;
dma_tab |= ((counter >> 31) << 5);
counter += step;
dma_tab |= ((counter >> 31) << 4);
counter += step;
dma_tab |= ((counter >> 31) << 3);
counter += step;
dma_tab |= ((counter >> 31) << 2);
counter += step;
dma_tab |= ((counter >> 31) << 1);
counter += step;
dma_tab |= ((counter >> 31) << 0);
}
}
void DS_DMA_HTF(void)
{
for(register int i = 0; i < 16; i++) {
dma_tab = 0;
counter += step;
dma_tab |= ((counter >> 31) << 7);
counter += step;
dma_tab |= ((counter >> 31) << 6);
counter += step;
dma_tab |= ((counter >> 31) << 5);
counter += step;
dma_tab |= ((counter >> 31) << 4);
counter += step;
dma_tab |= ((counter >> 31) << 3);
counter += step;
dma_tab |= ((counter >> 31) << 2);
counter += step;
dma_tab |= ((counter >> 31) << 1);
counter += step;
dma_tab |= ((counter >> 31) << 0);
}
}
实测这两个中断子程序需要470个时钟周期左右, SPI时钟用主频的四分频, 128*4=512, 稍微有点紧张, 用8分频就很宽松了.
其他基本不变, 把涉及dac的部分改成spi就完事.
实测在200M左右的GD32上输出几百k的方波, 波形相当稳, 输出几M时就比较抖了.
SPI是单线,要输出DA, 当成PWM用? 跟IO并口比,速度不是慢了很多吗。 huangqi412 发表于 2022-6-26 17:07
SPI是单线,要输出DA, 当成PWM用? 跟IO并口比,速度不是慢了很多吗。
(引用自2楼)
不是pwm, 和dds类似, 关键是可以输出任意频率啊. tomzbj 发表于 2022-6-26 17:13
不是pwm, 和dds类似, 关键是可以输出任意频率啊.
(引用自3楼)
lz 是高手, 看了知乎上的回答,感觉高度很高 DMA全传输完成中断改成
for(i = 16; i < 32; i++)
{
tab = ...;
}
是否能快一点? zrp123 发表于 2022-6-27 08:07
DMA全传输完成中断改成
是否能快一点?
(引用自5楼)
有可能, 不过估计这里编译器已经给优化过了吧
改成汇编470 clock是否会明显减少么 sczh0001 发表于 2022-6-29 13:57
改成汇编470 clock是否会明显减少么
(引用自7楼)
应该差不多到头了, 128个点, 470/128, 一个点只有3.67个时钟周期
每个点要累加, 两次移位, 再位与, 应该是这部分优化到了3个时钟周期, 128*3=384.
再加上循环体两头的load/store, 循环变量累加, 比较, 函数体入栈/出栈, 没多少优化空间了.
页:
[1]