首页 > 代码库 > 直接访问树莓派的SPI,不通过驱动程序

直接访问树莓派的SPI,不通过驱动程序

pispi.h:

 1 #ifndef PI_SPI_H 2 #define PI_SPI_H 3  4 #define SPICLKDIV               32              /* ~8 Mhz */ 5  6 #define SPIBUFSIZE              32              /* SPI buffer size */ 7 #define BUFSIZE                 (SPIBUFSIZE/4) 8  9 /* Broadcom defines */10 11 #define BCM2835_PERI_BASE       0x2000000012 #define BCM2835_GPIO_BASE       (BCM2835_PERI_BASE + 0x200000) /* GPIO controller */13 #define BCM2835_SPI_BASE        (BCM2835_PERI_BASE + 0x204000) /* SPI controller */14 15 #define BCM2835_GPFSEL0         *(gpio)16 #define BCM2835_GPFSEL1         *(gpio + 1)17 #define BCM2835_GPFSEL2         *(gpio + 2)18 19 #define BCM2835_SPICS           *(spi + 0)20 #define BCM2835_SPIFIFO         *(spi + 1)21 #define BCM2835_SPICLK          *(spi + 2)22 23 #define SPI_CS_LEN_LONG         0x0200000024 #define SPI_CS_DMA_LEN          0x0100000025 #define SPI_CS_CSPOL2           0x0080000026 #define SPI_CS_CSPOL1           0x0040000027 #define SPI_CS_CSPOL0           0x0020000028 #define SPI_CS_RXF              0x0010000029 #define SPI_CS_RXR              0x0008000030 #define SPI_CS_TXD              0x0004000031 #define SPI_CS_RXD              0x0002000032 #define SPI_CS_DONE             0x0001000033 #define SPI_CS_LEN              0x0000200034 #define SPI_CS_REN              0x0000100035 #define SPI_CS_ADCS             0x0000080036 #define SPI_CS_INTR             0x0000040037 #define SPI_CS_INTD             0x0000020038 #define SPI_CS_DMAEN            0x0000010039 #define SPI_CS_TA               0x0000008040 #define SPI_CS_CSPOL            0x0000004041 #define SPI_CS_CLEAR_RX         0x0000002042 #define SPI_CS_CLEAR_TX         0x0000001043 #define SPI_CS_CPOL             0x0000000844 #define SPI_CS_CPHA             0x0000000445 #define SPI_CS_CS_10            0x0000000246 #define SPI_CS_CS_01            0x0000000147 48 #define BLOCK_SIZE              (4*1024)49 50 #endif51            

pispi.c

/* Copyright (C) 2015 Zhang Wei *  * Read write Raspberry Pi SPI without SPI driver * */#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <sys/mman.h>#include "pispi.h"volatile unsigned *gpio, *spi;volatile unsigned txBuf[BUFSIZE], rxBuf[BUFSIZE+1];static int map_gpio();static void setup_gpio();static void restore_gpio();static void transfer_data();int main(int argc, char *argv[]){        /* put "HELLO, WORLD\n" in txBuf */        txBuf[0] = 0x4C4C4548; //0x48454C4C; "HELL" reversed         txBuf[1] = 0x57202C4F; //0x4F2C2057; "O, W" reversed        txBuf[2] = 0x444C524F; //0x4F524C44; "ORLD" reversed        txBuf[3] = 0x2020200A; //0x0A202020; "\n   " reversed        map_gpio();        setup_gpio();        transfer_data();        restore_gpio();        munmap((void *)gpio, BLOCK_SIZE);        munmap((void *)spi, BLOCK_SIZE);        return 0;}int map_gpio() {        int fd;        fd = open("/dev/mem", O_RDWR | O_SYNC);        if (fd < 0)                printf("can‘t open /dev/mem \n");        /* mmap GPIO */        gpio = mmap(                NULL,                BLOCK_SIZE,                PROT_READ | PROT_WRITE,                MAP_SHARED,                fd,                BCM2835_GPIO_BASE);        if (gpio == MAP_FAILED) {                printf("can‘t map gpio \n");                close(fd);                return -1;        }        /* mmap SPI */        spi = mmap(                NULL,                BLOCK_SIZE,                PROT_READ | PROT_WRITE,                MAP_SHARED,                fd,                BCM2835_SPI_BASE);        close(fd);        if (spi == MAP_FAILED) {                printf("can‘t map spi\n");                return -1;        }        return 0;}void setup_gpio(){        unsigned int x;        /* change SPI pins */        x = BCM2835_GPFSEL0;        x &= ~(0b111 << (9*3));        x |=   0b111 << (9*3);        BCM2835_GPFSEL0 = x;        x = BCM2835_GPFSEL1;        x &= ~(0b111 << (0*3) | 0b111 << (1*3));        x |= (0b100 << (0*3) | 0b100 << (1*3));        BCM2835_GPFSEL1 = x;        /* set up SPI */        BCM2835_SPICLK = SPICLKDIV;        BCM2835_SPICS = 0;        /* clear FIFOs */        BCM2835_SPICS |= SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX;        /* clear done bit */        BCM2835_SPICS |= SPI_CS_DONE;}void restore_gpio() {        unsigned int x;        /* change SPI pins to inputs*/        x = BCM2835_GPFSEL0;        x &= ~(0b111 << (9*3));        BCM2835_GPFSEL0 = x;        x = BCM2835_GPFSEL1;        x &= ~(0b111 << (0*3) | 0b111 << (1*3));        BCM2835_GPFSEL1 = x;}void transfer_data(){        char *buf;        int i;        /* acitvate transfer */        BCM2835_SPICS = SPI_CS_TA;        /* send txBuf */        buf = (char *)txBuf;        for (i=0; i<SPIBUFSIZE; i++) {                BCM2835_SPIFIFO = *buf++;        }        /* wait until transfer is finished */        while (!(BCM2835_SPICS & SPI_CS_DONE));        /* clear done bit */        BCM2835_SPICS = SPI_CS_DONE;        /* read buffer */        buf = (char *)rxBuf + 3; /* ignore 1st byte and align data */        for (i=0; i<SPIBUFSIZE; i++) {                *buf++ = BCM2835_SPIFIFO;        }}

 

直接访问树莓派的SPI,不通过驱动程序