搜索
bottom↓
回复: 47

A simple AD9850-based signal generator

[复制链接]

出0入0汤圆

发表于 2013-6-16 07:06:36 | 显示全部楼层 |阅读模式
I got a ad9850 module a while ago. after having played with it, i decided to build a signal generator around it.

some design goals:

1) as simple as possible. a minimalist implementation.
2) controlled by a mcu (12F675, 8pdip).
3) multiple bands. AF + RF.
4) can function as a frequency sweeper as well.

the project was inspired by this page:

http://www.sm7ucz.se/DDS/DDS.htm

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2013-6-16 07:09:19 | 显示全部楼层
Here is the module I have:



In serial mode, it needs three pins to control: WCLK (for clock), SDATA (for serial data), and FQUD (to update frequency).

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-6-16 07:31:23 | 显示全部楼层
The ad9850 module is controlled via two routines: ad9850_init() resets the gpio pins, and ad9850_freq() sets out a frequency on the two output pins.

  1. //convert frequency / phase defaults to 0
  2. void ad9850_freq(unsigned long freq) {
  3.         freq = ad9850_f2w(freq);                                                //convert 32-bit freq to 32-bit tuning words
  4.         ad9850_sendwords(freq);
  5. }
复制代码
ad9850_sendwords() sends a 40-bit string to the chip, and then stroke the FQUD pin to execute the command.

  1. //send ad9850 words - lsb first
  2. void ad9850_sendwords(unsigned long words) {
  3.         IO_CLR(AD9850_PORT, AD9850_FQUD);                                //clear the pin
  4.         ad9850_sendbyte(words);                                                //send words
  5.         words = words >> 8; ad9850_sendbyte(words);
  6.         words = words >> 8; ad9850_sendbyte(words);
  7.         words = words >> 8; ad9850_sendbyte(words);
  8.         words = words >> 8; ad9850_sendbyte(words & 0xfc);                                //send the final words -> control1..0 = 0b00
  9.         IO_SET(AD9850_PORT, AD9850_FQUD);
  10.         AD9850_DELAY();                                                                        //wait tFH > 7ns
  11.         IO_CLR(AD9850_PORT, AD9850_FQUD);                                //reset FQUD
  12. }
复制代码

出0入0汤圆

 楼主| 发表于 2013-6-16 07:36:02 | 显示全部楼层
The most interesting thing is the ad9850_f2w() routine: it converts a 32-bit number (for the desired frequency) and convert it to a 32-bit tuning word.

AD9850 is a 32-bit DDS, the module itself has a 125Mhz master clock.

So the tuning word corresponding to the desired frequency is:

frequency = tuning word * 125Mhz / 2^32.

Two issues:

1) if you were to use integer math, tuning word * 125Mhz would be very very big. It will take a lot of space + time.
2) if you were to use floating point math, well, it is going to be even worse.

The implementation (original to somebody else) is very efficient in space and time. I will publish it in a couple of days, so you may think how it works, :)

出0入211汤圆

发表于 2013-6-16 07:52:23 来自手机 | 显示全部楼层
看你敲的英语的口气,感觉你是个真正的老外,哪国家的呢?

出0入0汤圆

发表于 2013-6-16 09:43:25 | 显示全部楼层
看精度了。我以前是直接先将频率除一部分。能整除就整除。

比如说125M的晶振,可以先直接缩小为125M/2^6,然后再算。

出0入0汤圆

发表于 2013-6-16 10:09:45 | 显示全部楼层
>>tuning word * 125Mhz would be very very big

I would do it in another way, if the multiplication factor is a constant.

I first converted the wanted DDS output frequency into milli-Hertz, represented by a binary value. Then I multiply this value by 0.034359738 to get the tuning word.

The multiplication is done using successive approximation, which involves only shifting, adding or subtracting.

Let says that binary value is X. Now shift right X five times and store in variable M and N. Next shift right N three more times and adds to M (which I will use S3P to denote). Then continue with:

S = shift right, 3 = three times, P = plus(add to M), M=minus(subtract from M)

S2M
S3P
S2M
S3P
S1P
S4M
S2P
S2M
S2P
S2M
S7P
S3P

The final error is just 6.4E-12, close enough. one can easily find out whether to add or subtract using Excel spreadsheet, viewing the difference between existing value and the target value.

出0入0汤圆

 楼主| 发表于 2013-6-16 18:32:45 | 显示全部楼层
I would do it in another way, if the multiplication factor is a constant.


that's an interesting approach.

put it in a piece of code and let's say how fast it is.

the time to beat is 0.9ms (1000 instructions) on a 1Mhz 12F675 or 0.7ms (700 instructions) on a 1Mhz AVR to convert 1Mhz into a 32-bit tuning word (125Mhz master clock)

出0入0汤圆

发表于 2013-6-16 18:51:24 | 显示全部楼层
标记一下,也许有机会用到。

出0入618汤圆

发表于 2013-6-16 19:46:29 | 显示全部楼层
据说9850也有内部PLL,不过不保证能工作,估计是和9851同一个die的筛选品。

出0入0汤圆

发表于 2013-6-16 22:23:55 | 显示全部楼层
millwood0 发表于 2013-6-16 18:32
that's an interesting approach.

put it in a piece of code and let's say how fast it is.

The packed 11 digits BCD(wanted frequency output in mill-Hz requested by user) to binary conversion consumes 495 cycles, while the multiplication routine takes 861 cycles.

i.e. from 1,000,000.000Hz user input to outputting tuning word 0x020C49BB takes a total of 1366 cycles on AVR.

Looks like your timing of 700 cycles is much faster, but how accurate is the tuning word result?  

出0入0汤圆

发表于 2013-6-16 22:58:49 | 显示全部楼层
hushaoxin 发表于 2013-6-16 07:52
看你敲的英语的口气,感觉你是个真正的老外,哪国家的呢?

据矿坛有人透露。这位大师是在米华侨。能看汉字。但不会写。所以他的回贴全是英文。

出0入0汤圆

 楼主| 发表于 2013-6-17 01:04:42 | 显示全部楼层
how accurate is the tuning word result?  


It is exact!

  1. int main(void)
  2. {
  3.     signed long freq=1000000ul;

  4.     //printf("Hello world!\n");
  5.     freq=1000000ul; printf("ad9850_f2w(%10d) = %10x\n", freq, ad9850_f2w(freq));
  6.     freq=1100000ul; printf("ad9850_f2w(%10d) = %10x\n", freq, ad9850_f2w(freq));
  7.     freq=1110000ul; printf("ad9850_f2w(%10d) = %10x\n", freq, ad9850_f2w(freq));
  8.     freq=1111000ul; printf("ad9850_f2w(%10d) = %10x\n", freq, ad9850_f2w(freq));

  9.     freq = - freq;
  10.     printf("ad9850_f2w(%10x) = %10d\n", freq, -ad9850_f2w(-freq) & 0xfffffffful);

  11.     return 0;
  12. }
复制代码
Generated the following output (under Turbo C):


As of now, it has no rounding.

The code also has the advantage of allowing user to specify the master clock and dds bitwidth. so it can be easily adopted for other applications.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-6-17 07:46:38 | 显示全部楼层
Basic design:

we will need three input:

1) mode selection: either output a given frequency, or sweep in a band. This is an on/off (latched) switch.
2) band selection: this is a pot that selects through a pre-determined band.
3) frequency selection: another pot that selects the frequency in  a given band.

I picked the band with the goal to use them for direct tuning, so they are heavily focused on broadcast bands:

  1. typedef struct {
  2.         unsigned long fstart, fend;                        //starting and ending frequencies
  3.         //unsigned char threshold;                        //band threshold
  4.         unsigned char dly;                                        //delay in each step, in ms
  5. } BAND_T;

  6. //global variable
  7. //frequency bands
  8. const BAND_T freq_bands[N_BANDS]={
  9.         //Fstart, Fend, DLY, /*THRESHOLD*/.
  10.         {455000ul - 20000ul, 455000ul + 20000ul, 300},                //455K IF scan, +/- 20Khz bandwidth. default output if BAND_ADC is grounded
  11.         {465000ul - 20000ul, 465000ul + 20000ul, 300},                //465K if scan, +/- 20Khz bandwidth
  12.         {10700000ul - 100000ul, 10700000ul + 100000ul, 100},        //FM if scan, +/- 100Khz bandwidth
  13.         {1, 20000, 300},                                        //audio frequencies
  14.         {10000ul, 600000ul, 200},                        //sub RF (LW band)
  15.         {153000ul, 279000ul, 300},                        //LW band
  16.         {500000ul, 1700000ul, 300},                        //am broadcast band
  17.         {1500000ul, 2300000ul, 300},                //1.5Mhz - 2.3Mhz,
  18.         {2100000ul, 3200000ul, 300},                //2.1Mhz - 3.2Mhz. 120m band
  19.         {3100000ul, 4600000ul, 300},                //3.1Mhz - 4.6Mhz. 90m and 75m bands
  20.         {4500000ul, 6700000ul, 300},                //4.5Mhz - 6.7Mhz. 60m and 49m bands
  21.         {6600000ul, 9600000ul, 300},                //6.6Mhz - 9.6Mhz. 41m and 31m (partial) bands
  22.         {9300000ul, 14000000ul, 300},                //9.3Mhz - 14.Mhz. 31m, 25m and 22m bands - may want to split this further
  23.         {1300000ul, 20000000ul, 300},                //13.Mhz - 20.Mhz. 22m, 19m, 16m, 15m bands - may want to split this further
  24.         {500000ul, 20000000ul, 300}                        //rf band, default if band pin is pulled high
  25. };
复制代码
You can adjust them for your liking.

出0入211汤圆

发表于 2013-6-17 07:50:49 | 显示全部楼层
chensi007 发表于 2013-6-16 22:58
据矿坛有人透露。这位大师是在米华侨。能看汉字。但不会写。所以他的回贴全是英文。 ...

能看,不会写,那就很奇怪...难道使用google翻译看的?

出0入0汤圆

 楼主| 发表于 2013-6-17 07:55:08 | 显示全部楼层
here is the hardware design.



Note: RV1 controls the output frequency. Right now, I am using 10-bit adc results so you have 1000+ steps in any given band. You can put a small value pot in sereial with RV1 to provide some fine tuning. However, I think in another implementation, you can use RV1 for major tuning and RV2 for fine tuning - I will publish that later.

The code is mostly there.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-6-17 07:57:19 | 显示全部楼层
RF buffer:

given that the chip utilizes a current drive, I decided that other than a serial resistor, I will not use any buffer on the output. If you want,  you can use a jfet or mmic as an output device, for simplicity.

出0入0汤圆

发表于 2013-6-17 07:58:37 | 显示全部楼层
Impressive results.

Does it limit the user choice of frequency to an integer value? How does the software perform if the DDS wanted frequency were say for example, 100.12, 100.23, 100.34 Hz etc...?

This is also the main reason I chose to work in units of milli-Hz instead.

出0入0汤圆

 楼主| 发表于 2013-6-17 07:58:41 | 显示全部楼层
With all the functions implemented, the code used up about 80% of the flash. Not bad.

出0入0汤圆

 楼主| 发表于 2013-6-17 08:02:47 | 显示全部楼层
Does it limit the user choice of frequency to an integer value?


Yes.

You can get around that, with minimal efforts. For example, you can specify all frequencies in .1Hz. so 125Mhz master clock becomes 1250000000ul. You just need to remember to shrink the corresponding tuning word by /10. This allows you to tune in steps of .1hz, with minimal efforts.

出0入0汤圆

 楼主| 发表于 2013-6-17 08:22:28 | 显示全部楼层
For example: assume fmclk=125Mhz on a 32-bit dds. you want to generate a 100,000.2hz signal. You inflate fmclk to 125,000,000Hz * 10, and desired frequency to 100,000.2hz * 10. The corresponding tuning word is 3435980. Divide that by 10, you have a tuning word of 343598, which yields an output frequency of 100,000.18hz on fmclk=125Mhz 32-bit dds.

Because of the 4G limit on 32-bit unsigned long, this approach doesn't allow you to go much more beyond .1hz (on a 125Mhz fmclk). you have more flexibility if the master clock is slower.

出0入0汤圆

发表于 2013-6-17 09:37:58 | 显示全部楼层
本帖最后由 alias 于 2013-6-17 09:41 编辑

I have moved one of the bit shifting subroutines inline and now the control word conversion routine takes only 1114-495 = 619 cycles. I might even be able to cut it down with the expense of additional flash bytes.

For a fair comparison of performance in the case 0.1Hz DDS output frequency resolution, I think you will need to include instruction timing of a x10 user input conditioning routine and a divide by 10 control word output conditioning routine in your timing test. That would make your total timing higher than 700 cycles.






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-6-17 18:01:26 | 显示全部楼层
no need for x10 as long as you use frequencies in .1hz format. or you can shift your way out of it.

/10 can be approximated by a series of shifting.

for mcus with hardware multipliers / divisors, it may be better to just code them as x10 or /10.

出0入0汤圆

 楼主| 发表于 2013-6-18 06:39:19 来自手机 | 显示全部楼层
"/10 can be approximated by a series of shifting."

Scratch that. Assuming that you are willing to take steps in .5hz, .25hz, .125hz, etc., you can simply left shift the master clock and right shifting the resulting tuning word.

It should be very fast as well.

出0入0汤圆

 楼主| 发表于 2013-6-18 08:27:41 | 显示全部楼层
The implementation (original to somebody else) is very efficient in space and time.


The algorithm is really successive approximation, as demonstrated by the following spreadsheet. It also shows how sub-1hz stepping could be added, in rows 40 and below.




the tuning word for 1,000,000hz on a 125Mhz 32-bit DDS is 0x020c 49ba (cell B6). rows 8 through 39 goes through the calculation. Column E shows the output of the approximation process.

This spreadsheet actually can be implemented via flash for a very fast algorithm if you know the fmclk and bitcount, :)

here is the generic version of the code I used:

  1. #define F_AD9850                125000000ul                //reference clock frequency
  2. #define W_AD9850                32                        //bitcount for the dds

  3. //convert frequency to words
  4. //calculate Freq * 2^BitCount / Divisor
  5. unsigned long ad9850_f2w(unsigned long freq) {

  6.    unsigned long Dividend = freq;
  7.    unsigned long Quotient = 0;
  8.    unsigned long Divisor = F_AD9850/*125000000ul*/;         //F_AD9850, in hz

  9.    unsigned char BitCount;

  10.    for( BitCount=W_AD9850/*32*/; BitCount!=0; BitCount-- ) {        //*2^32
  11.        Dividend <<= 1;
  12.        Quotient <<= 1;

  13.        if( Dividend >= Divisor ) {
  14.            Dividend -= Divisor;

  15.            Quotient |= 1;
  16.        }
  17.    }

  18.    return Quotient /*+ 1*/;
  19. }

复制代码
Hope it helps.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-6-18 09:12:59 | 显示全部楼层
millwood0 发表于 2013-6-16 18:32
that's an interesting approach.

put it in a piece of code and let's say how fast it is.

Your open challenge is to beat the 700 instructions conversion time from wanted DDS output frequency to DDS control word.

Well I have done it in 335 instructions. Can you(or anyone) do better?


  1. ;====================================================================================
  2. ;
  3. ;       Subroutine to shift right a 5-byte word(located in TempV) 'X' number of times,
  4. ;          depending on entry point to the subroutine.
  5. ;       It then adds/subtracts this shifted value in TempV into FinalV
  6. ;
  7. ;====================================================================================

  8. ;--- the entries for adding TempV to FV afterwards

  9. S15P:
  10.         lsr     TV4
  11.         ror     TV3
  12.         ror     TV2
  13.         ror     TV1
  14.         ror     TV0
  15.         ;
  16. S14P:
  17.         lsr     TV4
  18.         ror     TV3
  19.         ror     TV2
  20.         ror     TV1
  21.         ror     TV0
  22.         ;
  23. S13P:
  24.         lsr     TV4
  25.         ror     TV3
  26.         ror     TV2
  27.         ror     TV1
  28.         ror     TV0
  29.         ;
  30. S12P:
  31.         lsr     TV4
  32.         ror     TV3
  33.         ror     TV2
  34.         ror     TV1
  35.         ror     TV0
  36.         ;
  37. S11P:
  38.         lsr     TV4
  39.         ror     TV3
  40.         ror     TV2
  41.         ror     TV1
  42.         ror     TV0
  43.         ;
  44. S10P:
  45.         lsr     TV4
  46.         ror     TV3
  47.         ror     TV2
  48.         ror     TV1
  49.         ror     TV0
  50.         ;
  51. S9P:
  52.         lsr     TV4
  53.         ror     TV3
  54.         ror     TV2
  55.         ror     TV1
  56.         ror     TV0
  57.         ;
  58. S8P:                            ; move a whole byte to next byte
  59.         mov     TV0,TV1         ; do first right most byte
  60.         mov     TV1,TV2
  61.         mov     TV2,TV3
  62.         mov     TV3,TV4
  63.         clr     TV4     
  64.         rjmp    AddTV           ; jump to add the result to final value
  65.         ;
  66. S7P:
  67.         lsr     TV4
  68.         ror     TV3
  69.         ror     TV2
  70.         ror     TV1
  71.         ror     TV0
  72.         ;
  73. S6P:
  74.         lsr     TV4
  75.         ror     TV3
  76.         ror     TV2
  77.         ror     TV1
  78.         ror     TV0
  79.         ;
  80. S5P:
  81.         lsr     TV4
  82.         ror     TV3
  83.         ror     TV2
  84.         ror     TV1
  85.         ror     TV0
  86.         ;
  87. S4P:
  88.         lsr     TV4
  89.         ror     TV3
  90.         ror     TV2
  91.         ror     TV1
  92.         ror     TV0
  93.         ;
  94. S3P:
  95.         lsr     TV4
  96.         ror     TV3
  97.         ror     TV2
  98.         ror     TV1
  99.         ror     TV0
  100.         ;
  101. S2P:
  102.         lsr     TV4
  103.         ror     TV3
  104.         ror     TV2
  105.         ror     TV1
  106.         ror     TV0
  107.         ;
  108. S1P:
  109.         lsr     TV4
  110.         ror     TV3
  111.         ror     TV2
  112.         ror     TV1
  113.         ror     TV0                        
  114.         ;                // Now add the result to final value
  115. AddTV:
  116.         add     FV0,TV0
  117.         adc     FV1,TV1
  118.         adc     FV2,TV2
  119.         adc     FV3,TV3
  120.         adc     FV4,TV4        
  121.         ;
  122.         ret              ; Return to calling routine  
  123.         
  124.         ;=================================================
  125.         ; Following codes perform the shift and subtract
  126.         ;=================================================
  127.         
  128. S15M:
  129.         lsr     TV4
  130.         ror     TV3
  131.         ror     TV2
  132.         ror     TV1
  133.         ror     TV0
  134.         ;
  135. S14M:
  136.         lsr     TV4
  137.         ror     TV3
  138.         ror     TV2
  139.         ror     TV1
  140.         ror     TV0
  141.         ;
  142. S13M:
  143.         lsr     TV4
  144.         ror     TV3
  145.         ror     TV2
  146.         ror     TV1
  147.         ror     TV0
  148.         ;
  149. S12M:
  150.         lsr     TV4
  151.         ror     TV3
  152.         ror     TV2
  153.         ror     TV1
  154.         ror     TV0
  155.         ;
  156. S11M:
  157.         lsr     TV4
  158.         ror     TV3
  159.         ror     TV2
  160.         ror     TV1
  161.         ror     TV0
  162.         ;
  163. S10M:
  164.         lsr     TV4
  165.         ror     TV3
  166.         ror     TV2
  167.         ror     TV1
  168.         ror     TV0
  169.         ;
  170. S9M:
  171.         lsr     TV4
  172.         ror     TV3
  173.         ror     TV2
  174.         ror     TV1
  175.         ror     TV0
  176.         ;
  177. S8M:                            ; move a whole byte to next byte
  178.         mov     TV0,TV1         ; do first right most byte
  179.         mov     TV1,TV2
  180.         mov     TV2,TV3
  181.         mov     TV3,TV4
  182.         clr     TV4     
  183.         rjmp    SubTV           ; jump to subtract result from final value
  184.         ;
  185. S7M:
  186.         lsr     TV4
  187.         ror     TV3
  188.         ror     TV2
  189.         ror     TV1
  190.         ror     TV0
  191.         ;
  192. S6M:
  193.         lsr     TV4
  194.         ror     TV3
  195.         ror     TV2
  196.         ror     TV1
  197.         ror     TV0
  198.         ;
  199. S5M:
  200.         lsr     TV4
  201.         ror     TV3
  202.         ror     TV2
  203.         ror     TV1
  204.         ror     TV0
  205.         ;
  206. S4M:
  207.         lsr     TV4
  208.         ror     TV3
  209.         ror     TV2
  210.         ror     TV1
  211.         ror     TV0
  212.         ;
  213. S3M:
  214.         lsr     TV4
  215.         ror     TV3
  216.         ror     TV2
  217.         ror     TV1
  218.         ror     TV0
  219.         ;
  220. S2M:
  221.         lsr     TV4
  222.         ror     TV3
  223.         ror     TV2
  224.         ror     TV1
  225.         ror     TV0
  226.         ;
  227. S1M:
  228.         lsr     TV4
  229.         ror     TV3
  230.         ror     TV2
  231.         ror     TV1
  232.         ror     TV0                        
  233.         ;                // Now subtract the result from final value
  234. SubTV:
  235.         sub     FV0,TV0
  236.         sbc     FV1,TV1
  237.         sbc     FV2,TV2
  238.         sbc     FV3,TV3
  239.         sbc     FV4,TV4
  240.         ;
  241.         ret        
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-6-18 09:35:26 | 显示全部楼层
表示不明觉厉。。我是属于9850玩出波形就over了的那种。   。 。 。

出0入0汤圆

 楼主| 发表于 2013-6-18 09:36:37 | 显示全部楼层
Can you(or anyone) do better?


if I could use a different chip:



two calls to ad9850_f2w takes 1,430us - 796us = 630us, or 310us per call, on a 1MIPS PIC24F.

in large part thanks to its barrel shift register.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-6-18 09:38:08 | 显示全部楼层
The difference is that you could optimize for a specific situation in assembler. Mine is done in C and is generic. so you pay for its ease of use and portability.

出0入0汤圆

 楼主| 发表于 2013-6-18 10:01:47 | 显示全部楼层
Now, that routine can be further enhanced. For example, you really don't need BitCount to control the loop. You can exit once Dividend has reached zero -> it can greatly speed up the execution for frequencies that are 2's multiples, like 32768hz.

出0入0汤圆

发表于 2013-6-18 10:27:25 | 显示全部楼层
Well said. Generic C is easier to understand and portable.   

出0入0汤圆

 楼主| 发表于 2013-6-21 07:29:41 | 显示全部楼层
Here is the first successful run of the code.
  1. //12F675 controller for ebay AD9850 module
  2. //connection:
  3. //AN0: analog voltage input, selects output band;
  4. //AN1: analog voltage input, controls output frequency (when not in the scanning mode)
  5. //GPIO3: digital pull-up/down: up: scanning (default). down: user selectable output frequency (per AN1)
  6. //GPIO2: to AD9850 WCLK
  7. //GPIO4: to AD9850 FQ_UD
  8. //GPIO5: to AD9850 SDATA

  9. //history:
  10. //v1.0 / 6/20/2013: first run.

  11. #include <htc.h>                                                //we use picc
  12. #include "gpio.h"
  13. #include "config.h"                                                //configuration words
  14. #include "delay.h"                                                //we use software delay
  15. #include "ad9850.h"                                                //we use ad9850
  16. #include "adc.h"                                                //we use hardware adc

  17. //hardware configuration
  18. //scan switch
  19. #define SCAN_PORT        GPIO
  20. #define SCAN_DDR        TRISIO
  21. #define SCAN_PIN        (1<<3)                                //scan switch on gpio3. 1->output set frequency. 0-> scan
  22. #define IS_SCAN(pin)        IO_GET(SCAN_PORT, pin)        //return 1 if pin is high (in scanning mode), weak pull-up default to on

  23. //freq pot
  24. #define FREQ_ADC        ADC_AN1                                //frequency pot on adc_an1
  25. #define BAND_ADC        ADC_AN0                                //band adc on adc_an0

  26. #define FREQ_STEP        1023                                //how many steps in a band
  27. #define FREQ_DLY        20                                        //delays per step
  28. #define N_BANDS                14                                        //number of bands

  29. //hardware configuration

  30. //global define
  31. typedef struct {
  32.         unsigned long fstart, fend;                        //starting and ending frequencies
  33.         //unsigned char threshold;                        //band threshold
  34.         unsigned char dly;                                        //delay in each step, in ms
  35. } BAND_T;

  36. //global variable
  37. //frequency bands
  38. const BAND_T freq_bands[N_BANDS]={
  39.         //Fstart, Fend, DLY, /*THRESHOLD*/.
  40.         {10700000ul - 100000ul, 10700000ul + 100000ul, 10},        //FM if scan, +/- 100Khz bandwidth
  41.         {1, 20000, 30},                                        //audio frequencies
  42.         {10000ul, 600000ul, 20},                        //sub RF (LW band)
  43.         {153000ul, 279000ul, 30},                        //LW band
  44.         {500000ul, 1700000ul, 30},                        //am broadcast band
  45.         {1500000ul, 2300000ul, 30},                //1.5Mhz - 2.3Mhz,
  46.         {2100000ul, 3200000ul, 30},                //2.1Mhz - 3.2Mhz. 120m band
  47.         {3100000ul, 4600000ul, 30},                //3.1Mhz - 4.6Mhz. 90m and 75m bands
  48.         {4500000ul, 6700000ul, 30},                //4.5Mhz - 6.7Mhz. 60m and 49m bands
  49.         {6600000ul, 9600000ul, 30},                //6.6Mhz - 9.6Mhz. 41m and 31m (partial) bands
  50.         {9300000ul, 14000000ul, 30},                //9.3Mhz - 14.Mhz. 31m, 25m and 22m bands - may want to split this further
  51.         {1300000ul, 20000000ul, 30},                //13.Mhz - 20.Mhz. 22m, 19m, 16m, 15m bands - may want to split this further
  52.         {500000ul, 20000000ul, 30},                        //rf band, default if band pin is pulled high
  53.         {455000ul - 20000ul, 465000ul + 20000ul, 30}                //455K/465K IF scan, +/- 20Khz bandwidth. default output if BAND_ADC is grounded
  54.         //{465000ul - 20000ul, 465000ul + 20000ul, 300},                //465K if scan, +/- 20Khz bandwidth
  55. };

  56. unsigned char band=0;                                        //band to tune
  57. unsigned char mode=1;                                        //mode. 0=output to a set frequency. 1=scan
  58. unsigned long freq;                                                //output frequency
  59. unsigned long freq_step;                                //frequency step, major
  60. //unsigned long freq_minor;                                //frequency step, minor

  61. //read the band setting
  62. unsigned char adc_band(void) {
  63.         unsigned char i;
  64.         unsigned char tmp;
  65.        
  66.         tmp=adc_read(BAND_ADC)>>2;                        //read band, as unsigned char
  67.         for (i=1; i<N_BANDS; i++)
  68.                 if (tmp < /*freq_bands[i].threshold*/((unsigned short) i<<8) / N_BANDS) return i-1;
  69.         return N_BANDS-1;                                        //default is 0
  70. }

  71. //read the frequency / step from a pot
  72. unsigned short adc_freq(void) {
  73.         return adc_read(FREQ_ADC);
  74.         //return 200;                                                //for debugging purposes only
  75. }

  76. //output a frequency
  77. void out_freq(void) {
  78.         static unsigned char band_prev=0xff;        //previous band
  79.         static unsigned char mode_prev=0xff;        //previous mode.
  80.         static unsigned short step_current=0;        //current step, major
  81.         //static unsigned short step_minor=0;                //current step, minor
  82.         static unsigned long freq_prev=0;        //previous output frequency
  83.        
  84.         if (band ^ band_prev) {                                //has band changed?
  85.                 freq_step = (freq_bands[band].fend - freq_bands[band].fstart) >> 10;        //calculat the frequency steps
  86.                 freq_prev = 0;                                        //reset previous frequency
  87.                 band_prev = band;                                //update band_prev
  88.         }
  89.                
  90.         if (!mode) {                                                //output a set frequency
  91.                 step_current = adc_freq();                //read the steps
  92.         } else {                                                        //output a scan
  93.                 step_current=(step_current == FREQ_STEP)?0:(step_current+1);        //increment steps
  94.         }

  95.         //generate the next frequency
  96.         freq = freq_bands[band].fstart + freq_step * step_current;
  97.         if (freq ^ freq_prev) {
  98.                 ad9850_freq(freq);                                //output the frequency
  99.                 freq_prev = freq;                                //update freq_prev
  100.         }
  101.        
  102.         delay_ms(freq_bands[band].dly);                //waste some time
  103. }

  104. //not used
  105. //tune to a frequency (step in [Fstart, Fend]) in a band
  106. void tune_freq(unsigned char band, unsigned short freq) {
  107.         static unsigned char band_prev=0;        //previous band
  108.         static unsigned short freq_prev=0;        //previous step
  109.         if ((band ^ band_prev) || (freq ^ freq_prev)) {        //execute only if band or step has changed
  110.                 ad9850_freq(freq_bands[band].fstart+((freq_bands[band].fend-freq_bands[band].fstart) >> 10) * freq);
  111.                 band_prev = band;
  112.                 freq_prev = freq;
  113.         }
  114.         delay_ms(freq_bands[band].dly);                //waste some time
  115. }

  116. //not used
  117. //sweep frequency in a band
  118. void sweep_freq(unsigned char band) {
  119.         //unsigned long freq;
  120.         static unsigned long fdelta;
  121.         static unsigned short step_current=0;
  122.         //static unsigned long fstart, fend;
  123.        
  124.         if (step_current)
  125.                 ad9850_freq(freq_bands[band].fstart + fdelta * step_current);        //set the frequency
  126.         else {
  127.                 ad9850_freq(freq_bands[band].fstart);        //start the frequency
  128.                 fdelta = ((freq_bands[band].fend - freq_bands[band].fstart) >> 10);        //frequency increment
  129.         }
  130.         //increment step_current
  131.         step_current=(step_current == FREQ_STEP)?0:(step_current+1);
  132.         delay_ms(freq_bands[band].dly);                //waste some time
  133. }

  134. void mcu_init(void) {                                        //initialize the mcu
  135.         ANSEL = 0x00;                                                //porta are digital io
  136.         //ANSELH = 0x00;                                                //all portB is digital io
  137.         CMCON = 0x07;                                                //analog comparators off
  138.         //IRCF2=1, IRCF1=1, IRCF0=0;                        //running at 4Mhz
  139.        
  140.         //enable weak pull-up
  141.         GPPU = 0;                                                        //enable gppu
  142.         WPU = 0xff;                                                        //enable weak pull-up on all pins

  143.         //scan pin as input
  144.         //not necessary on 12f675 as gpio3 is only input capable
  145.         IO_IN(SCAN_DDR, SCAN_PIN);

  146.         //initialize frequency step
  147.         freq_step = ((freq_bands[band].fend - freq_bands[band].fstart) >> 10);        //calculat the frequency steps
  148. }

  149. //main program
  150. int main(void) {
  151.         //unsigned short i;
  152.         //unsigned long freq;
  153.         static unsigned short count=0;
  154.         mcu_init();                                                        //initialize the mcu
  155.         adc_init();                                                        //reset the adc module
  156.         ad9850_init();                                                //reset ad9850
  157.         //ad9850_freq(AD9850_1Khz);                        //2^32 / (125Mhz / 1Mhz) =34359738->1Mhz
  158.         //ad9850_freq(ad9850_f2w(AD9850_100Khz));
  159.         mode = 1;                                                        //defaults to scan
  160.         band = N_BANDS-1;                                        //default band, 455k IF
  161.         while (1) {
  162.                 band=adc_band();                                //read the band setting
  163.                 mode=IS_SCAN(SCAN_PIN);                        //1 for fixed frequency and 0 for scanning
  164.                 out_freq();                                                //output the frequency
  165.         }
  166. }
复制代码
The controller can act as a scanner or output a user-selectable frequency. Another pot will select the output band.

I can report that it functions perfectly, :)

出0入0汤圆

 楼主| 发表于 2013-6-21 07:30:05 | 显示全部楼层
The rom is 94.5% used, :)

出0入0汤圆

 楼主| 发表于 2013-6-26 06:05:36 | 显示全部楼层
The minimalist implementation above requires a lot of real estate to calibrate the dial to control the output frequency. An easier alternative is to use an lcd, :)

so I am porting the code to a 16f674 (pdip14 chip), with 12 gpio pins: 3 for the ad9850 module, 2 for the pots, 1 for the mode switch, and 6 for the lcd (in 4-bit mode).

here is the code, without the lcd module:
  1. //12F675 controller for ebay AD9850 module
  2. //connection:
  3. //AN0: analog voltage input, selects output band;
  4. //AN1: analog voltage input, controls output frequency (when not in the scanning mode)
  5. //GPIO3: digital pull-up/down: up: scanning (default). down: user selectable output frequency (per AN1)
  6. //GPIO2: to AD9850 WCLK
  7. //GPIO4: to AD9850 FQ_UD
  8. //GPIO5: to AD9850 SDATA

  9. //history:
  10. //v1.0 / 6/20/2013: first run.

  11. #include <htc.h>                                                //we use picc
  12. #include "gpio.h"
  13. #include "config.h"                                                //configuration words
  14. #include "delay.h"                                                //we use software delay
  15. #include "ad9850.h"                                                //we use ad9850
  16. #include "adc.h"                                                //we use hardware adc

  17. //hardware configuration
  18. //scan switch
  19. #define SCAN_PORT        PORTA
  20. #define SCAN_DDR        TRISA
  21. #define SCAN_PIN        (1<<3)                                //scan switch on gpio3. 1->output set frequency. 0-> scan
  22. #define IS_SCAN(pin)        IO_GET(SCAN_PORT, pin)        //return 1 if pin is high (in scanning mode), weak pull-up default to on

  23. //freq pot
  24. #define FREQ_ADC        ADC_AN1                                //frequency pot on adc_an1
  25. #define BAND_ADC        ADC_AN0                                //band adc on adc_an0

  26. #define FREQ_STEP        1023                                //how many steps in a band
  27. #define FREQ_DLY        20                                        //delays per step
  28. #define N_BANDS                14                                        //number of bands

  29. //hardware configuration

  30. //global define
  31. typedef struct {
  32.         unsigned long fstart, fend;                        //starting and ending frequencies
  33.         //unsigned char threshold;                        //band threshold
  34.         unsigned char dly;                                        //delay in each step, in ms
  35. } BAND_T;

  36. //global variable
  37. //frequency bands
  38. const BAND_T freq_bands[N_BANDS]={
  39.         //Fstart, Fend, DLY, /*THRESHOLD*/.
  40.         {10700000ul - 100000ul, 10700000ul + 100000ul, 10},        //FM if scan, +/- 100Khz bandwidth
  41.         {1, 20000, 30},                                        //audio frequencies
  42.         {10000ul, 600000ul, 20},                        //sub RF (LW band)
  43.         {153000ul, 279000ul, 30},                        //LW band
  44.         {500000ul, 1700000ul, 30},                        //am broadcast band
  45.         {1500000ul, 2300000ul, 30},                //1.5Mhz - 2.3Mhz,
  46.         {2100000ul, 3200000ul, 30},                //2.1Mhz - 3.2Mhz. 120m band
  47.         {3100000ul, 4600000ul, 30},                //3.1Mhz - 4.6Mhz. 90m and 75m bands
  48.         {4500000ul, 6700000ul, 30},                //4.5Mhz - 6.7Mhz. 60m and 49m bands
  49.         {6600000ul, 9600000ul, 30},                //6.6Mhz - 9.6Mhz. 41m and 31m (partial) bands
  50.         {9300000ul, 14000000ul, 30},                //9.3Mhz - 14.Mhz. 31m, 25m and 22m bands - may want to split this further
  51.         {1300000ul, 20000000ul, 30},                //13.Mhz - 20.Mhz. 22m, 19m, 16m, 15m bands - may want to split this further
  52.         {500000ul, 20000000ul, 30},                        //rf band, default if band pin is pulled high
  53.         {455000ul - 20000ul, 465000ul + 20000ul, 30}                //455K/465K IF scan, +/- 20Khz bandwidth. default output if BAND_ADC is grounded
  54.         //{465000ul - 20000ul, 465000ul + 20000ul, 300},                //465K if scan, +/- 20Khz bandwidth
  55. };

  56. unsigned char band=0;                                        //band to tune
  57. unsigned char mode=1;                                        //mode. 0=output to a set frequency. 1=scan
  58. unsigned long freq;                                                //output frequency
  59. unsigned long freq_step;                                //frequency step, major
  60. //unsigned long freq_minor;                                //frequency step, minor

  61. //read the band setting
  62. unsigned char adc_band(void) {
  63.         unsigned char i;
  64.         unsigned char tmp;
  65.        
  66.         tmp=adc_read(BAND_ADC)>>2;                        //read band, as unsigned char
  67.         for (i=1; i<N_BANDS; i++)
  68.                 if (tmp < /*freq_bands[i].threshold*/((unsigned short) i<<8) / N_BANDS) return i-1;
  69.         return N_BANDS-1;                                        //default is 0
  70. }

  71. //read the frequency / step from a pot
  72. unsigned short adc_freq(void) {
  73.         return adc_read(FREQ_ADC);
  74.         //return 200;                                                //for debugging purposes only
  75. }

  76. //output a frequency
  77. void out_freq(void) {
  78.         static unsigned char band_prev=0xff;        //previous band
  79.         static unsigned char mode_prev=0xff;        //previous mode.
  80.         static unsigned short step_current=0;        //current step, major
  81.         //static unsigned short step_minor=0;                //current step, minor
  82.         static unsigned long freq_prev=0;        //previous output frequency
  83.        
  84.         if (band ^ band_prev) {                                //has band changed?
  85.                 freq_step = (freq_bands[band].fend - freq_bands[band].fstart) >> 10;        //calculat the frequency steps
  86.                 freq_prev = 0;                                        //reset previous frequency
  87.                 band_prev = band;                                //update band_prev
  88.         }
  89.                
  90.         if (!mode) {                                                //output a set frequency
  91.                 step_current = adc_freq();                //read the steps
  92.         } else {                                                        //output a scan
  93.                 step_current=(step_current == FREQ_STEP)?0:(step_current+1);        //increment steps
  94.         }

  95.         //generate the next frequency
  96.         freq = freq_bands[band].fstart + freq_step * step_current;
  97.         if (freq ^ freq_prev) {
  98.                 ad9850_freq(freq);                                //output the frequency
  99.                 freq_prev = freq;                                //update freq_prev
  100.         }
  101.        
  102.         delay_ms(freq_bands[band].dly);                //waste some time
  103. }

  104. //not used
  105. //tune to a frequency (step in [Fstart, Fend]) in a band
  106. void tune_freq(unsigned char band, unsigned short freq) {
  107.         static unsigned char band_prev=0;        //previous band
  108.         static unsigned short freq_prev=0;        //previous step
  109.         if ((band ^ band_prev) || (freq ^ freq_prev)) {        //execute only if band or step has changed
  110.                 ad9850_freq(freq_bands[band].fstart+((freq_bands[band].fend-freq_bands[band].fstart) >> 10) * freq);
  111.                 band_prev = band;
  112.                 freq_prev = freq;
  113.         }
  114.         delay_ms(freq_bands[band].dly);                //waste some time
  115. }

  116. //not used
  117. //sweep frequency in a band
  118. void sweep_freq(unsigned char band) {
  119.         //unsigned long freq;
  120.         static unsigned long fdelta;
  121.         static unsigned short step_current=0;
  122.         //static unsigned long fstart, fend;
  123.        
  124.         if (step_current)
  125.                 ad9850_freq(freq_bands[band].fstart + fdelta * step_current);        //set the frequency
  126.         else {
  127.                 ad9850_freq(freq_bands[band].fstart);        //start the frequency
  128.                 fdelta = ((freq_bands[band].fend - freq_bands[band].fstart) >> 10);        //frequency increment
  129.         }
  130.         //increment step_current
  131.         step_current=(step_current == FREQ_STEP)?0:(step_current+1);
  132.         delay_ms(freq_bands[band].dly);                //waste some time
  133. }

  134. void mcu_init(void) {                                        //initialize the mcu
  135.         ANSEL = 0x00;                                                //porta are digital io
  136.         //ANSELH = 0x00;                                                //all portB is digital io
  137.         CMCON0 = 0x07;                                                //analog comparators off
  138.         IRCF2=1, IRCF1=1, IRCF0=0;                        //running at 4Mhz
  139.        
  140.         //enable weak pull-up
  141.         RAPU = 0;                                                        //enable weak pull-up on porta
  142.         WPUA = 0xff;                                                //enable weak pull-up on all pins

  143.         //scan pin as input
  144.         //not necessary on 12f675 as gpio3 is only input capable
  145.         IO_IN(SCAN_DDR, SCAN_PIN);

  146.         //initialize frequency step
  147.         freq_step = ((freq_bands[band].fend - freq_bands[band].fstart) >> 10);        //calculat the frequency steps
  148. }

  149. //main program
  150. int main(void) {
  151.         //unsigned short i;
  152.         //unsigned long freq;
  153.         static unsigned short count=0;
  154.         mcu_init();                                                        //initialize the mcu
  155.         adc_init();                                                        //reset the adc module
  156.         ad9850_init();                                                //reset ad9850
  157.         //ad9850_freq(AD9850_1Khz);                        //2^32 / (125Mhz / 1Mhz) =34359738->1Mhz
  158.         //ad9850_freq(ad9850_f2w(AD9850_100Khz));
  159.         mode = 1;                                                        //defaults to scan
  160.         band = N_BANDS-1;                                        //default band, 455k IF
  161.         while (1) {
  162.                 band=adc_band();                                //read the band setting
  163.                 mode=IS_SCAN(SCAN_PIN);                        //1 for fixed frequency and 0 for scanning
  164.                 out_freq();                                                //output the frequency
  165.         }
  166. }
复制代码
As you can see, it is identical to the 12f675 version, other than some defines at the beginning and the mcu_init() module, to reset the mcu and to enable weak pull-up on the PORTA pins.

I will add the lcd module later. Right now, the flash is about 50% used.

出0入0汤圆

 楼主| 发表于 2013-6-26 06:15:53 | 显示全部楼层
Now, the lcd support is up and running!
  1. //16F684 controller for ebay AD9850 module
  2. //connection:
  3. //AN0: analog voltage input, selects output band;
  4. //AN1: analog voltage input, controls output frequency (when not in the scanning mode)
  5. //PORTA3: digital pull-up/down: up: scanning (default). down: user selectable output frequency (per AN1)
  6. //PORTA2: to AD9850 WCLK
  7. //PORTA4: to AD9850 FQ_UD
  8. //PORTA5: to AD9850 SDATA

  9. //history:
  10. //v1.0 / 6/20/2013: first run.

  11. #include <htc.h>                                                //we use picc
  12. #include <string.h>                                                //we use strcpy
  13. #include "gpio.h"
  14. #include "config.h"                                                //configuration words
  15. #include "delay.h"                                                //we use software delay
  16. #include "ad9850.h"                                                //we use ad9850
  17. #include "adc.h"                                                //we use hardware adc
  18. #include "lcd_4bit.h"                                        //we use the lcd module, in 4-bit mode
  19. #include "misc.h"                                                //we use ultoa()

  20. //hardware configuration
  21. //scan switch
  22. #define SCAN_PORT        PORTA
  23. #define SCAN_DDR        TRISA
  24. #define SCAN_PIN        (1<<3)                                //scan switch on gpio3. 1->output set frequency. 0-> scan
  25. #define IS_SCAN(pin)        IO_GET(SCAN_PORT, pin)        //return 1 if pin is high (in scanning mode), weak pull-up default to on

  26. //freq pot
  27. #define FREQ_ADC        ADC_AN1                                //frequency pot on adc_an1
  28. #define BAND_ADC        ADC_AN0                                //band adc on adc_an0

  29. #define FREQ_STEP        1023                                //how many steps in a band
  30. #define FREQ_DLY        20                                        //delays per step
  31. #define N_BANDS                14                                        //number of bands

  32. //hardware configuration

  33. //global define
  34. typedef struct {
  35.         unsigned long fstart, fend;                        //starting and ending frequencies
  36.         //unsigned char threshold;                        //band threshold
  37.         unsigned char dly;                                        //delay in each step, in ms
  38. } BAND_T;

  39. //global variable
  40. //frequency bands
  41. const BAND_T freq_bands[N_BANDS]={
  42.         //Fstart, Fend, DLY, /*THRESHOLD*/.
  43.         {10700000ul - 100000ul, 10700000ul + 100000ul, 10},        //FM if scan, +/- 100Khz bandwidth
  44.         {1, 20000, 30},                                        //audio frequencies
  45.         {10000ul, 600000ul, 20},                        //sub RF (LW band)
  46.         {153000ul, 279000ul, 30},                        //LW band
  47.         {500000ul, 1700000ul, 30},                        //am broadcast band
  48.         {1500000ul, 2300000ul, 30},                //1.5Mhz - 2.3Mhz,
  49.         {2100000ul, 3200000ul, 30},                //2.1Mhz - 3.2Mhz. 120m band
  50.         {3100000ul, 4600000ul, 30},                //3.1Mhz - 4.6Mhz. 90m and 75m bands
  51.         {4500000ul, 6700000ul, 30},                //4.5Mhz - 6.7Mhz. 60m and 49m bands
  52.         {6600000ul, 9600000ul, 30},                //6.6Mhz - 9.6Mhz. 41m and 31m (partial) bands
  53.         {9300000ul, 14000000ul, 30},                //9.3Mhz - 14.Mhz. 31m, 25m and 22m bands - may want to split this further
  54.         {1300000ul, 20000000ul, 30},                //13.Mhz - 20.Mhz. 22m, 19m, 16m, 15m bands - may want to split this further
  55.         {500000ul, 20000000ul, 30},                        //rf band, default if band pin is pulled high
  56.         {455000ul - 20000ul, 465000ul + 20000ul, 30}                //455K/465K IF scan, +/- 20Khz bandwidth. default output if BAND_ADC is grounded
  57.         //{465000ul - 20000ul, 465000ul + 20000ul, 300},                //465K if scan, +/- 20Khz bandwidth
  58. };

  59. //lcd strings
  60. const unsigned char str0[]="AD9850 SigGenv1";
  61. const unsigned char str1[]="f=           Hz";
  62. unsigned char vRAM[17];                                        //display buffer
  63. unsigned long freq_prev=0;                                //previous frequency

  64. unsigned char band=0;                                        //band to tune
  65. unsigned char mode=1;                                        //mode. 0=output to a set frequency. 1=scan
  66. unsigned long freq;                                                //output frequency
  67. unsigned long freq_step;                                //frequency step, major
  68. //unsigned long freq_minor;                                //frequency step, minor

  69. //read the band setting
  70. unsigned char adc_band(void) {
  71.         unsigned char i;
  72.         unsigned char tmp;
  73.        
  74.         tmp=adc_read(BAND_ADC)>>2;                        //read band, as unsigned char
  75.         for (i=1; i<N_BANDS; i++)
  76.                 if (tmp < /*freq_bands[i].threshold*/((unsigned short) i<<8) / N_BANDS) return i-1;
  77.         return N_BANDS-1;                                        //default is 0
  78. }

  79. //read the frequency / step from a pot
  80. unsigned short adc_freq(void) {
  81.         return adc_read(FREQ_ADC);
  82.         //return 200;                                                //for debugging purposes only
  83. }

  84. //output a frequency
  85. void out_freq(void) {
  86.         static unsigned char band_prev=0xff;        //previous band
  87.         static unsigned char mode_prev=0xff;        //previous mode.
  88.         static unsigned short step_current=0;        //current step, major
  89.         //static unsigned short step_minor=0;                //current step, minor
  90.         static unsigned long freq_prev=0;        //previous output frequency
  91.        
  92.         if (band ^ band_prev) {                                //has band changed?
  93.                 freq_step = (freq_bands[band].fend - freq_bands[band].fstart) >> 10;        //calculat the frequency steps
  94.                 freq_prev = 0;                                        //reset previous frequency
  95.                 band_prev = band;                                //update band_prev
  96.         }
  97.                
  98.         if (!mode) {                                                //output a set frequency
  99.                 step_current = adc_freq();                //read the steps
  100.         } else {                                                        //output a scan
  101.                 step_current=(step_current == FREQ_STEP)?0:(step_current+1);        //increment steps
  102.         }

  103.         //generate the next frequency
  104.         freq = freq_bands[band].fstart + freq_step * step_current;
  105.         if (freq ^ freq_prev) {
  106.                 ad9850_freq(freq);                                //output the frequency
  107.                 freq_prev = freq;                                //update freq_prev
  108.         }
  109.        
  110.         delay_ms(freq_bands[band].dly);                //waste some time
  111. }

  112. //not used
  113. //tune to a frequency (step in [Fstart, Fend]) in a band
  114. void tune_freq(unsigned char band, unsigned short freq) {
  115.         static unsigned char band_prev=0;        //previous band
  116.         static unsigned short freq_prev=0;        //previous step
  117.         if ((band ^ band_prev) || (freq ^ freq_prev)) {        //execute only if band or step has changed
  118.                 ad9850_freq(freq_bands[band].fstart+((freq_bands[band].fend-freq_bands[band].fstart) >> 10) * freq);
  119.                 band_prev = band;
  120.                 freq_prev = freq;
  121.         }
  122.         delay_ms(freq_bands[band].dly);                //waste some time
  123. }

  124. //not used
  125. //sweep frequency in a band
  126. void sweep_freq(unsigned char band) {
  127.         //unsigned long freq;
  128.         static unsigned long fdelta;
  129.         static unsigned short step_current=0;
  130.         //static unsigned long fstart, fend;
  131.        
  132.         if (step_current)
  133.                 ad9850_freq(freq_bands[band].fstart + fdelta * step_current);        //set the frequency
  134.         else {
  135.                 ad9850_freq(freq_bands[band].fstart);        //start the frequency
  136.                 fdelta = ((freq_bands[band].fend - freq_bands[band].fstart) >> 10);        //frequency increment
  137.         }
  138.         //increment step_current
  139.         step_current=(step_current == FREQ_STEP)?0:(step_current+1);
  140.         delay_ms(freq_bands[band].dly);                //waste some time
  141. }

  142. void mcu_init(void) {                                        //initialize the mcu
  143.         ANSEL = 0x00;                                                //porta are digital io
  144.         //ANSELH = 0x00;                                                //all portB is digital io
  145.         CMCON0 = 0x07;                                                //analog comparators off
  146.         IRCF2=1, IRCF1=1, IRCF0=0;                        //running at 4Mhz
  147.        
  148.         //enable weak pull-up
  149.         RAPU = 0;                                                        //enable weak pull-up on porta
  150.         WPUA = 0xff;                                                //enable weak pull-up on all pins

  151.         //scan pin as input
  152.         //not necessary on 12f675 as gpio3 is only input capable
  153.         IO_IN(SCAN_DDR, SCAN_PIN);

  154.         //initialize frequency step
  155.         freq_step = ((freq_bands[band].fend - freq_bands[band].fstart) >> 10);        //calculat the frequency steps
  156. }

  157. //main program
  158. int main(void) {
  159.         //unsigned short i;
  160.         //unsigned long freq;
  161.         static unsigned short count=0;
  162.         mcu_init();                                                        //initialize the mcu
  163.         lcd_init();                                                        //reset the lcd
  164.         adc_init();                                                        //reset the adc module
  165.         ad9850_init();                                                //reset ad9850
  166.         strcpy(vRAM, str0); lcd_display(LCD_Line0, vRAM);        //display the signon message
  167.         strcpy(vRAM, str1);                                        //prepare line1
  168.         ultoa(&vRAM[2], freq, 10);                        //convert freq
  169.         lcd_display(LCD_Line1, vRAM);                //display line1
  170.         //ad9850_freq(AD9850_1Khz);                        //2^32 / (125Mhz / 1Mhz) =34359738->1Mhz
  171.         //ad9850_freq(ad9850_f2w(AD9850_100Khz));
  172.         mode = 1;                                                        //defaults to scan
  173.         band = N_BANDS-1;                                        //default band, 455k IF
  174.         while (1) {
  175.                 band=adc_band();                                //read the band setting
  176.                 mode=IS_SCAN(SCAN_PIN);                        //1 for fixed frequency and 0 for scanning
  177.                 out_freq();                                                //output the frequency
  178.                 if (freq ^ freq_prev) {                        //frequency has changed -> update the display
  179.                         freq_prev=freq;                                //update the frequency
  180.                         strcpy(vRAM, str1);                                        //prepare line1
  181.                         ultoa(&vRAM[2], freq, 10);                        //convert freq
  182.                         lcd_display(LCD_Line1, vRAM);                //display line1
  183.                 }
  184.         }
  185. }
复制代码
the flash is 72% used -> still lots of space to waste, :)

出0入0汤圆

 楼主| 发表于 2013-6-26 06:25:22 | 显示全部楼层
slight revision:
  1. //16F684 controller for ebay AD9850 module
  2. //connection:
  3. //AN0: analog voltage input, selects output band;
  4. //AN1: analog voltage input, controls output frequency (when not in the scanning mode)
  5. //PORTA3: digital pull-up/down: up: scanning (default). down: user selectable output frequency (per AN1)
  6. //PORTA2: to AD9850 WCLK
  7. //PORTA4: to AD9850 FQ_UD
  8. //PORTA5: to AD9850 SDATA

  9. //history:
  10. //v1.0 / 6/25/2013: first run.

  11. #include <htc.h>                                                //we use picc
  12. #include <string.h>                                                //we use strcpy
  13. #include "gpio.h"
  14. #include "config.h"                                                //configuration words
  15. #include "delay.h"                                                //we use software delay
  16. #include "ad9850.h"                                                //we use ad9850
  17. #include "adc.h"                                                //we use hardware adc
  18. #include "lcd_4bit.h"                                        //we use the lcd module, in 4-bit mode
  19. #include "misc.h"                                                //we use ultoa()

  20. //hardware configuration
  21. //scan switch
  22. #define SCAN_PORT        PORTA
  23. #define SCAN_DDR        TRISA
  24. #define SCAN_PIN        (1<<3)                                //scan switch on gpio3. 1->output set frequency. 0-> scan
  25. #define IS_SCAN(pin)        IO_GET(SCAN_PORT, pin)        //return 1 if pin is high (in scanning mode), weak pull-up default to on

  26. //freq pot
  27. #define FREQ_ADC        ADC_AN1                                //frequency pot on adc_an1
  28. #define BAND_ADC        ADC_AN0                                //band adc on adc_an0

  29. #define FREQ_STEP        1023                                //how many steps in a band
  30. #define FREQ_DLY        20                                        //delays per step
  31. #define N_BANDS                14                                        //number of bands

  32. //hardware configuration

  33. //global define
  34. typedef struct {
  35.         unsigned long fstart, fend;                        //starting and ending frequencies
  36.         //unsigned char threshold;                        //band threshold
  37.         unsigned char dly;                                        //delay in each step, in ms
  38. } BAND_T;

  39. //global variable
  40. //frequency bands
  41. const BAND_T freq_bands[N_BANDS]={
  42.         //Fstart, Fend, DLY, /*THRESHOLD*/.
  43.         {10700000ul - 100000ul, 10700000ul + 100000ul, 10},        //FM if scan, +/- 100Khz bandwidth
  44.         {1, 20000, 30},                                        //audio frequencies
  45.         {10000ul, 600000ul, 20},                        //sub RF (LW band)
  46.         {153000ul, 279000ul, 30},                        //LW band
  47.         {500000ul, 1700000ul, 30},                        //am broadcast band
  48.         {1500000ul, 2300000ul, 30},                //1.5Mhz - 2.3Mhz,
  49.         {2100000ul, 3200000ul, 30},                //2.1Mhz - 3.2Mhz. 120m band
  50.         {3100000ul, 4600000ul, 30},                //3.1Mhz - 4.6Mhz. 90m and 75m bands
  51.         {4500000ul, 6700000ul, 30},                //4.5Mhz - 6.7Mhz. 60m and 49m bands
  52.         {6600000ul, 9600000ul, 30},                //6.6Mhz - 9.6Mhz. 41m and 31m (partial) bands
  53.         {9300000ul, 14000000ul, 30},                //9.3Mhz - 14.Mhz. 31m, 25m and 22m bands - may want to split this further
  54.         {1300000ul, 20000000ul, 30},                //13.Mhz - 20.Mhz. 22m, 19m, 16m, 15m bands - may want to split this further
  55.         {500000ul, 20000000ul, 30},                        //rf band, default if band pin is pulled high
  56.         {455000ul - 20000ul, 465000ul + 20000ul, 30}                //455K/465K IF scan, +/- 20Khz bandwidth. default output if BAND_ADC is grounded
  57.         //{465000ul - 20000ul, 465000ul + 20000ul, 300},                //465K if scan, +/- 20Khz bandwidth
  58. };

  59. //lcd strings
  60. const unsigned char str0[]="AD9850 SigGen v1";
  61. const unsigned char str1[]="f=            Hz";
  62. unsigned char vRAM[17];                                        //display buffer
  63. unsigned long freq_prev=0;                                //previous frequency

  64. unsigned char band=0;                                        //band to tune
  65. unsigned char mode=1;                                        //mode. 0=output to a set frequency. 1=scan
  66. unsigned long freq;                                                //output frequency
  67. unsigned long freq_step;                                //frequency step, major
  68. //unsigned long freq_minor;                                //frequency step, minor

  69. //read the band setting
  70. unsigned char adc_band(void) {
  71.         unsigned char i;
  72.         unsigned char tmp;
  73.        
  74.         tmp=adc_read(BAND_ADC)>>2;                        //read band, as unsigned char
  75.         for (i=1; i<N_BANDS; i++)
  76.                 if (tmp < /*freq_bands[i].threshold*/((unsigned short) i<<8) / N_BANDS) return i-1;
  77.         return N_BANDS-1;                                        //default is 0
  78. }

  79. //read the frequency / step from a pot
  80. unsigned short adc_freq(void) {
  81.         return adc_read(FREQ_ADC);
  82.         //return 200;                                                //for debugging purposes only
  83. }

  84. //output a frequency
  85. void out_freq(void) {
  86.         static unsigned char band_prev=0xff;        //previous band
  87.         static unsigned char mode_prev=0xff;        //previous mode.
  88.         static unsigned short step_current=0;        //current step, major
  89.         //static unsigned short step_minor=0;                //current step, minor
  90.         static unsigned long freq_prev=0;        //previous output frequency
  91.        
  92.         if (band ^ band_prev) {                                //has band changed?
  93.                 freq_step = (freq_bands[band].fend - freq_bands[band].fstart) >> 10;        //calculat the frequency steps
  94.                 freq_prev = 0;                                        //reset previous frequency
  95.                 band_prev = band;                                //update band_prev
  96.         }
  97.                
  98.         if (!mode) {                                                //output a set frequency
  99.                 step_current = adc_freq();                //read the steps
  100.         } else {                                                        //output a scan
  101.                 step_current=(step_current == FREQ_STEP)?0:(step_current+1);        //increment steps
  102.         }

  103.         //generate the next frequency
  104.         freq = freq_bands[band].fstart + freq_step * step_current;
  105.         if (freq ^ freq_prev) {
  106.                 ad9850_freq(freq);                                //output the frequency
  107.                 freq_prev = freq;                                //update freq_prev
  108.         }
  109.        
  110.         delay_ms(freq_bands[band].dly);                //waste some time
  111. }

  112. //not used
  113. //tune to a frequency (step in [Fstart, Fend]) in a band
  114. void tune_freq(unsigned char band, unsigned short freq) {
  115.         static unsigned char band_prev=0;        //previous band
  116.         static unsigned short freq_prev=0;        //previous step
  117.         if ((band ^ band_prev) || (freq ^ freq_prev)) {        //execute only if band or step has changed
  118.                 ad9850_freq(freq_bands[band].fstart+((freq_bands[band].fend-freq_bands[band].fstart) >> 10) * freq);
  119.                 band_prev = band;
  120.                 freq_prev = freq;
  121.         }
  122.         delay_ms(freq_bands[band].dly);                //waste some time
  123. }

  124. //not used
  125. //sweep frequency in a band
  126. void sweep_freq(unsigned char band) {
  127.         //unsigned long freq;
  128.         static unsigned long fdelta;
  129.         static unsigned short step_current=0;
  130.         //static unsigned long fstart, fend;
  131.        
  132.         if (step_current)
  133.                 ad9850_freq(freq_bands[band].fstart + fdelta * step_current);        //set the frequency
  134.         else {
  135.                 ad9850_freq(freq_bands[band].fstart);        //start the frequency
  136.                 fdelta = ((freq_bands[band].fend - freq_bands[band].fstart) >> 10);        //frequency increment
  137.         }
  138.         //increment step_current
  139.         step_current=(step_current == FREQ_STEP)?0:(step_current+1);
  140.         delay_ms(freq_bands[band].dly);                //waste some time
  141. }

  142. void mcu_init(void) {                                        //initialize the mcu
  143.         ANSEL = 0x00;                                                //porta are digital io
  144.         //ANSELH = 0x00;                                                //all portB is digital io
  145.         CMCON0 = 0x07;                                                //analog comparators off
  146.         IRCF2=1, IRCF1=1, IRCF0=0;                        //running at 4Mhz
  147.        
  148.         //enable weak pull-up
  149.         RAPU = 0;                                                        //enable weak pull-up on porta
  150.         WPUA = 0xff;                                                //enable weak pull-up on all pins

  151.         //scan pin as input
  152.         //not necessary on 12f675 as gpio3 is only input capable
  153.         IO_IN(SCAN_DDR, SCAN_PIN);

  154.         //initialize frequency step
  155.         freq_step = ((freq_bands[band].fend - freq_bands[band].fstart) >> 10);        //calculat the frequency steps
  156. }

  157. //main program
  158. int main(void) {
  159.         //unsigned short i;
  160.         //unsigned long freq;
  161.         static unsigned short count=0;
  162.         mcu_init();                                                        //initialize the mcu
  163.         lcd_init();                                                        //reset the lcd
  164.         adc_init();                                                        //reset the adc module
  165.         ad9850_init();                                                //reset ad9850
  166.         strcpy(vRAM, str0); lcd_display(LCD_Line0, vRAM);        //display the signon message
  167.         strcpy(vRAM, str1);                                        //prepare line1
  168.         ultoa_s(&vRAM[2], freq, 10);                //convert freq, with ','
  169.         lcd_display(LCD_Line1, vRAM);                //display line1
  170.         //ad9850_freq(AD9850_1Khz);                        //2^32 / (125Mhz / 1Mhz) =34359738->1Mhz
  171.         //ad9850_freq(ad9850_f2w(AD9850_100Khz));
  172.         mode = 1;                                                        //defaults to scan
  173.         band = N_BANDS-1;                                        //default band, 455k IF
  174.         while (1) {
  175.                 band=adc_band();                                //read the band setting
  176.                 mode=IS_SCAN(SCAN_PIN);                        //1 for fixed frequency and 0 for scanning
  177.                 out_freq();                                                //output the frequency
  178.                 if (freq ^ freq_prev) {                        //frequency has changed -> update the display
  179.                         freq_prev=freq;                                //update the frequency
  180.                         strcpy(vRAM, str1);                                        //prepare line1
  181.                         ultoa_s(&vRAM[2], freq, 12);                //convert freq, with ','
  182.                         lcd_display(LCD_Line1, vRAM);                //display line1
  183.                 }
  184.         }
  185. }
复制代码
Not fully wired up but it shows ad9850 in scan mode:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-6-26 06:27:06 | 显示全部楼层
another slight revision: re-using freq_prev:

  1. //16F684 controller for ebay AD9850 module
  2. //connection:
  3. //AN0: analog voltage input, selects output band;
  4. //AN1: analog voltage input, controls output frequency (when not in the scanning mode)
  5. //PORTA3: digital pull-up/down: up: scanning (default). down: user selectable output frequency (per AN1)
  6. //PORTA2: to AD9850 WCLK
  7. //PORTA4: to AD9850 FQ_UD
  8. //PORTA5: to AD9850 SDATA

  9. //history:
  10. //v1.0 / 6/25/2013: first run.

  11. #include <htc.h>                                                //we use picc
  12. #include <string.h>                                                //we use strcpy
  13. #include "gpio.h"
  14. #include "config.h"                                                //configuration words
  15. #include "delay.h"                                                //we use software delay
  16. #include "ad9850.h"                                                //we use ad9850
  17. #include "adc.h"                                                //we use hardware adc
  18. #include "lcd_4bit.h"                                        //we use the lcd module, in 4-bit mode
  19. #include "misc.h"                                                //we use ultoa()

  20. //hardware configuration
  21. //scan switch
  22. #define SCAN_PORT        PORTA
  23. #define SCAN_DDR        TRISA
  24. #define SCAN_PIN        (1<<3)                                //scan switch on gpio3. 1->output set frequency. 0-> scan
  25. #define IS_SCAN(pin)        IO_GET(SCAN_PORT, pin)        //return 1 if pin is high (in scanning mode), weak pull-up default to on

  26. //freq pot
  27. #define FREQ_ADC        ADC_AN1                                //frequency pot on adc_an1
  28. #define BAND_ADC        ADC_AN0                                //band adc on adc_an0

  29. #define FREQ_STEP        1023                                //how many steps in a band
  30. #define FREQ_DLY        20                                        //delays per step
  31. #define N_BANDS                14                                        //number of bands

  32. //hardware configuration

  33. //global define
  34. typedef struct {
  35.         unsigned long fstart, fend;                        //starting and ending frequencies
  36.         //unsigned char threshold;                        //band threshold
  37.         unsigned char dly;                                        //delay in each step, in ms
  38. } BAND_T;

  39. //global variable
  40. //frequency bands
  41. const BAND_T freq_bands[N_BANDS]={
  42.         //Fstart, Fend, DLY, /*THRESHOLD*/.
  43.         {10700000ul - 100000ul, 10700000ul + 100000ul, 10},        //FM if scan, +/- 100Khz bandwidth
  44.         {1, 20000, 30},                                        //audio frequencies
  45.         {10000ul, 600000ul, 20},                        //sub RF (LW band)
  46.         {153000ul, 279000ul, 30},                        //LW band
  47.         {500000ul, 1700000ul, 30},                        //am broadcast band
  48.         {1500000ul, 2300000ul, 30},                //1.5Mhz - 2.3Mhz,
  49.         {2100000ul, 3200000ul, 30},                //2.1Mhz - 3.2Mhz. 120m band
  50.         {3100000ul, 4600000ul, 30},                //3.1Mhz - 4.6Mhz. 90m and 75m bands
  51.         {4500000ul, 6700000ul, 30},                //4.5Mhz - 6.7Mhz. 60m and 49m bands
  52.         {6600000ul, 9600000ul, 30},                //6.6Mhz - 9.6Mhz. 41m and 31m (partial) bands
  53.         {9300000ul, 14000000ul, 30},                //9.3Mhz - 14.Mhz. 31m, 25m and 22m bands - may want to split this further
  54.         {1300000ul, 20000000ul, 30},                //13.Mhz - 20.Mhz. 22m, 19m, 16m, 15m bands - may want to split this further
  55.         {500000ul, 20000000ul, 30},                        //rf band, default if band pin is pulled high
  56.         {455000ul - 20000ul, 465000ul + 20000ul, 30}                //455K/465K IF scan, +/- 20Khz bandwidth. default output if BAND_ADC is grounded
  57.         //{465000ul - 20000ul, 465000ul + 20000ul, 300},                //465K if scan, +/- 20Khz bandwidth
  58. };

  59. //lcd strings
  60. const unsigned char str0[]="AD9850 SigGen v1";
  61. const unsigned char str1[]="f=            Hz";
  62. unsigned char vRAM[17];                                        //display buffer
  63. unsigned long freq_prev=0;                                //previous frequency

  64. unsigned char band=0;                                        //band to tune
  65. unsigned char mode=1;                                        //mode. 0=output to a set frequency. 1=scan
  66. unsigned long freq;                                                //output frequency
  67. unsigned long freq_step;                                //frequency step, major
  68. //unsigned long freq_minor;                                //frequency step, minor

  69. //read the band setting
  70. unsigned char adc_band(void) {
  71.         unsigned char i;
  72.         unsigned char tmp;
  73.        
  74.         tmp=adc_read(BAND_ADC)>>2;                        //read band, as unsigned char
  75.         for (i=1; i<N_BANDS; i++)
  76.                 if (tmp < /*freq_bands[i].threshold*/((unsigned short) i<<8) / N_BANDS) return i-1;
  77.         return N_BANDS-1;                                        //default is 0
  78. }

  79. //read the frequency / step from a pot
  80. unsigned short adc_freq(void) {
  81.         return adc_read(FREQ_ADC);
  82.         //return 200;                                                //for debugging purposes only
  83. }

  84. //output a frequency
  85. void out_freq(void) {
  86.         static unsigned char band_prev=0xff;        //previous band
  87.         static unsigned char mode_prev=0xff;        //previous mode.
  88.         static unsigned short step_current=0;        //current step, major
  89.         //static unsigned short step_minor=0;                //current step, minor
  90.         static unsigned long freq_prev=0;        //previous output frequency
  91.        
  92.         if (band ^ band_prev) {                                //has band changed?
  93.                 freq_step = (freq_bands[band].fend - freq_bands[band].fstart) >> 10;        //calculat the frequency steps
  94.                 freq_prev = 0;                                        //reset previous frequency
  95.                 band_prev = band;                                //update band_prev
  96.         }
  97.                
  98.         if (!mode) {                                                //output a set frequency
  99.                 step_current = adc_freq();                //read the steps
  100.         } else {                                                        //output a scan
  101.                 step_current=(step_current == FREQ_STEP)?0:(step_current+1);        //increment steps
  102.         }

  103.         //generate the next frequency
  104.         freq = freq_bands[band].fstart + freq_step * step_current;
  105.         if (freq ^ freq_prev) {
  106.                 ad9850_freq(freq);                                //output the frequency
  107.                 freq_prev = freq;                                //update freq_prev
  108.         }
  109.        
  110.         delay_ms(freq_bands[band].dly);                //waste some time
  111. }

  112. //not used
  113. //tune to a frequency (step in [Fstart, Fend]) in a band
  114. void tune_freq(unsigned char band, unsigned short freq) {
  115.         static unsigned char band_prev=0;        //previous band
  116.         //static unsigned short freq_prev=0;        //previous step
  117.         if ((band ^ band_prev) || (freq ^ freq_prev)) {        //execute only if band or step has changed
  118.                 ad9850_freq(freq_bands[band].fstart+((freq_bands[band].fend-freq_bands[band].fstart) >> 10) * freq);
  119.                 band_prev = band;
  120.                 freq_prev = freq;
  121.         }
  122.         delay_ms(freq_bands[band].dly);                //waste some time
  123. }

  124. //not used
  125. //sweep frequency in a band
  126. void sweep_freq(unsigned char band) {
  127.         //unsigned long freq;
  128.         static unsigned long fdelta;
  129.         static unsigned short step_current=0;
  130.         //static unsigned long fstart, fend;
  131.        
  132.         if (step_current)
  133.                 ad9850_freq(freq_bands[band].fstart + fdelta * step_current);        //set the frequency
  134.         else {
  135.                 ad9850_freq(freq_bands[band].fstart);        //start the frequency
  136.                 fdelta = ((freq_bands[band].fend - freq_bands[band].fstart) >> 10);        //frequency increment
  137.         }
  138.         //increment step_current
  139.         step_current=(step_current == FREQ_STEP)?0:(step_current+1);
  140.         delay_ms(freq_bands[band].dly);                //waste some time
  141. }

  142. void mcu_init(void) {                                        //initialize the mcu
  143.         ANSEL = 0x00;                                                //porta are digital io
  144.         //ANSELH = 0x00;                                                //all portB is digital io
  145.         CMCON0 = 0x07;                                                //analog comparators off
  146.         IRCF2=1, IRCF1=1, IRCF0=0;                        //running at 4Mhz
  147.        
  148.         //enable weak pull-up
  149.         RAPU = 0;                                                        //enable weak pull-up on porta
  150.         WPUA = 0xff;                                                //enable weak pull-up on all pins

  151.         //scan pin as input
  152.         //not necessary on 12f675 as gpio3 is only input capable
  153.         IO_IN(SCAN_DDR, SCAN_PIN);

  154.         //initialize frequency step
  155.         freq_step = ((freq_bands[band].fend - freq_bands[band].fstart) >> 10);        //calculat the frequency steps
  156. }

  157. //main program
  158. int main(void) {
  159.         //unsigned short i;
  160.         //unsigned long freq;
  161.         static unsigned short count=0;
  162.         mcu_init();                                                        //initialize the mcu
  163.         lcd_init();                                                        //reset the lcd
  164.         adc_init();                                                        //reset the adc module
  165.         ad9850_init();                                                //reset ad9850
  166.         strcpy(vRAM, str0); lcd_display(LCD_Line0, vRAM);        //display the signon message
  167.         strcpy(vRAM, str1);                                        //prepare line1
  168.         ultoa_s(&vRAM[2], freq, 10);                //convert freq, with ','
  169.         lcd_display(LCD_Line1, vRAM);                //display line1
  170.         //ad9850_freq(AD9850_1Khz);                        //2^32 / (125Mhz / 1Mhz) =34359738->1Mhz
  171.         //ad9850_freq(ad9850_f2w(AD9850_100Khz));
  172.         mode = 1;                                                        //defaults to scan
  173.         band = N_BANDS-1;                                        //default band, 455k IF
  174.         while (1) {
  175.                 band=adc_band();                                //read the band setting
  176.                 mode=IS_SCAN(SCAN_PIN);                        //1 for fixed frequency and 0 for scanning
  177.                 out_freq();                                                //output the frequency
  178.                 if (freq ^ freq_prev) {                        //frequency has changed -> update the display
  179.                         //freq_prev=freq;                                //update the frequency
  180.                         strcpy(vRAM, str1);                                        //prepare line1
  181.                         ultoa_s(&vRAM[2], freq, 12);                //convert freq, with ','
  182.                         lcd_display(LCD_Line1, vRAM);                //display line1
  183.                 }
  184.         }
  185. }

复制代码

出0入0汤圆

 楼主| 发表于 2013-7-6 19:20:24 | 显示全部楼层
a quick update: the circuit is fully functional - I made a couple minor updates to the code posted above. Working on the box today, and waiting for a couple bnc connectors to come in soon.

Power supply: the module consumes 100 - 110ma (depending on the oscillators used) @ 5v and 70 - 80ma @ 3.3v. At 5v, the chip and the oscillator run warm. at 3.3v, they are room temperature. As such, I am running mine at 3.3v, powered from a 5v usb power supply through a TO220 1117 regulator (to minimize noise). I also soldered a L7805 there in case I need to power from a 12v+ source. However, at 12v, that regulator runs fairly warm and requires a heatsink for sure.

出0入0汤圆

 楼主| 发表于 2013-7-6 20:26:34 | 显示全部楼层
the ad9850 I posted earlier can be used to drive ad9851 as well, with this modification in ad9850_sendwords():
  1.         words = words >> 8; ad9851_sendbyte(AD9851_PLL | (words & 0xfc));        //send the final words -> control1..0 = 0b01 -> 6* PLL enabled
复制代码

出0入0汤圆

发表于 2013-7-6 21:35:30 | 显示全部楼层
这个模块价格很便宜,我也淘宝上买了2片,发现生成的波形干扰很大,并且是固定在正弦波某个位置出现尖峰的。放大后发现尖峰是由数个较大幅度较高频率的正弦波组成的。怎么都无法彻底消除这个干扰,PCB布线不合理,后来我是自己LAYOUT画了个小板子,就没有这个干扰了

出0入0汤圆

 楼主| 发表于 2013-7-7 02:06:27 | 显示全部楼层
发现生成的波形干扰很大,并且是固定在正弦波某个位置出现尖峰的。


that has not been my experience.

I have tried four ad9850 modules. I think the chip is well done - maybe lower power consumption but that's minor for this chip if you run it at 3.3v.

the modules are pretty good - the layout is nice and well thought out - I wish they had routed Rset out. Of the four modules I have tried, the ones with green pcb are well made. the blue pcbs are skinny. they all work out of the box, as expected.

Here are some pictures.

1Mhz fixed frequency:


AM band sweep:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-7-7 02:08:12 | 显示全部楼层
glitches may happen if you overload the square wave output pins or use too long, unshielded output wires (=antenna).

出0入0汤圆

 楼主| 发表于 2013-7-7 02:08:31 | 显示全部楼层
glitches may happen if you overload the square wave output pins or use too long, unshielded output wires (=antenna).

出0入0汤圆

 楼主| 发表于 2013-7-7 02:20:52 | 显示全部楼层
the code, as it stands now:

  1. //16F684 controller for ebay AD9850 module
  2. //connection:
  3. //AN0: analog voltage input, selects output band;
  4. //AN1: analog voltage input, controls output frequency (when not in the scanning mode)
  5. //PORTA3: digital pull-up/down: up: scanning (default). down: user selectable output frequency (per AN1)
  6. //PORTA2: to AD9850 WCLK
  7. //PORTA4: to AD9850 FQ_UD
  8. //PORTA5: to AD9850 SDATA

  9. //history:
  10. //v1.0 / 6/25/2013: first run.
  11. //v1.1 / 6/26/2013: clean up the code, adding banner display
  12. //v1.2 / 6/29/2013: revised the band definitions
  13. //v1.3 / 7/5/2013: fixed lower limit for SW7; swapped BAND_ADC and FREQ_ADC pins for easier lay-out

  14. #include <htc.h>                                                //we use picc
  15. #include <string.h>                                                //we use strcpy
  16. #include "gpio.h"
  17. #include "config.h"                                                //configuration words
  18. #include "delay.h"                                                //we use software delay
  19. #include "ad9850.h"                                                //we use ad9850
  20. #include "adc.h"                                                //we use hardware adc
  21. #include "lcd_4bit.h"                                        //we use the lcd module, in 4-bit mode
  22. #include "misc.h"                                                //we use ultoa()

  23. //hardware configuration
  24. //scan switch
  25. #define SCAN_PORT                PORTA
  26. #define SCAN_DDR                TRISA
  27. #define SCAN_PIN                (1<<3)                                //scan switch on gpio3. 1->output set frequency. 0-> scan
  28. #define IS_SCAN(pin)        IO_GET(SCAN_PORT, pin)        //return 1 if pin is high (in scanning mode), weak pull-up default to on

  29. //freq pot
  30. #define FREQ_ADC                ADC_AN0                                //frequency pot on adc_an0
  31. #define BAND_ADC                ADC_AN3                                //band adc on adc_an3

  32. #define FREQ_STEP                1023                                //how many steps in a band
  33. #define FREQ_INC                20                                        //increments for freq in the sweep / scan mode
  34. //#define FREQ_DLY                20                                        //delays per step, not used
  35. #define N_BANDS                        14                                        //number of bands

  36. //hardware configuration

  37. //global define
  38. typedef struct {
  39.         unsigned char str[17];                //string to be displayed, for 16x2 lcd
  40.         unsigned long fstart, fend;                        //starting and ending frequencies
  41.         //unsigned char threshold;                        //band threshold
  42.         unsigned char dly;                                        //delay in each step, in ms
  43. } BAND_T;

  44. //global variable
  45. //frequency bands
  46. const BAND_T freq_bands[N_BANDS]={
  47.         //Fstart, Fend, DLY, /*THRESHOLD*/.
  48.         {"IF0:435 - 485Khz", 455000ul - 20000ul, 465000ul + 20000ul, 0},                //455K/465K IF scan, +/- 20Khz bandwidth. default output if BAND_ADC is grounded
  49.         {"IF1:10.6-10.9Mhz", 10700000ul - 100000ul, 10700000ul + 100000ul, 0},        //FM if scan, +/- 100Khz bandwidth
  50.         {"AF :  1 -  20Khz", 1, 20000, 10},                                        //audio frequencies
  51.         {"RF-: 10 - 600Khz", 10000ul, 600000ul, 10},                        //sub RF (LW band)
  52.         {"LW :153 - 279Khz", 153000ul, 279000ul, 10},                        //LW band
  53.         {"AM :500 -1700Khz", 500000ul, 1700000ul, 10},                        //am broadcast band
  54.         {"SW1:1500-2300Khz", 1500000ul, 2300000ul, 10},                //1.5Mhz - 2.3Mhz,
  55.         {"SW2:2100-3200Khz", 2100000ul, 3200000ul, 10},                //2.1Mhz - 3.2Mhz. 120m band
  56.         {"SW3:3100-4600Khz", 3100000ul, 4600000ul, 10},                //3.1Mhz - 4.6Mhz. 90m and 75m bands
  57.         {"SW4:4500-6700Khz", 4500000ul, 6700000ul, 10},                //4.5Mhz - 6.7Mhz. 60m and 49m bands
  58.         {"SW5:6600-9600Khz", 6600000ul, 9600000ul, 10},                //6.6Mhz - 9.6Mhz. 41m and 31m (partial) bands
  59.         {"SW6:9.3 -14.0Mhz", 9300000ul, 14000000ul, 10},                //9.3Mhz - 14.Mhz. 31m, 25m and 22m bands - may want to split this further
  60.         {"SW7:13.0-20.0Mhz", 13000000ul, 20000000ul, 10},                //13.Mhz - 20.Mhz. 22m, 19m, 16m, 15m bands - may want to split this further
  61.         {"RF :0.5 -20.0Mhz", 500000ul, 20000000ul, 10}                        //rf band, default if band pin is pulled high
  62.         //{465000ul - 20000ul, 465000ul + 20000ul, 300},                //465K if scan, +/- 20Khz bandwidth
  63. };

  64. //lcd strings
  65. const unsigned char str0[]="AD9850 SigGen1.2";
  66. const unsigned char str1[]="f=            Hz";
  67. unsigned char vRAM[17];                                        //display buffer
  68. unsigned long freq_prev=0;                                //previous frequency

  69. unsigned char band=0;                                        //band to tune
  70. unsigned char mode=1;                                        //mode. 0=output to a set frequency. 1=scan
  71. unsigned long freq;                                                //output frequency
  72. unsigned long freq_step;                                //frequency step, major
  73. //unsigned long freq_minor;                                //frequency step, minor

  74. //read the band setting
  75. unsigned char adc_band(void) {
  76.         unsigned char i;
  77.         unsigned char tmp;
  78.        
  79.         tmp=adc_read(BAND_ADC)>>2;                        //read band, as unsigned char
  80.         for (i=1; i<N_BANDS; i++)
  81.                 if (tmp < /*freq_bands[i].threshold*/((unsigned short) i<<8) / N_BANDS) return i-1;
  82.         return N_BANDS-1;                                        //default is 0
  83. }

  84. //read the frequency / step from a pot
  85. unsigned short adc_freq(void) {
  86.         return adc_read(FREQ_ADC);
  87.         //return 200;                                                //for debugging purposes only
  88. }

  89. //output a frequency
  90. void out_freq(void) {
  91.         static unsigned char band_prev=0xff;        //previous band
  92.         static unsigned char mode_prev=0xff;        //previous mode.
  93.         static unsigned short step_current=0;        //current step, major
  94.         //static unsigned short step_minor=0;                //current step, minor
  95.         static unsigned long freq_prev=0;        //previous output frequency
  96.        
  97.         if (band ^ band_prev) {                                //has band changed?
  98.                 freq_step = (freq_bands[band].fend - freq_bands[band].fstart) >> 10;        //calculat the frequency steps
  99.                 freq_prev = 0;                                        //reset previous frequency
  100.                 band_prev = band;                                //update band_prev
  101.                 //update the display
  102.                 strcpy(vRAM, freq_bands[band].str);
  103.                 lcd_display(LCD_Line0, vRAM);
  104.         }
  105.                
  106.         if (!mode) {                                                //output a set frequency
  107.                 step_current = adc_freq();                //read the steps
  108.         } else {                                                        //output a scan
  109.                 step_current=(step_current >= FREQ_STEP)?0:(step_current+FREQ_INC);        //increment steps
  110.         }

  111.         //generate the next frequency
  112.         freq = freq_bands[band].fstart + freq_step * step_current;
  113.         if (freq ^ freq_prev) {
  114.                 ad9850_freq(freq);                                //output the frequency
  115.                 freq_prev = freq;                                //update freq_prev
  116.         }
  117.        
  118.         delay_ms(freq_bands[band].dly);                //waste some time
  119. }

  120. void mcu_init(void) {                                        //initialize the mcu
  121.         ANSEL = 0x00;                                                //porta are digital io
  122.         //ANSELH = 0x00;                                                //all portB is digital io
  123.         CMCON0 = 0x07;                                                //analog comparators off
  124.         IRCF2=1, IRCF1=1, IRCF0=0;                        //running at 4Mhz
  125.        
  126.         //enable weak pull-up
  127.         //RAPU = 0;                                                        //enable weak pull-up on porta
  128.         //WPUA = 0xff;                                                //enable weak pull-up on all pins

  129.         //scan pin as input
  130.         //not necessary on 12f675 as gpio3 is only input capable
  131.         IO_IN(SCAN_DDR, SCAN_PIN);

  132.         //initialize frequency step
  133.         freq_step = ((freq_bands[band].fend - freq_bands[band].fstart) >> 10);        //calculat the frequency steps
  134. }

  135. //main program
  136. int main(void) {
  137.         //unsigned short i;
  138.         //unsigned long freq;
  139.         //static unsigned short count=0;
  140.         mcu_init();                                                        //initialize the mcu

  141.         adc_init();                                                        //reset the adc module

  142.         lcd_init();                                                        //reset the lcd
  143.         strcpy(vRAM, str0); lcd_display(LCD_Line0, vRAM);        //display the signon message
  144.         delay_ms(1000);                                                //wait for a short while to display the sign-on message
  145.         //strcpy(vRAM, str1);                                        //prepare line1
  146.         //ultoa_s(&vRAM[2], freq, 10);                //convert freq, with ','
  147.         //lcd_display(LCD_Line1, vRAM);                //display line1
  148.        
  149.         ad9850_init();                                                //reset ad9850
  150.         //ad9850_freq(AD9850_1Khz); while (1);

  151.         //mode = 1;                                                        //defaults to scan
  152.         //band = N_BANDS-1;                                        //default band, 455k IF
  153.         while (1) {
  154.                 band=adc_band();                                //read the band setting
  155.                 mode=IS_SCAN(SCAN_PIN);                        //1 for fixed frequency and 0 for scanning
  156.                 out_freq();                                                //output the frequency

  157.                 if (freq ^ freq_prev) {                        //frequency has changed -> update the display
  158.                         freq_prev=freq;                                //update the frequency
  159.                         strcpy(vRAM, str1);                                        //prepare line1
  160.                         ultoa_s(&vRAM[2], freq, 12);                //convert freq, with ','
  161.                         lcd_display(LCD_Line1, vRAM);                //display line1
  162.                 }

  163.         }
  164. }
复制代码

出0入0汤圆

 楼主| 发表于 2013-7-7 02:26:45 | 显示全部楼层
hardware connection:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-7-7 02:30:41 | 显示全部楼层
ad9850 module connection:

AD9850 <-> mcu
FQ_UD <-> FQUD
WCLK <-> WCLK
SDATA <-> SDATA
RST <-> GND
D0/D1 <-> VCC
D2 <-> GND

values of the resistors / pots / capacitors are NOT critical.

Output pins:
IOUT: unfiltered RF out (DC), to bnc
IOUTB: filtered RF out (AC), to bnc
Vout_P: square wave out (DC), to bnc

Powered supply: outboard 5v (usb), step'd down to 3.3v.

出0入0汤圆

 楼主| 发表于 2013-7-7 02:33:46 | 显示全部楼层
hex file (it can be burned to a 16F684):

  1. :100000009B27F6009A27F5005730840070300F20A8
  2. :100010008317773084007E300F2083011728640017
  3. :100020008001840A04060319003404061028F22310
  4. :10003000872165237830AC000730AD005F30CC21DC
  5. :100040005F30AC0000305821E830AC000330AD0028
  6. :1000500096216C21FD21F7000508F5000830F50513
  7. :10006000E0245708A0005808A1005908A2005A0827
  8. :10007000A3005B08A0065C08A1065D08A2065E0856
  9. :10008000A306230822042104200403192A285E0859
  10. :10009000DA005D08D9005C08D8005B08D700893019
  11. :1000A000AC000730AD005F30CC210C30A8005E08FA
  12. :1000B000A7005D08A6005C08A5005B08A4006130ED
  13. :0C00C000E3225F30AC00403058212A28B9
  14. :1002B000AD005C212C087829AE00AF01803E232BD5
  15. :1002C000B100B103310F61290800003063242F0809
  16. :1002D000AD002E08AC000800D930850583168505D1
  17. :1002E0008312051500000511851400008510080013
  18. :1002F000AE008129AF01AF0A2E0884000008232335
  19. :10030000AE0A2E0884008008031908007A29831693
  20. :100310001F179F161F1283129F111F119F171F1364
  21. :100320000C1383160C1383121F1408009B29C8306A
  22. :10033000AE00AF01A5210130AC02031CAD032C0AB5
  23. :1003400003192D0A0319080097292E0860212F0888
  24. :10035000AE00AF01AD29FF3060210130AE02031CB9
  25. :10036000AF032E0A03192F0A03190800AB29B400A2
  26. :10037000B501B50AF93085050511340835050319AD
  27. :10038000C3298516C429851205150310B50DB508B6
  28. :10039000031DBC2905110800AE00AF002D08B100F7
  29. :1003A0002C08B000AC0A0319AD0A840031080026FD
  30. :1003B000B2002F088400AF0A32088313800080083F
  31. :1003C00003190800CE292F08B3002E08B2002D080B
  32. :1003D000B1002C08B0009C273308AF003208AE00F3
  33. :1003E0003108AD003008AC002F08B3002E08B20071
  34. :1003F0002D08B1002C08B0004E2A0C3063240310E5
  35. :10040000AF0CAE0C0310AF0CAE0C2E08A400A5016F
  36. :10041000A50A0E30AA00AB012508A900A8012322D5
  37. :100420002408A600A70129082702031D192A280865
  38. :10043000260203181D2A25030800A50A0E302502EE
  39. :1004400003180D34092AAD01AE012B082A04031943
  40. :10045000492AAC01AC0A0310AB1B322AAA0DAB0D22
  41. :100460002A2A0310AD0DAE0D2B082902031D3A2ACE
  42. :100470002A082802031C452A2A08A8022B08031C64
  43. :10048000A903A9020130AD040310AB0CAA0CAC0BFC
  44. :10049000312A2E08A9002D08A80008008510300870
  45. :1004A000B7213108B0003208B1003308B200B301FF
  46. :1004B0003008B7213108B0003208B1003308B2006B
  47. :1004C000B3013008B7213108B0003208B100330859
  48. :1004D000B200B3013008B7213108B0003208B100D2
  49. :1004E0003308B200B3013008FC39B721851400008D
  50. :1004F00085100800B401B501B601B7012C1C942A7F
  51. :100500003008B407310803110318310A031DB50779
  52. :10051000320803110318320A031DB607330803110A
  53. :100520000318330A031DB7070310B00DB10DB20D48
  54. :10053000B30D0310AF0CAE0CAD0CAC0C2F082E0499
  55. :100540002D042C04031D7E2A3708AF003608AE00A8
  56. :100550003508AD003408AC0008003208310430041E
  57. :100560002F0403190800B301B30AB21BBD2A0310FC
  58. :10057000AF0DB00DB10DB20DB42A32082E02031D1D
  59. :10058000CB2A31082D02031DCB2A30082C02031D73
  60. :10059000CB2A2F082B02031CDC2A2F08AB023008C1
  61. :1005A000031C300FAC023108031C310FAD023208BE
  62. :1005B000031C320FAE020310B20CB10CB00CAF0C26
  63. :1005C000B30BBD2A0800A900AA012A08033A031D9B
  64. :1005D000F02AAA01A8032808290784002C308000EB
  65. :1005E000AA0AA8032808290784000A30AF00B0012E
  66. :1005F000B101B2012708AE002608AD002508AC0005
  67. :100600002408AB00AD222B08303E80000A30AF003A
  68. :10061000B001B101B2012708AE002608AD002508DF
  69. :10062000AC002408AB00A8232E08A7002D08A600C4
  70. :100630002C08A5002B08A400270826042504240460
  71. :1006400003190800E52AB000B01F282B0714292B36
  72. :100650000710301F2D2B87142E2B8710B01E322B26
  73. :100660000715332B0711301E372B8715382B8711B1
  74. :1006700000306021AF0803193F2B8716402B8712EB
  75. :100680000716003060210712B01D482B0714492BB4
  76. :100690000710301D4D2B87144E2B8710B01C522B8A
  77. :1006A0000715532B0711301C572B8715582B871113
  78. :1006B00000306021AF0803195F2B8716602B87126B
  79. :1006C00007160030602107120800CF308316870517
  80. :1006D000F03087050F308312AC00AD0196210C304D
  81. :1006E0008704FC3087050030602187120716003030
  82. :1006F000602107120530AC00AD0196210030602169
  83. :1007000087120716003060210712C830AE00AF0113
  84. :10071000A5210030602187120716003060210712E2
  85. :10072000C830AE00AF01A52187120715F430870548
  86. :100730000030602187120716003060210712AF01D8
  87. :100740002B302323AF010C302323AF010630232BA2
  88. :10075000B401B501B601B7013208310430042F04E9
  89. :100760000319E92BB301B30A0310B21BBD2BAF0D64
  90. :10077000B00DB10DB20DB32B0310B40DB50DB60D08
  91. :10078000B70D32082E02031DCF2B31082D02031D99
  92. :10079000CF2B30082C02031DCF2B2F082B02031C5C
  93. :1007A000E32B2F08AB023008031C300FAC023108DA
  94. :1007B000031C310FAD023208031C320FAE020130B0
  95. :1007C000B40400300310B20CB10CB00CAF0CB30B7E
  96. :1007D000BC2B3708AE003608AD003508AC00340835
  97. :1007E000AB0008008316910107308312990083162D
  98. :1007F0000F178F160F1285151A308312AE00AF0136
  99. :100800007708AC00AD01E7271D302C0784000630C7
  100. :10081000031807302D07A7000026A400840A031937
  101. :10082000A70A27080026A500840A0319A70A270893
  102. :100830000026A600840A0319A70A27080026A70095
  103. :100840001A30AE00AF017708AC00AD01E7272130C8
  104. :100850002C0784000630031807302D07AB00002654
  105. :10086000A800840A0319AB0A2B080026A900840AF1
  106. :100870000319AB0A2B080026AA00840A0319AB0A45
  107. :100880002B080026AB002408A8022508031C250F0E
  108. :10089000A9022608031C260FAA022708031C270FFB
  109. :1008A000AB020A300310AB0CAA0CA90CA80CFF3E3B
  110. :1008B000031D522C2B08F3002A08F2002908F1002E
  111. :1008C0002808F0000800B000982CE3309F0583163C
  112. :1008D0009101910ABC2C1F08E33904389F000230B3
  113. :1008E000942C1F08E33908389F000430942C1F080B
  114. :1008F000E3390C389F000830942C1F08E339103876
  115. :100900009F001030942C1F08E33914389F002030CA
  116. :10091000942C1F08E33918389F004030942C1F088E
  117. :10092000E3391C389F00803083169100BC2C972C33
  118. :1009300030081C39B100B201B72C3108003A031954
  119. :10094000652C043A03196B2C0C3A0319712C043AE8
  120. :100950000319772C1C3A03197D2C043A0319832CB4
  121. :100960000C3A0319892C043A03198F2C972C32085E
  122. :10097000003A03199D2C972C000000000000000095
  123. :100980000000000000000000000000000000000067
  124. :100990000000000000000000000000000000000057
  125. :1009A000000000000000000083129F149F18D62C46
  126. :1009B00083121E08AF0083161E088312AE000800C3
  127. :1009C000770876060319682D1A30AE00AF01770854
  128. :1009D000AC00AD01E7271D302C078400063003185A
  129. :1009E00007302D07A7000026A400840A0319A70AD0
  130. :1009F00027080026A500840A0319A70A270800264D
  131. :100A0000A600840A0319A70A27080026A7001A309F
  132. :100A1000AE00AF017708AC00AD01E72721302C070D
  133. :100A200084000630031807302D07AB000026A8000D
  134. :100A3000840A0319AB0A2B080026A900840A0319AB
  135. :100A4000AB0A2B080026AA00840A0319AB0A2B085C
  136. :100A50000026AB002408A8022508031C250FA902C4
  137. :100A60002608031C260FAA022708031C270FAB0227
  138. :100A70000A300310AB0CAA0CA90CA80CFF3E031DF6
  139. :100A8000392D2B08F3002A08F2002908F100280864
  140. :100A9000F000FA01FB01FC01FD017708F6001A30B5
  141. :100AA000AE00AF017708AC00AD01E7270C30A40021
  142. :100AB0000630A5002C082407AC002D0803182D0AC9
  143. :100AC0002507AD005F30CC215F30AC0000305821ED
  144. :100AD000F508031D712D65212D08F9002C08F8007B
  145. :100AE0007F2D03307902FF300319780203187D2D22
  146. :100AF0001430F8070318F90A7F2DF801F9011A30AC
  147. :100B0000AE00AF017708AC00AD01E7271D302C0720
  148. :100B100084000630031807302D07A7000026A40024
  149. :100B2000840A0319A70A27080026A500840A0319C6
  150. :100B3000A70A27080026A600840A0319A70A27087F
  151. :100B40000026A7007308B3007208B2007108B10054
  152. :100B50007008B0007808AC007908AD00AE01AF01B4
  153. :100B60007A222C08A4072D0803182D0FA5072E089C
  154. :100B700003182E0FA6072F0803182F0AA707270808
  155. :100B8000DE002608DD002508DC002408DB007A08EA
  156. :100B9000A4007B08A5007C08A6007D08A7005B08D0
  157. :100BA000A4065C08A5065D08A6065E08A706270839
  158. :100BB0002604250424040319EE2D5E08AF005D0809
  159. :100BC000AE005C08AD005B08AC00E3215E08FD00F0
  160. :100BD0005D08FC005C08FB005B08FA001A30AE0000
  161. :100BE000AF017708AC00AD01E72725302C07840062
  162. :100BF0000630031807302D070026AC00AD019629FA
  163. :100C0000FE00FE1F082E83137E18831700080800BD
  164. :100C10008A000408820000344934463430343A34BF
  165. :100C200034343334353420342D34203434343834AF
  166. :100C300035344B3468347A3400343834A3340634D1
  167. :100C40000034883466340734003400344934463480
  168. :100C500031343A34313430342E3436342D34313466
  169. :100C600030342E3439344D3468347A3400344034DE
  170. :100C7000BE34A13400348034CB34A4340034003486
  171. :100C80004134463420343A34203420343134203452
  172. :100C90002D3420342034323430344B3468347A34B8
  173. :100CA0000034013400340034003420344E34003435
  174. :100CB00000340A34523446342D343A34203431343A
  175. :100CC000303420342D3420343634303430344B3406
  176. :100CD00068347A3400341034273400340034C0349B
  177. :100CE0002734093400340A344C34573420343A342D
  178. :100CF00031343534333420342D34203432343734E5
  179. :100D000039344B3468347A340034A83455340234DE
  180. :100D10000034D8344134043400340A3441344D347E
  181. :100D200020343A3435343034303420342D343134B6
  182. :100D30003734303430344B3468347A34003420342F
  183. :100D4000A13407340034A034F034193400340A34A8
  184. :100D50005334573431343A34313435343034303418
  185. :100D60002D3432343334303430344B3468347A34C4
  186. :100D700000346034E33416340034603418342334DF
  187. :100D800000340A345334573432343A343234313440
  188. :100D9000303430342D3433343234303430344B3416
  189. :100DA00068347A34003420340B3420340034003476
  190. :100DB000D434303400340A345334573433343A346E
  191. :100DC00033343134303430342D34343436343034F8
  192. :100DD00030344B3468347A34003460344D342F343A
  193. :100DE0000034C0343034463400340A345334573479
  194. :100DF00034343A3434343534303430342D343634B9
  195. :100E00003734303430344B3468347A34003420345E
  196. :100E1000AA3444340034E0343B34663400340A34B9
  197. :100E20005334573435343A3436343634303430343D
  198. :100E30002D3439343634303430344B3468347A34E9
  199. :100E400000344034B5346434003400347C3492349B
  200. :100E500000340A345334573436343A3439342E3467
  201. :100E6000333420342D34313434342E3430344D3452
  202. :100E700068347A3400342034E8348D3400348034DB
  203. :100E80009F34D53400340A345334573437343A3429
  204. :100E9000313433342E3430342D34323430342E3433
  205. :100EA00030344D3468347A34003440345D34C634E0
  206. :100EB000003400342D34313401340A345234463491
  207. :100EC00020343A3430342E34353420342D34323416
  208. :100ED00030342E3430344D3468347A340034203495
  209. :100EE000A1340734003400342D34313401340A3451
  210. :100EF0004134443439343834353430342034533484
  211. :100F000069346734473465346E3431342E343234C6
  212. :100F1000003466343D3420342034203420342034EE
  213. :100F200020342034203420342034203420344834F9
  214. :100F30007A3400340134FF343308C0003208BF0073
  215. :100F40003108BE003008BD00B901BA01BB01BC01C7
  216. :100F50000730B8007330B7005930B6004030B500E4
  217. :100F60002030B4000310BD0DBE0DBF0DC00D031029
  218. :100F7000B90DBA0DBB0DBC0D38084002031DCA2FB8
  219. :100F800037083F02031DCA2F36083E02031DCA2F31
  220. :100F900035083D02031CDC2F3508BD023608031C52
  221. :100FA000360FBE023708031C370FBF023808031C78
  222. :100FB000380FC0020130B904B40BB22F3C08B300A3
  223. :100FC0003B08B2003A08B1003908B0000800B0018F
  224. :100FD000B1012C1CF12F2E08B0070318B10A2F08FD
  225. :100FE000B1070310AE0DAF0D0310AD0CAC0C2D0806
  226. :100FF0002C04031DE92F3108AD003008AC000800B7
  227. :02400E00C430BC
  228. :00000001FF
复制代码
flash usage is about 88%. That means you can add additional bands - about 10 more bands.

出0入0汤圆

发表于 2013-10-23 16:16:31 | 显示全部楼层
非常感谢分享!刚接触DDS,需要慢慢消化。

另,不知DDS用作扫频和调频FM有何异同?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-28 04:11

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表