PDA

Просмотр полной версии : Работаем с AD9832



Страницы : [1] 2 3

UR4QBP
03.04.2008, 12:37
Доброго времени суток!
Кто занимался написанием программ для DDS AD9832? Пытаюсь разобраться как управлять AD9832 с помощью МК ATmega8. Вопрос такого плана: как правильно управлять DDS по шинам FSYNH, SDATA, SCLK?

03.04.2008, 13:25
александр прочитайте даташит тогда вопросы возникнут более конкретные.

UR4QBP
03.04.2008, 13:34
Я в английском не силен. Но, как я понимаю, выходная частота, устанавливается после записи 16 битного слова в SDATA, при записи какие должны быть логические уровни FSYNC и SCLK? Запись в DDS идет наподобие как в ИР2, наверное? Подскажите.

Explorer
03.04.2008, 13:56
Вот гдето нашел, во вложении исходный код, правда на BASCom там передаются последовательно четыре байта начиная со старшего

daemon
03.04.2008, 14:00
Здравствуйте, Александр.
Я работал с ad9832 и у меня есть исходник на ассемблере под Atmega8. Ничего сложного в работе с этим DDS нет (это когда разберешься :D )
Прошивка у меня дома, вечером отправлю.

03.04.2008, 14:02
FSYNC в ноль
далее по заднему фронту CLK заносятся 16бит
FSYNC в единицу - чтобы защелка сработала.

Explorer
03.04.2008, 14:09
to daemon

А вы выкладывайте сюда интересно посмотреть, на то он и форум.

UR4QBP
03.04.2008, 15:19
Здравствуйте, Александр.
Я работал с ad9832 и у меня есть исходник на ассемблере под Atmega8. Ничего сложного в работе с этим DDS нет (это когда разберешься :D )
Прошивка у меня дома, вечером отправлю.
В асме я ни бум-бум, пишу только в Си. Сигнал SCLK уже запустил через таймер, кстати, какая длительность SCLK оптимальна для AD9832? Как програмно в Си определить что начался спад?

VladI+
03.04.2008, 20:26
AD9832 и WinAVR
http://members.jcom.home.ne .jp/0434383301/DDS_SG.htm
http://members.jcom.home.ne .jp/0434383301/pdf/DDS_SG.pdf
http://members.jcom.home.ne .jp/0434383301/file/DDS_SG/DDS_SG.zip
http://members.jcom.home.ne .jp/0434383301/file/DDS_PC/DDS_PC2.zip

UR4QBP
03.04.2008, 20:42
Спасибо VladI+, буду разбираться в комментариях по китайски. По аське Виктор US5CAA подсказал мне алгоритм заливки в AD9832, теперь надо с битами разобраться. Читая даташит я понял что у нее куча режимов:
FREQ0 REG 8 L LSBs
FREQ0 REG 8 H LSBs
FREQ0 REG 8 L MSBs
FREQ0 REG 8 H MSBs
FREQ1 REG 8 L LSBs
FREQ1 REG 8 H LSBs
FREQ1 REG 8 L MSBs
FREQ1 REG 8 H MSBs
PHASE0 REG 8 LSBs
PHASE0 REG 8 MSBs
PHASE1 REG 8 LSBs
PHASE1 REG 8 MSBs
PHASE2 REG 8 LSBs
PHASE2 REG 8 MSBs
PHASE3 REG 8 LSBs
PHASE3 REG 8 MSBs.
Что мне из этого надо выбрать чтобы синус генерить?
Сейчас я на работе, посмотрю еще в инете чего либо по этой теме, а завтра дома буду разбираться на макете.

daemon
03.04.2008, 22:52
Вот, как и обещал, прошивка и схема подключения ATmega8 к AD9832 (см. на схеме сигналы с префиксом "DDS_")

Прошивка тестовая, она писалась и компилируется без ошибок в AVR Studio 4.13 SP2 build 571.

Назначения ножек см. в файле main.asm, функции работы с DDS AD9832 - в файле dds.asm, функции пересылки данных по последовательному интерфейсу - в файле serial.asm. Все файлы снабжены комментариями. Если возникнут проблемы, обращайтесь помогу чем смогу.
Прошивку предоставляю "как есть", можете свободно модифицировать и использовать ее или ее части в своих проектах.

Успехов!

UR4QBP
03.04.2008, 23:34
Спасибо UR4MCK, но для меня ассемблер.... туговат.
Исходя из пересмотренных мною данных, сначала надо инициализировать DDS.
1. Биты инициализации: 1111100000000000
2. Затем запись MSB H: 110011000000 +4бита F
3. запись MSB L: 100010000000 +4бита F
4. запись LSB H: 110001000000 +4бита F
5. запись LSB L: 100000000000 +4бита F
6. И переход в спящий режим: 1000000000000000
Это так у "китайца", потом только вводятся данные частоты пункты 2, 3, 4 и 5. Кто сталкивался с этим подскажите что не правильно я делаю.[/i]

EU1ME
04.04.2008, 00:44
http://www.analog.com/Analog_Root/static/techSupport/designTools/interactiveTools/ad98325/ad9832.html
http://www.analog.com/UploadedFiles/Application_Notes/522433833AN621_0.pdf

Explorer
04.04.2008, 11:05
to Александр Карнаух
1. 1111 1000 0000 0000

2. 0011 0011 0000 0000 + 8бит F
3. 0010 0010 0000 0000 + 8бит F
4. 0011 0001 0000 0000 + 8бит F
5. 0010 0000 0000 0000 + 8бит F

6. 1100 0000 0000 0000
Frequency Reg 0 (pin DDS FSELECT - GRD )

daemon
04.04.2008, 11:26
Alex007 дал хорошие ссылки! В частности по "AD9832 Device Configuration Assistant". Знал бы я про них раньше, сэкономил бы целый вечер. :D А так сам разбирался по datasheet, вооружившись бумагой, ручкой и осциллографом. Но это тоже полезно. После того, как разобрался все показалось достаточно просто. О встретившихся мне подводных камнях также расскажу.

Итак, постановка задачи:
Есть плата с напаянными вместе с "обвязкой"ad9832, тактовым генератором и atmega8. Плата и пайка проверена на отсутствие замыканий. Микроконтроллер настроен (fuse bits), программируется и работает с тестовой программой (например, "hello, world"). В качестве примера будем считать, что и ad9832,и генератор, и atmega8 работают от 5V. Пусть также DDS_MCLK = 16 MHz. Также (в качестве упрощения) предполагаем, что ножка выбора частоты (FSELECT) dds выбирают частоту из регистра FREG0, а ножки выбора фазы (PSEL0, PSEL1) выбирают фазу из регистра PHASE0.
Цель: запрограммировать ad9832 так, чтобы на выходе было 5.5 MHz.

Алгоритм:

0. Инициализация микроконтроллера и портов ввода вывода:
(DDS_FSYNC = 1, DDS_SCLK = 0, DDS_SDATA = 0)

1. Выполнить задержку на несколько десятков миллисекунд (подбирается экспериментально) чтобы дать возможность стабилизироваться питанию на dds (там обычно ставять конденсаторы большой емкости) и тактовому генератору выйти в рабочий режим.

2. Инициализация DDS
2.1 Выполняем программный сброс ad9832:
(SLEEP = 1, RESET = 1, CLR = 1 (см. табл. IX из ad9832 datasheet), получается слово (16 бит): 0b1111|1000|0000|000 0 = 0xf800
2.1.1: DDS_FSYNC = 0
2.1.2: передаем старший байт 0b11111000 (порядок бит - MSB - от старшего к младшему)
2.1.3: передаем младший байт 0b00000000
2.1.4: DDS_FSYNC = 1

2.2 Первый раз устанавливаем значение выходной частоты:
Частота расчитывается следующим образом:
Fout = FREG0 * Fmclk / 2^32, где
Fout - частота на выходе dds, Hz (5.5 MHz в этом примере);
FREG0 - значение регистра, определяющего частоту (32 бит);
Fmclk - тактовая частота dds, Hz (16 MHz в этом примере);
2^32 = 4 294 967 296.

Решая это простое уровнение относительно FREG0, находим:
FREG0 = (Fout / Fmclk) * 2^32;
FREG0 = (5 500 000 / 16 000 000) * 2^32 = 1 476 395 008 = 0x58000000.

(пишем старший (3-й) байт FREG0:)
2.2.1: DDS_FSYNC = 0
2.2.2: передаем байт 0b00110011 (выбор 3-го байта из FREG0)
2.2.3: передаем байт 0b0101|1000 = 0x58
2.2.4: DDS_FSYNC = 1

(пишем 2-й байт FREG0:)
2.2.5: DDS_FSYNC = 0
2.2.6: передаем байт 0b00100010 (выбор 2-го байта из FREG0)
2.2.7: передаем байт 0b0000|0000 = 0x00
2.2.8: DDS_FSYNC = 1

(пишем 1-й байт FREG0:)
2.2.9: DDS_FSYNC = 0
2.2.10: передаем байт 0b00110001 (выбор 1-го байта из FREG0)
2.2.11: передаем байт 0b0000|0000 = 0x00
2.2.12: DDS_FSYNC = 1

(пишем младший (0-й) байт FREG0:)
2.2.13: DDS_FSYNC = 0
2.2.14: передаем байт 0b00100000 (выбор 0-го байта из FREG0)
2.2.15: передаем байт 0b0000|0000 = 0x00
2.2.16: DDS_FSYNC = 1

2.3 Переводим dds в оперативный режим
(SLEEP = 0, RESET = 0, CLR = 0)
2.3.1: DDS_FSYNC = 0
2.3.2: передаем старший байт 0b1100|0000
2.3.3: передаем младший байт 0b00000000
2.3.4: DDS_FSYNC = 1

Все, после этого DDS выдает на выходе 5.5MHz.
В дальнейшем при перестройке dds выполняются только шаги 2.2.1 - 2.2.16 (см. подпрограмму dds_tune из моей прошивки)

Комментарий: как легко видеть, DDS_FSYNC - это огибающая (активный уровень - '0') для данных, посылаемых по последовательному интерфейсу. Данные посылаются по линиям DDS_SCLK, DDS_SDATA и считываются ядром dds по заднему фронту DDS_SCLK. Я делал так:
1. выставить в порту бит b (DDS_SDATA = b);
/* do_clock */
2. DDS_SCLK = 1;
3. пауза1
4. DDS_SCLK = 0;
5. пауза2
(обычно пауза2 < пауза1, и подбирается так, чтобы DDS_SCLK был похож на меандр, хотя это и необязательно)

Подводные камни.
Когда я в свое время разбирался с ad9832, то были такие трудности:
1. все сигналы и данные передаваемые на dds правильные (каждый бит проверялся вручную по осциллографу), но все равно на выходе dds нет никакого сигнала.
Причина: а) недостаточный уровень сигнала DDS_MCLK, b) недостаточный или черезмерный(!) уровень на сигнальных линиях DDS_SDATA, DDS_SCLK, DDS_FSYNC (актуально, когда напряжение питания dds и мк отличаются)

2. даже при отсутствии питания на dds он производит частоту на выходе (но только после нескольких последовательных вызовов dds_tune и довольно случайным образом).
Причина: превышен уровень сигналов DDS_MCLK, DDS_SDATA, DDS_SCLK, DDS_FSYNC (одного или нескольких). Проявилось когда питание dds было около 3.0 V, а atmega8 и тактового генератора 5.0 V. Устранилось путем установки резистивных делителей на этих ножках.

Вот пока все, что в подробностях я смог описать. Надеюсь, ничего не напутал и не забыл. Если все еще будут проблемы, спрашивайте.

Удачи в конструировании!
---
Dmitry ur4mck

UR4QBP
04.04.2008, 12:15
Дмитрий, спасибо большое за алгоритм, все понятно. Но не хочу глупо выглядеть, но не получается у меня на Си из "слов" (HEX или BIN) побитно вытягивать каждый бит отдельно. Просто не знаю как это сделать, надо наверное на форум "Кота" заглянуть, если тут никто не откликнется. В "Коте" ребята оперативно отвечают.

rv3bj
04.04.2008, 12:30
Александр Карнаух

не получается у меня на Си из "слов" (HEX или BIN) побитно вытягивать каждый бит отдельно. Просто не знаю как это сделать
Самый наглядный способ
1. Скопировать слово в temp того же типа
2. Наложить маску temp = temp & 10000000
3. После этого в temp будет значения старшего бита
и так далее для всех других битов

UR4QBP
04.04.2008, 12:37
Александр Карнаух

не получается у меня на Си из "слов" (HEX или BIN) побитно вытягивать каждый бит отдельно. Просто не знаю как это сделать
Самый наглядный способ
1. Скопировать слово в temp того же типа
2. Наложить маску temp = temp & 10000000
3. После этого в temp будет значения старшего бита
и так далее для всех других битов
Не могли бы вы подробней описать.

UR4QBP
04.04.2008, 13:07
Александр Карнаух

не получается у меня на Си из "слов" (HEX или BIN) побитно вытягивать каждый бит отдельно. Просто не знаю как это сделать
Самый наглядный способ
1. Скопировать слово в temp того же типа
2. Наложить маску temp = temp & 10000000
3. После этого в temp будет значения старшего бита
и так далее для всех других битов
Вот функция записи по маске:
void save_dds()
{
unsigned long int temp;
FSYNC=1; SCLK=1;
FSYNC=0; temp=data; temp=temp & 10000000; SDATA=temp; SCLK=0; delay_us(5);
SCLK=1; temp=data; temp=temp & 01000000; SDATA=temp; SCLK=0; delay_us(5);
SCLK=1; temp=data; temp=temp & 00100000; SDATA=temp; SCLK=0; delay_us(5);
SCLK=1; temp=data; temp=temp & 00010000; SDATA=temp; SCLK=0; delay_us(5);
SCLK=1; temp=data; temp=temp & 00001000; SDATA=temp; SCLK=0; delay_us(5);
SCLK=1; temp=data; temp=temp & 00000100; SDATA=temp; SCLK=0; delay_us(5);
SCLK=1; temp=data; temp=temp & 00000010; SDATA=temp; SCLK=0; delay_us(5);
SCLK=1; temp=data; temp=temp & 00000001; SDATA=temp; SCLK=0;
FSYNC=1;
}
data=11001100;
Сигналы на осциллографе:
PD0 FSYNC
PD1 SDATA
PD2 SCLK
Что неправильно?

daemon
04.04.2008, 13:28
Попробую я описать.




#define SCLK_DELAY 128

void send_byte(const char byte) {
int i, j;
char tmp;

tmp = byte; /* temporary byte holder to work with */

/* Cycle for each bit in byte (MSB first) */
for (i = 0; i < 8; i++) {
if (tmp & 0x80) /* Check for most significant bit (bit15) */
/* Send '1' */
else /* Send '0' */

tmp <<= 1; /* Get next bit in bit15 */

/* do clock */
/* set SLCK = '1' */
for (j = SCLK_DELAY; j > 0; j--); /* some delay */
/* set SCLK = '0' */
for (j = SCLK_DELAY - 8; j > 0; j--); /* another delay */
}
}

void dds_init(void) {

/* Reset DDS */
/* set FSYNC = '0' */
send_byte(0x58);
send_byte(0x00);
/* set FSYNC = '1' */

/* Set inital frequency */
/* set FSYNC = '0' */
send_byte(0x33);
send_byte(freq3); /* byte 3 */
/* set FSYNC = '1' */

/* set FSYNC = '0' */
send_byte(0x22);
send_byte(freq2); /* byte 2 */
/* set FSYNC = '1' */

/* set FSYNC = '0' */
send_byte(0x31);
send_byte(freq1); /* byte 1 */
/* set FSYNC = '1' */

/* set FSYNC = '0' */
send_byte(0x20);
send_byte(freq0); /* byte 0 */
/* set FSYNC = '1' */

/* Go to operational mode */
/* set FSYNC = '0' */
send_byte(0xc0);
send_byte(0x00);
/* set FSYNC = '1' */
}


Частота задается в freq3...0.
Предоставляю вам самим написать остальные функции.
В приведенном выше листинге строки с "Send '1'", "Send '0'", "set SLCK = '1'", "set SLCK = '0'", "set FSYNC = '1'", "set FSYNC = '0'" нужно заменить на команды вывода в порт для соответствующей ножки. Как дергать ножками AVR на Си, надеюсь, знаете? :)

Желаю удачи!

----
dmitry

EU1ME
04.04.2008, 14:17
Что мешает использовать аппаратный SPI меги?

UR4QBP
04.04.2008, 14:57
Спасибо большое Дмитрий что разжевали, все получилось. Теперь, благодаря вашим усилиям могу генерить частоту... Далее буду функцию перестройки писать. Вот проект для Code Vision AVR & VMLAB. DDS ка выдает 500кГц.

Genadi Zawidowski
04.04.2008, 15:26
daemon, у меня сейчас нет возможности про
Что неправильно?


На первый взгляд - вместо

SDATA=temp
использовать
SDATA=(temp != 0)

daemon
04.04.2008, 15:51
Спасибо большое Дмитрий что разжевали, все получилось.

Рад был помочь, Александр. Форум для этого и нужен. :)



Что мешает использовать аппаратный SPI меги?


Не знаю какие мотивы у Александра UR4QBP, но лично я не стал использовать аппаратный SPI по трем причинам:

1. Кто-то все равно должен дергать сигнал FSYNC. Если использовать SPI без прерываний, то нужно в цикле ждать окончания пересылки очередного байта. Если использовать прерывания, то в обработчике нужно управлять FSYNC'ом. Лично у меня последовательная шина SCLK, SDATA заходят не только в DDS, но и на PLL, и на индикатор и еще кое-куда, а там свои управляющие линии, которые нужно "дергать". От этого обработчик прерывания усложняется т.к. надо определять куда именно пишется очередной передаваемый по SPI байт. Но в случае когда данные нужно передавать _только_ в DDS, использовать аппаратный SPI сравнительно легко и оправдано.

2. SPI сигналы в ATmega8 (да и не только в нем) совпадают с сигналами, по которым прошивается микроконтроллер. Поэтому, когда работаешь с новой микросхемой, всегда хочется избавиться от лишних неизвестных (мало ли как программатор повлияет на работу dds и др.)

3. Когда формируешь сигналы сам, то гораздо легче их контролировать, а значит и отлаживать устройство.

Надеюсь, автор этой темы и все ее читающие не сочтут эти рассуждения за off topic.

---
73! de ur4mck dmitry

UR4QBP
04.04.2008, 15:59
Спасибо еще раз Дмитрий ur4mck, я пытаюсь сделать генератор/ГКЧ для настройки ПЧ до 10Мгц. Повторять чьи то конструкци не интересно....

EU1ME
04.04.2008, 16:06
daemon
Спасибо за ответ. Я с мегами практически не работал, поэтому про удобство/неудобство программирования как-то не подумал.
У меня сейчас в ходу силабсы, конкретно C8051F360. Пользую в трансивере аппаратный SPI для сдвиговых регистров, флэши, ддс, дисплея... Удобство в простоте, предсказуемости, возможности оперативно менять скорость интерфеса под каждого ведомого вплоть до 50МГц, т.е. половины тактовой (не знаю, прадла, где такое может понадобиться :) ). Обработчик с прерываниями не делал (не нужное усложнение).

UR4QBP
04.04.2008, 22:03
HELP! Теперь появилась новая проблемма, как биты freq0...freq3 обьеденить целое слово. Надо чтобы высчиывать частоту на выходе DDS Fout=FREG0/2^32*Fmclk.

EU1ME
05.04.2008, 09:24
Можно по-разному.
Самый понятный вариант - freq0+2^8*freq1+2^16 freq2+2^24freq3
Естественно умножение делаем сдвгом влево и желательно в цикле.
Второй путь - через указатели.

UR4QBP
05.04.2008, 10:31
Как сделать наоборот из FREG(32bit) получить freq3,2,1,0?

UR4QBP
05.04.2008, 12:11
Как сделать наоборот из FREG(32bit) получить freq3,2,1,0?
Получилось таким образом:
freq3=freq/0x1000000;
freq2=freq/0x10000-freq3/0x100;
freq1=freq/0x100-(freq3*0x100+freq2);
freq0=freq-(((freq3*0x100+freq2 )*0x100)+freq1)*0x10 0;
Эта функция из 32битного слова freq, присваивает значения freq3, freq2, freq1, freq0 от старшего к младшему.

vld_rx
05.04.2008, 12:22
Как сделать наоборот из FREG(32bit) получить freq3,2,1,0?

Как при операции объединения, только сдвигом вправо.




freq0 = DDS_Fout & 0x000000ff;
freq1 = (DDS_Fout >> 8) & 0x000000ff;
freq2 = (DDS_Fout >> 16) & 0x000000ff;
freq3 = (DDS_Fout >> 24) & 0x000000ff;



_________________
Владислав

UR4QBP
05.04.2008, 13:03
Отказывается работать: freq=(fdds/fgen)*2^32;
Где моя ошибка? Либо компилятор отказывается работать с 2^32 или с результатом fdds/fgen.

EU1ME
05.04.2008, 13:40
Александр, все же обратите внимание на указатели, это очень пригодится вскоре.
Вот пример из моей программы

void ddsSetFTW (unsigned long ftw)
{
unsigned char *ptrFTW;
ptrFTW = &ftw;
// Set FTW0 (Frequency Tuning Word 0)

DDSCS=0;
Send_SPI (DDS_AD9954_FTW0);
Send_SPI ( *ptrFTW );
Send_SPI ( *(ptrFTW+1) );
Send_SPI ( *(ptrFTW+2) );
Send_SPI_END ( *(ptrFTW+3) );
DDSCS=1;
}


Отказывается работать: freq=(fdds/fgen)*2^32;...
Посмотрите соседнюю тему, там это хорошо обсуждалось
Программа для любого трансивера или приёмника
(http://forum.cqham.ru/viewtopic.php?t=1527 4)

rv3bj
05.04.2008, 18:11
Александр Карнаух

Отказывается работать: freq=(fdds/fgen)*2^32;
Где моя ошибка?
Александр, чтобы выяснить причину просто разбейте ваше выражение на несколько простых. В результате вы увидите в чем проблема.

Genadi Zawidowski
05.04.2008, 19:36
Отказывается работать: freq=(fdds/fgen)*2^32;
Где моя ошибка? Либо компилятор отказывается работать с 2^32 или с результатом fdds/fgen.
Как Вам подсказали, в процессе расчёта образовалось число, непредставимое в том вычислителе, который Вы нагрузили.

Есть простой способ обойти на данном этапе эту проблему -
вместо разрядности 32 для расчётов возмиите меньшее число - например 24. При выдаче в DDS младшее слово (с меньшими весами битов) заполнять 0.

При тактовой частоте 50 МГц 24 бита обеспечат ошибку около 3-х герц.

UR4QBP
05.04.2008, 19:46
Спасибо Геннадий, просмотрев ветку по программе для любого трансивера, сделал вот так:
freq=(4294967296/fgen)*fout;
Но работает несколько неккоректно, частота DDS отличается от заданоой fout.

Genadi Zawidowski
05.04.2008, 20:12
А на сколько отличается? Раза в два?
Добавьте в ответ на вопрос информацию о тактовой частоте - и что получилось в результате, например, попытки программирования вызода на 2 МГц - 4, 23, 1 МГц?

UR4QBP
05.04.2008, 20:33
А на сколько отличается? Раза в два?
Добавьте в ответ на вопрос информацию о тактовой частоте - и что получилось в результате, например, попытки программирования вызода на 2 МГц - 4, 23, 1 МГц?
Изначально fout=1 000 000 Hz, на выходе соответствует fout.
Делаю кнопкой fout+100, на выходе ничего не меняется, fout=1000100
Делаю кнопкой fout+100, на выходе 1 000 347 Hz, fout=1000200
Делаю кнопкой fout+100, на выходе 1 000 200 Hz, fout=1000300
Делаю кнопкой fout+100, на выходе 1 000 300 Hz, fout=1000400
Делаю кнопкой fout+100, на выходе 1 000 647 Hz, fout=1000500
Делаю кнопкой fout+100, на выходе 1 000 500 Hz, fout=1000600
Делаю кнопкой fout+100, на выходе 1 000 847 Hz, fout=1000700
Делаю кнопкой fout+100, на выходе 1 000 700 Hz, fout=1000800
Делаю кнопкой fout+100, на выходе 1 001 047 Hz, fout=1000900
Делаю кнопкой fout+100, на выходе 1 000 900 Hz, fout=1001000
Делаю кнопкой fout+100, на выходе 1 001 000 Hz, fout=1001100
и так далее повторяется как закономерность.
В обратную сторону несколько по другому.

Genadi Zawidowski
05.04.2008, 20:38
Попробуйте без каких-либо расчётов загнать в микросхему слово ftw со значением
20000000h
это должно заставить генерировать частоту в 1/8 от тактовой.

А посмотрите на двухстраничный документ - может поможет.

http://www.analog.com/UploadedFiles/Application_Notes/522433833AN621_0.pdf

Genadi Zawidowski
05.04.2008, 20:44
Я не знаю, как считает тот бэйсик, на котором вы пишете управление.
В каком состоянии sclk в момент перехода fclk в 0? Помнится, я советовал держать в "1". Судя по отставанию в выдачи частот, у считается правильно, но неправильно что-то в инициализации... или на хардварном уровне (в том числе при формировании управляющих сигналов).

UR4QBP
05.04.2008, 20:52
Я не знаю, как считает тот бэйсик, на котором вы пишете управление.
В каком состоянии sclk в момент перехода fclk в 0? Помнится, я советовал держать в "1". Судя по отставанию в выдачи частот, у считается правильно, но неправильно что-то в инициализации... или на хардварном уровне (в том числе при формировании управляющих сигналов).
Пишу на Си в Code Vision AVR.

Genadi Zawidowski
05.04.2008, 20:59
Я не знаю, как считает тот бэйсик, на котором вы пишете управление.
В каком состоянии sclk в момент перехода fclk в 0? Помнится, я советовал держать в "1". Судя по отставанию в выдачи частот, у считается правильно, но неправильно что-то в инициализации... или на хардварном уровне (в том числе при формировании управляющих сигналов).
Пишу на Си в Code Vision AVR.
Тогда проект сюда можно? Ил мне на мыло = mgs2001 поцхтамт ру

UR4QBP
05.04.2008, 20:59
Когда делаю рестарт DDS перед записью битов и переход в оперативный режим в конце, тогда выдает правильно. В чем причина?

Genadi Zawidowski
05.04.2008, 21:01
Когда делаю рестарт DDS перед записью битов и переход в оперативный режим в конце, тогда выдает правильно.

каждый раз рестарт или один раз после включение питания?

UR4QBP
05.04.2008, 21:05
Рестарт при инициализации делаю один раз, затем запись битов частоты. Когда рестарт делаю все время перед записью... тогда все ОК.

Genadi Zawidowski
05.04.2008, 21:05
входы psel0 и psel1 на земле висят?
без кода больше ничего не подскажу. Выход - проверить по датаашиту все слова, что используются при программировании.
двухстраничный документ свет пролил?

зы: возвращаясь назад, к формуле - в ней число 4294967296 приобрело тип signed long long - 64-х битный тип.

UR4QBP
05.04.2008, 21:09
Вот проэкт для CVAVR

UR4QBP
05.04.2008, 21:16
входы psel0 и psel1 на земле висят?
без кода больше ничего не подскажу. Выход - проверить по датаашиту все слова, что используются при программировании.
двухстраничный документ свет пролил?

зы: возвращаясь назад, к формуле - в ней число 4294967296 приобрело тип signed long long - 64-х битный тип.
входы psel0 и psel1 на земле висят.

Genadi Zawidowski
05.04.2008, 21:33
надеюсь, что fselect (pin 10) тоже на земле висит.

Предлагаю -
программировать микросхему на использование внутреннего управления выбором частоты.

После выдачи всех байтов программирования частоты, дёрнуть SYNC с слове управления.

FSYNC=0;
send_byte(0xa0);
send_byte(0x00);
FSYNC = 1;


FSYNC=0;
send_byte(0x80);
send_byte(0x00);
FSYNC = 1;

Genadi Zawidowski
05.04.2008, 21:43
Попробуйте заменить код на такой:


void initialization(void)
{DDRD=0xFF; //сделать весь PORTD выходом
PORTB=0xFF;
PORTC=0x00;
DDRC=0x3C;

SCLK =1;
}

#define SCLK_DELAY 128
void send_byte(const char byte) {
int i, j;
char tmp;
tmp = byte; /* temporary byte holder to work with */
/* Cycle for each bit in byte (MSB first) */
for (i = 0; i < 8; i++) {
if (tmp & 0x80) /* Check for most significant bit (bit15) */
{SDATA=1;} else {SDATA=0;}
tmp <<= 1; /* Get next bit in bit15 */
/* do clock */
SCLK =0;
for (j = SCLK_DELAY; j > 0; j--); /* some delay */
SCLK =1;
for (j = SCLK_DELAY - 8; j > 0; j--); /* another delay */
}
}

UR4QBP
05.04.2008, 21:45
Сделал вот так:
void save_dds(unsigned long int fout)
{ freq=(4294967296/fgen)*fout;
freq0 =freq & 0x000000ff ;
freq1 = (freq >> 8) & 0x000000ff;
freq2 = (freq >> 16) & 0x000000ff;
freq3 = (freq >> 24) & 0x000000ff;
/* Установка частоты DDS */
FSYNC=0;
send_byte(0x33);
send_byte(freq3); /* byte 3 */
FSYNC = 1;
FSYNC=0;
send_byte(0x22);
send_byte(freq2); /* byte 2 */
FSYNC = 1;
FSYNC=0;
send_byte(0x31);
send_byte(freq1); /* byte 1 */
FSYNC = 1;
FSYNC = 0;
send_byte(0x20);
send_byte(freq0); /* byte 0 */
FSYNC = 1;

FSYNC=0;
send_byte(0xa0);
send_byte(0x00);
FSYNC = 1; //это я добавил
}
Заработало правильно, спасибо Геннадий.

Genadi Zawidowski
05.04.2008, 21:55
Попробуйте без добавления выдачи
send_byte(0xa0);
send_byte(0x00);

заменить подпрограмму инициализации и выдачи байта на мои - такое вчечетление, что "недодвигается" последнее выданное на интерфейс число. перенесите a0 00 в инициализацию...
Добавьте задержку после выдачи значения бита на вывод перед дёрганием sclk (как вы поняли, я предлагаю дёргать из 1 в 0).

UR4QBP
05.04.2008, 22:15
Попробуйте без добавления выдачи
send_byte(0xa0);
send_byte(0x00);

заменить подпрограмму инициализации и выдачи байта на мои - такое вчечетление, что "недодвигается" последнее выданное на интерфейс число. перенесите a0 00 в инициализацию...
Добавьте задержку после выдачи значения бита на вывод перед дёрганием sclk (как вы поняли, я предлагаю дёргать из 1 в 0).
Пробовал все что вы написали, ничего не дает. В принципе Геннадий работает нормально, пробовал с разными шагами, работает четко.

Genadi Zawidowski
05.04.2008, 22:18
А ешё, Ваши мучения убедили меня в том, что надо делать так -
программировать микросхему на использование внутренних битов для переключения регистра частоты, программировать неиспользуемый в данный момент регистр а затем переключать вновь на загруженный.
Такое мне пришлось в своё время сделать при использовании AD9834 и аналогичный алгоритм наблюдается в программе Johan Bodin, SM6LKM, лежащей на жтом сайте. После первода с ассемблера PIC-а это выглядит примерно так:

инициализация
0xF8, 0x00 ; SLEEP = RESET = CLR = 1
0xB0, 0x00 ; SYNC = SELSRC = 1
0xC0, 0x00 ; SLEEP = RESET = 0

программирование нового знаачения частоты

если использовался регистр 1 - программируем в 0-й
0x30, ftw_07_00
0x21, ftw_15_00
0x32, ftw_23_16
0x23, ftw_31_24

0x50, 0x00 - переключаемся на регистр 0

иначе, программируем 1-й
0x34, ftw_07_00
0x25, ftw_15_00
0x36, ftw_23_16
0x27, ftw_31_24

0x58, 0x00 - переключаемся на регистр 1

UR4QBP
05.04.2008, 22:27
А ешё, Ваши мучения убедили меня в том, что надо делать так -
программировать микросхему на использование внутренних битов для переключения регистра частоты, программировать неиспользуемый в данный момент регистр а затем переключать вновь на загруженный.....
Точно не знаю... Зато благодаря моим мучениям и вашим усилиям мой проект потихоньку реализуется. В моем коде частота DDS задается в десятичном виде, что очень удобно при дальнейшем управлении частотой. Делаем save_dds(fout) и все, на выходе частота соответствует значению fout. Это очень удобно...

UR4QBP
06.04.2008, 09:27
Покрутил сегодня программу в VMLAB, после загрузки битов SCLK переходит в 0, и только перед записью в 1. По окончании записи битов я добавил SCLK=1, теперь получилось вот так.

UR4QBP
06.04.2008, 09:38
Попробуйте заменить код на такой:
#define SCLK_DELAY 128
void send_byte(const char byte) {
int i, j;
char tmp;
tmp = byte; /* temporary byte holder to work with */
/* Cycle for each bit in byte (MSB first) */
for (i = 0; i < 8; i++) {
if (tmp & 0x80) /* Check for most significant bit (bit15) */
{SDATA=1;} else {SDATA=0;}
tmp <<= 1; /* Get next bit in bit15 */
/* do clock */
SCLK =0;
for (j = SCLK_DELAY; j > 0; j--); /* some delay */
SCLK =1;
for (j = SCLK_DELAY - 8; j > 0; j--); /* another delay */
}
} [/code]
Я сначала не обратил внимания что сначала SCLK =0; потом SCLK =1;
у меня наоборот, так как мне Дмитрий предложил. На VMLAB SCLK после записи битов остается в 1. Сейчас на работе, поэтому проверить на AD9832 нет возможности, вечером приеду домой обязательно проверю как вы подсказали.

Genadi Zawidowski
06.04.2008, 11:04
Я сначала не обратил внимания что сначала SCLK =0; потом SCLK =1;
Там (в моём варианте) ещё при инициализации ставился sclk в 1.

UR4QBP
06.04.2008, 11:19
Я сначала не обратил внимания что сначала SCLK =0; потом SCLK =1;
Там (в моём варианте) ещё при инициализации ставился sclk в 1.
Обязательно переделаю... Сегодня коллега по работе принесет Microsoft Visual C+ 6.0, попробую DDS управлять через LPT. Ни разу не писал в данной проге, но поучиться можно. Уроки по работе с данной прогой и LPT есть. Хотел Microsoft Visual C+ 6.0 скачать с инета, так аж 224МВ!!!! Для моего GPRS/EDGE интернета это много. Геннадий еще раз спасибо за помощь!

UR4QBP
07.04.2008, 14:36
Закончил написание программы, работает отлично, чтобы реализовать режим ГКЧ пришлось убрать паузы межу SCLK, дабы повысить скорость записи битов в DDS. При входной частоте 16МГц работает без замечаний, попробовал установить генератор 25.000.000 Гц, DDS AD9832 работать отказалась. По даташиту Fup=25МГц... Какая частота клока максимально возможная для AD9832?

UR4QBP
07.04.2008, 14:52
Дал на вход DDS 32МГц, работает.... Fout_max=11.600.000Г ц, наверное, генератор глючный попался.

Sabuhi
16.04.2008, 17:19
ЗНАТОКИ у меня след. проблема. Спаял AD9832 на платку. Подаю питание 5 в. На выходе REFOUT 0 в. Так должно быть? Может напруга появится после записи упр. слова? Или я ееё уже спалил, надо было 3.3 в?

daemon
16.04.2008, 17:52
Дал на вход DDS 32МГц, работает.... Fout_max=11.600.000Г ц, наверное, генератор глючный попался.
Похоже на Over Clocking :lol:
Вы же сами писали, что AD9832 до 25 МГц. Короче, подавая больше, видимо, стоит ожидать непредсказуемое поведение. Хотя, может есть кто-то, кто использовал ее в таком режиме. Лично я нет.


Подаю питание 5 в. На выходе REFOUT 0 в. Так должно быть? Может напруга появится после записи упр. слова?
Давно уже дело было, но вот помниться, что когда я с AD9832 разбирался, то напряжение 1.21 В на REFOUT было даже до программирования. Ну и потребляемый ток был всего несколько миллиампер. После программирования он увеличивался.
AD9832 работает и от 3.3 В и от 5 В. Так что беспокоиться нужно не по этому поводу, а по поводу замыканий или плохого монтажа.

Sabuhi
16.04.2008, 19:02
Люди добрые помогите. Спаял схему согласно даташиту. На выходе REFOUT и соответственно на входе RFIN 0 вольт. В чем может быть причина?

Sabuhi
16.04.2008, 19:03
У меня резистор вместо 3.9 ком стоит 3.3ком, может это повлиять?

US5CAA
16.04.2008, 20:04
У меня резистор вместо 3.9 ком стоит 3.3ком, может это повлиять?
До "0" повлиять не может, что бы поднять амплитуду выхода ДДС пробывал этот резистор уменьшать до 2К. Так что ищите ошибку в схеме или монтаже.

UR4QBP
16.04.2008, 21:57
Дал на вход DDS 32МГц, работает.... Fout_max=11.600.000Г ц, наверное, генератор глючный попался.
Похоже на Over Clocking :lol:
Вы же сами писали, что AD9832 до 25 МГц. Короче, подавая больше, видимо, стоит ожидать непредсказуемое поведение. Хотя, может есть кто-то, кто использовал ее в таком режиме. Лично я нет.


Подаю питание 5 в. На выходе REFOUT 0 в. Так должно быть? Может напруга появится после записи упр. слова?
Давно уже дело было, но вот помниться, что когда я с AD9832 разбирался, то напряжение 1.21 В на REFOUT было даже до программирования. Ну и потребляемый ток был всего несколько миллиампер. После программирования он увеличивался.
AD9832 работает и от 3.3 В и от 5 В. Так что беспокоиться нужно не по этому поводу, а по поводу замыканий или плохого монтажа.
Не отрицаю, по Dataseet 25 МГц, но при 32 тоже работает. У меня DDS включена 1:1 как у ситнеза RD3AY, я ее даже из платы этого синтеза не выпаивал, а только отключил ФНЧ на выходе. Ни токи ни напряжение на пинах не измерял, так как она 100% работает и сейчас в данном синтезе.

UR4QBP
21.05.2008, 23:41
Немного отвлекаясь на SDR технику, появилась новая идея... Как переписать программу управления AD9832 под Windows по LPT? Решил изобретать велосипед в Microsoft Visual C++ 6.0, простые команды записи данных в LPT изучил, вроде бы работает, теперь задача переписать программу управления DDS под Microsoft Visual C++ 6.0. Кто пишет в такой среде Microsoft Visual C++ 6.0 прошу к столу... Окно через которое будет работать программа выглядеть будет вот так

Genadi Zawidowski
22.05.2008, 01:50
Немного отвлекаясь на SDR технику, появилась новая идея... Как переписать программу управления AD9832 под Windows по LPT? Решил изобретать велосипед в Microsoft Visual C++ 6.0, простые команды записи данных в LPT изучил, вроде бы работает, теперь задача переписать программу управления DDS под Microsoft Visual C++ 6.0. Кто пишет в такой среде Microsoft Visual C++ 6.0 прошу к столу... Окно через которое будет работать программа выглядеть будет вот так

Попробуйте разобраться в приготовленном для Вас проекте.
В приложенном архиве - два каталога. Один (PCTEST) - исходники драйвера для прямого доступа к портам LPT под WindowsXP или 98. Это лежит просто так, скомпилированный драйвер и файл для установки лежат в корне архива (.sys & .inf).

Другой каталог (SYNTH) - исходники проекта управления всякими платами синтезаторов. Поищите по своему позывному в этих исходниках - там конфигурация (частота генератора и тип микросхем) для Вашего случая. Придётся переписать немного код функции prog_sel - что он делает - ставит чипселект и снимает его.
Правда, AD9832.CPP не проверялся... но должно работать.

Выводы LPT: D0 - клок, D1 - DATA, D2..D4 - адрес чипа (смотрите targetdds1), D5 - "1" - разрешение чипселекта.

Мне кажется, начать проще будет с этого.


ps: ночью выкладывал - отрезая лишнее (для синтезаторв примого синтеза случайно испортил функциональность - потому выкладываю исправленный вариант исходников.

Genadi Zawidowski
22.05.2008, 13:55
Ататчмент в предидущем сообщении обновлён - исправлена функция calcglobals() в файле dds7.cpp

UR4QBP
22.05.2008, 15:24
Да.... в Code Vision AVR попроще было... Выдал на порт любое значение и оно там висит пока не перезальешь... с LPT потуже... Не получается пока ничерта, я уже и на выводы порта светодиоды прилепил, аля лог.пробник. У меня FSYNC-D0, SDATA-D1, SCLK-D2. Записываю FSYNC, например 1, потом пытаюсь записать в SDATA-1 и получается какая то ерунда... Уже пол дня промучался... Уже тестовую прогу накалякал под это дело. Геннадий, вы меня извените.. но в вашем сложном для меня проэкте мне трудновато разбираться.

Genadi Zawidowski
22.05.2008, 15:47
Так разбираться по началу не надо.
1) Ставите драйвер доступа к LPT.
2) компилите проект
3) смотрите на результат на выводах порта.

Вам поправить исходник под то, как у Вас распаяны ноги синтезатора?
Тогда скажите, какая тактовая идёт на DDS, чтобы получить что надо.

ps: могу предсказать, что через некоторое время Ваш проект начнёт разрастаться и станет почти таким, как и мой.

Genadi Zawidowski
22.05.2008, 15:54
Да.... в Code Vision AVR попроще было... Выдал на порт любое значение и оно там висит пока не перезальешь... с LPT потуже... Не получается пока ничерта, я уже и на выводы порта светодиоды прилепил, аля лог.пробник. У меня FSYNC-D0, SDATA-D1, SCLK-D2. Записываю FSYNC, например 1, потом пытаюсь записать в SDATA-1 и получается какая то ерунда... Уже пол дня промучался... Уже тестовую прогу накалякал под это дело. Геннадий, вы меня извените.. но в вашем сложном для меня проэкте мне трудновато разбираться.
FSYNC - это аналог чипселекта (при нуле активен).

Выдал на порт любое значение и оно там висит пока не перезальешь...
В PC аналогично, выведенное в порт значение хранится, пока новое не запишут.

UR4QBP
22.05.2008, 21:55
В PC аналогично, выведенное в порт значение хранится, пока новое не запишут.
Геннадий, немного повозившись, у меня кое что получилось... А все таки по поводу вашей цитаты... Данные на DDS вывожу через LPT порт по шине Data, адрес 0х378. У меня FSYNH=D0, SDATA=D1, SCLK=D2, но при записи в порт например числа 1 (001 в двоичной ситеме), мы будем иметь FSYNH=1, SDATA=0, SCLK=0. Теперь, например, не меняя значения FSYNH=1 надо изменить значения SDATA или SCLK. Как правильно выполнить эту процедуру записи битов, чтобы заранее записанные биты не сдвигались... Может быть это делается математическим каким то методом... Пробовал по разному... DDS-ка работает, но как то коряво... При выводе одного и того же значения частоты она устанавливается по разному, при каждом нажатии на кнопку, которая выполняет функцию save_dds(fout).

vadim_d
22.05.2008, 22:03
Данные на DDS вывожу через LPT порт по шине Data, адрес 0х378. У меня FSYNH=D0, SDATA=D1, SCLK=D2, но при записи в порт например числа 1 (001 в двоичной ситеме), мы будем иметь FSYNH=1, SDATA=0, SCLK=0. Теперь, например, не меняя значения FSYNH=1 надо изменить значения SDATA или SCLK. Как правильно выполнить эту процедуру записи битов, чтобы заранее записанные биты не сдвигались... Может быть это делается математическим каким то методом... Александр, назвать это математикой можно, но это чересчур :D
Имеем: FSYNH=D0, двоичный вес 2^0=1
SDATA=D1, двоичный вес 2^1=2
SCLK=D2, двоичный вес 2^2=4
В Вашем примере, когда активен только FSYNH, в порт выведена единица. Если нужно взвести SCLK, вес которого 4, складываете имеющуюся единицу и четверку - в порт надо вывести пять. Ну и так далее :D

UR4QBP
22.05.2008, 22:15
Александр, назвать это математикой можно, но это чересчур :D
Имеем: FSYNH=D0, двоичный вес 2^0=1
SDATA=D1, двоичный вес 2^1=2
SCLK=D2, двоичный вес 2^2=4
В Вашем примере, когда активен только FSYNH, в порт выведена единица. Если нужно взвести SCLK, вес которого 4, складываете имеющуюся единицу и четверку - в порт надо вывести пять. Ну и так далее :D
А если в порт записано например:
110=6, это
SDATA=D1=1, SCLK=D2=1, FSYNH=D0=0;
как теперь мне сделать сложив какое то число к 110=6;
чтобы получить на шине
SDATA=D1=1, SCLK=D2=0, FSYNH=D0=0
а это 100=4.
Сложением не получается, надо уже вычитать
6-SDATA( SDATA=D1, двоичный вес 2^1=2 )...

Genadi Zawidowski
22.05.2008, 22:45
В PC аналогично, выведенное в порт значение хранится, пока новое не запишут.
Геннадий, немного повозившись, у меня кое что получилось... А все таки по поводу вашей цитаты... Данные на DDS вывожу через LPT порт по шине Data, адрес 0х378. У меня FSYNH=D0, SDATA=D1, SCLK=D2, но при записи в порт например числа 1 (001 в двоичной ситеме), мы будем иметь FSYNH=1, SDATA=0, SCLK=0. Теперь, например, не меняя значения FSYNH=1 надо изменить значения SDATA или SCLK. Как правильно выполнить эту процедуру записи битов, чтобы заранее записанные биты не сдвигались... Может быть это делается математическим каким то методом... Пробовал по разному... DDS-ка работает, но как то коряво... При выводе одного и того же значения частоты она устанавливается по разному, при каждом нажатии на кнопку, которая выполняет функцию save_dds(fout).


Образуйте число для вывода каждый раз по-новой, в зависимости от того, что требуется в каждый момент.
арифметическая операция ИЛИ -
result = value1 | value2 | value3

UR4QBP
22.05.2008, 22:51
Образуйте число для вывода каждый раз по-новой, в зависимости от того, что требуется в каждый момент.
Проверил все на калькуляторе, вроде бы получается, сейчас буду писать...

vadim_d
22.05.2008, 23:13
Сложением не получается, надо уже вычитать
6-SDATA( SDATA=D1, двоичный вес 2^1=2 )...
Александр, все правильно излагаете - если бит уже взведен и его надо сбросить, то вычитаете его вес из последнего значения, выведенного в порт.

UR4QBP
23.05.2008, 09:34
Сложением не получается, надо уже вычитать
6-SDATA( SDATA=D1, двоичный вес 2^1=2 )...
Александр, все правильно излагаете - если бит уже взведен и его надо сбросить, то вычитаете его вес из последнего значения, выведенного в порт. Вот фрагмент кода программы:
#define SCLK_DELAY 256
void send_byte(const int byte) {
int i, j;
char tmp;
tmp = byte; /* temporary byte holder to work with *** FSYNC=0 ***
/* Cycle for each bit in byte (MSB first) */
for (i = 0; i < 8; i++) {
if (tmp & 0x80) /* Check for most significant bit (bit15) */
{set_port(code=code+ SDATA);} else {set_port (code=code-SDATA);};
tmp <<= 1; /* Get next bit in bit15 */
/* do clock */
set_port(code=code-SCLK); for (j = SCLK_DELAY; j > 0; j--); /* some delay */
set_port(code=code+S CLK); for (j = SCLK_DELAY - 8; j > 0; j--); /* another delay */
}
}
Это функция вывода в порт битов записи в DDS. Работает не корректно, что не правильно подскажите?

Genadi Zawidowski
23.05.2008, 09:43
void send_byte(const int byte) {
int i, j;
char tmp;
tmp = byte; /* temporary byte holder to work with *** FSYNC=0 ***
/* Cycle for each bit in byte (MSB first) */
for (i = 0; i < 8; i++) {
if (tmp & 0x80) /* Check for most significant bit (bit15) */
{
set_port(SDATA | SCLK);
// здесь задержка
set_port(SDATA | 0);
// здесь задержка
set_port(SDATA | SCLK);
// здесь задержка
}
else
{
set_port(0 | SCLK);
// здесь задержка
set_port(0 | 0);
// здесь задержка
set_port(0 | SCLK);
// здесь задержка
};
tmp <<= 1; /* Get next bit in bit8 */

}
} [/quote]

Genadi Zawidowski
23.05.2008, 09:45
Да, начальное значение выдать в порт -
FSEL = 1, SCLK=1
Затем -
FSEL = 0, SCLK=1 - выбрали микросхему
потом выдаем биты
потом
FSEL = 1, SCLK=1

UR4QBP
23.05.2008, 10:56
Геннадий, какое значение лучше для цикла паузы?

Genadi Zawidowski
23.05.2008, 12:10
Под Windows XP простыми способами получить задержку меньше чем на 20 милисекунд (или 10) - с помощью Sleep(10) - не получится.
Для выдержки времени, достаточного для успокоения переходных процессов на кабеле к DDS (по моему) вполне достаточно тех задержек, которые идут как накладные расходы при обращении к драйверу, через который идёт выдача данных в порт.

UR4QBP
23.05.2008, 12:38
Геннадий, как мне установить FSYNC=0 или FSYNC=1 так, чтобы значения SCLK и SDATA не изменялись после записи FSYNC=0 или FSYNC=1...

Genadi Zawidowski
23.05.2008, 12:51
Я нарисовал ведь, как.
Каждый раз собирать все нужные биты через операцию "|" и выводить. Если у драйвера паралельного порта нет операции прочитать старое состояние.

Ещё способ - хранить где-то последнее выданное значение.


unsigned char last;
last = FSYNC | SCLK; // начальное состояние -два битика установлены
outport(last);
last &= ~ FSYNC; // сбросили FSYNC
outport(last);
last |= SDATA; // установили бит SDATA
outport(last); // выдали

last &= ~ SCLK; // сбросили SCLK
outport(last); // выдали
last |= SCLK; // установили SCLK
outport(last);

Выложи проект, поправлю.

UR4QBP
23.05.2008, 13:14
Драйвер порта LPT inpout32, архив с проектом выкладываю...

UR4QBP
23.05.2008, 13:34
Подкорректировал программу, но частоту выдает правильно после многократного нажатия на кнопку записи в DDS. Может быть из за того что я подключил DDS на прямую к LPT? Буфер надо наверное поставить? Мой LPT при лог. 1 выдает 3,3В, наверное DDS не хватает уровня?

UR4QBP
23.05.2008, 14:11
Геннадий, как я и думал. Подключил DDS к LPT через буфер 74HC244N и все заработало нормально.

23.05.2008, 14:16
вот мой полуфабрикат :)

Genadi Zawidowski
23.05.2008, 14:20
Драйвер порта LPT inpout32, архив с проектом выкладываю...

Лови поправленный файл.

А вообще - пересчёт частоты настройки в управляющие слова DDS я бы советовал внести в одно место - рядом с выдаче в dds, например.

Просто, когда код с одинаковой функциональностью размазан по многим местам программы, тяжелее модифицировать.


вот мой полуфабрикат :)
Красивый "полуфабрикат"! Блокировочный конденсатор между резистором в нагрузке усилка и дросселем - я бы убрал. Но если усиления хватает - то пусть стоит... но на мой вкус - я регулировал бы по входу (аттенюатором).

23.05.2008, 14:48
эх.. был бы аттенюатор :)

Genadi Zawidowski
23.05.2008, 14:57
Ну там три резистора... сейчас-то ставить некуда, вижу.
О! хорошая идея - AD9832 на выход поставить не 270 ом, а поменьше... тогда и фильтр "прямее" будет нагружен (неравномерность меньше будет) и уровень снизится на НЧ.

23.05.2008, 15:00
эт смотря под какое сопротивление фильтр считать.
а так интересно пробывать. это так сказать пилотная версия ковырять можно в полный рост еще 4 платы есть голые :)

Genadi Zawidowski
23.05.2008, 15:20
эт смотря под какое сопротивление фильтр считать.
А тут вариантов нет - под то, какое у усилителя в документе (99%, что там говорили пол 50 Ом!)

;)

ps: а вот экзотику типа ФНЧ с разными сопротивлениями и при этом без потерь... я не смог получить.

UR4QBP
23.05.2008, 16:34
Геннадий, в коде программы есть функция инициализации LPT

void lpt_initialize()
{
last_code = FSYNC | SCLK;
set_port(last_code);
}
Но эта функция нигде в программе не фигурирует. Частота DDS устанавливается неточно, пробовал уже разные методы, ничего не получается. Чатота генератора установлена такая же как на плате управления на МК ATmega8, на меге работает нормально. Где то наверное какой то битик "затирается"...

Genadi Zawidowski
23.05.2008, 17:11
Извиняюсь, забыл!
Вставить сюда


BOOL CDdsDlg::OnInitDialo g()
{
...
// TODO: Add extra initialization here
lpt_initialize();
return TRUE; // return TRUE unless you set the focus to a control
}

Hасчёт FTW из частоты попробуй такой:


#define PHASE_RESOLUTION 32
static unsigned long osc = 16256370; // = SYNTH_DDSOSC; /* тактовая частота на входе DDS */

/* функция преобразования требуемой частоты в FTW при заданной тактовой частоте DDS */
static unsigned long freq2ftw(unsigned long freq)
{
unsigned __int64 t = (unsigned __int64) freq << PHASE_RESOLUTION;
return (unsigned long) (t / osc);
}
Если всё равно не так, проверяй адреса регистров, в которые четыре байта выдаются.

ps: когда замучают щелчки при перестройке частоты, наконец-то загляните в мои исходники в файл AD9832.CPP - так кое-что полезное лежит.

UR4QBP
23.05.2008, 17:45
Спасибо Геннадий, я думал что Си везде одинаковый, в CodeVisionAVR тот код работал, а здесь увы... Вообще у меня задача написать программу PLL синтезатора для ТПП на DDS AD9832. Он у меня работал под ATmega8, но там надо ЖКИ, кнопки и т.д. А работать в эфире на SDRе и клацать кнопками где то на ящике не удобно. Вот по этому пришлось вас в очередной раз помучать, за что вам очень благодарен. Видел в вашем проэкте что то вроде вывода в окне данных типа ЦШ, как это делается? В общих чертах... Надо же частоту вывести на мониторе в окне проги, кнопки нажимть уже научился, а как данные выводить? Спасибо, теперь все работает корректно.

Genadi Zawidowski
23.05.2008, 18:16
Различия между разными компиляторами начинают мешать только тогда, когда что-то некорректно написано (я не про случаи, когда нестандартные встроенные типы по разному называются).

Жаль, что Вы до сих пор не посмотрели внутрь показавшегося Вам сложным проекта...
Нестандартное отображение делается правляющим элементом, порождённым от CButton (CLedDigits, файл LedDigits.cpp), в котором в обработчике сообщения DrawItem всё что надо рисуется. Боюсь, что тут сильно не в тему будет объяснять, как делаются такие "контролы". Попробуйте начать отсюда - www.rsdn.ru - CButton, owndraw, DrawItem и так далее.

А вообще, предлагаю все-таки такой процесс -
1) Мой проект компилируете - убеждаетесь в том, что он на Вашем компютере нормально запускается.
2) Ищите функции prog_select_init и prog_select. Корректируете начальное состояние порта LPT и битик чипслекта. Корректирует макросы, которые устанавливают-сбрасывабт биты данных и синхронизации на LPT.
3) в файле product.h рядом с вашим позывным ижите и меняете частоту 50 МГц на ту, которая подается на DDS в вашей плате.

Контролируете работоспособность.

Когда дело дойдет до PLL, этот же проект Вам поможет.

UR4QBP
23.05.2008, 18:24
Да... Геннадий, для меня который написал первую прогу в Visual C++ сложновато... Из стандартного набора Visual C++ есть что то чтобы выводить данные?