当前位置: 首页 > news >正文

好看的手机网站模板免费下载海南最新情况最新消息今天

好看的手机网站模板免费下载,海南最新情况最新消息今天,河南省新闻联播视频,价格营销策略案例SPI驱动SPI全称更是serial Peripheral interface的缩写,由美国摩托罗拉公司推出的一种同步串行传输规范。1、特点(1)SPI是一种高速,全双工,同步串行总线。(2)SPI由主从两种模式,通常…

SPI驱动

SPI全称更是serial Peripheral interface的缩写,由美国摩托罗拉公司推出的一种同步串行传输规范。

1、特点

(1)SPI是一种高速,全双工,同步串行总线。

(2)SPI由主从两种模式,通常由一个主设备或者多个从设备组从。SPI不支持多主控i,

(3)SPI通信至少需要四根线,分别是MISO(主设备数据输入,从设备输出),MOSI(主设备数据输出从设备输入),SCLK(时钟信号),CS/SS(片选信号)

2、硬件连接

3、SPI通信原理

SPI主设备和从设备都有一个串行移位寄存器,主设备通过向SPI串行寄存器写入一个字节来发起一次数据传输。

举例:(可设置,默认先传输高位)

4、通信过程

5、SPI极性和相位

6、SPI子系统框架

绝大多数情况下,你只需要使用SPI核心层提供的API函数来编写你的具体外设驱动,而SPI控制器设备驱动层(你所说的“芯片原厂实现的部分”)通常已经由芯片厂商或主线Linux内核提供了。

当然,设备驱动层也可以学习一下怎么写的

6.1 spi外设代码框架编写:device部分

在没有设备树之前,是要用c代码的方式实现device部分的,非常麻烦,有设备树之后直接写就行:

6.2 spi外设代码框架编写:driver部分

#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
​
int mcp2515_probe(struct spi_device *spi)
{printk("This is mcp2515_probe\n");​return 0;
​
}
​
int mcp2515_remove(struct spi_device *spi)
{printk("This is mcp2515_remove\n");​return 0;
​
}
​
const struct of_device_id mcp2515_of_match_table[] = {{.compatible = "my-mcp2515"),{}
};
​
const struct spi_device_id mcp2515_id_table[] = {{"mcp2515"),{}
};
​
struct spi_driver spi_mcp2515 = {.probe = mcp2515_probe,.remove = mcp2515_remove,.driver = {.name = "mcp2515",.owner = THIS_MODULE,.of_match_table = mcp2515_of_match_table,},.id_table = mcp2515_id_table
};
​
static int __init mcp2515_init(void)
{int ret;ret = spi_register_driver(&spi_mcp2515);if (ret < 0) {printk("spi_register_driver error\n");return ret;}return ret;
}
​
static int __exit mcp2515_exit(void)
{int ret;ret = spi_unregister_driver(&spi_mcp2515);if (ret < 0) {printk("spi_unregister_driver error\n");return ret;}return ret;
}
​
module_init(mcp2515_init);
module_exit(mcp2515_exit);
MODULE_LICENSE("GPL");

下面我们通过追踪一下代码来看一下为什么没有进probe函数:

1、当spi的设备和驱动匹配成功会执行下面这个prboe函数

2、在这个prboe函数中,这段会注册一个spi控制器。

3、在spi_register_controller函数中调用了下面这个,会对设备树的属性进行提取

4、在of_register_spi_device函数中,看到下面函数:

5、在of_spi_parse_dt函数中,可以看到如果子节点一些属性没写,就会报错返回,所以就进不了probe函数了:

6、总结

编译后没有进probe函数,是因为dts没有添加相应属性,return掉了

所以dts应该配置如下:

7、实验硬件:mcp2515介绍

先了解一下mcp2515。

8、mcp2515驱动编写:注册字符设备

前面已经可以匹配进probe函数了,接下面就是完善驱动程序,可以在驱动程序注册一个字符设备,创建相应的设备节点

#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
​
dev_t dev_num;
struct cdev mcp2515_cdev;
struct class *mcp2515_class;
struct device *mcp2515_device;
​
int mcp2515_open(strct inode, struct file *file)
{return 0;
}
​
ssize_t mcp2515_read(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{return 0;
}
​
ssize_t mcp2515_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{return 0;
}
​
ssize_t mcp2515_relese(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{return 0;
}
​
struct file_operations mcp2515_fops = {.open = mcp2515_open,.read = mcp2515_read,.write = mcp2515_write,.relese = mcp2515_relese,
};
​
int mcp2515_probe(struct spi_device *spi)
{int ret;printk("This is mcp2515_probe\n");ret = alloc_chrdev_region(&dev_num, 0, 1, "mcp2515");if (ret < 0) {printk("alloc_chrdev_region\n");return -1;}cdev_init(&mcp2515_cdev, &mcp2515_fops);mcp2515_cdev.owner = THIS_MODULE;ret = cdev_add(&mcp2515_cdev, dev_num, 1);if (ret < 0) {printk("cdev_add error\n");return -1;}mcp2515_class = class_create(THIS_MODULE, "spi_to_can");if (IS_ERR(mcp2515_class)) {printk("class_create error\n");return PTR_ERR(mcp2515_class);}mcp2515_device = device_create(mcp2515_class, NULL, dev_num, NULL, "mcp2515");if (IS_ERR(mcp2515_device)) {printk("device_create error\n");return PTR_ERR(mcp2515_device);}return 0;
}
​
int mcp2515_remove(struct spi_device *spi)
{printk("This is mcp2515_remove\n");return 0;
}
​
const struct of_device_id mcp2515_of_match_table[] = {{.compatible = "my-mcp2515"),{}
};
​
const struct spi_device_id mcp2515_id_table[] = {{"mcp2515"),{}
};
​
struct spi_driver spi_mcp2515 = {.probe = mcp2515_probe,.remove = mcp2515_remove,.driver = {.name = "mcp2515",.owner = THIS_MODULE,.of_match_table = mcp2515_of_match_table,},.id_table = mcp2515_id_table
};
​
static int __init mcp2515_init(void)
{int ret;ret = spi_register_driver(&spi_mcp2515);if (ret < 0) {printk("spi_register_driver error\n");return ret;}return ret;
}
​
static void __exit mcp2515_exit(void)
{device_destory(mcp2515_class, dev_num);class_destory(mcp2515_class);cdev_del(&mcp2515_dev);unregister_chrdev_region(dev_num, 1);spi_unregister_driver(&spi_mcp2515);
​
}
​
module_init(mcp2515_init);
module_exit(mcp2515_exit);
MODULE_LICENSE("GPL");

​
​

9、mcp2515驱动编写:复位函数

下面继续对上面的驱动进行完善:

9.1 配置dts:

上图红线内就是配置spi的模式,如果两个都没有注释,就是1 1,否则注释了就是0 0

上图红框内如果没有注释则代表spi从低位开始传输,注释了则代表从高位开始传输。

上图红框内如果没有注释则代表spi的cs片选脚是高电平选中,注释了则代表spi的cs片选脚是低电平选中。

最终配置:

2、添加复位函数

10、探究:SPI的通信流程

11、mcp2515驱动编写:读寄存器函数

#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
​
dev_t dev_num;
struct cdev mcp2515_cdev;
struct class *mcp2515_class;
struct device *mcp2515_device;
​
struct spi_device *spi_dev;
​
int mcp2515_open(strct inode, struct file *file)
{return 0;
}
​
ssize_t mcp2515_read(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{return 0;
}
​
ssize_t mcp2515_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{return 0;
}
​
ssize_t mcp2515_relese(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{return 0;
}
​
struct file_operations mcp2515_fops = {.open = mcp2515_open,.read = mcp2515_read,.write = mcp2515_write,.relese = mcp2515_relese,
};
​
void mcp2515_reset(void)
{int ret;char write_buf[] = {0xc0};ret = spi_write(spi_dev, write_buf, sizeof(write_buf));if (ret < 0) {printk("spi_write is error\n");}
}
​
void mcp2515_read_reg(char reg) {char write_buf[] = {0x03, reg};char read_buf;int ret;ret = spi_write_then_read(spi_dev, write_buf, sizeof(write_buf), &read_buf, sizeof(read_buf));if (ret < 0) {printk("spi_write_then_read error\n");return ret;}return read_buf;
}
​
int mcp2515_probe(struct spi_device *spi)
{int ret;char value;printk("This is mcp2515_probe\n");spi_dev = spi;ret = alloc_chrdev_region(&dev_num, 0, 1, "mcp2515");if (ret < 0) {printk("alloc_chrdev_region\n");return -1;}cdev_init(&mcp2515_cdev, &mcp2515_fops);mcp2515_cdev.owner = THIS_MODULE;ret = cdev_add(&mcp2515_cdev, dev_num, 1);if (ret < 0) {printk("cdev_add error\n");return -1;}mcp2515_class = class_create(THIS_MODULE, "spi_to_can");if (IS_ERR(mcp2515_class)) {printk("class_create error\n");return PTR_ERR(mcp2515_class);}mcp2515_device = device_create(mcp2515_class, NULL, dev_num, NULL, "mcp2515");if (IS_ERR(mcp2515_device)) {printk("device_create error\n");return PTR_ERR(mcp2515_device);}mcp2515_reset();value = mcp2515_read_reg(0x0e);printk("value is %x\n", vlaue);return 0;
}
​
int mcp2515_remove(struct spi_device *spi)
{printk("This is mcp2515_remove\n");return 0;
}
​
const struct of_device_id mcp2515_of_match_table[] = {{.compatible = "my-mcp2515"),{}
};
​
const struct spi_device_id mcp2515_id_table[] = {{"mcp2515"),{}
};
​
struct spi_driver spi_mcp2515 = {.probe = mcp2515_probe,.remove = mcp2515_remove,.driver = {.name = "mcp2515",.owner = THIS_MODULE,.of_match_table = mcp2515_of_match_table,},.id_table = mcp2515_id_table
};
​
static int __init mcp2515_init(void)
{int ret;ret = spi_register_driver(&spi_mcp2515);if (ret < 0) {printk("spi_register_driver error\n");return ret;}return ret;
}
​
static void __exit mcp2515_exit(void)
{device_destory(mcp2515_class, dev_num);class_destory(mcp2515_class);cdev_del(&mcp2515_dev);unregister_chrdev_region(dev_num, 1);spi_unregister_driver(&spi_mcp2515);
​
}
​
module_init(mcp2515_init);
module_exit(mcp2515_exit);
MODULE_LICENSE("GPL");
0x80就是处于配置模式。

12、配置cnf1 cnf2 cnf3等寄存器

12.1 分析

12.2 驱动代码

13、配置RXB0CTRL CANINTE寄存器(使用位修改指令和屏蔽字节)

14、mcp2515驱动编写:修改工作模式

让其进入回环模式。

0x40就是进入回环模式:

15、mcp2515驱动编写:编写write函数

16、mcp2515驱动编写:编写read函数

17、编写测试APP

18、Linux中通用SPI驱动以及spidev的使用

19、应用程序中如何使用SPI

参考18小节的工具spi_test源码修改,当然也要配置好相应的通用驱动:

20、如何在Linux中使用模拟SPI

21、实践:移植官方mcp2515驱动

http://www.dtcms.com/a/567377.html

相关文章:

  • 网站后台无法编辑文字seo推广沧州公司电话
  • 网站增长期怎么做做律师网站的网络公司
  • 网站建设单选按钮昭通市有做网站的吗
  • 建设施工合同网站电商平台网站有哪些
  • 手机网站适配代码free theme wordpress
  • 舟山网站建设推广广州网络建站
  • 浙江省建设工程监理管理协会网站app开发定制公司如何选择
  • 环保部网站官网建设项目限批办法特色的佛山网站建设
  • 安徽住房和建设厅网站西安企业注册
  • 主题资源网站创建时 如何突出设计的特点专业的广州微网站建设
  • 网站开发就业薪酬凡客 网站设计
  • 景安网络网站建设教程网站建设贰金手指下拉贰壹
  • 怎么知道网站有没有做301重定向在线销售型网站产品
  • 海宁网站开发优惠做网站
  • 目前做汽配的网站有哪些官方网站怎么制作
  • 镇江建设网站的公司十大免费行情软件推荐
  • 网站用什么语言编写加强政务公开与网站建设
  • 湖南有实力的关键词优化网络优化工程师吃香吗
  • 精品课程网站建设项目验收单西安网站建设小程序开发
  • 企业网站的页面布局南昌寻南昌网站设计
  • 找建站公司做网站注意事项wordpress微信启动
  • wordpress电影站模版html5网站开发需要框架吗
  • 怎么搭建视频网站应税服务网站开发开票
  • 外贸网站seo推广教程排版设计视频教程
  • 备案网站ip重庆网站建设套餐
  • 各级院建设网站的通知c语言新手入门代码
  • 做网站需要监事吗设计得好的网站推荐
  • 郑州做网站推广价格做网站的公司风险大不大
  • 《道德经》第四十六章
  • 网站自助搭建wordpress如何做一个导航页面