s5pv210與stm32 spi通信
以下我我修改的用戶(hù)空間的驅(qū)動(dòng):
本文引用地址:http://butianyuan.cn/article/201611/318267.htm/** spidev.c -- simple synchronous userspace interface to SPI devices** Copyright (C) 2006 SWAPP* Andrea Paterniani * Copyright (C) 2007 David Brownell (simplification, cleanup)** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include文件名:spidev_gzsd.c#include #include #include #include #include #include #include #include #include #include #include interrupt.h>#include #include #include #include #include #include #include #include #define SPI_IRQ IRQ_EINT(2)#define IRQSTATE S5PV210_GPH0(2)#define BUF_SIZE 38u8 gzsd_buffer[BUF_SIZE];struct spi_transfer *gk_xfers;struct spi_ioc_transfer *g_uxfers;/** This supports acccess to SPI devices using normal userspace I/O calls.* Note that while traditional UNIX/POSIX I/O semantics are half duplex,* and often mask message boundaries, full SPI support requires full duplex* transfers. There are several kinds of internal message boundaries to* handle chipselect management and other protocol options.** SPI has a character major number assigned. We allocate minor numbers* dynamically using a bitmask. You must use hotplug tools, such as udev* (or mdev with busybox) to create and destroy the /dev/spidevB.C device* nodes, since there is no fixed association of minor numbers with any* particular SPI bus or device.*/#define SPIDEV_MAJOR 153 /* assigned */#define N_SPI_MINORS 32 /* ... up to 256 */static DECLARE_BITMAP(minors, N_SPI_MINORS);/* Bit masks for spi_device.mode management. Note that incorrect* settings for some settings can cause *lots* of trouble for other* devices on a shared bus:** - CS_HIGH ... this device will be active when it shouldnt be* - 3WIRE ... when active, it wont behave as it should* - NO_CS ... there will be no explicit message boundaries; this* is completely incompatible with the shared bus model* - READY ... transfers may proceed when they shouldnt.** REVISIT should changing those flags be privileged?*/#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP | SPI_NO_CS | SPI_READY)struct spidev_data {dev_t devt;spinlock_t spi_lock;struct spi_device *spi;struct list_head device_entry;/* buffer is NULL unless this device is open (users > 0) */struct mutex buf_lock;unsigned users;u8 *buffer;int irq;//add by daowait_queue_head_t rqueue;};static flag_poll = 0;static LIST_HEAD(device_list);static DEFINE_MUTEX(device_list_lock);static unsigned bufsiz = 4096;module_param(bufsiz, uint, S_IRUGO);MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");/*-------------------------------------------------------------------------*//** We cant use the standard synchronous wrappers for file I/O; we* need to protect against async removal of the underlying spi_device.*/static void spidev_complete(void *arg){complete(arg);}static ssize_tspidev_sync(struct spidev_data *spidev, struct spi_message *message){DECLARE_COMPLETION_ONSTACK(done);int status;message->complete = spidev_complete;message->context = &done;spin_lock_irq(&spidev->spi_lock);if (spidev->spi == NULL)status = -ESHUTDOWN;elsestatus = spi_async(spidev->spi, message);spin_unlock_irq(&spidev->spi_lock);if (status == 0) {wait_for_completion(&done);status = message->status;if (status == 0)status = message->actual_length;}return status;}static inline ssize_tspidev_sync_write(struct spidev_data *spidev, size_t len){struct spi_transfer t = {.tx_buf = spidev->buffer,.len = len,};struct spi_message m;spi_message_init(&m);spi_message_add_tail(&t, &m);return spidev_sync(spidev, &m);}static inline ssize_tspidev_sync_read(struct spidev_data *spidev, size_t len){struct spi_transfer t = {.rx_buf = spidev->buffer,.len = len,};struct spi_message m;spi_message_init(&m);spi_message_add_tail(&t, &m);return spidev_sync(spidev, &m);}/*-------------------------------------------------------------------------*//* Read-only message with current device setup */static ssize_tspidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){struct spidev_data *spidev;ssize_t status = 0;/* chipselect only toggles at start or end of operation */if (count > bufsiz)return -EMSGSIZE;spidev = filp->private_data;mutex_lock(&spidev->buf_lock);status = spidev_sync_read(spidev, count);if (status > 0) {unsigned long missing;missing = copy_to_user(buf, spidev->buffer, status);if (missing == status)status = -EFAULT;elsestatus = status - missing;}mutex_unlock(&spidev->buf_lock);return status;}/* Write-only message with current device setup */static ssize_tspidev_write(struct file *filp, const char __user *buf,size_t count, loff_t *f_pos){struct spidev_data *spidev;ssize_t status = 0;unsigned long missing;/* chipselect only toggles at start or end of operation */if (count > bufsiz)return -EMSGSIZE;spidev = filp->private_data;mutex_lock(&spidev->buf_lock);missing = copy_from_user(spidev->buffer, buf, count);if (missing == 0) {status = spidev_sync_write(spidev, count);} elsestatus = -EFAULT;mutex_unlock(&spidev->buf_lock);return status;}static int spidev_message(struct spidev_data *spidev,struct spi_ioc_transfer *u_xfers, unsigned n_xfers){struct spi_message msg;struct spi_transfer *k_xfers;struct spi_transfer *k_tmp;struct spi_ioc_transfer *u_tmp;unsigned n, total;u8 *buf;int status = -EFAULT;spi_message_init(&msg);k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL);if (k_xfers == NULL)return -ENOMEM;/* Construct spi_message, copying any tx data to bounce buffer.* We walk the array of user-provided transfers, using each one* to initialize a kernel version of the same transfer.*/buf = spidev->buffer;total = 0;for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;n;n--, k_tmp++, u_tmp++) {k_tmp->len = u_tmp->len;total += k_tmp->len;if (total > bufsiz) {status = -EMSGSIZE;goto done;}if (u_tmp->rx_buf) {k_tmp->rx_buf = buf;if (!access_ok(VERIFY_WRITE, (u8 __user *)(uintptr_t) u_tmp->rx_buf,u_tmp->len))goto done;}if (u_tmp->tx_buf) {k_tmp->tx_buf = buf;if (copy_from_user(buf, (const u8 __user *)(uintptr_t) u_tmp->tx_buf,u_tmp->len))goto done;}buf += k_tmp->len;k_tmp->cs_change = !!u_tmp->cs_change;k_tmp->bits_per_word = u_tmp->bits_per_word;k_tmp->delay_usecs = u_tmp->delay_usecs;k_tmp->speed_hz = u_tmp->speed_hz;#ifdef VERBOSEdev_dbg(&spidev->spi->dev," xfer len %zd %s%s%s%dbits %u usec %uHzn",u_tmp->len,u_tmp->rx_buf ? "rx " : "",u_tmp->tx_buf ? "tx " : "",u_tmp->cs_change ? "cs " : "",u_tmp->bits_per_word ? : spidev->spi->bits_per_word,u_tmp->delay_usecs,u_tmp->speed_hz ? : spidev->spi->max_speed_hz);#endifspi_message_add_tail(k_tmp, &msg);}printk("%s :----line is %dn",__func__,__LINE__);status = spidev_sync(spidev, &msg);printk("%s :----line is %dn",__func__,__LINE__);if (status < 0)goto done;/* copy any rx data out of bounce buffer */buf = spidev->buffer;for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {if (u_tmp->rx_buf) {if (__copy_to_user((u8 __user *)(uintptr_t) u_tmp->rx_buf, buf,u_tmp->len)) {status = -EFAULT;goto done;}}buf += u_tmp->len;}status = total;done:kfree(k_xfers);return status;}static DECLARE_WAIT_QUEUE_HEAD(gzsd_spi_wait);static irqreturn_t gzsd_spiread(int irq, void *dev_id){struct spidev_data *spidev = (struct spidev_data *)dev_id;//dev_err(&spidev->spi->dev, "is spi dev now.n");disable_irq_nosync(irq);flag_poll = 1;//printk("%s:------------line is %dn",__func__,__LINE__);#if 1wake_up_interruptible(&spidev->rqueue);#elsewake_up(&gzsd_spi_wait);#endif//wake_up_interruptible_sync(&spidev->rqueue);//wake_up(&spidev->rqueue);enable_irq(irq);return IRQ_HANDLED;}unsigned int gzsd_poll(struct file *filp, poll_table *wait){struct spidev_data *spidev;spidev = filp->private_data;unsigned int mask = 0;//printk("%s:------------line is %dn",__func__,__LINE__);#if 1poll_wait(filp, &spidev->rqueue, wait);#elsepoll_wait(filp, &gzsd_spi_wait, wait);#endifif(flag_poll) {mask = POLLIN | POLLRDNORM; //can be readflag_poll = 0;}return mask;}static longspidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){int err = 0;int retval = 0;struct spidev_data *spidev;struct spi_device *spi;u32 tmp;unsigned n_ioc;struct spi_ioc_transfer *ioc;/* Check type and command number */if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC)return -ENOTTY;/* Check access direction once here; dont repeat below.* IOC_DIR is from the user perspective, while access_ok is* from the kernel perspective; so they look reversed.*/if (_IOC_DIR(cmd) & _IOC_READ)err = !access_ok(VERIFY_WRITE,(void __user *)arg, _IOC_SIZE(cmd));if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE)err = !access_ok(VERIFY_READ,(void __user *)arg, _IOC_SIZE(cmd));if (err)return -EFAULT;/* guard against device removal before, or while,* we issue this ioctl.*/spidev = filp->private_data;spin_lock_irq(&spidev->spi_lock);spi = spi_dev_get(spidev->spi);spin_unlock_irq(&spidev->spi_lock);if (spi == NULL)return -ESHUTDOWN;/* use the buffer lock here for triple duty:* - prevent I/O (from us) so calling spi_setup() is safe;* - prevent concurrent SPI_IOC_WR_* from morphing* data fields while SPI_IOC_RD_* reads them;* - SPI_IOC_MESSAGE needs the buffer locked "normally".*/mutex_lock(&spidev->buf_lock);switch (cmd) {/* read requests */case SPI_IOC_RD_MODE:retval = __put_user(spi->mode & SPI_MODE_MASK,(__u8 __user *)arg);break;case SPI_IOC_RD_LSB_FIRST:retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0,(__u8 __user *)arg);break;case SPI_IOC_RD_BITS_PER_WORD:retval = __put_user(spi->bits_per_word, (__u8 __user *)arg);break;case SPI_IOC_RD_MAX_SPEED_HZ:retval = __put_user(spi->max_speed_hz, (__u32 __user *)arg);break;/* write requests */case SPI_IOC_WR_MODE:retval = __get_user(tmp, (u8 __user *)arg);if (retval == 0) {u8 save = spi->mode;if (tmp & ~SPI_MODE_MASK) {retval = -EINVAL;break;}tmp |= spi->mode & ~SPI_MODE_MASK;spi->mode = (u8)tmp;retval = spi_setup(spi);if (retval < 0)spi->mode = save;elsedev_dbg(&spi->dev, "spi mode %02xn", tmp);}break;case SPI_IOC_WR_LSB_FIRST:retval = __get_user(tmp, (__u8 __user *)arg);if (retval == 0) {u8 save = spi->mode;if (tmp)spi->mode |= SPI_LSB_FIRST;elsespi->mode &= ~SPI_LSB_FIRST;retval = spi_setup(spi);if (retval < 0)spi->mode = save;elsedev_dbg(&spi->dev, "%csb firstn",tmp ? l : m);}break;case SPI_IOC_WR_BITS_PER_WORD:retval = __get_user(tmp, (__u8 __user *)arg);if (retval == 0) {u8 save = spi->bits_per_word;spi->bits_per_word = tmp;retval = spi_setup(spi);if (retval < 0)spi->bits_per_word = save;elsedev_dbg(&spi->dev, "%d bits per wordn", tmp);}break;case SPI_IOC_WR_MAX_SPEED_HZ:retval = __get_user(tmp, (__u32 __user *)arg);if (retval == 0) {u32 save = spi->max_speed_hz;spi->max_speed_hz = tmp;retval = spi_setup(spi);if (retval < 0)spi->max_speed_hz = save;elsedev_dbg(&spi->dev, "%d Hz (max)n", tmp);}break;default:/* segmented and/or full-duplex I/O request */if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))|| _IOC_DIR(cmd) != _IOC_WRITE) {retval = -ENOTTY;break;}tmp = _IOC_SIZE(cmd);if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) {retval = -EINVAL;break;}n_ioc = tmp / sizeof(struct spi_ioc_transfer);if (n_ioc == 0)break;g_uxfers = kmalloc(tmp, GFP_KERNEL);if (!g_uxfers) {printk("g_uxfers alloc failedn");}if (__copy_from_user(g_uxfers, (void __user *)arg, tmp)) {kfree(g_uxfers);printk("g_uxfers copy failedn");}/* copy into scratch area */ioc = kmalloc(tmp, GFP_KERNEL);if (!ioc) {retval = -ENOMEM;break;}if (__copy_from_user(ioc, (void __user *)arg, tmp)) {kfree(ioc);retval = -EFAULT;break;}/* translate to spi_message, execute */retval = spidev_message(spidev, ioc, n_ioc);kfree(ioc);break;}mutex_unlock(&spidev->buf_lock);spi_dev_put(spi);return retval;}static int spidev_open(struct inode *inode, struct file *filp){struct spidev_data *spidev;int status = -ENXIO;mutex_lock(&device_list_lock);gk_xfers = kcalloc(1, sizeof (*gk_xfers), GFP_KERNEL);if (gk_xfers == NULL)printk("alloc gk_xfers_failedn");list_for_each_entry(spidev, &device_list, device_entry) {if (spidev->devt == inode->i_rdev) {status = 0;break;}}if (status == 0) {if (!spidev->buffer) {spidev->buffer = kmalloc(bufsiz, GFP_KERNEL);if (!spidev->buffer) {dev_dbg(&spidev->spi->dev, "open/ENOMEMn");status = -ENOMEM;}}if (status == 0) {spidev->users++;filp->private_data = spidev;nonseekable_open(inode, filp);}} elsepr_debug("spidev: nothing for minor %dn", iminor(inode));mutex_unlock(&device_list_lock);return status;}static int spidev_release(struct inode *inode, struct file *filp){struct spidev_data *spidev;int status = 0;mutex_lock(&device_list_lock);spidev = filp->private_data;filp->private_data = NULL;/* last close? */spidev->users--;if (!spidev->users) {int dofree;kfree(spidev->buffer);spidev->buffer = NULL;/* ... after we unbound from the underlying device? */spin_lock_irq(&spidev->spi_lock);dofree = (spidev->spi == NULL);spin_unlock_irq(&spidev->spi_lock);if (dofree)kfree(spidev);}//disable_irq_nosync(spidev->irq);kfree(gk_xfers);kfree(g_uxfers);mutex_unlock(&device_list_lock);return status;}static const struct file_operations spidev_fops = {.owner = THIS_MODULE,/* REVISIT switch to aio primitives, so that userspace* gets more complete API coverage. Itll simplify things* too, except for the locking.*/.write = spidev_write,.read = spidev_read,.unlocked_ioctl = spidev_ioctl,.open = spidev_open,.release = spidev_release,.poll =gzsd_poll,};/*-------------------------------------------------------------------------*//* The main reason to have this class is to make mdev/udev create the* /dev/spidevB.C character device nodes exposing our userspace API.* It also simplifies memory management.*/static struct class *spidev_class;/*-------------------------------------------------------------------------*/static int __devinit spidev_probe(struct spi_device *spi){struct spidev_data *spidev;int status;unsigned long minor;int err;/* Allocate driver data */spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);if (!spidev)return -ENOMEM;/* Initialize the driver data */spidev->spi = spi;spin_lock_init(&spidev->spi_lock);mutex_init(&spidev->buf_lock);INIT_LIST_HEAD(&spidev->device_entry);/* If we can allocate a minor number, hook up this device.* Reusing minors is fine so long as udev or mdev is working.*/mutex_lock(&device_list_lock);minor = find_first_zero_bit(minors, N_SPI_MINORS);if (minor < N_SPI_MINORS) {struct device *dev;spidev->devt = MKDEV(SPIDEV_MAJOR, minor);dev = device_create(spidev_class, &spi->dev, spidev->devt,spidev, "spidev%d.%d",spi->master->bus_num, spi->chip_select);status = IS_ERR(dev) ? PTR_ERR(dev) : 0;} else {dev_dbg(&spi->dev, "no minor number available!n");status = -ENODEV;}if (status == 0) {set_bit(minor, minors);list_add(&spidev->device_entry, &device_list);}spidev->irq = SPI_IRQ;err = request_irq(spidev->irq, gzsd_spiread, IRQ_TYPE_EDGE_FALLING,"spi", spidev);if(err < 0) {dev_err(&spidev->spi->dev, "Unable to request spi IRQ.n");}init_waitqueue_head(&spidev->rqueue);mutex_unlock(&device_list_lock);if (status == 0)spi_set_drvdata(spi, spidev);elsekfree(spidev);return status;}static int __devexit spidev_remove(struct spi_device *spi){struct spidev_data *spidev = spi_get_drvdata(spi);/* make sure ops on existing fds can abort cleanly */spin_lock_irq(&spidev->spi_lock);spidev->spi = NULL;spi_set_drvdata(spi, NULL);spin_unlock_irq(&spidev->spi_lock);/* prevent new opens */mutex_lock(&device_list_lock);list_del(&spidev->device_entry);device_destroy(spidev_class, spidev->devt);clear_bit(MINOR(spidev->devt), minors);if (spidev->users == 0)kfree(spidev);mutex_unlock(&device_list_lock);return 0;}static struct spi_driver spidev_spi_driver = {.driver = {.name = "spidev",.owner = THIS_MODULE,},.probe = spidev_probe,.remove = __devexit_p(spidev_remove),/* NOTE: suspend/resume methods are not necessary here.* We dont do anything except pass the requests to/from* the underlying controller. The refrigerator handles* most issues; the controller driver handles the rest.*/};/*-------------------------------------------------------------------------*/static int __init spidev_init(void){int status;/* Claim our 256 reserved device numbers. Then register a class* that will key udev/mdev to add/remove /dev nodes. Last, register* the driver which manages those device numbers.*/BUILD_BUG_ON(N_SPI_MINORS > 256);status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);if (status < 0)return status;spidev_class = class_create(THIS_MODULE, "spidev");if (IS_ERR(spidev_class)) {unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);return PTR_ERR(spidev_class);}status = spi_register_driver(&spidev_spi_driver);if (status < 0) {class_destroy(spidev_class);unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);}return status;}module_init(spidev_init);static void __exit spidev_exit(void){spi_unregister_driver(&spidev_spi_driver);class_destroy(spidev_class);unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);}module_exit(spidev_exit);MODULE_AUTHOR("Andrea Paterniani, ");MODULE_DESCRIPTION("User mode SPI device interface");MODULE_LICENSE("GPL");MODULE_ALIAS("spi:spidev");
位置: drivers/spi
將drivers/spi/Makefile里的spidev.c修改為spidev_gzsd.c
210 spi測(cè)試程序如下:
/** SPI testing utility (using spidev driver)** Copyright (c) 2007 MontaVista Software, Inc.* Copyright (c) 2007 Anton Vorontsov ** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License.** Cross-compile with cross-gcc -I/path/to/cross-kernel/include*/#include#include #include #include #include #include #include #include #include "spidev.h"http://#include #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))#define BUF_SIZE 38#define READ_SIZE (BUF_SIZE + 1)static const char *device = "/dev/spidev0.0";static uint8_t mode;static uint8_t bits = 8;static uint32_t speed = 140000;//140000;static uint16_t delay;static void transfer(int fd){int ret;uint8_t tx[] = {0x01, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9,0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3,0xF2, 0xF1, 0xF0, 0xEF, 0xEE, 0xED,0xEC, 0xEB, 0xEA, 0xE9, 0xE8, 0xE7,0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1,0xE0, 0xDF, 0xDE, 0xDD, 0xDC, 0xDB,0xDA, 0xD9,};uint8_t rx[ARRAY_SIZE(tx)] = {0, };struct spi_ioc_transfer tr = {.tx_buf = (unsigned long)tx,.rx_buf = (unsigned long)rx,.len = ARRAY_SIZE(tx),.delay_usecs = delay,.speed_hz = speed,.bits_per_word = bits,};ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);#if 1if(rx[0] != 0xff){for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {if (!(ret % 6))puts("");printf("%.2d ", rx[ret]);}puts("");}#endif}static void do_read(int fd, int len){uint8_t buf[len], bp[len];int status;/* read at least 2 bytes, no more than 32 */if (len < 2)len = 2;else if (len > sizeof(buf))len = sizeof(buf);memset(buf, 0, sizeof buf);status = read(fd, buf, len);if (status < 0) {printf("read error n");return;}if (status != len) {fprintf(stderr, "short readn");return;}#if 0printf("read(%2d, %2d): %02x %02x,", len, status,buf[0], buf[1]);status -= 2;bp = buf + 2;while (status-- > 0)printf(" %02x", *bp++);printf("n");#elseint i;#if 1printf("do read data is :n");for(i = 0;i < len;i++)printf(" %d",buf[i]);printf("n");#elsefor(i = 0;i < (len - 1);i++){bp[i] = buf[i+1];}bp[len-1] = buf[0];printf("data is :n");for(i = 0;i < len;i++)printf(" %d",bp[i]);printf("n");#endif#endif}static void do_write(int fd,int cmd){struct spi_ioc_transfer xfer;//unsigned char buf[BUF_SIZE], *bp;uint8_t buf[BUF_SIZE], *bp;int status;int len;uint8_t tx[] = {cmd, (cmd +1), (cmd+2), 0xFB, 0xFA, 0xF9,0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3,0xF2, 0xF1, 0xF0, 0xEF, 0xEE, 0xED,0xEC, 0xEB, 0xEA, 0xE9, 0xE8, 0xE7,0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1,0xE0, 0xDF, 0xDE, 0xDD, 0xDC, 0xDB,0xDA, 0xD9,};//memset(xfer, 0, sizeof xfer);memset(buf, 1, sizeof buf);len = sizeof buf;//buf[0] = cmd;#if 0buf[0] = cmd;buf[1] = cmd;xfer.tx_buf = (unsigned long)buf;xfer.len = len;status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer);if (status < 0) {printf("SPI_IOC_MESSAGEn");return;}//printf("do write data is %dn",buf[0]);printf("response(%2d, %2d)n", len, status);#endifstatus = write(fd,tx,BUF_SIZE);if(status < 0)printf("do write failedn");#if 0for (bp = buf; len; len--)printf(" %02x", *bp++);printf("n");#endif}int main(int argc, char *argv[]){int ret = 0;int fd;int data;fd_set rds; struct timeval tv;#if 0if(argc < 2) {printf("please enter one parameter at leastn");return 0;}data = atoi(argv[1]);#elsedata = 0;#endiffd = open(device, O_RDWR);if (fd < 0)printf("cant open device");mode = SPI_MODE_1;/** spi mode*/ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);if (ret == -1)printf("cant set spi mode");ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);if (ret == -1)printf("cant get spi mode");/** bits per word*/ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);if (ret == -1)printf("cant set bits per word");ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);if (ret == -1)printf("cant get bits per word");/** max speed hz*/ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);if (ret == -1)printf("cant set max speed hz");ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);if (ret == -1)printf("cant get max speed hz");printf("spi mode: %dn", mode);printf("bits per word: %dn", bits);printf("max speed: %d Hz (%d KHz)n", speed, speed/1000);//FD_ZERO(&rds); //FD_SET(fd, &rds);//tv.tv_sec = 10;//tv.tv_usec = 0;int i;while(1){FD_ZERO(&rds); FD_SET(fd, &rds);tv.tv_sec = 1;tv.tv_usec = 0;printf("send daia is -----------------------%dn",data);do_write(fd,data);sleep(1); ret = select(fd+1,&rds,NULL,NULL,&tv);if(ret < 0) {printf("select error!n");//break;}printf("ret is +++++++++++++++++++%dn",ret);if (FD_ISSET(fd, &rds))do_read(fd,BUF_SIZE);data++;if(data > 8)data = 0;sleep(1);}close(fd);return ret;}
這兩部分源碼下載地址為:點(diǎn)擊打開(kāi)鏈接
STM32主函數(shù)代碼:
#include "stm32f10x.h"#include "uart.h"#include "spi.h"void SPItest(void);void UARTtest(USART_TypeDef *port);extern void Uart_SendStringn(USART_TypeDef *port,char *pt,int n);extern void Delay_ARMJISHU(__IO uint32_t nCount);void SPIsend_Init(void){GPIO_InitTypeDef GPIO_InitStructure;//spi send interrupt controlRCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC, ENABLE);// 使能PC,AFIOGPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //推挽輸出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO_Init(GPIOC, &GPIO_InitStructure); //end}void send_onoff(int onoff){if(onoff)GPIO_WriteBit(GPIOC, GPIO_Pin_7, Bit_RESET);elseGPIO_WriteBit(GPIOC, GPIO_Pin_7, Bit_SET);}int main(void){//int i;NVIC_Configuration();//配置 NVIC 和 Vector Table Uart1_COMInit(115200); //串口1連接v210或PC機(jī)SPI1_Init();SPIsend_Init(); send_onoff(Bit_RESET);Uart_SendString(USART1,"串口1開(kāi)始:rn") ; //串口1接PC機(jī)while (1){SPItest();}}void send_data(int mode){int i;send_onoff(Bit_SET);switch(mode){case 0x01:for(i=0;i<38;i++){SPI_I2S_SendData(SPI1,i + 1);}break;case 0x02:for(i=0;i<38;i++){SPI_I2S_SendData(SPI1,i + 2);}break;case 0x03:for(i=0;i<38;i++){SPI_I2S_SendData(SPI1,i + 3);}break;default:break;}send_onoff(Bit_RESET);cmd = 0;return;}void SPItest(void){int i;//static int x=0;if(RxIdx==SPI_BufferSize) //中斷方式接收{(diào)cmd = SPI1_Buffer_Rx[0];for(i=0;i< RxIdx;i++){Uart_SendByte(USART1,SPI1_Buffer_Rx[i]);//向PC機(jī)發(fā)送// SPI_I2S_SendData(SPI1,0xff); SPI1_Buffer_Rx[i]=0;}//while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);//SPI_I2S_SendData(SPI1,x++);//send_onoff(1);//SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);//Delay_ARMJISHU(10000000);RxIdx=0;SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);}if(cmd)send_data(cmd);//查詢(xún)方式接收:/*while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET);SPI3_Buffer_Rx[RxIdx++] = SPI_I2S_ReceiveData(SPI3);if(RxIdx==SPI_BufferSize){for(i=0;i< RxIdx;i++){Uart_SendByte(USART1,SPI3_Buffer_Rx[i]);//向PC機(jī)發(fā)送}RxIdx=0;}*/}void UARTtest(USART_TypeDef *port){int i;for(i=0;i<10;i++)Uart_SendByte(port,0+i);Delay_ARMJISHU(10000000);}具體代碼我就不作說(shuō)明了
評(píng)論