s5pv210与stm32 spi通信

来源:互联网 发布:期货平板看盘软件 编辑:程序博客网 时间:2024/06/08 11:53

spi通信不支持从设备主动给主设备发送数据,所以我把spi的用户空间驱动改了一下,实现过程是这样的,用一个中断来响应从设备的要求,即当STM32要主动给主设备发送数据的时候,将中断脚拉低,用户空间检测到中断后,主动给STM32发送一个空数据,这样spi就能读到STM32所要发送的数据了。SPI通信发数据与接数据是同时进行的,这个大家可以看下SPI协议。

以下我我修改的用户空间的驱动:

/* * spidev.c -- simple synchronous userspace interface to SPI devices * * Copyright (C) 2006 SWAPP *Andrea Paterniani <a.paterniani@swapp-eng.it> * 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 <linux/init.h>#include <linux/module.h>#include <linux/ioctl.h>#include <linux/fs.h>#include <linux/device.h>#include <linux/err.h>#include <linux/list.h>#include <linux/errno.h>#include <linux/mutex.h>#include <linux/slab.h>#include <linux/irq.h>#include <linux/interrupt.h>#include <mach/gpio.h>#include <plat/gpio-cfg.h>#include <mach/regs-gpio.h>#include <linux/delay.h>#include <linux/spi/spi.h>#include <linux/spi/spidev_gzsd.h>#include <asm/uaccess.h>#include <linux/poll.h>#defineSPI_IRQIRQ_EINT(2)#defineIRQSTATES5PV210_GPH0(2)#define BUF_SIZE38u8 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_MAJOR153/* assigned */#define N_SPI_MINORS32/* ... 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 shouldn't be *  - 3WIRE ... when active, it won't 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 shouldn't. * * 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_tdevt;spinlock_tspi_lock;struct spi_device*spi;struct list_headdevice_entry;/* buffer is NULL unless this device is open (users > 0) */struct mutexbuf_lock;unsignedusers;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 can't 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_transfert = {.tx_buf= spidev->buffer,.len= len,};struct spi_messagem;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_transfert = {.rx_buf= spidev->buffer,.len= len,};struct spi_messagem;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_tstatus = 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 longmissing;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_tstatus = 0;unsigned longmissing;/* 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_messagemsg;struct spi_transfer*k_xfers;struct spi_transfer*k_tmp;struct spi_ioc_transfer *u_tmp;unsignedn, total;u8*buf;intstatus = -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 %uHz\n",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 %d\n",__func__,__LINE__);status = spidev_sync(spidev, &msg);printk("%s :----line is %d\n",__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 %d\n",__func__,__LINE__);#if1wake_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 %d\n",__func__,__LINE__);#if1poll_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){interr = 0;intretval = 0;struct spidev_data*spidev;struct spi_device*spi;u32tmp;unsignedn_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; don't 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) {u8save = 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 %02x\n", tmp);}break;case SPI_IOC_WR_LSB_FIRST:retval = __get_user(tmp, (__u8 __user *)arg);if (retval == 0) {u8save = 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 first\n",tmp ? 'l' : 'm');}break;case SPI_IOC_WR_BITS_PER_WORD:retval = __get_user(tmp, (__u8 __user *)arg);if (retval == 0) {u8save = 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 word\n", tmp);}break;case SPI_IOC_WR_MAX_SPEED_HZ:retval = __get_user(tmp, (__u32 __user *)arg);if (retval == 0) {u32save = 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 failed\n");}if (__copy_from_user(g_uxfers, (void __user *)arg, tmp)) {kfree(g_uxfers);printk("g_uxfers copy failed\n");}/* 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;intstatus = -ENXIO;mutex_lock(&device_list_lock);gk_xfers = kcalloc(1, sizeof (*gk_xfers), GFP_KERNEL);if (gk_xfers == NULL)printk("alloc gk_xfers_failed\n");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/ENOMEM\n");status = -ENOMEM;}}if (status == 0) {spidev->users++;filp->private_data = spidev;nonseekable_open(inode, filp);}} elsepr_debug("spidev: nothing for minor %d\n", iminor(inode));mutex_unlock(&device_list_lock);return status;}static int spidev_release(struct inode *inode, struct file *filp){struct spidev_data*spidev;intstatus = 0;mutex_lock(&device_list_lock);spidev = filp->private_data;filp->private_data = NULL;/* last close? */spidev->users--;if (!spidev->users) {intdofree;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.  It'll 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;intstatus;unsigned longminor;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 don't 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, <a.paterniani@swapp-eng.it>");MODULE_DESCRIPTION("User mode SPI device interface");MODULE_LICENSE("GPL");MODULE_ALIAS("spi:spidev");
文件名:spidev_gzsd.c

位置: drivers/spi

drivers/spi/Makefile里的spidev.c修改为spidev_gzsd.c

210 spi测试程序如下:

/* * SPI testing utility (using spidev driver) * * Copyright (c) 2007  MontaVista Software, Inc. * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com> * * 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 <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 "spidev.h"//#include <termios.h>#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))#define BUF_SIZE38#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);#if1if(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_tbuf[len], bp[len];intstatus;/* 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 read\n");return;}#if0printf("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;#if1printf("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_transferxfer;//unsigned charbuf[BUF_SIZE], *bp;uint8_tbuf[BUF_SIZE], *bp;intstatus;intlen;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;#if0buf[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_MESSAGE\n");return;}//printf("do write data is %d\n",buf[0]);printf("response(%2d, %2d)\n", len, status);#endifstatus = write(fd,tx,BUF_SIZE);if(status < 0)printf("do write failed\n");#if0for (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;#if0if(argc < 2) {printf("please enter one parameter at least\n");return 0;}data = atoi(argv[1]);#elsedata = 0;#endiffd = open(device, O_RDWR);if (fd < 0)printf("can't open device");mode = SPI_MODE_1;/* * spi mode */ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);if (ret == -1)printf("can't set spi mode");ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);if (ret == -1)printf("can't get spi mode");/* * bits per word */ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);if (ret == -1)printf("can't set bits per word");ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);if (ret == -1)printf("can't get bits per word");/* * max speed hz */ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);if (ret == -1)printf("can't set max speed hz");ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);if (ret == -1)printf("can't get max speed hz");printf("spi mode: %d\n", mode);printf("bits per word: %d\n", 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 -----------------------%d\n",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 +++++++++++++++++++%d\n",ret);if (FD_ISSET(fd, &rds))do_read(fd,BUF_SIZE);data++;if(data > 8)data = 0;sleep(1);}close(fd);return ret;}

这两部分源码下载地址为:点击打开链接

STM32主函数代码:

#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机 SPI1_Init();SPIsend_Init();  send_onoff(Bit_RESET);Uart_SendString(USART1,"串口1开始:\r\n") ;//串口1接PC机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 intx=0;if(RxIdx==SPI_BufferSize) //中断方式接收{cmd = SPI1_Buffer_Rx[0];for(i=0;i< RxIdx;i++){Uart_SendByte(USART1,SPI1_Buffer_Rx[i]);//向PC机发送// 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); //查询方式接收:/*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机发送}RxIdx=0;}*/}void UARTtest(USART_TypeDef *port){int i;for(i=0;i<10;i++)Uart_SendByte(port,'0'+i);Delay_ARMJISHU(10000000);}
具体代码我就不作说明了

原创粉丝点击