zoukankan      html  css  js  c++  java
  • 直接访问树莓派的SPI,不通过驱动程序

    /dev/mem是物理内存的全映像,可以用来访问物理内存,一般用法是open("/dev/mem",O_RDWR|O_SYNC),然后mmap,接着就可以用mmap的地址来访问物理内存,这实际上就是实现用户空间驱动的一种方法。

    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       0x20000000
    12 #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         0x02000000
    24 #define SPI_CS_DMA_LEN          0x01000000
    25 #define SPI_CS_CSPOL2           0x00800000
    26 #define SPI_CS_CSPOL1           0x00400000
    27 #define SPI_CS_CSPOL0           0x00200000
    28 #define SPI_CS_RXF              0x00100000
    29 #define SPI_CS_RXR              0x00080000
    30 #define SPI_CS_TXD              0x00040000
    31 #define SPI_CS_RXD              0x00020000
    32 #define SPI_CS_DONE             0x00010000
    33 #define SPI_CS_LEN              0x00002000
    34 #define SPI_CS_REN              0x00001000
    35 #define SPI_CS_ADCS             0x00000800
    36 #define SPI_CS_INTR             0x00000400
    37 #define SPI_CS_INTD             0x00000200
    38 #define SPI_CS_DMAEN            0x00000100
    39 #define SPI_CS_TA               0x00000080
    40 #define SPI_CS_CSPOL            0x00000040
    41 #define SPI_CS_CLEAR_RX         0x00000020
    42 #define SPI_CS_CLEAR_TX         0x00000010
    43 #define SPI_CS_CPOL             0x00000008
    44 #define SPI_CS_CPHA             0x00000004
    45 #define SPI_CS_CS_10            0x00000002
    46 #define SPI_CS_CS_01            0x00000001
    47 
    48 #define BLOCK_SIZE              (4*1024)
    49 
    50 #endif
    51            

    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
    " 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; "
       " 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 
    ");
    
            /* 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 
    ");
                    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
    ");
                    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;
            }
    }
  • 相关阅读:
    QtDBus编程详解
    QProcess详解
    python 爬虫 亚航 指定日期间的航线
    python 模块
    centos postgres 安装、远程连接
    python 爬虫 anyproxy
    python_scrapy_filespipe重写
    python_xpath
    常见问题汇总
    python_scrapy_log日志
  • 原文地址:https://www.cnblogs.com/brep/p/4270590.html
Copyright © 2011-2022 走看看