AD9833 met PIC en MikroBasic

Bavelt

Golden Member

Ik ben nu zelf ook aan het spelen met een AD9833.
Ik zag deze post van Arco:

https://www.circuitsonline.net/forum/view/127613#highlight=ad9833

@Arco, het lukte je toen niet het ding aan de praat te krijgen. Is dat inmiddels wel gelukt?

Zo ja, heb je toevallig een voorbeeldje in MikroBasic?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Was achteraf vrij simpel, maar 2 subs... :) (ik gebruikte een PIC24FJ256GA108)


'======================================================================================================================
program test9833
routine/pin declarations
'--------------------------------------------------------------------------------------------------
Dim DDS_FSYNC    As sBit At LATB.13                                 'Pin name configuration

Dim DDS_Value    As LongInt                                         'Divider value for the AD9833

Dim DDS          As Word                                            'DDS ctrl register. Bits used
    DDS_Mode     As sBit At DDS.1                                   'in the AD9833 control register
    DDS_Div2     As sBit At DDS.3                                   '
    DDS_OpBiten  As sBit At DDS.5                                   '
    DDS_Sleep12  As sBit At DDS.6                                   '
    DDS_Sleep1   As sBit At DDS.7                                   '
    DDS_Reset    As sBit At DDS.8                                   '
    DDS_PSelect  As sBit At DDS.10                                  '
    DDS_FSelect  As sBit At DDS.11                                  '
    DDS_HLB      As sBit At DDS.12                                  '
    DDS_B28      As sBit At DDS.13                                  '
    DDS_Freq0    As sBit At DDS.14                                  '
    DDS_Freq1    As sBit At DDS.15                                  '
'--------------------------------------------------------------------------------------------------
' Prototypes for forward references
'--------------------------------------------------------------------------------------------------
Sub Procedure DDS_Init() Forward
Sub Procedure DDS_Set()  Forward

  Spi2_Init_Advanced(_SPI_MASTER,                                   'Init DDS SPI port
                     _SPI_16_BIT,                                   '
                     _SPI_PRESCALE_SEC_8,                           '
                     _SPI_PRESCALE_PRI_64,                          '
                     _SPI_SS_DISABLE,                               '
                     _SPI_DATA_SAMPLE_MIDDLE,                       '
                     _SPI_CLK_IDLE_HIGH,                            '
                     _SPI_IDLE_2_ACTIVE)                            '

'==================================================================================================
Sub Procedure DDS_Init()                                            'Init the DDS chip
'==================================================================================================
  DDS_FSYNC    = 0                                                  'Select DDS chip (spi #1)
  DDS          = 0                                                  'All Flags are '0'
  DDS_Reset = 1                                                     '(except the reset flag)
  Spi2_Write(DDS)                                                   '
  DDS_Reset = 0                                                     '
  Spi2_Write(DDS)                                                   '
  DDS_FSYNC = 1                                                     'Disable chip
End Sub                                                             '

'==================================================================================================
Sub Procedure DDS_Set()                                             'Set value from DDS_Value into the DSS chip
'==================================================================================================
  DDS_FSYNC = 0                                                     'Select DDS chip (spi #1)
  SPI2_Write(0x2000)                                                'Set 2x14bits cmd mode
  SPI2_Write((DDS_Value And 0x00003FFF) Or 0x4000)                  'Low 14 bit word first
  SPI2_Write((DDS_Value >> 14) Or 0x4000)                           'Hi 14 bits
  DDS_FSYNC = 1                                                     '
End Sub                                                             '

'======================================================================================================================
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

DDS_Reset As sBit At DDS.8

DDS is een Word.
Toch vindt de MB-compiler alles boven de .7 "out of range.."

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Nooit geprobeerd (24F is een 16 bit controller), zal eens kijken...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Op maandag 16 december 2024 16:51:38 schreef Arco:
Nooit geprobeerd (24F is een 16 bit controller), zal eens kijken...

Een Word als local variabele is toch onafhankelijk van de controller?

Ik had ook even geprobeerd om die ..24 te kiezen, maar die staat helemaal niet in mijn lijst.

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

De 24F heb je de dsPic (16 bit) compiler voor nodig...
Er is wel verschil: een word in een 16 bits controller bestaat echt, in een 8 bits niet.
(dan moet de compiler 2 bytes aan elkaar 'plakken' en rekenkundig bewerken bij verandering...)

[Bericht gewijzigd door Arco op maandag 16 december 2024 17:18:41 (63%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Op maandag 16 december 2024 17:15:33 schreef Arco:
De 24F heb je de dsPic (16 bit) compiler voor nodig...
Er is wel verschil: een word in een 16 bits controller bestaat echt, in een 8 bits niet.
(dan moet de compiler 2 bytes aan elkaar 'plakken' en rekenkundig bewerken bij verandering...)

Ok. Maar is dat dan op te lossen met een 8-bits controller?
Dat ik DDS in 2 bytes verdeel en dan twee keer schrijven of iets in die geest?

Voor de main: begrijp ik dat het zou volstaan met



DDS_INIT()
DDS_SET()

?

Ik ken dat Forward (nog) niet..

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

De forward declaration gebruik je om de sub/functie vooraf te declareren: Dit is om forward references mogelijk te maken.

Omdat de compiler een one-pass compiler is, moet iedere sub die aangeroepen wordt gedefinieerd zijn voordat die wordt aangeroepen.
(dat kan met forward, of door de subs in de juiste volgorde te zetten.)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Ik liep daar wel eens tegenaan en loste dat dan op door alles in de goede volgorde te zetten.

Alleen lukt het me niet om met een 8-bits zoals de PIC 16F1847 het register van de 9833 zodanig te schrijven dat het goed gaat. DWZ in MikroBasic.

Met een Arduino UNO-sketch lukt het wel. Dat is toch ook een 8-bits geval?

Maar die maakt gebruikt van een AD9833.h. En dan weet ik niet meer wat ik doe.

[Bericht gewijzigd door Bavelt op maandag 16 december 2024 23:41:56 (29%)

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Waarschijnlijk doet die Arduino dat met softwarematige SPI, geen hardware SPI. (dat kan met de PIC ook...)
Softwarematige SPI stelt niet veel voor, zou zoiets moeten zijn (niet getest):
(DDS_CLK, DDS_SYNC, DDS_DATA zijn de te gebruiken pinnen)


'==================================================================================================
Sub Procedure SoftSpi_Write(Dim pVal As Word)
'==================================================================================================
  Dim lCnt As Byte
  DDS_SYNC = 1
  DDS_CLK  = 1
  DDS_SYNC = 0
  For lCnt = 0 to 15
    DDS_DATA = (pVal >> lCnt) And 0x0001 
    DDS_CLK  = 0
    DDS_CLK  = 1
  Next lCnt
  DDS_CLK  = 0
  DDS_SYNC   = 1
End Sub

'==================================================================================================
Sub Procedure DDS_Init()                                            'Init the DDS chip
'==================================================================================================
  DDS_SYNC    = 0                                                  'Select DDS chip (spi #1)
  DDS         = 0                                                  'All Flags are '0'
  DDS_Reset   = 1                                                  '(except the reset flag)
  SoftSpi_Write(DDS)                                               '
  DDS_Reset   = 0                                                  '
  SoftSpi_Write(DDS)                                               '
  DDS_SYNC    = 1                                                  'Disable chip
End Sub                                                            '

'==================================================================================================
Sub Procedure DDS_Set()                                            'Set value from DDS_Value into the DSS chip
'==================================================================================================
  DDS_SYNC = 0                                                     'Select DDS chip (spi #1)
  SoftSpi_Write(0x2000)                                            'Set 2x14bits cmd mode
  SoftSpi_Write((DDS_Value And 0x00003FFF) Or 0x4000)              'Low 14 bit word first
  SoftSpi_Write((DDS_Value >> 14) Or 0x4000)                       'Hi 14 bits
  DDS_SYNC = 1                                                     '
End Sub                                                            '

'======================================================================================================================
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Mijn probleem zit hem niet zozeer in de SPI.
Softwarematige SPI heb ik inderdaad wel eens gebruikt.

De Arduino heeft een hardware matige SPI aan boord begreep ik. (vaste pinnen).

Waar ik mee worstel is om het register van de ADR9833 te schrijven. Dat lukt me niet omdat het 16-bits is en de PIC een 8-bits.
Dat schrijven zal dan in 2 keer moeten.
De Arduino doet dat ook in zijn sketch (o.a. via library AD9833.h).
Maar dat vind ik ondoorgrondelijk hoe ze dat doen.

Het liefst werk ik met het vertrouwde MikroBasic .



/*
 * AD9833.h
 * 
 * Copyright 2016 Bill Williams <wlwilliams1952@gmail.com, github/BillWilliams1952>
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 * 
 * 
 */

#ifndef __AD9833__

#define __AD9833__

#include <Arduino.h>
#include <SPI.h>

//#define FNC_PIN 4			// Define FNC_PIN for fast digital writes

#ifdef FNC_PIN
	// Use digitalWriteFast for a speedup
	#include "digitalWriteFast.h"
	#define WRITE_FNCPIN(Val) digitalWriteFast2(FNC_PIN,(Val))
#else  // otherwise, just use digitalWrite
	#define WRITE_FNCPIN(Val) digitalWrite(FNCpin,(Val))
#endif

#define pow2_28				268435456L	// 2^28 used in frequency word calculation
#define BITS_PER_DEG		11.3777777777778	// 4096 / 360

#define RESET_CMD			0x0100		// Reset enabled (also CMD RESET)
/*		Sleep mode
 * D7	1 = internal clock is disabled
 * D6	1 = put DAC to sleep
 */
#define SLEEP_MODE			0x00C0		// Both DAC and Internal Clock
#define DISABLE_DAC			0x0040
#define	DISABLE_INT_CLK		0x0080

#define PHASE_WRITE_CMD		0xC000		// Setup for Phase write
#define PHASE1_WRITE_REG	0x2000		// Which phase register
#define FREQ0_WRITE_REG		0x4000		// 
#define FREQ1_WRITE_REG		0x8000
#define PHASE1_OUTPUT_REG	0x0400		// Output is based off REG0/REG1
#define FREQ1_OUTPUT_REG	0x0800		// ditto

typedef enum { SINE_WAVE = 0x2000, TRIANGLE_WAVE = 0x2002,
			   SQUARE_WAVE = 0x2028, HALF_SQUARE_WAVE = 0x2020 } WaveformType;
			   
typedef enum { REG0, REG1, SAME_AS_REG0 } Registers;

class AD9833 {

public:
	
	AD9833 ( uint8_t FNCpin, uint32_t referenceFrequency = 25000000UL );

	// Must be the first command after creating the AD9833 object.
	void Begin ( void );

	// Setup and apply a signal. Note that any calls to EnableOut,
	// SleepMode, DisableDAC, or DisableInternalClock remain in effect
	void ApplySignal ( WaveformType waveType, Registers freqReg,
		float frequencyInHz,
		Registers phaseReg = SAME_AS_REG0, float phaseInDeg = 0.0 );

	// Resets internal registers to 0, which corresponds to an output of
	// midscale - digital output at 0. See EnableOutput function
	void Reset ( void );

	// Update just the frequency in REG0 or REG1
	void SetFrequency ( Registers freqReg, float frequency );

	// Increment the selected frequency register by freqIncHz
	void IncrementFrequency ( Registers freqReg, float freqIncHz );

	// Update just the phase in REG0 or REG1
	void SetPhase ( Registers phaseReg, float phaseInDeg );

	// Increment the selected phase register by phaseIncDeg
	void IncrementPhase ( Registers phaseReg, float phaseIncDeg );

	// Set the output waveform for the selected frequency register
	// SINE_WAVE, TRIANGLE_WAVE, SQUARE_WAVE, HALF_SQUARE_WAVE,
	void SetWaveform ( Registers waveFormReg, WaveformType waveType );

	// Output based on the contents of REG0 or REG1
	void SetOutputSource ( Registers freqReg, Registers phaseReg = SAME_AS_REG0 );

	// Turn ON / OFF output using the RESET command.
	void EnableOutput ( bool enable );

	// Enable/disable Sleep mode.  Internal clock and DAC disabled
	void SleepMode ( bool enable );

	// Enable / Disable DAC
	void DisableDAC ( bool enable );

	// Enable / Disable Internal Clock
	void DisableInternalClock ( bool enable );

	// Return actual frequency programmed in register 
	float GetActualProgrammedFrequency ( Registers reg );

	// Return actual phase programmed in register
	float GetActualProgrammedPhase ( Registers reg );

	// Return frequency resolution 
	float GetResolution ( void );

private:

	void 			WriteRegister ( int16_t dat );
	void 			WriteControlRegister ( void );
	uint16_t		waveForm0, waveForm1;
#ifndef FNC_PIN
	uint8_t			FNCpin;
#endif
	uint8_t			outputEnabled, DacDisabled, IntClkDisabled;
	uint32_t		refFrequency;
	float			frequency0, frequency1, phase0, phase1;
	Registers		activeFreq, activePhase;
};

#endif



Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

WriteRegister is zo te zien ook een zelf geschreven 16 bits software SPI routine. (de hardware SPI is 8 bits in een 8 bitter en kan dat niet)
Mijn SoftSpi_Write() routine boven verstuurt toch ook 16 bits?


'==================================================================================================
Sub Procedure SoftSpi_Write(Dim pVal As Word)
'==================================================================================================
  Dim lCnt As Byte                       '
  DDS_SYNC = 1                           'Sync and clock high
  DDS_CLK  = 1                           '
  DDS_SYNC = 0                           'Sync low
  For lCnt = 0 to 15                     '16 bits loop
    DDS_DATA = (pVal >> lCnt) And 0x0001 'Load the next databit 
    DDS_CLK  = 0                         'Toggle clock 
    DDS_CLK  = 1                         '
  Next lCnt                              'Loop
  DDS_CLK  = 0                           'Clock low, sync high 
  DDS_SYNC   = 1                         '
End Sub                                  '

[Bericht gewijzigd door Arco op dinsdag 17 december 2024 16:09:25 (69%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Jawel, maar die gaat uit van een DDS van 16-bits en dat vindt de compiler niet goed, die wil niet verder dan 8 bits omdat mijn PIC een 8-bitter is...

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Ik heb trouwens jouw eerdere tip bekeken en getest; gebruik maken van de Reference Clock Module van de PIC16F1847.
Dat gaat inderdaad heel eenvoudig:


 CLKRCON    = %11010111

En voilà; een 16Mhz gedeeld door 128 op poort A.6... :)

Door slim de clocksnelheid te kiezen heb je een scala van mogelijkheden.
Komt wel alleen een blok uit, maar dat is wel anders op te lossen als je een sinus wilt.

Ik heb zelfs in de datasheet gelezen dat je dat signaal nog kunt moduleren ook. Nog niet verder uitgezocht hoe, maar wel redelijk makkelijk te doen zo te zien!

Dat scheelt gewoon een boel hardware.

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Je hebt gelijk, de compiler zit een foutje in, bits hoger als 7 worden (ten onrechte) als fout gezien. (heb ik al jaren terug gemeld maar is niks aan gedaan)
Is gelukkig wel een hack voor: een extra array gebruiken...



Dim DDS_Value    As LongInt                                           'Divider value for the AD9833
Dim DDS_Array    As Byte[2] At DDS_Value                              'Extra array for bit addressing. 

Dim DDS          As Word                                               'DDS ctrl register. Bits used
    DDS_Mode     As sBit At DDS_Array[0].1                                   'in the AD9833 control register
    DDS_Div2     As sBit At DDS_Array[0].3                                   '
    DDS_OpBiten  As sBit At DDS_Array[0].5                                   '
    DDS_Sleep12  As sBit At DDS_Array[0].6                                   '
    DDS_Sleep1   As sBit At DDS_Array[0].7                                   '
    DDS_Reset    As sBit At DDS_Array[1].0                                   '
    DDS_PSelect  As sBit At DDS_Array[1].2                                   '
    DDS_FSelect  As sBit At DDS_Array[1].3                                   '
    DDS_HLB      As sBit At DDS_Array[1].4                                   '
    DDS_B28      As sBit At DDS_Array[1].5                                   '
    DDS_Freq0    As sBit At DDS_Array[1].6                                   '
    DDS_Freq1    As sBit At DDS_Array[1].7 
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Is dat ook een foutje van de compiler?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Oeps!... (schijnbaar kun je geen bitnamen toewijzen binnen een array...)


'====================================================================================================
Program Test        'Test program
'====================================================================================================
' MCU:          PIC16F1847
' Oscillator:   Internal -- MHz
'====================================================================================================
Dim   DDS_Value As LongInt                              'Divider value for the AD9833Dim DDS_SYNC As sBit At PortB.0
      DDS_CLK   As sBit At Portb.1                      'Change if needed
      DDS_DATA  As sBit At PortB.2                      '
      DDS_SYNC  As sBit At PortB.3                      '
      DDS          As Word                              'DDS ctrl register. Bits used
      DDS_Array    As Byte[2] At DDS

Const DDS_Mode    = 1                                   'in the AD9833 control register
      DDS_Div2    = 3                                   '
      DDS_OpBiten = 5                                   '
      DDS_Sleep12 = 6                                   '
      DDS_Sleep1  = 7                                   '
      DDS_Reset   = 8                                   '
      DDS_PSelect = 10                                  '
      DDS_FSelect = 11                                  '
      DDS_HLB     = 12                                  '
      DDS_B28     = 13                                  '
      DDS_Freq0   = 14                                  '
      DDS_Freq1   = 15

'==================================================================================================
Sub Procedure ChangeBit(Dim pBitnr As Byte, Dim pValue As Byte)
'==================================================================================================
  DDS_Array[pBitnr And 0x1000].(pBitnr And 0x0111) = pValue 'And 0x0111 = pValue
End Sub

'==================================================================================================
Sub Procedure SoftSpi_Write(Dim pVal As Word)
'==================================================================================================
  Dim lCnt As Byte
  DDS_SYNC = 1
  DDS_CLK  = 1
  DDS_SYNC = 0
  For lCnt = 0 to 15
    DDS_DATA = (pVal >> lCnt) And 0x0001
    DDS_CLK  = 0
    DDS_CLK  = 1
  Next lCnt
  DDS_CLK  = 0
  DDS_SYNC   = 1
End Sub

'==================================================================================================
Sub Procedure DDS_Init()                                            'Init the DDS chip
'==================================================================================================
  DDS_SYNC    = 0                                                  'Select DDS chip (spi #1)
  DDS         = 0                                                  'All Flags are '0'
  ChangeBit(DDS_Reset, 1)                                          '(except the reset flag)
  SoftSpi_Write(DDS)                                               '
  ChangeBit(DDS_Reset, 0)                                          '
  SoftSpi_Write(DDS)                                               '
  DDS_SYNC    = 1                                                  'Disable chip
End Sub                                                            '

'==================================================================================================
Sub Procedure DDS_Set()                                            'Set value from DDS_Value into the DSS chip
'==================================================================================================
  DDS_SYNC = 0                                                     'Select DDS chip (spi #1)
  SoftSpi_Write(0x2000)                                            'Set 2x14bits cmd mode
  SoftSpi_Write((DDS_Value And 0x00003FFF) Or 0x4000)              'Low 14 bit word first
  SoftSpi_Write((DDS_Value >> 14) Or 0x4000)                       'Hi 14 bits
  DDS_SYNC = 1                                                     '
End Sub                                                            '
End.
'==============================================================================
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op dinsdag 17 december 2024 15:59:51 schreef Arco:


  For lCnt = 0 to 15                     '16 bits loop
    DDS_DATA = (pVal >> lCnt) And 0x0001 'Load the next databit 
    DDS_CLK  = 0                         'Toggle clock 
    DDS_CLK  = 1                         '
  Next lCnt                              'Loop
                      '

Op dinsdag 17 december 2024 16:30:23 schreef Arco:
Je hebt gelijk, de compiler zit een foutje in, bits hoger als 7 worden (ten onrechte) als fout gezien.

Wat gebeurt er als je schrijft:


  For lCnt = 0 to 15                     '16 bits loop
    DDS_DATA = pVal And 0x0001 'Load the next databit 
    DDS_CLK  = 0                         'Toggle clock 
    pVal = pVal >> 1                     '
    DDS_CLK  = 1                         '
  Next lCnt                              'Loop              '

?

Ziet ie het als error of doet ie gewoon een 8-bit shift? (dus met nul voor de hogere bitjes?

De "shift X bits" zal "lastig" op de hardware mappen. dwz, prima te doen voor 1 byte, maar lastig voor meerdere bytes (een word).

De hardware heeft vrijwel altijd support om een >>1 te doen die makkelijk naar langere woordlengtes uit te breiden is.

ALS er nog wat te berekenen valt dan zet ik dat tussen de hoog-laag van de clock. Op een snelle processor (e.g. RP2040) kan het zijn dat de clock hoog, clock laag tot ieder 1 instructie worden gereduceerd. Dan krijg je een 1 clock puls: 8ns op de RP2040. Dat kan te kort zijn om een geldige puls aan de buitenkant van de CPU te krijgen. Met IETS er tussen wordt het altijd minstens 1 clock langer. :-)

edit: Ik heb geen pic(*), geen enkele interesse om weer in basic te gaan programmeren. dus zelf proberen zit er niet in.

(*) Nouja, er liggen hier een paar, maar niemand wil ze kopen.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Dan toch liever programmeren in C/C++ en een goed doorontwikkelde C/C++ compiler gebruiken... :)

Arco

Special Member

Ik vind altijd bugs in compilers die anderen nooit meemaken... :+
(ook in 'goede' assemblers en C compilers als Keil al vele gevonden...)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Hier is het programma zoals ik het nu heb.
Er gebeurt evenwel niets (dwz geen output op de AD9833).

De TRIS staat toch goed? (CLK en SDO op input, latch/sync op output?}
Geen pull-up weerstanden?


'====================================================================================================
Program Signal
' SCK (D0):     PORT B.1                 Pin 7
' SDO (D1):     PORT B.2                 Pin 8
' Sync          LAT B.3                  Pin 9
'====================================================================================================

Dim   DDS_Value As LongInt                              'Divider value for the AD9833Dim DDS_SYNC As sBit At PortB.0
      DDS_CLK   As sBit At Portb.1                      'Change if needed
      DDS_DATA  As sBit At PortB.2                      '
      DDS_SYNC  As sBit At LATB.3                       '
      DDS          As Word                              'DDS ctrl register. Bits used
      DDS_Array    As Byte[2] At DDS

Const DDS_Mode    = 1                                   'in the AD9833 control register
      DDS_Div2    = 3                                   '
      DDS_OpBiten = 5                                   '
      DDS_Sleep12 = 6                                   '
      DDS_Sleep1  = 7                                   '
      DDS_Reset   = 8                                   '
      DDS_PSelect = 10                                  '
      DDS_FSelect = 11                                  '
      DDS_HLB     = 12                                  '
      DDS_B28     = 13                                  '
      DDS_Freq0   = 14                                  '
      DDS_Freq1   = 15

'==================================================================================================
Sub Procedure ChangeBit(Dim pBitnr As Byte, Dim pValue As Byte)
'==================================================================================================
  DDS_Array[pBitnr And 0x1000].(pBitnr And 0x0111) = pValue 'And 0x0111 = pValue
End Sub

'==================================================================================================
Sub Procedure SoftSpi_Write(Dim pVal As Word)
'==================================================================================================
  Dim lCnt As Byte
  DDS_SYNC = 1
  DDS_CLK  = 1
  DDS_SYNC = 0
  For lCnt = 0 to 15
    DDS_DATA = (pVal >> lCnt) And 0x0001
    DDS_CLK  = 0
    DDS_CLK  = 1
  Next lCnt
  DDS_CLK  = 0
  DDS_SYNC   = 1
End Sub

'==================================================================================================
Sub Procedure DDS_Init()                                            'Init the DDS chip
'==================================================================================================
  DDS_SYNC    = 0                                                  'Select DDS chip (spi #1)
  DDS         = 0                                                  'All Flags are '0'
  ChangeBit(DDS_Reset, 1)                                          '(except the reset flag)
  SoftSpi_Write(DDS)                                               '
  ChangeBit(DDS_Reset, 0)                                          '
  SoftSpi_Write(DDS)                                               '
  DDS_SYNC    = 1                                                  'Disable chip
End Sub                                                            '

'==================================================================================================
Sub Procedure DDS_Set()                                            'Set value from DDS_Value into the DSS chip
'==================================================================================================
  DDS_SYNC = 0                                                     'Select DDS chip (spi #1)
  SoftSpi_Write(0x2000)                                            'Set 2x14bits cmd mode
  SoftSpi_Write((DDS_Value And 0x00003FFF) Or 0x4000)              'Low 14 bit word first
  SoftSpi_Write((DDS_Value >> 14) Or 0x4000)                       'Hi 14 bits
  DDS_SYNC = 1                                                     '
End Sub                                                            '

Main:

  ANSELA     =  %00000000                             'All Port A Digital
  ANSELB     =  %00000000                             'All Port B Digital
  TRISA      =  %11101111
  TRISB      =  %00000110                             'Port B.1 and B.2 input
  OSCCON     =  %01111000                             '16 MHz internal

  DDS_INIT()
  DDS_SET()
  
  End.
Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

De bug met de 16-bits SPI dateert al van 2005...Kennelijk hebben ze dat voor Mikroe-C destijds wel opgelost en nieuwe libraries gemaakt.

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

PortB0,1,2 moeten allemaal outputs zijn.
Waar ik Port heb gebruikt zou LAT moeten zijn...

Die 2005 bug is niet van deze compiler, naar van de voorloper ervan.

[Bericht gewijzigd door Arco op donderdag 19 december 2024 00:39:30 (29%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Ja, nu doet-ie het wel.. :)

Ik had de Sync al op LATB.3 staan. maar omdat B.1 en B.2 ook output moeten zijn, moeten die dan inderdaad ook naar LAT.
En uiteraard de TRISB ook instellen op 0x00.

Nu nog even uitvogelen hoe je makkelijk de frequentie en outputvorm instelt.
Dat zit nu in de coderegels als literals gebakken.

Fouten zijn het bewijs dat je het probeert..