I am trying to use a PIC16F690 to control an Analog Devices AD9850. I have read all the documentation many times concerning the I2C to control the AD9850. I have the control words worked out with no translation, etc. So my question is this; does the I2C routines send the data out MSB first, or LSB first? Additionally, is there any translation of the data or is it just sent out straight? In I2C, the address is shifted left one bit and typically a 0 or 1 added at the end of the address to indicate whether the operation is a read or write. While I don't see that in the AD9850 datasheet, so I'm wondering if the I2C routines in Great Cow Basic do any address or other data translation.
Please help!
Thanks,
Harley Burton
N5BFB
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Harley,
Looking at the AD9850 datasheet for serial control the LSB (b0)goes out first. followed by the other 39 bits. The bitsare sent to Pin 25 (D7) data input and are shifted in on the rising edge of the w_clk, Pin 7. after 40 bits are shifted in then FQ_UD Pin 8 is told to rise which loads the new info into frequency and control. This also resets t bit pointer back to b0 .
This is not I2C protocol nor SPI . The PIC16F690 does have a Synchronous Serial Port (SSP) module but it shifts the msb out first.
There is no addressing issues on the AD9850 because you are directly controlling the 3 pins for input not through a common bus structure with addresses or chip selects.
So this leads to the need for a software solution to shift the 40 bits out , toggle the clock, and tell it to load.
I have a couple of the AD9850 boards but never did anything with them.
GL
73
Mike W9YS
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Mike,
Thanks. I guess since it only had the one clock and data lines, I assumed it was an I2C interface...duh. I should have read it more thoroughly and it has been a real challenge to me to make it all come together. I didn one as a parallel interface many years ago but it has been a long time. The PIC16F690 has a synchronous serial port and it looks like that is exactly what I am looking for. You really cleared it up to me.
This site looks to be very good and I am looking forward to working with all of you. When I get a load routine working, I'll be sure and post it for others.
Thanks again,
Harley
N5BFB
73's
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I did this years ago in PIcBasicPro. PBP has a function called SHIFTOUT that does this but my method is actually faster and produces more compact object code
Herei s the section of code that sends the 40 bits of data to the AD9850. It's written as a 'bit bang' equivalent of PicBasicPro's SHIFTOUT, but you should get the idea and easily translate it to GCB. You'll have to create a 5 byte freq_byte () array (40 bits) with the binary frequency in the 1st 4 bytes and the control byte in the 5th byte. You'll also have to define port bits for spi_data, spi_clk and spi_latch.
Joe
'***********
' SUBROUTINES
'***********
'Update the DDS frequency
Update_dds:
For i = 0 To 3
freq_byte = freq(i) 'Send the 4 frequency bytes
Gosub send_spi
Next i
freq_byte = $00 'Send the control byte
Gosub send_spi
spi_latch_dds = 1 'Toggle the DDS Latch line after all 5 bytes
spi_latch_dds = 0 'have been sent.
Return
'***********
' Clocks a single byte out the SPI port
' This 'brute force' single-byte SPI transmit routine is 3-4 times faster than
' SHIFTOUT and it actually compiles to fewer bytes of object code
send_spi:
spi_data = freq_byte.0 'Iterate through all 8 bits of the byte;
spi_clk = 1 'set the SPI_DATA line to the state of that
spi_clk = 0 'bit, and toggle the SPI_CLK line.
spi_data = freq_byte.1
spi_clk = 1
spi_clk = 0
spi_data = freq_byte.2
spi_clk = 1
spi_clk = 0
spi_data = freq_byte.3
spi_clk = 1
spi_clk = 0
spi_data = freq_byte.4
spi_clk = 1
spi_clk = 0
spi_data = freq_byte.5
spi_clk = 1
spi_clk = 0
spi_data = freq_byte.6
spi_clk = 1
spi_clk = 0
spi_data = freq_byte.7
spi_clk = 1
spi_clk = 0
Return
'************
Last edit: joe rocci 2017-11-05
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The synchronous serial serial port hardware sends the MSB first, so you would have to swap the bits of the byte before sending. This could be done.
OR
Joe has a good solution above, just bitbanging the bits out.
The port's Pins would be defined at the beginning of the program like:
#define spi_data PortC.5
#define spi_clk PortC.4
#define spi_latch_dds PortC.3
dir spi_data out
dir spi_clk out
dir spi_latch_dds out
spi_dat = 0
spi_clk = 0
spi_latch_dds = 0
Gl
73
Mike w9ys
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks all. I have been looking at using the built in serial port in the synchronous mode. it should be exactly what I need if I can figure out how to use it. It accepts the byte to be sent out with easy to use (I hope) double buffering and the exact number of clocks for each word. It appears there are also no interruptions in the datastream and clock stream when it is working properly. So, now I have to find out how to set it up. Not enough infformation in the GCB reference manual. Anybody who knows how, that would be the best method. Otherwise, I'll probably fix above and use it. I have the bytes reversed but in serial mode, it sends the 0x00 LAST, not first as your example. The synchronous serial mode though would be my preference. There may actually be less code. For what I have to do, I might even be able to fit it into something like a PIC10F322 or something like that. That would really be great.
Advise?
Harley
N5BFB
73's to all.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Harley
My. code sends the control byte last and and all other bytes in correct order. One other advantage of this method is that it works on any port of any PIC
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I had a thought. If I'm correct, the serial port wouldn't know whether it was in Synchronous or Asynchronous mode when setting the baud rate. So if I used the asynchronous baud rate setup SER1_BAUD 128000 it should set up the port for the highest data rate which then could use the same for synchronous mode at that same speed. Do you agree?
I also copied setting the proper bits from someone else's routine in assembler. Do you concur with this as well?
;Set SYNC On
bsf TXSTA,SYNC
;Set CSRC On
bsf TXSTA, CSRC
;Set SREN Off
bcf TXSTA, SREN
;Set CREN Off
bcf RCSTA, CREN
;Set SPEN On
bsf RCSTA,SPEN
;Set SCKP On
bsf TXSTA, SCKP
;Set TXEN On
bsf TXSTA,TXEN
banksel STATUS
I think this is what it should look like. Do you agree or have any other comments.
Thanks,
Harley
N5BFB
73's
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
While I cannot speak to the method of communication with the AD9850 as I have not studied the protocol in the datasheet, I can suggest some other stuff.
GCB will create optimized ASM for you, so there is generally no need to use inline ASM in the source code. For example this BASIC code....
Set SYNC On
Set CSRC On
Set SREN Off
Set CREN Off
Set SPEN On
Set SCKP On
Set TXEN On
STATUS = 0
.
Note: GCB will not accept "banksel" as the GCB compiler will automatically generate a "banksel" to select the correct bank for the register being written or read.
There is no need to use "banksel status" as the status register is available to all 4 register banks. You could simply use STATUS = 0 which will generate "clrf status" to select bank 0 if that is the purpose of "banksel status".
William
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am trying to use a PIC16F690 to control an Analog Devices AD9850. I have read all the documentation many times concerning the I2C to control the AD9850. I have the control words worked out with no translation, etc. So my question is this; does the I2C routines send the data out MSB first, or LSB first? Additionally, is there any translation of the data or is it just sent out straight? In I2C, the address is shifted left one bit and typically a 0 or 1 added at the end of the address to indicate whether the operation is a read or write. While I don't see that in the AD9850 datasheet, so I'm wondering if the I2C routines in Great Cow Basic do any address or other data translation.
Please help!
Thanks,
Harley Burton
N5BFB
Harley,
Looking at the AD9850 datasheet for serial control the LSB (b0)goes out first. followed by the other 39 bits. The bitsare sent to Pin 25 (D7) data input and are shifted in on the rising edge of the w_clk, Pin 7. after 40 bits are shifted in then FQ_UD Pin 8 is told to rise which loads the new info into frequency and control. This also resets t bit pointer back to b0 .
This is not I2C protocol nor SPI . The PIC16F690 does have a Synchronous Serial Port (SSP) module but it shifts the msb out first.
There is no addressing issues on the AD9850 because you are directly controlling the 3 pins for input not through a common bus structure with addresses or chip selects.
So this leads to the need for a software solution to shift the 40 bits out , toggle the clock, and tell it to load.
I have a couple of the AD9850 boards but never did anything with them.
GL
73
Mike W9YS
Mike,
Thanks. I guess since it only had the one clock and data lines, I assumed it was an I2C interface...duh. I should have read it more thoroughly and it has been a real challenge to me to make it all come together. I didn one as a parallel interface many years ago but it has been a long time. The PIC16F690 has a synchronous serial port and it looks like that is exactly what I am looking for. You really cleared it up to me.
This site looks to be very good and I am looking forward to working with all of you. When I get a load routine working, I'll be sure and post it for others.
Thanks again,
Harley
N5BFB
73's
Harley,
I did this years ago in PIcBasicPro. PBP has a function called SHIFTOUT that does this but my method is actually faster and produces more compact object code
Herei s the section of code that sends the 40 bits of data to the AD9850. It's written as a 'bit bang' equivalent of PicBasicPro's SHIFTOUT, but you should get the idea and easily translate it to GCB. You'll have to create a 5 byte freq_byte () array (40 bits) with the binary frequency in the 1st 4 bytes and the control byte in the 5th byte. You'll also have to define port bits for spi_data, spi_clk and spi_latch.
Joe
'***********
' SUBROUTINES
'***********
'Update the DDS frequency
Update_dds:
For i = 0 To 3
freq_byte = freq(i) 'Send the 4 frequency bytes
Gosub send_spi
Next i
freq_byte = $00 'Send the control byte
Gosub send_spi
spi_latch_dds = 1 'Toggle the DDS Latch line after all 5 bytes
spi_latch_dds = 0 'have been sent.
Return
'***********
' Clocks a single byte out the SPI port
' This 'brute force' single-byte SPI transmit routine is 3-4 times faster than
' SHIFTOUT and it actually compiles to fewer bytes of object code
send_spi:
spi_data = freq_byte.0 'Iterate through all 8 bits of the byte;
spi_clk = 1 'set the SPI_DATA line to the state of that
spi_clk = 0 'bit, and toggle the SPI_CLK line.
spi_data = freq_byte.1
spi_clk = 1
spi_clk = 0
spi_data = freq_byte.2
spi_clk = 1
spi_clk = 0
spi_data = freq_byte.3
spi_clk = 1
spi_clk = 0
spi_data = freq_byte.4
spi_clk = 1
spi_clk = 0
spi_data = freq_byte.5
spi_clk = 1
spi_clk = 0
spi_data = freq_byte.6
spi_clk = 1
spi_clk = 0
spi_data = freq_byte.7
spi_clk = 1
spi_clk = 0
Return
'************
Last edit: joe rocci 2017-11-05
Harley,
The synchronous serial serial port hardware sends the MSB first, so you would have to swap the bits of the byte before sending. This could be done.
OR
Joe has a good solution above, just bitbanging the bits out.
The port's Pins would be defined at the beginning of the program like:
Gl
73
Mike w9ys
Harley
I should have included these test constants in case you want to try it out
'Set DDS to 7.000 MHz
Freq(0) = $1F 'LSB of frequency
Freq(1) = $85
Freq(2) = $EB
Freq(3) = $11 'MSB of frequency
gosub update_dds
Last edit: joe rocci 2017-11-05
Thanks all. I have been looking at using the built in serial port in the synchronous mode. it should be exactly what I need if I can figure out how to use it. It accepts the byte to be sent out with easy to use (I hope) double buffering and the exact number of clocks for each word. It appears there are also no interruptions in the datastream and clock stream when it is working properly. So, now I have to find out how to set it up. Not enough infformation in the GCB reference manual. Anybody who knows how, that would be the best method. Otherwise, I'll probably fix above and use it. I have the bytes reversed but in serial mode, it sends the 0x00 LAST, not first as your example. The synchronous serial mode though would be my preference. There may actually be less code. For what I have to do, I might even be able to fit it into something like a PIC10F322 or something like that. That would really be great.
Advise?
Harley
N5BFB
73's to all.
Harley
My. code sends the control byte last and and all other bytes in correct order. One other advantage of this method is that it works on any port of any PIC
Sorry, I read it wrong. Thanks for correcting me.
Harley
I had a thought. If I'm correct, the serial port wouldn't know whether it was in Synchronous or Asynchronous mode when setting the baud rate. So if I used the asynchronous baud rate setup SER1_BAUD 128000 it should set up the port for the highest data rate which then could use the same for synchronous mode at that same speed. Do you agree?
I also copied setting the proper bits from someone else's routine in assembler. Do you concur with this as well?
;Set SYNC On
bsf TXSTA,SYNC
;Set CSRC On
bsf TXSTA, CSRC
;Set SREN Off
bcf TXSTA, SREN
;Set CREN Off
bcf RCSTA, CREN
;Set SPEN On
bsf RCSTA,SPEN
;Set SCKP On
bsf TXSTA, SCKP
;Set TXEN On
bsf TXSTA,TXEN
banksel STATUS
I think this is what it should look like. Do you agree or have any other comments.
Thanks,
Harley
N5BFB
73's
While I cannot speak to the method of communication with the AD9850 as I have not studied the protocol in the datasheet, I can suggest some other stuff.
GCB will create optimized ASM for you, so there is generally no need to use inline ASM in the source code. For example this BASIC code....
Will generate this ASM code. ( comments removed)
Note: GCB will not accept "banksel" as the GCB compiler will automatically generate a "banksel" to select the correct bank for the register being written or read.
There is no need to use "banksel status" as the status register is available to all 4 register banks. You could simply use STATUS = 0 which will generate "clrf status" to select bank 0 if that is the purpose of "banksel status".
William