Как я понимаю связь 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, это результат на моем устройстве,
когда я меняю частоту, нет никаких изменений, просто значение составляет примерно 400 Гц на моем прицеле. Итак, я пробую это простое решение, я помещаю кодsend_data(0x2000)
, 0x2000 означает сброс AD9833 согласно даташиту, указанному вышеsend_data(LSB)
код. Таким образом, код стал,
send_data(0x2000)
send_data(LSB)
send_data(MSB)
send_data(phase)
и это результат,
-
freq_out = 400
частота_выход = 400 -
freq_out = 500
частота_выход = 500 - частота_выход = 600
-
freq_out = 1000
частота_выход = 1000
я не знаю почему, когда я пишуfreq_out = 600
выходная частота значения не соответствует тому, что я ввожу. Итак, может ли кто-нибудь прокомментировать/изложить аргумент по моему вопросу?
1 ответ
Эту задачу можно разбить на ряд подзадач.
- Значения для отправки
- Значения последовательности отправлены
- Как значения передаются по 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()