Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 20, 2017 13:03:53

Oolong
Зарегистрирован: 2017-06-20
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

SPI exchange

Здравствуйте, друзья!
Прошу вашего совета по следующему вопросу…
У меня есть двухканальный передатчик, позволяющий взаимодействовать с ним по SPI протоколу, Имею в наличии нечто вроде протокола информационного взаимодействия. В качестве “железки” для работы по указанному протоколу я решил использовать Raspberry Pi 2. Задача вроде бы вполне решаемая этими средствами и применением Python.
Параметры обмена: CPOL=0, CPHA=1. Период обмена 2,5 мс. Частота – 500 кГц..10 МГц.
Состав слов MOSI:
1 байт - 6 бит контрольное слово (checkword), полученное от передатчика в предыдущем цикле обмена + 2 бита - установка уровня выходной мощности (полная мощность, -3 дБ, -6 дБ, -9 дБ).
3 байт - кодовое слово, передаваемое в передатчик для подтверждения целостности канала.
2,4,5,6 байты - резерв, не используются
Состав слов MISO:
1 байт - 6 бит контрольное слово (передаваемое передатчиком) + 1 бит подтверждение запроса + 1 бит признак исправности.
2 байт - выходная мощность основного канала (Pout_o в моей программе).
3 байт - выходная мощность резервного канала (Pout_k в моей программе).
4 байт - контрольное слово, полученное от стенда.
5 байт - коэффициент стоячей волны по основному каналу (KSV_o в моей программе).
6 байт - коэффициент стоячей волны по резервному каналу (KSV_k в моей программе).

Вот мой код:

import spidev
import time
import math
import random
from tkinter import *

spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 110000
spi.bits_per_word = 8
spi.mode = 0b00
spi.cshigh = False
#spi.loop = True

root = Tk()
root.title("SPI-CONFIG")
root.geometry("500x300+600+300")

def printer(event):
print("SPI-test")

def Pout(sec_byte):
P=100*(10**(0.0058*sec_byte))
return P

def KSV(fifth_byte):
k=1+0.1*fifth_byte
return k

var=IntVar()
radbut1 = Radiobutton(root,variable=var,text = "3 dB",value=1)
radbut2 = Radiobutton(root,variable=var,text = "6 dB",value=2)
radbut3 = Radiobutton(root,variable=var,text = "9 dB",value=3)
radbut3.pack(side=BOTTOM)
radbut2.pack(side=BOTTOM)
radbut1.pack(side=BOTTOM)

KSV_o=StringVar()
P_o=StringVar()
P_k=StringVar()

lab_P_o = Label(root, textvariable=P_o)
lab_P_o.pack(side=TOP)
lab_P_k = Label(root,textvariable=P_k)
lab_P_k.pack(side=TOP)
lab_KSV_o = Label(root, textvariable=KSV_o)
lab_KSV_o.pack(side=TOP)

b_in_0 = 0

def callback(event=None):
global b_in_0

Pset=0b00000011

b_out_0 = (b_in_0 << 2) + int(Pset) ## Control word TRMTT - answer
b_out_1 = 0xAA #in_dat_0[2] ## Reserve
b_out_2 = 0xAB #in_dat_0[3] ## Control word RPi
b_out_3 = 0xAD #in_dat_0[4] ## Reserve
b_out_4 = 0xFA #in_dat_0[5] ## Reserve
b_out_5 = 0xFB #in_dat_0[6] ## Reserve
b_out_6 = 0xFC #in_dat_0[7] ## Reserve
b_out_7 = 0xFD #in_dat_0[8] ## Reserve

out_dat= spi.writebytes([b_out_0,b_out_1,b_out_2,b_out_3,b_out_4,b_out_5])

in_dat = spi.readbytes(6)

b_in_0 = int(in_dat[0]) >> 2 ## Control word TRMTT
b_in_1 = 100*(10**(0.0058*int(in_dat[1]))) ## Pout_o
b_in_2 = 100*(10**(0.0058*in_dat[4]))#in_dat[2] ## Pout_k
b_in_3 = in_dat[3] ## Control word RPi
b_in_4 = in_dat[4] ## KSV_0
b_in_5 = in_dat[5] ## KSV_k

KSV_o.set('KSV = '+ str(b_in_5))
P_o.set('Pout_o = '+ str(b_in_1))
P_k.set('Pout_k = '+ str(b_in_2))
#lab_P_o.after(50,callback)
#lab_P_k.after(50,callback)
lab_KSV_o.after(50,callback)
#print(in_dat)
lab_P_o.after(50,callback)
lab_P_k.after(50,callback)
lab_KSV_o.after(50,callback)

root.mainloop()

Итак, теперь о проблеме…. Данные пишутся и читаются, но… Неодновременно! Насколько я понял суть SPI протокола, чтение по команде “spi.readbytes” должно начаться с первым битом сообщения, переданного по команде spi.writebytes. У меня же картина другая - сначала все байты записываются, потом читаются, всилу чего информационный полнодуплексный обмен невозможен. Вот осциллограмма обмена (желтый - MOSI, пурпурный - MISO, синий - SCLK) :
Your text to link here…

Я подумал, что не помешает замкнуть выход расберри со входом и посмотреть, будет ли идти прием. Оказалось, нет. Соответственно, передатчик тут не при чем. Никак не пойму, где в моем кривом коде ошибка?

Отредактировано Oolong (Июнь 20, 2017 13:06:37)

Офлайн

#2 Июнь 20, 2017 13:32:56

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

SPI exchange

readbytes только читает, writebytes только пишет. Для обмена xfer, что-то типа:

 in_dat = spi.xfer([b_out_0,b_out_1,b_out_2,b_out_3,b_out_4,b_out_5])
количество прочитанных, как сами понимаете, равно кол-ву переданных



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

#3 Июнь 20, 2017 13:44:20

Oolong
Зарегистрирован: 2017-06-20
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

SPI exchange

PooH
readbytes только читает, writebytes только пишет. Для обмена xfer, что-то типа:
Но тогда, как я понимаю, я не имею возможности “вклиниться” в обмен? То есть spi.xfer позволит мне делать что? При этом расберри будет ждать повторения переданной информации? Вообще не очень понимаю эту функцию. Мне кажется она нужна только при какой-нибудь проверке работоспособности канала… Или я неправ?

Офлайн

#4 Июнь 20, 2017 13:56:43

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

SPI exchange

Ээээ, вы представляете себе как SPI работает? По каждому такты синхры бит из буфера сдвигается на MOSI, бит с MISO встает на сдвинутое место. Тоже самое только линии наоборот у приемника. Это и есть обмен, xfer. readbytes и writebytes просто отбрасывают соответственно записанные/прочитанные данные. Полноценного дуплекса вы не получите.

ЗЫ: Первый раз бестолково написал, пришлось редактировать



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Отредактировано PooH (Июнь 20, 2017 14:00:42)

Офлайн

#5 Июнь 20, 2017 14:13:02

Oolong
Зарегистрирован: 2017-06-20
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

SPI exchange

PooH
Ээээ, вы представляете себе как SPI работает? По каждому такты синхры бит из буфера сдвигается на MOSI, бит с MISO встает на сдвинутое место. Тоже самое только линии наоборот у приемника. Это и есть обмен, xfer. readbytes и writebytes просто отбрасывают соответственно записанные/прочитанные данные. Полноценного дуплекса вы не получите.ЗЫ: Первый раз бестолково написал, пришлось редактировать
Хм… То есть результатом этого “отбрасывания” и является наличие двух последовательных пачек синхроимпульсов на осциллограмме? И, судя по всему, чтобы реализовать свой замысел, мне придется каким-то образом делать динамически изменяемые данные в xfer ?

Отредактировано Oolong (Июнь 20, 2017 14:14:20)

Офлайн

#6 Июнь 20, 2017 15:33:32

vic57
Зарегистрирован: 2015-07-07
Сообщения: 913
Репутация: +  127  -
Профиль  

SPI exchange

вроде есть модуль spi для RPi
https://geektimes.ru/post/255052/

Офлайн

#7 Июнь 20, 2017 15:40:48

Oolong
Зарегистрирован: 2017-06-20
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

SPI exchange

vic57
вроде есть модуль spi для RPihttps://geektimes.ru/post/255052/
Ну именно его я и использую. Я еще попробовал проверил скомпилировал С-шный код с помощью gcc, как там описано. Замкнул - работает. Так что железо в норме. Дело “за малым” - разобраться, как написать с использованием xfer, чтобы работало.
Ну а вообще, реально ли сделать то, что я описал выше, с помощью xfer?

Отредактировано Oolong (Июнь 20, 2017 15:47:44)

Офлайн

#8 Июнь 20, 2017 16:58:47

vic57
Зарегистрирован: 2015-07-07
Сообщения: 913
Репутация: +  127  -
Профиль  

SPI exchange

Oolong
оманде “spi.readbytes” должно начаться с первым битом сообщения, переданного по команде spi.writebytes. У меня же картина другая :
spi.readbytes != spi.readbits
в nix чтение-запись идет байтами а не битами. в микропроцессорной системе контроллер читает байт, пишет в свой маленький буфер и выставляет флаг прерывания - “в буфере есть данные”. программа по этому прерыванию должна вовремя забрать данные, при этом буфер очищается. на уровне битов работает только сам контроллер (аппаратно)
Устройство, управляющее шиной тактирования (то есть генерирующее на ней синхроимпульсы), является “Ведущим” или “Мастером”. Собственно, “Master” управляет всем обменом данными, - он решает: когда начинать обмен, когда заканчивать, сколько бит передать и т.д. Второе устройство, участвующее в обмене, является “Ведомым” или “Slave”. В SPI, в отличии от, например, того же I2C, “Slave” совсем бесправен, он вообще никак не может влиять на шину тактирования и никак не может сообщить мастеру, что не успевает или, наоборот, что уже готов к обмену. То есть “Мастер” сам должен знать: когда, что и на какой скорости спросить у “Слэйва”, чтобы тот смог ему ответить.
http://www.radiohlam.ru/teory/SPI.htm

Отредактировано vic57 (Июнь 20, 2017 17:26:09)

Офлайн

#9 Июнь 20, 2017 17:49:28

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

SPI exchange

Oolong
И, судя по всему, чтобы реализовать свой замысел, мне придется каким-то образом делать динамически изменяемые данные в xfer
Что-то я не пойму в чем вы проблему видите? Подготовили свои данные, вызвали xfer, в результате получили данные со слейва, а свои туда закинули, обработали, снова выставили, снова вызвали. Как-то в упор проблемы не вижу. Просто передача идет одновременно в две стороны.



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Отредактировано PooH (Июнь 20, 2017 17:50:09)

Офлайн

#10 Июнь 21, 2017 10:40:48

Oolong
Зарегистрирован: 2017-06-20
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

SPI exchange

PooH
Что-то я не пойму в чем вы проблему видите? Подготовили свои данные, вызвали xfer, в результате получили данные со слейва, а свои туда закинули, обработали, снова выставили, снова вызвали. Как-то в упор проблемы не вижу. Просто передача идет одновременно в две стороны.
Ну в общем я сделал вывод, что с xfer надо поработать плотнее. Просто у меня в голове пока не совсем укладывается, как я смогу получить какие-то данные со слейка, кроме тех, что я ему отправлял, если использовать именно xfer. Я считал, что он не предполагает возврат каких-либо значений.

Отредактировано Oolong (Июнь 21, 2017 10:41:44)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version