/*
* 说明: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("nt");
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("nt");
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 errorn");
else
{
#if SPI_DEBUG
int i;
pr_debug("nSPI Write [Len:%d]: ", len);
for (i = 0; i < len; i++)
{
if (i % 8 == 0)
printf("nt");
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 errorn");
else
{
#if SPI_DEBUG
int i;
pr_debug("SPI Read [len:%d]:", len);
for (i = 0; i < len; i++)
{
if (i % 8 == 0)
printf("nt");
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: %dn", mode);
pr_debug("bits per word: %dn", 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 errorn");
//pabort("error");
}
else
pr_debug("SPI - LookBack Mode OKn");
}

return ret;
}

Linux下SPI测试程序的更多相关文章

  1. linux驱动基础系列--Linux下Spi接口Wifi驱动分析

    前言 本文纯粹的纸上谈兵,我并未在实际开发过程中遇到需要编写或调试这类驱动的时候,本文仅仅是根据源码分析后的记录!基于内核版本:2.6.35.6 .主要是想对spi接口的wifi驱动框架有一个整体的把 ...

  2. linux 下SPI通信注意事项(待续)

    一.2台Linux设备之间使用SPI通信 1.标准Linux只支持Master 模式.但是可以在驱动中修改为Slave模式: 2.硬件SPI可能支持Slave模式,也可能不支持.这个要提前确认好: 3 ...

  3. [DM8168]Linux下SPI驱动测试

    1.内核自带的SPI相关的驱动文件 项目中有CPU与FPGA进行通信,用到SPI接口: SPI头文件在: linux-kernel/include/linux/spi.h SPI实现在: linux- ...

  4. linux下串口测试程序

    通过简单的参数配置,执行文件+串口号+波特率 #include <stdio.h> #include <stdlib.h> #include <unistd.h> ...

  5. Linux下SPI读写外部寄存器的操作

    SPI写寄存器操作: staticvoid mcp251x_write_reg(struct spi_device *spi, uint8_t reg, uint8_t val)   {   stru ...

  6. linux下SPI接口和stm32通讯

    struct mcu_data{    struct spi_device* spi;    struct input_dev *input;    struct keymcu_platform_da ...

  7. 以Linux下的测试程序说明递归型互斥量和普通互斥量的区别

    先贴代码和测试结果 // Mutex.h: 对pthread的互斥量的RAII包装 #ifndef _MUTEX_H_ #define _MUTEX_H_ #include <stdio.h&g ...

  8. 在Linux下的中断方式读取按键驱动程序

    // 在Linux下的中断方式读取按键驱动程序 //包含外部中断 休眠 加入poll机制 // 采用异步通知的方式 // 驱动程序发 ---> app接收 (通过kill_fasync()发送) ...

  9. linux下对2个连通的串口读写遇到的问题

    想要分析下zmodem协议,搜索发现linux下的工具lrzsz是一个包含x,y,z modem传输的工具,下载其源码,下载.它可以借助各种串行的接口进行数据传输,比如串口,socket也可以,这点描 ...

随机推荐

  1. Unity3D 移动开发代码优化

    1. 尽量避免每帧处理 比方: function Update() { DoSomeThing(); } 可改为每5帧处理一次: function Update() { if(Time.frameCo ...

  2. 谁是云的王者?OpenStack与VMware优劣对比

    [编者按]在云计算生态系统中,有两种类型的用户需要使用云计算资源:传统型(Traditional IT applications)和在互联网大潮下逐渐崛起云计算应用型(Cloud-aware appl ...

  3. 什么时候触发MinorGC?什么时候触发FullGC?

    触发MinorGC(Young GC) 虚拟机在进行minorGC之前会判断老年代最大的可用连续空间是否大于新生代的所有对象总空间 1.如果大于的话,直接执行minorGC 2.如果小于,判断是否开启 ...

  4. Audiosink design

    Audiosink的设计,需要满足下列一些需求: 良好的chain_based 支持.绝大多数简单playback pipelines都是将音频数据从decoder直接push给audiosink; ...

  5. 简单熟悉eclipse

  6. 报错:org.apache.jasper.JasperException: /jsp/head.jsp (line: 1, column: 2) Page directive: illegal to

    上面报错提示的是org.apache.jasper.JasperException: /jsp/head.jsp (line: 1, column: 2) Page directive: illega ...

  7. Java(System类,currentTimeMillis())

    CurrentTimeMillis()方法来记录程序的执行时间.currentTimeMillis()方法将返回自1970年1月1日午夜起到现在的时间,时间单位是ms,如果要记录程序中一段程序的运行时 ...

  8. Java基础 - 强引用、弱引用、软引用、虚引用

    1.强引用(StrongReference) 强引用是使用最普遍的引用. 假设一个对象具有强引用.那垃圾回收器绝不会回收它.例如以下: [java] view plaincopyprint" ...

  9. Android-ViewPagerIndicator框架使用——TabPageIndicator

    前言:TabPageIndicator这个类和之前的不大一样,他不仅提供了展示的功能,而且可以点击,下面的viewpager可以跳转的有点tabhost的感觉. 一:布局文件的定义,simple_ta ...

  10. OC对象给分类加入属性

    OC对象中不能给分类加入属性.可是在实际开发中.常常为了更好的性能须要给分类加入属性,那么 加入的属性不能有默认的成员变量.须要我们自己实现set和get方法,要用到执行时 例如以下: #import ...