Menu

Controlling AD9850 DDS using the PIC16

2017-11-16
2018-07-10
  • Harley Burton

    Harley Burton - 2017-11-16

    Hi. First, I want to thank everyone for helping me getting my DDS Controller working. Although it is not working yet, it is very close. I have the synchronous mode working perfectly, transmitting the bytes in the proper data order and giving us the exact number of bits to clock in the 40 data bits of frequency ivisor and control word. Now I have a new problem.

    After the data is clocked into the DDS, I have to send a Frequency Load pulse. I have that working but it is occuring too soon. I need to know if when the last byte of data to send has been completely sent. Can I read the TXREG and see if it is empty? If so, I could use this to know it's time to generate the pulse. Alternatively, how about polling the TRMT bit?

    Reminder I am using the PIC16F690.

    Thanks again for the help,

    Harley
    N5BFB

     

    Last edit: Harley Burton 2017-11-16
    • Harley Burton

      Harley Burton - 2018-07-10

      I wanted to let y'all know that I have my HF-APRS tracker working. I am able to transmit packets, but still testing. I don't have enough transmit power but I'm working that too.

       
  • mmotte

    mmotte - 2017-11-16

    Harley,
    To check that the Tx buffer is empty is checking the SSPBF bit.
    1 = Transmit in progress, SSPBUF is full
    0 = Transmit complete, SSPBUF is empty

    Wait While SSPBUF = On
    

    then do the load pulse

    You could use this ame statement between loading each of the 5 bytes too.

    (For more intense jobs you would enable the interrupts SSPIE and check the SSPIF bit.)

    Alert!
    I am hoping you understand that SSP sends MSB first and the AD9850 is expecting LSB first. The bits need to be swapped before you send them to the SSP txbuf. I mentioned this before but you have acknowledged doing it and i haven't seen your code.

    GL
    Mike w9ys

     

    Last edit: mmotte 2017-11-16
  • Harley Burton

    Harley Burton - 2017-11-16

    Thank you Mike, I will try that tomorrow. I have a little work to do tonight. You guys are all great help.

    Thanks again.

    Harley
    N5BFB

     
  • Harley Burton

    Harley Burton - 2017-11-17

    Sorry Mike, I turn the data around byte and bitwise before I do anything with it. I have only two frequencies to send to the DDS so this can be canned in thed code. I want to write a routine to do it regardless of what I want to send but I haven't taken time to figure out what how to reverse the bit order of a byte or word of data. That's tomorrows job. For now, I'll just do it by hand.

    Bye the way, I don't think I told you, I am building an HF APRS. The goal is to do it as an under $100 kit buying modules off of ebay. If this goes well, I should have it testing in a couple weeeks. It's going well thanks to you and the others on this forum.

    Thanks again,
    Harley
    N5BFB

     
  • mmotte

    mmotte - 2017-11-17

    Harley,
    Thatis in the tradition of ham radio, building equipment and now programming it! I like it. I am a biulder, some work, some don't.

    GCB has a section in demos on radios but there isn't much in there right now. Maybe you can share some working code for the AD9850.

    GL
    Mike w9ys

     
  • Harley Burton

    Harley Burton - 2017-11-18

    Mike,

    I'm making great headway with my DDS Controller. However, I am having difficulty with the Synchronous port. As I read the PIC16F690 manual, when I load a series of 5 bytes into the TXREG, the device should send out the 5 bytes but it should also provide 40 clocks. When I looked on at the signals with a logic analyzer, I see that I get 42 pulses instead of 40 clock pulses. For some reason, the PIC adds two pulses to the front of the transmission and first one is a very short one followed by a long one neither on of which belong there.
    Additionally, I used a bit on PORTC to provide my load pulse. Unfortunately, it also has a high going glitchy load pulse that is an exact copy of the two extraneous pulse at the beginning of the synchronous pulse stream.
    Finally, if you notice, the first 24 valid synchronous pulses are twice as long as the last 16. The 16 pulses are the correct length, 0.1 msec, but the 24 pulses are twice that length, almost exactly. There are no operations between the loading 5 bytes. Here's the code that sends the bytes:

    Sub SendMark 'Send the bytes that set the FSK frequency to a Mark

    TCounter = 0
    Do
    'Check TRMT bit to see if a new value can be loaded into Transmit
    'Shift Register (TSR)
    If TRMT then
    'Transmit byte synchronously
    HSerSend MarkOut(TCounter)
    TCounter = TCounter + 1
    End If
    Loop until TCounter = 5
    'Wait till the last byte has been shifted out
    Wait 1000 us
    'Pulse the Frequency Load Bit (FQ_UD)
    PulseOut PORTC.5, 50 us

    End sub

    Some short explainations. I use TCounter to send exactly 5 bytes, 4 of frequency and 1 of control. I added your code suggestion "Wait While SSPBUF = On" to move my load pulse out to the end of the synchronous transmission where it should be. Unfortunately, it only move it out 8 bits, not the 16 I needed. At that time I decided to just put a timer to hold off until the message was completely shifted out. That actually worked and it pulses a millisecond or so after the final bit is shifted out and the last clock has completed. For some reason, during that time is when the shift clock is pulsing at the correct timing. Prior to that 1000 us time, the pulses are twice as long as they should be. After one transmission, five bytes, it all stops until I command it to transmit again.

    It also appears I don't have my load constants worked out correctly but right now I only want to load any frequency, then work out the right numbers.

    I have not figured out how to reverse the bit order of a byte or long. Until I do, I won't have a generic module for controlling a DDS but I'll do it if I have to rotate the byte and then shift it one bit at a time and test the "C" bit. Lousy way to do it but if that's what it takes, I may do it in assembler.

    In response to your suggestion, I definitely will upload the code or some symplified version if I can make one when I get it all working.

    Thanks again,

    Harley
    N5BFB

     
  • Harley Burton

    Harley Burton - 2017-11-18

    Quick update. I changed the code so that it repeated sending the 5 bytes once a second. Interestingly enough, it only glitched on the very first time. I could probably just hold the DDS in reset, send the 5 bytes the first time to initialize it then release reset and continue to use it normally. It isn't a true fix but it will probably make it work. I'll keep working on the glitches. I think they are related to initializing the port and port bit.

    I also searched the forum for something to reverse the bit order. Someone wrote a small function called "Reorder". It works great. I don't know how much code it generates, nor how fast it executes, but I'll try to find out. I'll post it if I can figure it out.

    Harley,
    N5BFB

     

    Last edit: Harley Burton 2017-11-18
    • Chris Roper

      Chris Roper - 2017-11-18

      This should do it:

      '
      ' ByteReversal.gcb
      '
      
      #chip 16f690,4
      
      dim TestByte as byte
      TestByte = 0b01101010
      
        dir PortC Out
      
        PortC = TestByte
      
        wait 1 s
      
        PortC = RevByte(TestByte)
      
      End
      
      Function RevByte(InByte)
        Dim OutByte, Index as Byte
        for Index = 0 to 7
          Rotate InByte  Left    ' Shift Left MSB into Carry
          Rotate OutByte Right   ' Shift Carry Right into MSB
        Next
        RevByte = OutByte
      End Function
      

      Cheers
      Chris

       

      Last edit: Chris Roper 2017-11-18
      • Chris Roper

        Chris Roper - 2017-11-18

        Subsequent to posting the above I refined it to use less space and to be able to reverse Byte, Word or Long Values so that it can handle 8,16 or 32 Bit chunks.

        You can find the latest version here:
        https://sourceforge.net/p/gcbasic/discussion/629990/thread/188543c6/

        Cheers
        Chris

         

Log in to post a comment.