Sub Procedure Write_Reg(dim pDat as Word)
'====================================================================================================
C_S = 1
Spi_Write(pDat)
Spi_Write (pDat >>8)
C_S = 0
Delay_ms(20)
End Sub
Ik zou denken dat C_S (FSYNC) laag moet zijn tijdens een SPI transfer.
Ik heb het omgedraaid:
'====================================================================================================
Sub Procedure Write_Reg(dim pDat as Word)
'====================================================================================================
C_S = 0
Spi_Write(pDat)
Spi_Write (pDat >>8)
C_S = 1
Delay_ms(20)
End Sub
De AD9833 lijkt er wel op te reageren. De uitkomst is echter wat onvoorspelbaar. Er komt af en toe na spanning er op zetten een blokgolf uit van 286,4 hz.
Maar het reageert niet op het commando voor andere outputvorm. Ook de frequentie instellen levert rare dingen op.
Na de eerste Spi_Write() aanroep even een bitje ergens in een register monitoren dat aangeeft dat de data volledig verstuurd is. En dan pas de volge de aanroep naar Spi_Write() doen. Of wacht Spi_Write() zelf totdat de actie klaar is (blokkerende functie)?
Kijk ook naar de timing, er is vast een prescaler te configureren die de snelheid van je Spi peripheral bepaalt. Kijk ook goed naar op welke flank van de klok de data overgenomen wordt door de AD9833, en zorg dat je MCU overeenkomstig geconfigureerd is.
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Heb je niks aan dit project: https://libstock.mikroe.com/projects/view/1865/driving-dds-ad9833-boar…
Dit was inderdaad wel een goede tip van Arco! 
Het programma uit de link oogde wat rommelig, met veel uitgeschakelde instructies, alternatieven, etc.
Bovendien was het voor een PIC16F690, die heb ik niet.
Daarom heb ik het maar omgezet naar mijn vertrouwde PIC16F1847 en de zaak wat vereenvoudigd.
En warempel het werkt na die aanpassingen ook nog!
Dit werd het voor even:
Program SPI_v14
dim Control_reg as word ' 16 bits
' D15-D14=00 -> change of Control-reg
' D13=1 : 28 bits sended in 2 writes in Freq_x registers
' D13=0 : 14 bits sended MSB or LSB (D12)
' D12=1/0 : MSB / LSB of Freq_x (D11)
' D11=1/0 : Freq_1/0 register
' D10=1/0 : Phase_1/0 register
' D9=0 : reserved
' D8=1 : Reset device
' D7=1 : Sleep1 MCLK disabled
' D6=1 : Sleep12 powerdown DAC
' D5=1 : OPBITEN ... MSB or MSB/2 bit pass (D3)
' D4=0 : reserved
' D3=1 : DIV2 (MSB or MSB/2)
' D2=0 : reserved
' D1=1 : MODE (with D5) SIN or TRIANGLE output
' !!! D1=0 if D5=1
' D0=0 : reserved
dim f_sortie, freq, Freq0, Freq1 as longword
' 2 Write with Control_reg D13=1 (28 bits)
' D15=0 D14=1 then Freq0 + 14 register bits
' D15=1 D14=0 then Freq1 + 14 register bits
Dim Phase0, Phase1 as word
' D15=1 D14=1 D13=0 D12=x then Phase0 + 12 register bits
' D15=1 D14=1 D13=1 D12=x then Phase1 + 12 register bits
' Definitions for SPI pins
dim Chip_Select as sbit at LATB.3
CS_MCP as sbit at LATB.0
SoftSpi_CLK as sbit at LATB.4
'SoftSpi_SDI as sbit at LATB.1
SoftSpi_SDO as sbit at LATB.2
dim Chip_Select_Direction as sbit at LATB.3
CS_MCP_Direction as sbit at LATB.0
SoftSpi_CLK_Direction as sbit at LATB.4
'SoftSpi_SDI_Direction as sbit at LATB.1
SoftSpi_SDO_Direction as sbit at LATB.2
sub procedure InitMain()
SoftSpi_CLK_direction = 0
'SoftSpi_SDI_direction = 1
SoftSpi_SDO_direction = 0
Chip_Select_Direction = 0 ' Set CS# pin as Output
Chip_select = 1 ' FSINK = 1
delay_us(100)
end sub
sub procedure SPI_Out(dim SPI_dat as word)
dim temp, i as byte
SoftSPI_CLK = 1 ' SoftSPI_SDO = 0
Chip_Select = 0 ' Select AD9833 FSYNC = 0 ...
SoftSPI_SDO = SPI_DAT.15 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.14 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.13 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.12 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.11 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.10 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.9 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.8 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.7 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.6 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.5 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.4 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.3 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.2 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.1 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_SDO = SPI_DAT.0 SoftSPI_CLK = 0 SoftSPI_CLK = 1
SoftSPI_CLK = 1
Chip_Select = 1
delay_us(10)
end sub
sub procedure Send_freq (dim freq as longword)
dim temp_MSB, temp_LSB as word
freq = freq and 0x0FFFFFFF '28 bits effective
temp_LSB = loword(freq) ' LSB 14 bits
temp_LSB.15=0 temp_LSB.14=1 ' freq0
SPI_Out(temp_LSB)
temp_MSB = hiword(freq * 4) div 4 ' MSB .. 2 bits to right
temp_MSB.15=0 temp_MSB.14=1 ' freq0
SPI_Out(temp_MSB)
end sub
main:
ANSELA = %00000000 'All Port A Digital
ANSELB = %00000000 'All Port B Digital
TRISA = %00100000 'Port A.5 input (MCLR)
TRISB = %00000000 'All Poert B Output
OSCCON = %01110000 '8Mhz internal
InitMain()
Control_reg=0x2100 ' B28=1 28 bits, D8 RESET ON, D11=0 Freq0
SPI_Out (Control_reg)
f_sortie = 500
freq0 = f_sortie * 10.73741824
Send_freq(freq0)
Phase0 = 0xC000
SPI_Out (phase0)
Control_reg=0x2002 ' B28=1 28 bits, D8 RESET Off, D11=0 Freq0
SPI_Out (Control_reg)
While True Wend
end.
Maar ik wil natuurlijk wel uitzoeken waarom dit nu wel werkt en die van mij niet. Ze gebruiken hier overigens een Soft_SPI.
Ik heb voor het gemak de pinnen aangehouden voor de ingebouwde SPI van de 1847.
Ik wist alleen niet wat ik met de SoftSpi_SDI aan moest. Ik heb hem maar op de SDI Pin (B.1) gezet, maar volgens mij doet dat niks. Ik heb van die SDI instructie dan ook maar commentaar gemaakt.
En het blijft gewoon werken.
De pinnen dedinitie:
dim C_S as sbit at LATB.3
SoftSpi_CLK as sbit at LATB.4
SoftSpi_SDO as sbit at LATB.2
Maar die 'Direction declaratie daaronder' hoeft toch niet persé?
'dim C_S_Direction as sbit at LATB.3
' SoftSpi_CLK_Direction as sbit at LATB.4
' SoftSpi_SDO_Direction as sbit at LATB.2
Zonder dit werkt het gewoon..
Het ziet er al wat appetijtelijker uit, nietwaar?
'====================================================================================================
Program SPI_v14
'Device: AD9833 Wave generator
' SDO (D1): LATB.2 SDATA Pin 8
' SCK (D0): LATB.4 SCLK Pin 10
' C_S LATB.3 FSYNC Pin 9
'====================================================================================================
Const Freq_Out As LongWord = 1000
Dim Control_reg As word ' 16 bits
' D15-D14=00 -> change of Control-reg
' D13=1 : 28 bits sended in 2 writes in Freq_x registers
' D13=0 : 14 bits sended MSB or LSB (D12)
' D12=1/0 : MSB / LSB of Freq_x (D11)
' D11=1/0 : Freq_1/0 register
' D10=1/0 : Phase_1/0 register
' D9=0 : reserved
' D8=1 : Reset device
' D7=1 : Sleep1 MCLK disabled
' D6=1 : Sleep12 powerdown DAC
' D5=1 : OPBITEN ... MSB or MSB/2 bit pass (D3)
' D4=0 : reserved
' D3=1 : DIV2 (MSB or MSB/2)
' D2=0 : reserved
' D1=1 : MODE (with D5) SIN or TRIANGLE output
' !!! D1=0 if D5=1
' D0=0 : reserved
Freq As Longword
Freq0 As Word
Freq1 As Word
Phase0 As word
Phase1 As Word
C_S As sbit At LATB.3
SoftSpi_CLK As sbit At LATB.4
SoftSpi_SDO As sbit At LATB.2
'====================================================================================================
Sub procedure SPI_Out(dim SPI_dat As word)
'====================================================================================================
Dim i1 As Byte
SoftSPI_CLK = 1
C_S = 0
For i1 = 15 to 0 step -1
SoftSPI_SDO = SPI_DAT.i1
SoftSPI_CLK = 0 Delay_us(1)
SoftSPI_CLK = 1 Delay_us(1)
next i1
C_S = 1
Delay_us(10)
End sub
'====================================================================================================
Sub Procedure Send_freq (dim freq as longword)
'====================================================================================================
dim temp_MSB, temp_LSB as word
freq = freq and 0x0FFFFFFF '28 bits effective
temp_LSB = loword(freq) 'LSB 14 bits
temp_LSB.15=0
temp_LSB.14=1
SPI_Out(temp_LSB) 'freq0
temp_MSB = hiword(freq * 4) div 4 'MSB .. 2 bits to right
temp_MSB.15=0
temp_MSB.14=1
SPI_Out(temp_MSB) 'freq0
end sub
Main:
ANSELA = %00000000 'All Port A Digital
ANSELB = %00000000 'All Port B Digital
TRISA = %00100000 'Port A.5 input (MCLR)
TRISB = %00000000 'All Poert B Output
OSCCON = %01110000 '8Mhz internal
C_S = 1 'FSYNC = 1
Delay_Ms(1)
SPI_Out (0x2100)
Freq0 = Freq_Out * 10.73741824
Send_freq(freq0)
SPI_Out (0xC000)
SPI_Out (0x2028) 'WaveForm Triangle
While True Wend 'Dummy endless loop
end.
het zou fijn zijn als ik mijn frequentiemetertje er aan kan hangen.
De output van de AD9833 is echter laag, zo'n 0,3 V komt er uit.
Te weinig voor mijn TTL-Schmitt-triggertje, dus moet ik het signaal iets versterken.
Ik heb een schakelingetje gezien waarbij er een OpAmp MCP601 wordt gebruikt.
Ik heb hier echter alleen een LM833 en een paar UA741. Die zijn meer bedoeld voor audio wat ik er van begrijp.
Maar om te testen zou het kunnen. Het zou wel fijn zijn als ik iets vind dat geen + en - voeding nodig heeft, maar gewoon werkt op 5V.
Is zo'n versterkertje ook met torren te maken? Het inputsignaal is wel heel klein..
Hier gaat nog iets niet goed met de formule.
Tot Freq_Out = 1525 gaat het helemaal goed.
Elke waarde daarboven geeft rare resultaten..
Edit: Ik ben er al uit.
Voor het schrijven van de MSB moet je beginnen met de ontbrekende bits die zijn weg gesloopt omdat bit 14 en 15 worden gebruikt voor het adres van het register freq0.

Const Freq_Out As LongWord = 1525
---
---
'====================================================================================================
Sub Procedure Send_freq (dim freq as longword)
'====================================================================================================
dim temp_MSB, temp_LSB as word
freq = freq and 0x0FFFFFFF '28 bits effective
temp_LSB = loword(freq) 'LSB 14 bits
temp_LSB.15=0
temp_LSB.14=1
SPI_Out(temp_LSB) 'freq0
temp_MSB = hiword(freq * 4) div 4 'MSB .. 2 bits to right
temp_MSB.15=0
temp_MSB.14=1
SPI_Out(temp_MSB) 'freq0
end sub
[Bericht gewijzigd door Bavelt op (17%)]
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
temp_MSB = hiword(freq * 4) div 4
is een (wat omslachtige) manier om de hoogste bits '0' te maken...
Da's sowieso overbodig, want dat heeft de regel
freq = freq and 0x0FFFFFFF al gedaan.
temp_MSB = hiword(freq)
zou moeten voldoen.
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Volgens mij verlies je dan bit 14 en 15 van het frequentiewoord.
Je moet de 28 bits frequentiewoord schrijven als
01<bit0...13>
10<bit14...27>
hiword zal neem ik aan bit 16...bit31 pakken.
Freq*4 schoffelt bit 14 en 15 naar bit 16 en 17 (en alles daarboven schuift ook op. En dan is "highword" een efficiente manier om de 14 freqbits + 2 nulletjes bij mekaar te schoffelen.
Ik zelf zou schrijven:
#define AD_FREQLO 0x4000
#define AD_FREQHI 0x8000
spi_out (((freqword >> 0) & 0x3fff) | AD_FREQLO);
spi_out (((freqword >> 14) & 0x3fff) | AD_FREQHI);
De compiler zoekt maar uit hoe ie dat efficient doet. Merk op dat ik de & 0x0fffffff overbodig maak door 2x met de 14 gewenste bits te and-en.
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Of zo:
'====================================================================================================
Sub Procedure Send_freq (dim freq as longword)
'====================================================================================================
freq = (freq and 0x7FFF7FFF) or 0x40004000 '28 bits effective
SPI_Out(hiword(freq)) 'freq0
SPI_Out(loword(freq)) 'freq0
end sub
Nee, dat klopt niet.
Dat komt omdat bit 14 en 15 van de Lo(freq) worden weggepoetst en vervangen door 14 = 1, 15 = 0. (= adres freq0 register)
Je mist dan dus 2 bits van de LSB die moeten verschuiven naar de MSB.
Dat gebeurt dan door
temp_MSB = Hiword(freq <<2) 'Shift 2 left because of bit 14/15 of LSB was ignored
Rest nu nog de output van de AD9833 te versterken.
De OpAmp MCP601 is hier niet verkrijgbaar. Wel een NE5534.
Deze ken ik niet, zou die zijn te gebruiken?
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Op dinsdag 24 december 2024 11:31:43 schreef Bavelt:
Dat gebeurt dan door
Precies!
Als die bitjes weg mogen, dan had het
freq = (freq and 0x3FFF3FFF) or 0x80004000
geweest.
Maar die bitjes zijn toch echt wel verdomd handig. Arco houdt wel degelijk 28 bitjes uit het "freq" woord over, maar dat zou freq compleet niet-lineair maken. Vandaar dat het in twee stappen moet.
Die NE5534 is niet bruikbaar. Die moet je met +/- 15V voeden (plus 15 en min 15), en dan is de common mode input range tot 3V uit de voedingsrails.
Neem een MCP6001 en je kan tot in de millivolts bij de voedingen komen. (ik ken de 6001/2/4, de "low power" versie van de 601/2/4).
Ik heb voor mezelf besloten om de -2 te gebruiken. 8 pins, niet heel veel groter dan de 1-opamp versie en 2 zijn niet veel groter dan de -4 versie. Dus niet ontzettend verspillend als je maar 1 of meer dan 2 nodig hebt. En dan maar 1 onderdeel op voorraad. Voor grote series kan je dat dan altijd nog herzien.
P.S. @Bavelt. Schrijf *4 en niet << 2 . De compiler is bekend met "fouten bij shiften van langere datatypes". Ik zou het niet riskeren.
PPS: Mijn AD9833 breakout-printje-uit-china is zojuist gearriveerd.
Op dinsdag 24 december 2024 12:56:54 schreef rew:
P.S. @Bavelt. Schrijf *4 en niet << 2 . De compiler is bekend met "fouten bij shiften van langere datatypes". Ik zou het niet riskeren.
Oh, ik had dat juist gedaan omdat ik dacht dat <<2 een meer natuurlijke bewerking is dan vermenigvuldigen met 4.
.
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Je kunt een 16F1709 of 16F1769 gebruiken, daar zitten 2 rail to rail opamps (OPA's) in...
Of gebruik een van de comparators in de 1847...
[Bericht gewijzigd door Arco op (17%)]
Daar heb ik nog niet eens aan gedacht...
Weer een uitdaging, ik heb nog nooit met de comparators van de 1847 gewerkt...
Ik heb hier ook nog wel een PIC16F1936 liggen, die heeft ook 2 comparators rail-to-rail, maar geen OPA"s zo te zien.
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Comparators gebruik ik heel vaak, o.a. voor audiodetectie (dtmf, tonen,...) en zero-cross detectie.
Er zijn niet zoveel 16F1x pics met OPA's, bij de 24F zie je die veel vaker.
Op dinsdag 24 december 2024 16:22:48 schreef Arco:
Comparators gebruik ik heel vaak, o.a. voor audiodetectie (dtmf, tonen,...) en zero-cross detectie.
Er zijn niet zoveel 16F1x pics met OPA's, bij de 24F zie je die veel vaker.
Is daar nog veel voor nodig om dat toe te passen qua registers?
Vermoedelijk een referentiespanning opgeven aan een van de ingangen, de andere voeden vanaf de output van de AD9833 en als hij de refspanning overstijgt krijg je een logische 1?
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Je kunt de min van de comparator aan Gnd leggen, en het signaal via een condensator aan de plus van de comparator leggen.
(met een hoogohmige pull-down aan de comparator plus (1M of zo) om de juiste offset te hebben.)
Pin op analoog zetten, comparator enablen, en kiezen welke pinnen je wilt gebruiken. (de min van de comparator blijft intern)
De uitgang van de comparator is ook direct intern beschikbaar (met interrupt indien gewenst)
[Bericht gewijzigd door Arco op (12%)]
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
TS wil de ad9833 uitgang maal 10 oid doen, dan moeten alledrie de aansluitingen van de opamp naàr buiten. Afhankelijk van wat voor frequenties je wil doen, kan het zijn dat je een heftige opamp moet nemen. Dan is mcp6002 mogelijk helemaal niet geschikt: die is erg traag.
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Comparators zijn vrij snel: 60nS response bij full-swing. (bij kleine signalen nog een stuk sneller,
En 0.3v input is meer als genoeg, hysteresis is 45mV.
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/