【RPi PICO】DDS正弦发生器和双路PWM输出

树莓派 PICO 和 RP2040 相关应用讨论
回复
头像
shaoziyang
帖子: 3917
注册时间: 2019年 10月 21日 13:48

【RPi PICO】DDS正弦发生器和双路PWM输出

#1

帖子 shaoziyang »

https://forum.micropython.org/viewtopic ... 587#p55587

DDS 的正弦发生器,使用第二个内核生成。为了实现更高的分辨率和更高的频率,它增加了2个PWM信号,每个6位。 

代码: 全选

# 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[x]= 2047+int(2047*math.sin(xr)) # 12 bit resolution
    #print(sineBuf[x])

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, [r1,4]) # buffer length
        
    ldr(r4, [r1,0]) # pwm counter compare register
    ldr(r7, [r1,12]) # 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,[r0,0]) # 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,[r4,0])
    #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, [r1,12]) # reload step index repeat?
    cmp(r7,0)
    bne(nextVal)
    
    label(retu)

    


@micropython.asm_thumb
def regPeek(r0): # Address
    mov(r1,r0)
    ldr(r0,[r1,0])

@micropython.asm_thumb
def regPoke(r0, r1): # Address, Data
    str(r1,[r0,0])
    mov(r0,r1)
    
def regSet(adress, mask):
    regPoke(adress, regPeek(adress) | mask)

def setF(f):
    ddsCtrl[3]=int(f/1000*(1<<16))

#sineBuf[0]=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[3]=0
    sys.exit()

   
"""
x=0
delta=10


while True:
    x+= delta
    if x>(sineBufLen-1):
        x-=sineBufLen
    a= sineBuf[x]
    #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)) 
 """  


回复

  • 随机主题
    回复总数
    阅读次数
    最新文章