Как я понимаю связь AD9833 SPI с использованием Python с моей малиной?

Привет, у меня есть проблема для обсуждения, и я действительно не понимаю, как отправлять данные с помощью SPI с помощью Python.

Я хочу отправлять данные с помощью своего Raspberry Pi 4 ver.b , используя Python для отправки данных в мой модуль с именем AD9833 DDS. Итак, я нашел в Интернете код, написанный на Python (сор. https://ez.analog.com/dds/f/qa/28431/ad9833-programming-in-raspberry-pi-using-python). Это код:

      # The code write by SamMaster, Oct 21 2016

# importing library
import time
import spidev

# activate spidev module and settings SPI
spi = spidev.SpiDev()
spi.open(0,1)
spi.max_speed_hz = 976000

# initialize frequency and another value
freq_out = 400
Two28 = 268435456
phase = 0

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

      def send_data(input):
    tx_msb = input >> 8
    tx_lsb = input & 0xFF
    spi.xfer([tx_msb,txlsb])
    print(input)

чтобы это значение частоты могло быть прочитано AD9833, эта частота должна быть преобразована в слово частоты, поэтому программист пишет код,

      freq_word = int(round(float(freq_out*Two28)/25000000))

а затем программист определяет все MSB и LSB

      MSB = (freq_word & 0xFFC000)>>14
LSB = (freq_word & 0x3FFF)

LSB |= 0x4000
MSB |= 0x4000

phase|= 0xC000

а затем функция, которую программист реализовал в этих блоках кодов

      send_data(LSB)
send_data(MSB)
send_data(phase)
send_data(0x2000)

это сработало на моем Raspberry Pi 4, это результат на моем устройстве,

  1. Результат для 400 Гц
  2. Результат для 500 Гц

когда я меняю частоту, нет никаких изменений, просто значение составляет примерно 400 Гц на моем прицеле. Итак, я пробую это простое решение, я помещаю кодsend_data(0x2000), 0x2000 означает сброс AD9833 согласно даташиту, указанному вышеsend_data(LSB)код. Таким образом, код стал,

      send_data(0x2000)
send_data(LSB)
send_data(MSB)
send_data(phase)

и это результат,

  1. freq_out = 400 частота_выход = 400
  2. freq_out = 500 частота_выход = 500
  3. частота_выход = 600
  4. freq_out = 1000частота_выход = 1000

я не знаю почему, когда я пишуfreq_out = 600выходная частота значения не соответствует тому, что я ввожу. Итак, может ли кто-нибудь прокомментировать/изложить аргумент по моему вопросу?

1 ответ

Эту задачу можно разбить на ряд подзадач.

  1. Значения для отправки
  2. Значения последовательности отправлены
  3. Как значения передаются по SPI

Как указал SamMaster, есть примечание по применению от Analog Devices, в котором показана последовательность значений, которые необходимо отправить, чтобы установить частоту на 400 Гц.

https://www.analog.com/media/en/technical-documentation/application-notes/AN-1070.pdf

Они суммируют пять значений для отправки и в каком порядке в следующей таблице:

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

      sending: [0x21, 0x00]
sending: [0x50, 0xc7]
sending: [0x40, 0x00]
sending: [0xc0, 0x00]
sending: [0x20, 0x00]

Это просто оставляет пулю 3, которая вызывает проблемы.

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

Глядя на ограниченную документацию на https://pypi.org/project/spidev/, можно увидеть две вероятные команды, которые можно использовать: или .

Разница между ними заключается в значении вывода выбора микросхемы между блоками.

Рисунок 4 в таблице данных, я думаю, говорит о том, что выбор микросхемы не должен быть освобожден между двумя байтами.

https://www.analog.com/media/en/technical-documentation/data-sheets/ad9833.pdf

Это предполагает, чтоxfer2должен использоваться для отправки блоков, а не как это сделал SamMaster. Хотя SamMaster, кажется, предполагает, что он работал сxferи вы смогли успешно установить значение 400 Гц. Вам понадобится ваш анализатор области/логики, чтобы увидеть, правильно ли работает GPIO на оборудовании.

В какой-то момент вашего развития вы, кажется, изменили последовательность отправляемых значений. Должен быть:

      send_data(0x2100)  # Start
send_data(LSB)  # Frequency 14 bits (LSB)
send_data(MSB)  # Frequency 14 bits (MSB)
send_data(phase)  # Phase value
send_data(0x2000)  # End

Это может быть еще одним источником вашей ошибки.

Я посмотрел, какие значения должны быть отправлены для другой частоты, которую вы тестировали. Я рассчитал значения следующим образом:

      For Frequency: 400
Frequency setting: 4295 = 0x10c7 = 0001000011000111
        send_data(0x2100)
        send_data(0x50c7)
        send_data(0x4000)
        send_data(0xc000)
        send_data(0x2000)
For Frequency: 500
Frequency setting: 5369 = 0x14f9 = 0001010011111001
        send_data(0x2100)
        send_data(0x54f9)
        send_data(0x4000)
        send_data(0xc000)
        send_data(0x2000)
For Frequency: 600
Frequency setting: 6442 = 0x192a = 0001100100101010
        send_data(0x2100)
        send_data(0x592a)
        send_data(0x4000)
        send_data(0xc000)
        send_data(0x2000)
For Frequency: 1000
Frequency setting: 10737 = 0x29f1 = 0010100111110001
        send_data(0x2100)
        send_data(0x69f1)
        send_data(0x4000)
        send_data(0xc000)
        send_data(0x2000)

И, наконец, я провел рефакторинг кода, чтобы упростить тестирование различных частей кода. Я разделяю его здесь для вашей информации. Мне пришлось закомментировать все части связи spi, потому что у меня нет аппаратного обеспечения.

      import time
import spidev

# activate spidev module and settings SPI
bus = 0
device = 1
spi = spidev.SpiDev()
spi.open(bus, device)
spi.max_speed_hz = 976000


def output_freq(hz_value):
    return int(round((hz_value * 2**28) / 25e6))


def freq_change_start():
    ctrl_reg = 0
    ctrl_reg += 2**13  # set DB13 (28 bit freq reg)
    ctrl_reg += 2**8  # set DB8 (Reset)
    return ctrl_reg


def freq_reg_lsb(freq_reg):
    fourteen_bit_mask = 0b0011111111111111
    write_value = 0
    write_value += 2**14  # set DB14
    lsb = freq_reg & fourteen_bit_mask
    write_value += lsb
    return write_value


def freq_reg_msb(freq_reg):
    fourteen_bit_mask = 0b0011111111111111
    write_value = 0
    write_value += 2**14  # set DB14
    msb = freq_reg >> 14 & fourteen_bit_mask
    write_value += msb
    return write_value


def phase_register():
    # Currently always the same value
    write_value = 0
    # Set phase register address
    write_value += 2 ** 15  # set DB15
    write_value += 2 ** 14  # set DB14
    return write_value


def freq_change_end():
    ctrl_reg = 0
    ctrl_reg += 2**13  # set DB13 (28 bit freq reg)
    return ctrl_reg


def word_split(word16):
    tx_msb = word16 >> 8
    tx_lsb = word16 & 0xFF
    return tx_msb, tx_lsb


def send_spi_sequence(sequence):
    for word16 in sequence:
        two_bytes = word_split(word16)
        print(f"\tsending:[{two_bytes[0]:#02x}, {two_bytes[1]:#02x}]")
        print(f"\tsend_data({word16:#06x})")
        spi.xfer(two_bytes)
        # spi.xfer2(two_bytes)


def change_freq(freq_hz):
    # Calc values to send
    print("For Frequency:", freq_hz)
    freq_reg = output_freq(freq_hz)
    print(f"Frequency setting: {freq_reg} = {freq_reg:#04x} = {freq_reg:016b}")
    ctrl_start = freq_change_start()
    print(f"Control register write: {ctrl_start:#04x}")
    lsb_value = freq_reg_lsb(freq_reg)
    print(f"lsb value: {lsb_value:#04x}")
    msb_value = freq_reg_msb(freq_reg)
    print(f"lsb value: {msb_value:#04x}")
    phase_reg = phase_register()
    print(f"Phase register write: {phase_reg:#04x}")
    ctrl_end = freq_change_end()
    print(f"Control register write: {ctrl_end:#04x}")

    # Write values to spi
    send_spi_sequence([ctrl_start, lsb_value, msb_value, phase_reg, ctrl_end])


def main():
    show_freq_for = 20
    change_freq(400)
    time.sleep(show_freq_for)
    change_freq(500)
    time.sleep(show_freq_for)
    change_freq(600)
    time.sleep(show_freq_for)
    change_freq(1000)
    time.sleep(show_freq_for)


if __name__ == '__main__':
    main()

Другие вопросы по тегам