【RPi PICO】DDS正弦发生器和双路PWM输出
<p>来自:https://forum.micropython.org/viewtopic.php?t=9945&p=55587#p55587</p><p> </p>
<p>DDS 的正弦发生器,使用第二个内核生成。为了实现更高的分辨率和更高的频率,它增加了2个PWM信号,每个6位。 </p>
<p> </p>
<pre>
<code class="language-python"># DDS Sine Generator in second core by CWE
# Example using Double PWM
# http://www.openmusiclabs.com/learning/digital/pwm-dac/dual-pwm-circuits/index.html 100k and 1.5k + 4.7nF
import time, _thread, sys
from machine import Pin, PWM
import math
import uarray
# Construct PWM object, with LED on Pin(25).
pwmA = PWM(Pin(15, Pin.OUT)) # upper 6 bits
pwmB = PWM(Pin(14, Pin.OUT)) # low 6 bits
# Set the PWM frequency.
pwmFreq= int(125_000_000/64) # 6 bit
pwmA.freq(pwmFreq)
pwmB.freq(pwmFreq)
pwmA.duty_u16(31<<10)
pwmB.duty_u16(31<<10)
sineBufLen= 6249 #1kHz: 6249
sineBuf=uarray.array("H",range(0,sineBufLen))
for x in range(0,sineBufLen):
xr= x/sineBufLen*2*math.pi
sineBuf= 2047+int(2047*math.sin(xr)) # 12 bit resolution
#print(sineBuf)
pwmA.duty_u16(0<<10)
pwmB.duty_u16(0<<10)
ddsCtrl = uarray.array('i',[
0x40050000 + 0x98, # 0 cc7
sineBufLen, # 4
1, # 8
int((1<<16)*1.0) # 12 1=run, step in half
])
@micropython.asm_thumb
def dds(r0, r1): # Buffer, ctrl-array
mov(r2,r0) # Buffer Start Address
ldr(r5, ) # buffer length
ldr(r4, ) # pwm counter compare register
ldr(r7, ) # step index fine
mov(r3,0) # Buffer Index fine
label(nextVal)
lsr(r0,r3,16) # index coarse
lsl(r0,r0,1) # index coarse half words
add(r0,r0,r2)
ldrh(r0,) # read buffer regPoke(0x40050000 + 0x98, ((a>>6)<<16) + (a&63))
lsl(r6,r0,26) # get the lowest 6 bit
lsr(r0,r0,6) # shift bits right (upper)
lsl(r0,r0,16)
lsr(r6,r6,26) # lower 6 bits
add(r0,r0,r6)
str(r0,)
#b(retu)
add(r3,r3,r7) # next buffer index fine
lsr(r0,r3,16)
cmp(r5,r0) # end not yet reached
bhi(nextVal)
lsl(r0,r5,16)
sub(r3,r3,r0)
mov(r0,r3)
ldr(r7, ) # reload step index repeat?
cmp(r7,0)
bne(nextVal)
label(retu)
@micropython.asm_thumb
def regPeek(r0): # Address
mov(r1,r0)
ldr(r0,)
@micropython.asm_thumb
def regPoke(r0, r1): # Address, Data
str(r1,)
mov(r0,r1)
def regSet(adress, mask):
regPoke(adress, regPeek(adress) | mask)
def setF(f):
ddsCtrl=int(f/1000*(1<<16))
#sineBuf=1<<6
#print(dds(sineBuf, ddsCtrl))
_thread.start_new_thread(dds, (sineBuf, ddsCtrl))
try:
while True:
f=10
while f<25_000:
setF(f)
time.sleep(.2)
print(f, end=" ")
f=f*1.5849 #math.sqrt(10)
except KeyboardInterrupt:
ddsCtrl=0
sys.exit()
"""
x=0
delta=10
while True:
x+= delta
if x>(sineBufLen-1):
x-=sineBufLen
a= sineBuf
#pwmA.duty_u16( (a<<4) & (255<<8)) # upper 6 bit
#pwmB.duty_u16( (a<<10) & (255<<8)) # lower 6 bit
regPoke(0x40050000 + 0x98, ((a>>6)<<16) + (a&63))
#regPoke(0x40050000 + 0x98, ((a>>6)<<16))
"""
</code></pre>
<p> </p>
<p>DDS 的正弦发生器</p>
<p>谢谢分享</p>
<p>没玩,不过点个赞!!!</p>
页:
[1]