1. 程式人生 > 其它 >linux spi讀寫

linux spi讀寫

用的xubuntu,發現有/dev/spidev0.0,是不是意味著驅動已經裝好。測試程式碼,如下:
/*
* Debug.h
* 摘要:用於列印除錯資訊
*         為了統一控制列印資訊是否輸出,而用巨集定義的列印函式。同時也可以起到開發版本與釋出版本是同一個版本
*  Created on: 2013-5-22
*      Author: lzy
*/

#ifndef DEBUG_H_
#define DEBUG_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

#define     DEBUG_SWITCH    1        /* 開啟除錯資訊列印功能 */
#define     ERR_DEBUG_SWITCH    1    /* 列印錯誤資訊列印功能 */

/**
* 簡單列印除錯資訊
*/
#if    DEBUG_SWITCH
#define pr_debug(fmt,args...) printf(fmt, ##args)
#else
#define pr_debug(fmt,args...) /*do nothing */
#endif

/**
* 錯誤資訊列印
* 自動打印發生錯誤時程式碼所在的位置
*/
#if    ERR_DEBUG_SWITCH
#define pr_err(fmt,args...) printf("\nError:\nFile:<%s> Fun:[%s] Line:%d\n "fmt, __FILE__, __FUNCTION__, __LINE__, ##args)
#else
#define pr_err(fmt,args...) /*do nothing */
#endif

#endif /* DEBUG_H_ */

/*
* 說明:SPI通訊實現
*           方式一: 同時傳送與接收實現函式: SPI_Transfer()
*           方式二:傳送與接收分開來實現
*           SPI_Write() 只發送
*           SPI_Read()  只接收
*           兩種方式不同之處:方式一,在發的過程中也在接收,第二種方式,收與發單獨進行
*  Created on: 2013-5-28
*      Author: lzy
*/

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#include "Debug.h"
#define SPI_DEBUG 0

static const char *device = "/dev/spidev0.0";
static uint8_t mode = 0; /* SPI通訊使用全雙工,設定CPOL=0,CPHA=0。 */
static uint8_t bits = 8; /* 8bits讀寫,MSB first。*/
static uint32_t speed = 12 * 1000 * 1000;/* 設定12M傳輸速度 */
static uint16_t delay = 0;
static int g_SPI_Fd = 0;

static void pabort(const char *s)
{
    perror(s);
    abort();
}

/**
*  功 能:同步資料傳輸
* 入口引數 :
*             TxBuf -> 傳送資料首地址
*             len -> 交換資料的長度
* 出口引數:
*             RxBuf -> 接收資料緩衝區
* 返回值:0 成功
* 開發人員:Lzy 2013-5-22
*/
int SPI_Transfer(const uint8_t *TxBuf, uint8_t *RxBuf, int len)
{
    int ret;
    int fd = g_SPI_Fd;

    struct spi_ioc_transfer tr =    {
            .tx_buf = (unsigned long) TxBuf,
            .rx_buf = (unsigned long) RxBuf,
            .len =    len,
            .delay_usecs = delay,
    };

    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1)
        pr_err("can't send spi message");
    else
    {
#if SPI_DEBUG
        int i;
        pr_debug("\nsend spi message Succeed");
        pr_debug("\nSPI Send [Len:%d]: ", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
            printf("\n\t");
            printf("0x%02X ", TxBuf[i]);
        }
        printf("\n");

        pr_debug("SPI Receive [len:%d]:", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
            printf("\n\t");
            printf("0x%02X ", RxBuf[i]);
        }
        printf("\n");
#endif
    }
    return ret;
}

/**
* 功 能:傳送資料
* 入口引數 :
*             TxBuf -> 傳送資料首地址
*            len ->  傳送與長度
*返回值:0 成功
* 開發人員:Lzy 2013-5-22
*/
int SPI_Write(uint8_t *TxBuf, int len)
{
    int ret;
    int fd = g_SPI_Fd;

    ret = write(fd, TxBuf, len);
    if (ret < 0)
        pr_err("SPI Write error\n");
    else
    {
#if SPI_DEBUG
        int i;
        pr_debug("\nSPI Write [Len:%d]: ", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
            printf("\n\t");
            printf("0x%02X ", TxBuf[i]);
        }
        printf("\n");

#endif
    }

    return ret;
}

/**
* 功 能:接收資料
* 出口引數:
*         RxBuf -> 接收資料緩衝區
*         rtn -> 接收到的長度
* 返回值:>=0 成功
* 開發人員:Lzy 2013-5-22
*/
int SPI_Read(uint8_t *RxBuf, int len)
{
    int ret;
    int fd = g_SPI_Fd;
    ret = read(fd, RxBuf, len);
    if (ret < 0)
        pr_err("SPI Read error\n");
    else
    {
#if SPI_DEBUG
        int i;
        pr_debug("SPI Read [len:%d]:", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
            printf("\n\t");
            printf("0x%02X ", RxBuf[i]);
        }
        printf("\n");
#endif
    }

    return ret;
}

/**
* 功 能:開啟裝置  並初始化裝置
* 入口引數 :
* 出口引數:
* 返回值:0 表示已開啟  0XF1 表示SPI已開啟 其它出錯
* 開發人員:Lzy 2013-5-22
*/
int SPI_Open(void)
{
    int fd;
    int ret = 0;

    if (g_SPI_Fd != 0) /* 裝置已開啟 */
        return 0xF1;

    fd = open(device, O_RDWR);
    if (fd < 0)
        pabort("can't open device");
    else
        pr_debug("SPI - Open Succeed. Start Init SPI...\n");

    g_SPI_Fd = fd;
    /*
     * spi mode
     */
    ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
    if (ret == -1)
        pabort("can't set spi mode");

    ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
    if (ret == -1)
        pabort("can't get spi mode");

    /*
     * bits per word
     */
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1)
        pabort("can't set bits per word");

    ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
    if (ret == -1)
        pabort("can't get bits per word");

    /*
     * max speed hz
     */
    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        pabort("can't set max speed hz");

    ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        pabort("can't get max speed hz");

    pr_debug("spi mode: %d\n", mode);
    pr_debug("bits per word: %d\n", bits);
    pr_debug("max speed: %d KHz (%d MHz)\n", speed / 1000, speed / 1000 / 1000);

    return ret;
}

/**
* 功 能:關閉SPI模組
*/
int SPI_Close(void)
{
    int fd = g_SPI_Fd;

    if (fd == 0) /* SPI是否已經開啟*/
        return 0;
    close(fd);
    g_SPI_Fd = 0;

    return 0;
}

/**
* 功 能:自發自收測試程式
*         接收到的資料與傳送的資料如果不一樣 ,則失敗
* 說明:
*         在硬體上需要把輸入與輸出引腳短跑
* 開發人員:Lzy 2013-5-22
*/
int SPI_LookBackTest(void)
{
    int ret, i;
    const int BufSize = 16;
    uint8_t tx[BufSize], rx[BufSize];

    bzero(rx, sizeof(rx));
    for (i = 0; i < BufSize; i++)
        tx[i] = i;

    pr_debug("\nSPI - LookBack Mode Test...\n");
    ret = SPI_Transfer(tx, rx, BufSize);
    if (ret > 1)
    {
        ret = memcmp(tx, rx, BufSize);
        if (ret != 0)
        {
            pr_err("LookBack Mode Test error\n");
//            pabort("error");
        }
        else
            pr_debug("SPI - LookBack Mode  OK\n");
    }

    return ret;
}

int main(int argc, char *argv[])
{
    int ret = 0;

    ret = SPI_Open();
    if (ret)
        return ret;

    SPI_LookBackTest();

//    unsigned char buf[10];
//    SPI_Write(buf, 10);
//    SPI_Read(buf, 10);

    SPI_Close();

return 0;
}