WiringPi includes a library which can make it easier to use the Raspberry Pi’s on-board SPI interface.
Firstly, you need to use the gpio utility to load the SPI drivers into the kernel:
gpio load spi
If you need a buffer size of greater than 4KB, then you can specify the size (in KB) on the command line:
gpio load spi 100
will allocate a 100KB buffer. (You should not need this though, the default is more than enough for most applications).
To use the SPI library, you need to:
#include <wiringPiSPI.h>
in your program.
Functions available:
- int wiringPiSPISetup (int channel, int speed) ;
This is the way to initialise a channel (The Pi has 2 channels; 0 and 1). The speed parameter is an integer in the range 500,000 through 32,000,000 and represents the SPI clock speed in Hz.
The returned value is the Linux file-descriptor for the device, or -1 on error. If an error has happened, you may use the standard errno global variable to see why.
- int wiringPiSPIDataRW (int channel, unsigned char *data, int len) ;
This performs a simultaneous write/read transaction over the selected SPI bus. Data that was in your buffer is overwritten by data returned from the SPI bus.
Programs need to be linked with -lwiringPi as usual.
That’s all there is in the helper library. It is possible to do simple read and writes over the SPI bus using the standard read() and write() system calls though – write() may be better to use for sending data to chains of shift registers, or those LED strings where you send RGB triplets of data. Devices such as A/D and D/A converters usually need to perform a concurrent write/read transaction though.
I cannot get the thing to initialise.
What could I be doing wrong?
#include
void main(void)
{
int chan=1;
int speed=1000000;
if( wiringPiSPISetup (chan, speed)==-1)
{
printf(“Could not initialise SPI\n”);
return;
}
printf(“When ready hit enter.\n”);
(void) getchar();// remove the CR
unsigned char buff[100];
while (1)
{
printf(“Input a string, Input 0 to finish “);
gets (buff);
if(buff[0]==’0′)
{
break;
}
else
{
int ret=wiringPiSPIDataRW (chan,buff,100) ;
printf (“%s \n”, buff);
}
}
} // main
Have you loaded the SPI module into the kernel?
The this if not: gpio load spi
-Gordon
Hey Alan! I got SPI working with the library, I actually used your code to base mine on, but there are some fundamental mistakes in your c code-
void main()
The above line for example, try using int main()
{
//Your code
return(0)
}
you also do not list your #includes
printf
The above function will require the std library to be included.
Also! I used gcc to compile my c code, and got it working with the line gcc TestCode.c -l wiringPi
The -l BASH there indicates you are linking wiringPi.
Also! (Alot of ‘also’s’ I know!) You should add the switches “-Wall and -Wextra (If u are using gcc) and it will troubleshoot whats wrong right there in BASH.
Cheers! Adam!
Hi,
I have used the ‘gpio load spi’ but the ‘module spidev’ is not found. Any suggestions on how to fix this issue?
Regards
Are you using Raspbian?
If not, then it sounds like your distribuition might not have the SPI modules.
-Gordon
Yeah I am using the Raspbian system but am pretty new to this. I have followed advice on installation but then encountered a problem with the PiFace board not initialising. Following advice on other threads has now brought me to this issue. I have thus tried the ‘gpio load spi’ but encounter that problem.
OK. I’m surprised it’s not finding the module then. Just one thing – what version of wiringPi do you have? Run gpio -v and let me know…
-Gordon
Maybe the module is blacklisted. In my standard raspbian distribution there was an entry in /etc/modprobe.d/raspi-blacklist.conf – remove it.
Working with your library…having trouble with a MCP2515 CAN bus module I am trying to command via SPI to send data on a CAN bus.
(This is a CAN BUS shield I got from sparkfun (https://www.sparkfun.com/products/10039). Works fine on arduino, and am using it on a arduino to raspberry shield from cooking hacks (http://www.cooking-hacks.com/index.php/documentation/tutorials/raspberry-pi-to-arduino-shields-connection-bridge))
Works fine on arduino with SPI code I wrote on that. On the raspberry, I am sending identical data raspberry using your SPI library, but the CAN bus will not respond.
have spend days and days on this. Checked timings, pins, tested backwards and forwards and have been watching the SPI bus via Salae Logic, so I can see exactly what is going on.
I have looked at the bus with a protocol analyzer. THe only major difference I see on the SPI bus between arduino (which works) and raspberry (which doesn’t) is the the MOSI on the arduino FALLS (neutral state is HIGH) when there is data, whereas on the raspberry it rises (neutral state is LOW).
Beyond that, I can see any difference. But the shield responds to the arduino and its SPI library, but not to the raspberry using this library.
Could it be that rising vs falling MOSI? And if so, how can I set that?
Really appreciate the help if you might have any thoughts or advice…
You might find that the Pi is simply not fast enough to respond to a CAN bus SPI interface. There is a big thread on it on the Raspbery Pi forums which starts here:
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=19489
-Gordon
Did you connected the RST pin of the CANBUS shield to +5V?
If not the MCP2515 remains in the reset state…
Hmmm…I missed this thread, which is surprising given the days of google and forum searching I’ve been doing!
Well, this may be applicable. However, in my case, on the logic analyzer I am not seeing any losses. And I am not reading anything from the slave, simply sending small data packets to it, and I see these show up just fine on the analyzer. This is a very slow situation with a device that is a 10mhz bus and even when I drop down speeds well below that.
The only thing I have been noticing is that is different from a capture that works from the arduino, is that inverted MISO line, starting HIGH nad dropping LOW for signals…and I am not sure if that is meaningful or not.
Thanks for the pointer, I do appreciate it. And it is great to have your library to work with…extremely useful.
There are 4 modes for SPI – to do with the clock and data polatirys. I’m initialising the Pi’s hardware in mode 0 – which is what I was under the impression that 99% of all devices seem to use – e.g. the A/D and D/A chips on the Gertboard (which is what I originally devleoped it for).
So it might be worth while seeing what polarity/mode the CAN ship itself actually wants – my suspicion is that the initial polarity isn’t important though as the CAN chip will sample the data line on the rising clock edge, as does the Pi. (MISO being the input into the Pi).
Are you also remembering to write enough bytes down the SPI bus to keep the other end clocking data back?
-Gordon
Not sure I follow: write enough for the other end to clock data back? Could you clarify?
(At any rate, in my use, the device doesn’t send anything back. It is being commanded and is not communicating back to the raspberry. )
Thanks for your help, and yes, it is mode 0. The signal really looks ok on the analyzer, really not sure why the CAN Bus shield isn’t responding to it.
I’d need to study the datasheet in detail to see what it needs – but e.g. if you expect the chip to send back (say) 16 bytes after you send it a 4-byte command, then you need to send it 4+16 bytes, so the clock can keep going for the full duration. Some of the A/D chips I’ve used work like that.
Although you can just use the standard write() and read() system calls too.
-Gordon
How do you start spi mode in 0? I’m using java.
I’ve no idea. My code is written in C, however if you’re using that from Java then be aware that it uses mode 0 by default.
-Gordon
Great job.
I got quick results with Discovery board (STM32F4).
However, when I tried to put the gpio load spi command in a crontab (@reboot), I got this errorlog:
sh: 1: modprobe: not found
sh: 1: modprobe: not found
/usr/local/bin/gpio: Unable to load spi_bcm2708
any ideas
In crontab, or any on the /etc/inti.d/ scripts there is no path setup..
So: /usr/local/bin/gpio will get you the gpio command, but modprobe (which is what the gpio command calls) is /sbin/modprobe – probably my fault for not coding the full path in….
So you might find that:
PATH=”/bin:/usr/bin:/sbin” /usr/local/bin/gpio modprobe spi
will do the trick.
However, if you need the SPI drivers loaded every time, then it might be easier to simply edit /etc/modules and put them in there.
-Gordon
Thanks, putting it in /etc/modules seems to be the better option indeed.
Hi,
I am looking for some sample code to interconnect discovery stm32f4 with pi using spi. code you help me with the same?
Hello & SOS
I’m trying to find a wiringPi code source example to write through a TM1640 to a 16*7 LED digit:
http://dx.com/p/jy-mcu-16x-digital-tube-yellow-led-module-104311 using the SPI port ( SCK and MISO)of the Raspberry.
MNY TNX,
73, Mike
Looks like someone has already done it with wiringPi – I found this link:
http://club.dx.com/forums/forums.dx/threadid.1221545
which leads to:
https://bitbucket.org/furyfire/raspi
So there is some stuff there – you might be able to pick out what you need?
-Gordon
Hi Gordon
Many thanks for the links.
But why to use digital pins of the raspberry but not the SPI0 or 1 output?
I understand that it’s more easy to import the Arduino pin definition to the RPI.
I will try to translate it to SPI “language”
Thanks for help.
Mike
Er, don’t know. I didn’t find a datasheet for that device, however to do it with GPIO pins needs too many – one for each digit and 7 for the segments. You run out of GPIO rather quickly, so using SPI to talk to an on-board controller which has the pins is an optimisation.
If you find me the datasheet I might be able to suggest someting…
-Gordon
Hi Gordon !
I got this link with TM1640 instructions and an Arduino emulation code :
http://skyduino.wordpress.com/2012/05/16/arduino-afficheur-7-segments-16-digits-base-tm1640/
Sorry, it’s in french…
Is it OK?
++ Mike
Well it doesn’t look too bad, but I don’t know why you can’t use the software that I pointed you to that’s already been written for it using wiringPi. Just click on the download link and it’s all there.
You don’t need the Arduino code – the Raspberry Pi code is already there. Just read it and implement it.
-Gordon
OK, Gordon, I will check the code …Now
++ Mike
Hi!
btw: Love you lib 🙂
I’m new to SPI comunication but i find his code realy useful:
http://raspberrypihobbyist.blogspot.de/2012/12/analog-interface.html
(he uses your lib)
If i want to do it his way, am I right that i just have to change chanel-parameter to the readadc()-method? (He is not giving me an answer by himself..)
Thanks so much! You do relay great work – please keep going!
Yes – if you’re using the same chip. It has 8 channels, so to read a different channel just call the readadc() function with the channel number you want.
-Gordon
Hello,
I’m a student from Belgium and I try to communicate with the radio module CC110L by SPI GPIO connector.
In the program below, I want to read a register from the radio module.
“0x84” means that I want to read register 0x04.
I received two bytes of radio module: status bytes
register value
But these two values are null when normally not.
My programme is correct ? I want to send one byte and receive two byte.
(In my code i use manually the chip select)
//—- Librairies —-
#include
#include
#include
#include
#include
#include
#include
//—- Pin Configuration —-//
#define GPIO0 0
#define RESET 1
#define GPIO2 2
#define GPIO3 3
#define CS 4
//—- Variables Configuration —-//
int channel =0 ; // channels : 0 ou 1
int speed = 500000; //speed : 500 000 to 32 000 000 => Clock speed Hz
// 0,5 MHz 1 MHz 2 MHz 4 MHz 8 MHz 16 MHz et 32 MHz.
uint8_t send_address[2];
//—- Programme —-//
int main()
{
printf (“Read register :\n”);
if(wiringPiSetup() == -1)
{
exit(1);
}
if (wiringPiSPISetup (channel, speed) error
{
fprintf (stderr, “SPI Setup failed: %s\n”, strerror (errno));
return 0;
}
pinMode (CS, OUTPUT);
digitalWrite (CS, 0);
delay (10);// On attend que la puce CC110L soit stable (SO == 0)
send_address[0]= 0x84;
printf(“Commande :%02X\n”, send_address[0]);
wiringPiSPIDataRW(channel,send_address,1);
printf(“Donnee recue : %02X \n”,send_address[0]);
printf(“Donnee recue : %02X \n”,send_address[1]);
digitalWrite (CS, 1);
return 0;
}
Thanking you in advance,
Jordan
Normally you’d use the CE0 or CE1 pins from the Pi as the Chip Select, but you may be doing other things here.
You write one byte, but check 2 bytes. you need to write 2 bytes to get 2 bytes back.
so wiringPiSPIDataRW(channel,send_address,1); should be: wiringPiSPIDataRW(channel,send_address,2);
-Gordon
Thank you for your answer
I do not use CE0 or CE1 because I use an adapter to connect the radio module. This adapter uses pin 4 (wiringPi) and not CE0, CE1. Do you think the problem could come from there?
I’ll try: wiringPiSPIDataRW (channel, send_address, 2). If i write 2 bytes, the second byte don’t perturb the module radio?
I will have the opportunity to work on Thursday, March 28 on the project. I’ll let you know, Thursday.
Jordan
Hi Gordon,
The MCP23S17 I/O expander has addressing provisions for 8 devices to share an SPI bus channel. PiFace has jumpering (J1 & J2) to support up to 4 devices on a channel. I’m not aware of any library support for such channel sharing. Am I missing something?
Thanks for your great work.
wiringPi v2 (will be released tomorrow or monday) will support 8 mcp23S17’s per Pi’s SPI bus, so 16 in total. Add on 8 mcp23017’s on the I2C bus and that gives you the potential for 384 more gpio pins…
-Gordon
Excellent and very timely 🙂
I presume that’s 8 MCP23017’s per I2C bus address which is a possible total of squillions of GPIOs.
Thanks again.
Well – there is only one easilly accessible I2C but on the Pi, so just 8 of them. However for each group of 3 pins (and these pins can be the Pi’s own or those off a GPIO expander), you can put 4 ‘595 shift registers to give an additional 32-bits of output, so the current theoretical limit is over 10K output pins.
They’re not fast though!
-Gordon
Correction to last. Agree 8 MCP23017’s on the I2C bus.
Does this news imply an update to the Arduino IDE’s Raspberry Pi GPIO programmer to allow sharing of SPI channel with PiFace etc?
The issue here is getting access to anything under the PiFace – although rumour has it that they’re looking at a breakout board to go in-between the PiFace and the Pi…
Personally, I won’t use SPI or I2C between the Pi and Arduino – serials more than good enough, although maybe if I did have a lot of data to transfer then I might look at SPI.
However there are 2 CE pins off the Pi, so one could go to Arduino and one to the PiFace, so it should not be an issue anyway.
-Gordon
Does this news imply an update to the Arduino IDE’s Raspberry Pi GPIO programmer to allow sharing of SPI channel with PiFace etc?
Later … On reflection I’ve realised that address conflict is a small issue compared with the fundamentally different understandings of the /CE signal. As (if) I understand it, the MCU23S17 takes the Low on /CE to mean “if your address matches, let’s talk” whereas an AVR MCU takes it to mean “drop whatever you are doing and let’s talk”, two entirely different and incompatible protocols.
with SPI, when a device sees it’s CE going low, it’s supposed to activate an internal “reset” operation – and at that point the MISO pin on the slave can be driven – that’s the only time a slave SPI device can drive that pin. This should allow for as many SPI devices as you have CE lines – 2 on the Pi.
One issue with programming an ATmega is that although it uses the SPI port, it doesnt use SPI prtocoll – as far as I’m aware, but I’ll need to do a bit more reading.
Have to say though – I’ve stopped using the Pi to program via GPIO and use serial or a programmer myself… I’ll be re-doing the Gertboards stuff soon and offering a means to program it via the serial line…
The 23S17’s are somewhat intersting in that the 3-bit address function is purely a convention used by the 23S17 – you also have to tell the 23S17 to look at those address bits too – if you don’t then all 23S17’s will accept the commands!
-Gordon
Hi Gordon, and Thank you for your work!
I’ve trouble to interface the Raspberry with a ADC AD7715 through SPI.
When you say:
“It is possible to do simple read and writes over the SPI bus using the standard read() and write() system calls though – write() may be better to use for sending data to chains of shift registers, or those LED strings where you send RGB triplets of data. Devices such as A/D and D/A converters usually need to perform a concurrent write/read transaction though.”
I don’t understand how to do it… Do I have to use MOSI and MISO as simple
in out port, and call digitalWrite or digitalRead 8 time to send or receive a byte?
You don’t need to fiddle with pins inidividually, just load the kernel SPI driver then off you go…
Start by looking at the Gertboard code I wrote for its ADC. You will need to use wiringPiSPIDataRW() for this chip though. So open the spi/chip, then you need to read the manual – stating on page 13. It looks like you need to write to the communiucations register once to setup the chip, then you write to it a 2nd time with bit 7 set high, and the RS bits high, then write/read another 2 bytes to get the data back. So 2 separate calls to wiringPiSPIDataRW() the first to send 1 byte – that happens once for initialisation, then to read the data, you do a wiringPiSPIDataRW() with 3 bytes – the first one is the communucations register bits, then next 2 are 0, but you read back the 3 bytes and extract the 16-bit value from the last 2 bytes.
I think!
-Gordon
Yes, you read quite rightly and quickly the datasheet 😉
I’ts already working with an Arduino, without any problem.
I am just trying to trace signals with a oscilloscope, and it seems
that my SCLK isn’t working… and I don’t know why…
You should see the relevant CE line go low, then the clock will wiggle for 8 bits of every byte that goes out. If you’re not seeing anything on SCLK then I’d unplug everything and try again – make sure the SPI driver is loaded (gpio load spi)
-Gordon
I’ve doubled, tripled check the wiring of my AD7715…
… and it works finaly 🙂
I’ve forgotten to say that I am using pi4J, sorry!
I code as you said before, with packet of only one
byte, but it didn’t work neither…
But I found the solution! It works perfectly when
the CS Pin of my AD7715 is wired to ground (no CS,
or in other words, AD7715 is the only slave). If I
wired it back on the CS of the Raspberry, the
communication doesn’t work anymore…
The “bug”* is absolutely reversible.
*I call it a bug, but I really can’t affirm if it is
a real one or not…
An idea?
PS: I will offer you some beer next time 😉
if it works, then leave it 🙂
However it’s odd – a lot of SPI interfaces will use the CE line as a ‘reset’ or trigger for some internal functions, but if this works with CE low all the time, then you’ll probably be ok…
-Gordon
Hi Gordon, your library is awesome. But I have one question which I could not figure out on my own:
How do you put the SPI-pins back into alt0 mode after you set them to input or output manually?
I did “gpio load spi” and then was able to send/receive data over SPI. Then i did “gpio mode 12 out” and now I’m not able to put that pin back into alt0 mode, other than rebooting the Pi.
Thanks for your help
To be honest – I don’t know! I suspect if you rmmod the kernel modules, then reload them (gpio load spi) it will do it though.
-Gordon
Okay, “sudo rmmod spi_bcm2708” and “gpio load spi” seems to do the trick.
Seems like my SPI is not working properly. When reading the values back from the wiringPiSPIDataRW function, I am getting -1. This means the ioctl functions used is returning -1.
When reading the errno, I get: “Invalid argument”
I am using your gertboard.c example and modify it for my purpose
THe only difference is I set chanBits to be fixed and only send one message to my device which is: AD7753 energy metering device.
Any help would be great!
Nvm, I used spidev_test.c and it works fine, which doesn’t use this library. I guess the only use of this library is to map the command “gpio load spi” instead of those complicated command.
Here is the website I used to get my spi to work
http://www.cmdrkeen.net/2012/11/06/playing-with-raspberry-pi-issue-2-using-spi-on-the-pi/
Been dealing with some family issues, so couldn’t reply. The usual issues with SPI is either not having the module loaded or permissions. Otherwise, it’s a fairly simple interface.
-Gordon
Hi!
I have the following code:
int main() {
int chan=0;
int speed=1000000;
int pepe=wiringPiSPISetup(chan, speed);
cout << pepe << endl;
return 0;
}
But i get pepe = 3
What does this mean?
Thanks
It’s the Linux file-handle returned when you open a device. You use it with the standard read(2), write(2) system calls. The wiringPiSPIDataRW() function takes the channel number (0 or 1) and works out the file handle allocated at setup time.
-Gordon
I was testing the functionality of your wiringPi’s SPI interface. I works well. One problem I am having. When I set length of write to a value over 4096 the SPI interface stops working. I am using the below code. Any help would be appreciated.
#include “wiringPi.h”
#include “wiringPiSPI.h”
#include
#include
#include
#include
#include
#define BUF_SIZE 4096
int main (void)
{
int channel=0 ;
int i=0 ;
int j=0 ;
int k=0 ;
int delaytime = 550 ;
char outbuffer[BUF_SIZE] ;
int cnt ;
printf(“Raspberry Pi wiringPi SPI LED test programn”);
// set output SPI channel to 0 and speed to 8MHz
if (wiringPiSPISetup (0,16000000) < 0)
{
fprintf (stderr, "Unable to open SPI device 0: %sn", strerror (errno)) ;
exit (1) ;
}
printf("Startingn") ;
wiringPiSetupSys() ;
while(1)
{
memset(outbuffer,0x33,BUF_SIZE);
wiringPiSPIDataRW (channel, outbuffer, BUF_SIZE) ;
delayMicroseconds (delaytime) ;
}
printf("Done\n") ;
return 0 ;
}
My bad. I issued command “gpio load spi” first. Then I issued “gpio load spi 100” thinking it would reload with larger buffer. When I rebooted and issued “gpoi load spi 100” it worked.
How do you unload the spi from command?
There isn’t a gpio command, but a standard linux one:
sudo rmmod [modulename]
type lsmod to list the currently loaded modules. (I’m not near a Pi and don’t recall the names of the spi ones, but they’re obvious)
-Gordon
Thanks Gordon. I am successfully transferring data to a PIC32 device at 16 Mhz.
Hi
I keep getting a “-1” for wiringPiSPISetup(0,2000);
I did gpio load spi and lsmod shows that bcm2807 is supposed to work.
wiringPiSetup works fine if that matters.
Are there any other reasons for spi not setting up properly?
The speed is probably too slow. Try 2000000.
-Gordon
Tried different speeds and different channels. Still -1
Great job Gordon! I now have two PICs talking to my RasPi over SPI from userspace via Qt. All other methods required SU access in some way, which was not what I wanted.
Is there no way to clock SPI less than 500kHz? I have to run the PICs at top speed to keep up!
I’ve not tried any lower clock rates – it won’t hurt to try – in the wiringPiSPISetup() routine… I know the current driver is powers of 2, so it’s likely to be 1Mb, 512Kb, 256Kb, 128Kb, etc.
-Gordon
Hi,
I want to connect two SPI devices on the same MOSI/MISO/SCLK Pins: the MCP23S17 (SCK->CE0) and a MCP3008 ADC (SCK->CE1). Will that work?
What happens when one program use the expansion chip and a separate program try to read the ADC at the same time?
Thanks for reading and for your great library,
Norman
It should work OK – that’s why there are 2 select lines – however you should use some locking to make sure that only one program is accessing the device at the same time.
-Gordon
Hi everybody !
Does someone have examples of code for MCP2515 ?
I have code for Arduino (SK-Pang Shield) working fine but on Raspberry (with Raspbian) I”m really a beginner !
Best regards.
Do you know of any sane way of doing synchronous operation between the 2 chip select lines? For example, I want to send/receive a ~4kB packet that alternates between CS0 and CS1 every couple of bytes.
linux/spi/spi.h says that the message priority function between multiple spi device children is undefined, which seems pretty unhelpful.
Is there any high-level way of doing this or am I going to have to hack apart the driver core?
Can’t you just open both devices and do the tx/rx operation on the alternatively?
-Gordon
Unfortunately not. One device is a DAC and the other an ADC, but they both have programmable state and would be affected by the signals sent to the other device if open simultaneously. I think they also inconveniently require operation in different modes.
Gordon,
Great work. I am pulling up a system and while waiting for some parts I wanted to get the SPI debugged and running while UPS meanders my package across the country. In the interim, I was looking at cross connecting 2 Pi’s to talk to each other. Is the SPI interface invertible? I don’t see any place to configure as master or slave.
Adam
The Pi’s SPI is master only. Use serial. (rs232) Much easier to program and almost always fast enough for most needs.
-Gordon
HI.
How can I change SPI mode ?
I need spi mode 2 (CPOL=1,CPHA=0)
I’ve done it.
Change const static uint8_t spiMode = yourchoice ;
in wiringPiSPI.c
then REBUILD!
Hi, Gordon.
I have one problem. When I use your SPI function, it works well the buffer size is under 4099, but over 4099 it doesn’t work.
for example~
wiringPiSPIDataRW(ch, arr, 4099); // everything is ok
wiringPiSPIDataRW(ch, arr, 4100); // OMG! it doesn’t work ;-(
and when I boot raspberry pi typed this “spi gpio load 1024”
Is it mean “i will allocate 1Megabyte for spi buf”?
I want to send data “unsigend char arr[320*240*2]” at a time…. help me please
I think you’ll find that the limit is exactly 4096 bytes…
You can increase the kernels SPI buffer by using the gpio command to load the SPI module:
gpio load spi 256
will allocate 256KB for the kernels SPI DMA buffer which ought to be enough for your purpose… Not sure why your 1024 isn’t working – it’s possible there is an upper limit, but I never went that far myself!
Sounds like you’re driving a display – I did this myself recently too and had to increase the buffer size…
-Gordon
Opps! It was all my mistake.
Before using your library, i changed file where /etc/modprobe.d/raspi-blacklist.conf
i remembered that added ‘#’ in front of ‘blacklist spi-bcm2708’. So i remove ‘#’ then, it works. Sorry Gordon~!
No wories. I tend to keep the SPI & I2C modules blacklisted and use the gpio command to load them when I need them.
e.g.
gpio load spi
-Gordon
Hey Gordon, thanks for this awesome library.
Do you have an example on how to use “write” to send the data to the SPI bus? How is the CE0 or CE1 Signal triggered?
I have an issue with wiringPiSPIDataRW and want to see it this can be solved by using direct write.
Thanks
Marc
Use wiringPiSPIGetFd() to return the Linux file descriptor of the channel you opened (0 or 1), then use the standard Linux system call write()
e.g.
fd = wiringPiSPIGetFd (0) ;
write (fd, buffer, len) ;
-Gordon
Thanks,
I thought there would be some more stuff that I have to do 🙂
Hello,
i try to communicate with a TI LMP90100 device. Read and write actions are working fine.
I using the CE0 Pin for chip selection. It is normal that the chip select wire is always low for a selected device ? How can i change this ? CE0 should only be zero, if data will be transmitted on MOSI.
Best regards
Hi Gordon.
I am trying to do some work with this library. But when I run my progam it gives me this error(Unable to opne SPI devide:Too many SPI descriptors).
Have y any idea how can I delete the file descriptor when I open a SPI comunication?.
Best Regards.
Only ever call wiringPiSPISetup() once per channel. ie. never more than twice in your entire program.
-Gordon
thank you so much Gordon.
I have another question
I am making a program and I use the pin 7 of my rasp as INPUT for an interrupt.
I use the function wiringPiISR(7, INT_EDGE_RISE,&myInterrupt), but in some parts of the program I would like to disable the interrupts and enables them later.
Can I do this? Wich way?.
Best Regards
it’s not easy at present. You could write your own version and simply stop the thread running, or just set a global flag to tell the interrupt handler to ignore the interrupts.
-Gordon
Ok Gordon I was trying to use this command to desactivate “system(“usr/local/gpio 22 edge none”)” and this to activate “system(“usr/local/gpio 22 edge falling”)” the interrupt in one pin. Can I do this?.
I will try the other way.
-Iñigo
I’ve no idea. Just ignore the interrupt is probably the easiest way. Or redesign your hardware so you never have to ignore/disable interrupts.
-Gordon
Hi Gordon,
I’m having trouble getting your SPI library going, specifically wiringPiSPIDataRW. I’ve written a post about it (link in the website section of this reply). Any comments appreciated!
Replied on the forum…
-gordon
Hi Gordon:
I really love your job with the community. Great job and I admire all you’ve done so far. I’ve got a question for you.
I’ve got a device that works under SPI but this device requires to load words of 16 bits straight without clock interruptions.
I know that with spidev is possible to change the “bits_per_word” to 16 (not success with this, it seems there is a bug) but I don’t know if that is possible with wiringpi. Do you know if it’s possible to load 16 bits words in the RasPi registers? Have you tried before?
Thanks for your help and lead!
Mario B.
Just write 2 bytes in a single operation – either use the write() system call, or wiringPiSPIDataRW() with a 2-byte buffer.
The 16-bit write will be accomplished by virtue of the CE line staying low for each byte transfered.
Make sure you get them the right way round!
-Gordon
Hi Gordon
Trying to use the MCP23S17 libs, but the CE0 pin is not changing. I can see the clk and MOSI line transfering data but CE0 never goes hi. As a result the port expander is not behaving as it should. I’ve looked deep into the code and don’t see where the CE0 (or CE1) pins are toggled, I presume that is part of IOctl function. Would appreciate your thoughts. W
The CE0/1 lines are controlled by the kernel driver that I use. At the start of the write (or ioctl), then CE line ought to go low, then it’s returned high at the end of the write/ioctl.
-Gordon
Hi Gordon,
It’s possible configure the SPI communication to falling edge using WiringPi?
Thanks for your help.
Marc Q.
Hi Gordon,
I am trying reading AS3935 Lightning sensor using SPI,
The sensor has 0x32 registers, to read any register, I am supposed to send 16 bits.From LSB, the first 2 bits are 01 indicating it is a read operation, the next 6 bits are for register to be read, the other 8 bits are 0 for read operation. For example, I needed to read register 0x00. So I had to send the command 01000000 00000000 to the sensor using SPI using the code below. The value returned is 2. I tried changing the testing with other registers, but it will always return 2. What I am I doing wrong?
#include
#include
#include
//#include
int channel = 0;
int speed = 1000000;
int i;
int main ()
{
if(wiringPiSetup() == -1)
printf(“Wiring Pi Failed to open”);
else
printf(“WiringPi library ok! NO: %d\n\n”,wiringPiSetup());
return(0);
char buff[0]=0b010000;
char buff[1]=0b0
int returned = wiringPiSPIDataRW(channel, buffer,2)
printf(“Value returned is %d”, returned);
}
You’re not doing anything wrong, however you might be failing to understand what’s going on….
wiringPiSPIDataRW() does not return data read as the functions return code. It returns the data read inside the buffer it reads from. Try printing out your buffer after the call to wiringPiSPIDataRW():
printf (“%02X %02X\n”, buffer [0], buffer [1]) ;
-Gordon
You are good!
In this function,
int wiringPiSPIDataRW (int channel, unsigned char *data, int len)
what does the function return as int?
I am dealing with integers, how do I handle them using unsigned char *data?
The number is returns is the return code from the underlying ioctl() function call. In this case anything >= 0 is good.
You need to take the 2 bytes that are overwritten in your data array and convert them back into a single 32-bit int. See some of my other code for examples – e.g. the A/D converters, but you’ll need to read the datasheet for your device – some devices put the bits in a funny order, or you need to pick out 12 bits from the 16, etc.
-Gordon
Hi Gordon,
I want to use your library with L3GD20 3-axis gyroscope. How can I change the data bits from 8 bit to 16 bit? It would be also better if We have the ability to change the SPI mode and bits per word parameters directly in the wiringPiSPISetup function.
thanks.
If you want to read/write more than 8 bits at a time, then just do it. See my examples. You just need to do it and as long as you ask it to write/read in a single operation, you can send MB over the SPI bus if required.
-Gordon
Is it possible to write data to SPI in chunks other then 8, 16, 24, … bits? For example, the Texas Instruments TLC5952 LED driver requires exactly 25 bits to be written each time (the most significant bit directs the data either to the command register or the output drivers latch. How can this be achieved?
You can write in chunks of 8 bits at a time, so to write 25 bits, you could write 32 bits in a single operation. See my examples – e.g. the Gertboard A/D converters – they exchange 16 bits in a single operation.
-Gordon
Isnt’t it possible to use both channels CE0 and CE1 in a program? Only the first initialized channel works. Initializing the second one seems to have no effect.
if (wiringPiSPISetup(0, 1000000) < 0 && wiringPiSPISetup(1, 1000000) < 0) {
fprintf (stderr, "SPI Setup failed: %s\n", strerror(errno));
exit(errno);
}
There should not be any issues with both channels – but the only time I’ve used both has been with the Gertboard – one channel is the A/D and the other is the A/D chips. It seemed to work well and I had no issues with it.
However I’m wondering about the logic in your code fragment here… C processes conditionals left to right and will stop evaluating when it deems the entire expression to be true or false. You also possible want to use a logical OR here (||) as you want to fail if channel 0 OR channel 1 fails to initialise, but personally I’d use two separate if statements here, so you can print an appropriate error message and then know which one failed to initialise.
-Gordon
Hi gordon, (or perhaps anyone else?)
Are there examples of code to read from an MCP3008 chip? Not sure where to start…
Thanks!
J
The mcp3004 module reads from the 3008 too.
-Gordon