我需要在 Raspberry 中使用 SPI,并且它使用这种方法,但是它将 SPI 总线的读取结果打印到屏幕上,这是我不想要的。Python 用我要发送的数据调用 Compiled C 模块,但我想在 python 内部接收响应,而不是屏幕。我从不使用 C,而且我对这种语言有点肤浅,所以有人可以告诉我一个选择吗?我读了一些关于获取 cout 和 fopen 的内容,但想知道是否有更多的东西融入到 python 中?有没有机会而不是将结果打印到屏幕上来从函数或其他东西中返回结果?
谢谢你。
C模块:
#include <Python.h>
#include "structmember.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <linux/spi/spidev.h>
#include <linux/types.h>
#include <sys/ioctl.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define MAXPATH 16
PyDoc_STRVAR(SPI_module_doc,
"This module defines an object type that allows SPI transactions\n"
"on hosts running the Linux kernel. The host kernel must have SPI\n"
"support and SPI device interface support.\n"
"All of these can be either built-in to the kernel, or loaded from\n"
"modules.\n"
"\n"
"Because the SPI device interface is opened R/W, users of this\n"
"module usually must have root permissions.\n");
typedef struct {
PyObject_HEAD
int fd; /* open file descriptor: /dev/spi-X.Y */
uint8_t mode; /* current SPI mode */
uint8_t bpw; /* current SPI bits per word setting */
uint32_t msh; /* current SPI max speed setting in Hz */
} SPI;
static PyObject *
SPI_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
SPI *self;
if ((self = (SPI *)type->tp_alloc(type, 0)) == NULL)
return NULL;
self->fd = -1;
self->mode = 0;
self->bpw = 0;
self->msh = 0;
Py_INCREF(self);
return (PyObject *)self;
}
PyDoc_STRVAR(SPI_close_doc,
"close()\n\n"
"Disconnects the object from the interface.\n");
static PyObject *SPI_close(SPI *self)
{
if ((self->fd != -1) && (close(self->fd) == -1)) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
self->fd = -1;
self->mode = 0;
self->bpw = 0;
self->msh = 0;
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(SPI_transfer_doc,
"transfer([values]) -> [values]\n\n"
"Perform SPI transaction.\n"
"CS will be released and reactivated between blocks.\n"
"delay specifies delay in usec between blocks.\n");
static PyObject* SPI_transfer(SPI *self, PyObject *args)
{
uint8_t bits = 8;
int ret = 0;
char* list;
int length_list = 1;
uint16_t delay = 5;
uint32_t speed = 500000;
int i=0;
PyArg_ParseTuple(args, "s|i:transfer", &list, &length_list);
char hexbyte[3] = {0};
uint8_t tx[length_list];
for (i=0; i < (length_list); i++){
//should grab first two characters
//Data Transfer from String list to 2 byte string
hexbyte[0] = list[2*i];
hexbyte[1] = list[(2*i)+1];
//Passing the 2 byte string into a Hex unsigned int 8-bit and then printing result
sscanf(hexbyte, "%X", &tx[i]);
}
for (ret=0; ret<ARRAY_SIZE(tx); ret++){
}
puts("\n");
uint8_t rx[ARRAY_SIZE(tx)];
/*This is the transfer part, and sets up
the details needed to transfer the data*/
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
//The Actuall Transfer command and data, does send and receive!! Very important!
ret = ioctl(self->fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
printf("ERROR: Can't send spi message");
//This part prints the Received data of the SPI transmission of equal size to TX
for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
if (!(ret % 6))
puts("");
printf("%.2X ", rx[ret]);
}
puts("");
Py_INCREF(list);
return list;
}
PyDoc_STRVAR(SPI_open_doc,
"open(bus, device)\n\n"
"Connects the object to the specified SPI device.\n"
"open(X,Y) will open /dev/spidev-X.Y\n");
static PyObject *SPI_open(SPI *self, PyObject *args, PyObject *kwds)
{
int bus, device;
char path[MAXPATH];
uint8_t tmp8;
uint32_t tmp32;
static char *kwlist[] = {"bus", "device", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "ii:open", kwlist, &bus, &device))
return NULL;
if (snprintf(path, MAXPATH, "/dev/spidev%d.%d", bus, device) >= MAXPATH) {
PyErr_SetString(PyExc_OverflowError,
"Bus and/or device number is invalid.");
return NULL;
}
if ((self->fd = open(path, O_RDWR, 0)) < 0) {
printf("can't open device");
abort();
}
if (ioctl(self->fd, SPI_IOC_RD_MODE, &tmp8) == -1) {
printf("can't get spi mode");
abort();
}
self->mode = tmp8;
if (ioctl(self->fd, SPI_IOC_RD_BITS_PER_WORD, &tmp8) == -1) {
printf("can't get bits per word");
abort();
}
self->bpw = tmp8;
if (ioctl(self->fd, SPI_IOC_RD_MAX_SPEED_HZ, &tmp32) == -1) {
printf("can't get max speed hz");
abort();
}
self->msh = tmp32;
Py_INCREF(Py_None);
return Py_None;
}
static int SPI_init(SPI *self, PyObject *args, PyObject *kwds)
{
int bus = -1;
int client = -1;
static char *kwlist[] = {"bus", "client", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii:__init__",
kwlist, &bus, &client))
return -1;
if (bus >= 0) {
SPI_open(self, args, kwds);
if (PyErr_Occurred())
return -1;
}
return 0;
}
static PyMethodDef SPI_module_methods[] = {
{ NULL },
};
PyDoc_STRVAR(SPI_type_doc,
"SPI([bus],[client]) -> SPI\n\n"
"Return a new SPI object that is (optionally) connected to the\n"
"specified SPI device interface.\n");
static PyMethodDef SPI_methods[] = {
{"open", (PyCFunction)SPI_open, METH_VARARGS | METH_KEYWORDS,
SPI_open_doc},
{"close", (PyCFunction)SPI_close, METH_NOARGS,
SPI_close_doc},
{"transfer", (PyCFunction)SPI_transfer, METH_VARARGS,
SPI_transfer_doc},
{NULL},
};
static PyTypeObject SPI_type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"SPI", /* tp_name */
sizeof(SPI), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
SPI_type_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
SPI_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)SPI_init, /* tp_init */
0, /* tp_alloc */
SPI_new, /* tp_new */
};
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC initspi(void)
{
PyObject* m;
if (PyType_Ready(&SPI_type) < 0)
return;
m = Py_InitModule3("spi", SPI_module_methods, SPI_module_doc);
Py_INCREF(&SPI_type);
PyModule_AddObject(m, "SPI", (PyObject *)&SPI_type);
}
和python脚本:
#Python example for SPI bus, written by Brian Hensley
#This script will take any amount of Hex values and determine
#the length and then transfer the data as a string to the "spi" module
import spi
from time import sleep
#At the beginning of the program open up the SPI port.
#this is port /dev/spidevX.Y
#Being called as as spi.SPI(X,Y)
a = spi.SPI(0,0)
print "PY: initialising SPI mode, reading data, reading length . . . \n"
#This is my data that I want sent through my SPI bus
data = ["53484f5728677275706f293b3b0d"]
#Calculates the length, and devides by 2 for two bytes of data sent.
length_data = len(data[0])/2
i=0
#transfers data string
while True:
a.transfer(data[0], length_data)
i=i+1
print i
sleep(0.5)
#At the end of your program close the SPI port
a.close()