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

个人电影网站做APP违法吗网上注册公司需要什么材料和手续

个人电影网站做APP违法吗,网上注册公司需要什么材料和手续,网站图片怎么做白色背景,建设隔热网站一、SPI硬件框架和协议内容每个 SPI 主控接口通常包含三条信号线:时钟线(SCK)、主输出从输入线(MOSI/DO(Master Out Slave In))和主输入从输出线(MISO/DI),此外还有一个片选引脚&…

一、SPI硬件框架和协议内容

每个 SPI 主控接口通常包含三条信号线:时钟线(SCK)、主输出从输入线(MOSI/DO(Master Out Slave In))和主输入从输出线(MISO/DI),此外还有一个片选引脚(CS)。为了保证同一时刻仅能访问一个从设备,片选引脚在任意时间只能有一个被激活。

要和从设备进行通信,首先应该发出片选信号,在每个时钟周期传输一位数据。

其中,我们要注意两个问题:SCK的初始电平(CPOL极性)和在SCK的第1/2个边沿传输数据(CPHA相位)?下面是SPI的模式选择(无论哪种模式,我们都可以同时接收和发出数据):

CPOL = 0 的时候表示SCK时钟线平时是0;为1表示平时是1;

CPHA = 0 的时候表示在SCK第一个边沿传输数据,为1 表示在SCK第二个边沿传输数据。

二、SPI控制器

三、 SPI总线驱动模型

3.1 SPI总线设备树

3.2 注册流程

在Linux系统中,将SPI控制器抽象成一个spi_master结构体。

按照总线驱动模型的工作流程,首先由设备树中 SPI 总线节点的 compatible 属性与驱动程序中定义的 compatible 属性进行匹配,匹配成功后会调用驱动程序中的 probe 函数。在 probe 函数中,会创建并初始化一个 spi_master 结构体,同时解析其下挂的 SPI 设备在设备树中的配置信息。随后,通过 spi_bus_type 中的 match 机制,将 SPI 设备与相应的驱动(spi_dev_drv)进行匹配和绑定。

以RK3568为例,找到对应驱动程序为spi_rockchip.c,当设备树中的spi总线compatible属性和id_table匹配,会调用改函数的probe函数,RK系列将spi_master封装成spi_controller结构体,调用到devm_spi_register_controller()-->spi_register_controller()-->of_spi_register_master()
去注册结构体并且解析设备树得到相关节点的片选引脚。

of_spi_register_master代码

在spi_register_controller()中注册完驱动之后继续注册了spi_device,of_register_spi_devices()。

四、spidev的使用(SPI用户态API)

对于简单的spi设备,不需要去写spi相关的设备驱动文件。直接使用应用程序就可以通过spidev去操作设备了。

弊端:如果是我们的spi设备需要涉及到中断相关的信息就不能使用这个万能的驱动程序了。

4.1 spidev.c 驱动程序分析 /drivers/spi/spidev.c

spidev.c这个驱动程序比较好理解,架构和字符设备驱动一样,首先是在init函数中register_chrdev和class_create,接着不是device_create而是使用spi_register_driver,注册这个驱动程序,当内核中设备树某一个节点的compatible属性和驱动程序提供的compatible属性一样,就会调用到驱动程序的probe函数。

在probe函数中会去构造一个spidev_data结构体,分配设置这个结构体,找到主设备下的为空的次设备号分配个这个device,然后再去device_create创建节点。

添加完节点之后会将这个设备挂入spidev的设备节点下。

等到当有应用函数调用open设备节点的时候,会进入到该驱动程序的open函数,在open函数中,遍历spi_dev设备链表,通过次设备号,找到挂在这个链表中的spidev设备,并且将这个设备设置成file的私有成员变量,下次调用read/write的时候直接可以从file中取出该spi设备。

我们再来看一下read/write函数。写函数也和读函数是一样的。

在这个驱动中,我们单独调用write/read函数是无法进行同时读写操作的,我们必须要调用该驱动的ioctl函数。

实例的应用程序如下(同时读写的长度是一样的):

4.2 如果要使用这个驱动程序,必须要满足的条件

五、SPI应用实例

5.1 原理图

DAC芯片如图所示,移位寄存器中只有中间10位有效数据会将数据上传到DAC寄存器。

看一下时序图,在时钟引脚的上升沿移入一位一位的数据到移位寄存器,在片选引脚的上升沿把其中的10位数据放入DAC寄存器。

这里在应用编程要注意的一点是:当SCLK第一个上升沿的时候,DOUT输出的第一位是由上次16位数据的最低位(必定是0),而不是当前传输的最高位。在传输最后的时候DOUT的输出是16位中的前15位。

5.2 使用spidev.c驱动程序的应用程序编写

5.2.1 将spidev这个驱动程序编译进内核

5.2.2 dts配置,找到一个spi_master,在其中添加一个子节点

根据dac芯片手册,可以看到时钟引脚的低电平最低25ns,高电平25ns.

合起来就是50ns,可以得出f = 1 / 10 ^ -6。

5.2.3  编写应用程序

要做的事情是:写入16位数据同时读出16位数据。(只能使用ioctl) LSB 00 MSB0000

// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>#include <linux/types.h>
#include <linux/spi/spidev.h>/* ./dac_test /dev/spidevB.D val*/
int main(int argc, char **argv)
{   int fd;struct spi_ioc_transfer	xfer[1];unsigned char buf[2];unsigned int val;int	status;unsigned char rx_buf[2];unsigned char tx_buf[2];if(argc != 3){printf("Usage: %s [/dev/spidevB.D] [val]\n" , argv[0]);return -1;}fd = open(argv[1] , O_RDWR);if (fd < 0) {printf("can not open file\n");return -1;}val = strtoul(argv[2], NULL, 0);val <<= 2; /* bit0,bit1 = 0, 强制让最低两位变成 0 */val &= 0xffc; /* 只保留10bit *//* 先传输tx_buf[0] 后传输tx_buf[1] , 所以tx_buf[0]存入高字节数据 */tx_buf[1] = val & 0xff;tx_buf[0] = (val >> 8) & 0xff;memset(xfer, 0, sizeof xfer);xfer[0].rx_buf = rx_buf;xfer[0].tx_buf = tx_buf;xfer[0].len = 2; status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer);val = (rx_buf[0] << 8) | (rx_buf[1]);val >>= 2;printf("Pre val = %d\n", val);return 0;
}

这里由于SPI 总线 一次只能传 8 位(一个字节),但是 DAC 芯片需要传一个 10 位或更多位的数值。所以你必须把这个多位整数拆成 高字节低字节 两部分,分别通过 SPI 发出去。

那么在这段代码中为什么我们要val <<= 2呢?原因是: DAC 芯片的 SPI 协议格式 上。低两位必须是0;

tx_buf[1] = val & 0xff;
tx_buf[0] = (val >> 8) & 0xff;

这两行的代码主要是因为,SPI先传高字节,再传低字节,所以先传的tx_buf[0]应该是高字节的内容,tx_buf[1]则是低字节的内容。

应用程序代码关键在于,在ioctl之前,如何去构造传输函数,拿到rxbuf之后如何去解析数据。

六、编写spi设备驱动程序

6.1 理论

重点是:如何发起SPI传输,构造read\write\ioctl函数?

特性:对于SPI传输,只要发送n个byte就会收到n个byte。

如果不在乎某个输入或者输出,可以将其的buf置为NULL。

如果有想进行多次传输,需要用链表将多个transfer结构题连接在一起,这时候需要一个链表头spi_message。

所以说构造流程如下:分配设置一个spi_message,将spi_message结构体挂在该msg下,使用spidev_sync函数发起spi传输。

6.2 spi传输实例:

6.3 spi_dev驱动程序代码

#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/of.h>
#include <linux/of_device.h>
#include <linux/acpi.h>#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>#include <linux/uaccess.h>static int major;
static struct spi_device *dac;
static struct class * dac_class;
static long spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{int val;int err;unsigned char rx_buf[2];unsigned char tx_buf[2];static struct spi_message msg;static struct spi_transfer t[1];memset(&t, 0, sizeof(t));err = copy_from_user(&val, (const void __user *)arg, sizeof(int));val <<= 2; /* bit0,bit1 = 0 */val &= 0xffc; /* 只保留10bit *//* 先传输高8字节,再传输低8字节 */tx_buf[1] = val & 0xff;tx_buf[0] = (val >> 8) & 0xff;t[0].tx_buf = tx_buf;t[0].rx_buf = rx_buf;t[0].len = 2;spi_message_init(&msg);spi_message_add_tail(t, &msg);spi_sync(dac, &msg);val = (rx_buf[0] << 8) | (rx_buf[1]);val >>= 2;err = copy_to_user((void __user*)arg, &val, sizeof(int));return 0;
}static const struct file_operations dac_fops = {.owner =	THIS_MODULE,.unlocked_ioctl = spidev_ioctl,
};static const struct of_device_id spidev_dt_ids[] = {{ .compatible = "xupt,dac" },{},
};static int spidev_probe(struct spi_device *spi)
{/* 记录spi_device */dac = spi;/* 注册字符设备驱动 */major = register_chrdev(0, "my_dac_drv", &dac_fops);dac_class = class_create(THIS_MODULE, "my_dac_drv");device_create(dac_class, NULL, MKDEV(major, 0), NULL, "my_dac_drv"); /* /dev/my_dac_drv */return 0;
}static int spidev_remove(struct spi_device *spi)
{device_destroy(dac_class, MKDEV(major, 0));class_destroy(dac_class);unregister_chrdev(major, "my_dac_drv");return 0;
}static struct spi_driver dac_spi_driver = {.driver = {.name =		"dac_drv",.of_match_table = of_match_ptr(spidev_dt_ids),},.probe =	spidev_probe,.remove =	spidev_remove,
};/*-------------------------------------------------------------------------*/static int __init spidev_init(void)
{spi_register_driver(&dac_spi_driver);return 0;
}
module_init(spidev_init);static void __exit spidev_exit(void)
{spi_unregister_driver(&dac_spi_driver);
}
module_exit(spidev_exit);MODULE_LICENSE("GPL");

总的来说,spi_device设备驱动程序和i2c_device设备驱动程序很类似,内核的传输方式也类似

spi_devicei2c_device
设备原型struct spi_devicestruct i2c_client
控制器原型struct spi_masterstruct i2c_adapter
传输函数spi_sync()i2c_transfer()
传输结构体

struct spi_message

struct spi_transfer

struct i2c_message
注册总线驱动spi_register_driver()i2c_register_driver()

6.4 应用程序代码

在6.3 驱动程序中,我们已经将传输的字符转换加入到驱动程序中,用户空间的代码不需要考虑对传输的字符做变换,所以用户态程序就很简单了。

// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>#include <linux/types.h>
#include <linux/spi/spidev.h>/* ./dac_test /dev/spidevB.D val*/
int main(int argc, char **argv)
{   int fd;unsigned int val;int	status;if(argc != 3){printf("Usage: %s [/dev/spidevB.D] [val]\n" , argv[0]);return -1;}fd = open(argv[1] , O_RDWR);if (fd < 0) {printf("can not open file\n");return -1;}val = strtoul(argv[2], NULL, 0);status = ioctl(fd, SPI_IOC_MESSAGE(1), &val);printf("Pre val = %d\n", val);return 0;
}
http://www.dtcms.com/a/498425.html

相关文章:

  • 盐城做网站的价格wordpress 文章 函数
  • 重庆网站推广运营公司python基础教程第二版答案
  • 网站建设怎么好2021个人网站盈利模式
  • 新手建站详细步骤wordpress 内链设置
  • wordpress仿站标签wordpress安装包文件夹
  • 网站有利于seo的细节潍坊网站建设熊掌号
  • 腾讯云做视频网站做网站先建立模型
  • 如何防止网站被镜像一个人免费视频在线观看高清
  • 东莞单位网站建设网页设计样图
  • 湘潭做网站 z磐石网络网站建设公司前十名
  • 东莞企业网站哪家好服装定制合同范本
  • 深圳东门希尔顿欢朋酒店洛阳seo
  • 做贸易的都有什么网站推广宣传方式有哪些
  • 关于微网站策划ppt怎么做电子商务网站建设考试重点
  • 建筑网页设计广州seo招聘网
  • 做网站和微信小程序hishop多用户商城源码
  • wordpress文章目录树汕头seo托管
  • 顺企网属于什么网站移动互联网站开发与维护
  • 湖南建设监理协会网站如何查网站的百度快照
  • 重庆品牌营销型网站建设宁夏网站开发
  • 少儿图书销售网站开发背景建筑网站大全玻璃
  • 2015网站排名镇海区住房建设网站怎么查
  • 国家建设工程注册管理中心网站建设部网站电子政务
  • 杭州学校网站建设粤信签微信小程序是什么
  • 丰县住房与城乡建设部网站wordpress旧版本下载
  • 临沧网站建设c3sales石家庄网站建设浩森宇特
  • 潍坊外贸网站建设深圳外贸10强公司
  • 学校网站首页设计php中英文网站源码
  • 哔哩哔哩黄页网站长沙在线注册公司
  • 网站怎么做分站unix做网站常用的数据库