日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

二十一、SPI设备驱动及应用(二)

發布時間:2025/4/5 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二十一、SPI设备驱动及应用(二) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、硬件電路

1、根據三星提供的exynos4412手冊,我們選擇我們要使用的SPI,如下圖,我們選擇SPI2

?

?

?

?由上圖可知,我們SPI2的四條線分別對應管腳:

SPI_2_CLK -> Xi2s2CDCLK -> AH25?

SPI_2_nSS ->?Xi2s2LRCK -> AG24

SPI_2_MISO -> Xi2s2SDI -> AJ25

SPI_2_MOSI ->?Xi2s2SDO -> AG22

我們根據上面的管腳,在原理圖中找到對應腳,已經連接大底板的位置

?二、關閉沖突配置

通過make menuconfig 打開linux配置

?? ??? ?rfid的驅動配置:(我們要重寫這個,所以先關掉)
?? ??? ?????????Device Drivers
?? ??? ?????????????????→SPI support
?? ??? ?????????????????????????→SPI_RC522


?? ??? ?can的驅動配置:(管腳沖突)
?? ??? ?????????Networking support
?? ??? ?????????????????→CAN bus subsystem support?
?? ??? ?????????????????????????→CAN Device Drivers
?? ??? ?????????????????????????????????Platform CAN drivers with Netlink support(默認配置,不用動)
?? ??? ?????????????????????????????????CAN_MCP251X?

?

?三、注冊設備

打開設備注冊文件arch\arm\mach-exynos\mach-itop4412.c,找到rc522關鍵詞

?????

?四、注冊驅動

1、spi_register_driver注冊驅動到SPI總線

2、my_rc522_probe運行,初始化rc522,同時注冊成雜項設備節點。

#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/compat.h> #include <linux/spi/spi.h> #include <linux/spi/spidev.h> #include <asm/uaccess.h> #include <linux/gpio.h> #include <mach/gpio.h> #include <plat/gpio-cfg.h> #include <linux/delay.h> #include <linux/miscdevice.h>struct spi_device *my_spi;#define RC522_RESET_PIN EXYNOS4_GPK1(0) void my_rc522_reset() {//printk("************************ %s\n", __FUNCTION__);if(gpio_request_one(RC522_RESET_PIN, GPIOF_OUT_INIT_HIGH, "RC522_RESET"))pr_err("failed to request GPK1_0 for RC522 reset control\n");s3c_gpio_setpull(RC522_RESET_PIN, S3C_GPIO_PULL_UP);gpio_set_value(RC522_RESET_PIN, 0);mdelay(5);gpio_set_value(RC522_RESET_PIN, 1);gpio_free(RC522_RESET_PIN); }//static ssize_t rc522_write(unsigned char *buffer, int len) static ssize_t rc522_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) {int status;unsigned char tx_buf[2];status = copy_from_user(tx_buf,buf,count);struct spi_transfer t = {.tx_buf = tx_buf,.len = count,};struct spi_message m;spi_message_init(&m);spi_message_add_tail(&t, &m);DECLARE_COMPLETION_ONSTACK(done);m.complete = complete;m.context = &done;printk("spi_async send begin!\n");status = spi_async(my_spi,&m);if(status == 0){wait_for_completion(&done);status = m.status;if (status == 0)status = m.actual_length;}return status; }//static ssize_t rc522_read(unsigned char *buffer, int len) static ssize_t rc522_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) {int status;unsigned char *rx_buf;struct spi_transfer t = {.rx_buf = &rx_buf,.len = count,};struct spi_message m;spi_message_init(&m);spi_message_add_tail(&t, &m);DECLARE_COMPLETION_ONSTACK(done);m.complete = complete;m.context = &done;printk("spi_async read begin!\n");status = spi_async(my_spi,&m);if(status == 0){wait_for_completion(&done);status = m.status;if (status == 0)status = m.actual_length;}status = copy_to_user(buf,&rx_buf,status);return status; }int rc522_open(struct inode *inode,struct file *filp) {return 0; }static struct file_operations rc522_ops = {.owner = THIS_MODULE,.open = rc522_open,.read = rc522_read,.write = rc522_write, };static struct miscdevice rc522_dev = {.minor = MISC_DYNAMIC_MINOR,.fops = &rc522_ops,.name = "rc522", };static int __devinit my_rc522_probe(struct spi_device *spi) {printk("my_rc522_probe!\n");/* reset */my_rc522_reset();my_spi = spi;misc_register(&rc522_dev);return 0; }static int __devexit my_rc522_remove(struct spi_device *spi) {printk("my_rc522_remove!\n");misc_deregister(&rc522_dev); return 0; }static struct spi_driver my_rc522_spi_driver = {.driver = {.name = "my_rc522",.owner = THIS_MODULE,},.probe = my_rc522_probe,.remove = __devexit_p(my_rc522_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 my_rc522_init(void) {spi_register_driver(&my_rc522_spi_driver);return 0; }static void __exit my_rc522_exit(void) {spi_unregister_driver(&my_rc522_spi_driver); }module_exit(my_rc522_exit); module_init(my_rc522_init);MODULE_AUTHOR("topeet: rty"); MODULE_LICENSE("GPL");

五、應用程序

/** 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 "spidev_test.h"#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))int fd;static void pabort(const char *s) {perror(s);abort(); }static const char *device = "/dev/rc522";int WriteSPI(int addr, int data) {int ret;unsigned char TxBuf[3];TxBuf[0] = (unsigned char)addr >> 8;TxBuf[1] = (unsigned char)addr & 0xFF;TxBuf[1] = (unsigned char)data;ret = write(fd, TxBuf, 3);if (ret < 0)printf("spi:SPI Write error\n");usleep(10);return ret; }unsigned char ReadSPI(int addr) {int ret;unsigned char ReData;unsigned char Address;Address = (unsigned char)addr | 0x80;ret = write(fd, &Address, 1);if (ret < 0)printf("spi:SPI Write error\n");usleep(100);ret = read(fd, &ReData, 1);if (ret < 0)printf("spi:SPI Read error\n");elseprintf("spi:SPI Read ReData =%x \n",ReData);return ReData; }int main(void) {unsigned char i;int ret = 0;fd = open(device, O_RDWR);if (fd < 0)pabort("can't open device");while(1)WriteSPI(0x5555,0x55);ReadSPI(0x5555);close(fd);return ret; }

總結

以上是生活随笔為你收集整理的二十一、SPI设备驱动及应用(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。