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

seo网站诊断方案济南百度代理

seo网站诊断方案,济南百度代理,海珠b2b网站建设公司,工商企业信息公示系统本文章相关专栏往期内容,SPI子系统专栏: SPI通信协议与Linux设备驱动框架解析SPI传输与驱动框架的实现spidev.c:SPI设备驱动的核心实现逻辑 PCI/PCIe子系统专栏: 专栏地址:PCI/PCIe子系统PCIe设备MSI/MSI-X中断源码分析…

本文章相关专栏往期内容,SPI子系统专栏:

  1. SPI通信协议与Linux设备驱动框架解析
  2. SPI传输与驱动框架的实现
  3. spidev.c:SPI设备驱动的核心实现逻辑

PCI/PCIe子系统专栏:

  1. 专栏地址:PCI/PCIe子系统
  2. PCIe设备MSI/MSI-X中断源码分析与驱动编写
    – 末片,有专栏内容观看顺序

Uart子系统专栏:

  1. 专栏地址:Uart子系统
  2. Linux内核早期打印机制与RS485通信技术
    – 末片,有专栏内容观看顺序

interrupt子系统专栏:

  1. 专栏地址:interrupt子系统
  2. Linux 链式与层级中断控制器讲解:原理与驱动开发
    – 末片,有专栏内容观看顺序

pinctrl和gpio子系统专栏:

  1. 专栏地址:pinctrl和gpio子系统

  2. 编写虚拟的GPIO控制器的驱动程序:和pinctrl的交互使用

    – 末片,有专栏内容观看顺序

input子系统专栏:

  1. 专栏地址:input子系统
  2. input角度:I2C触摸屏驱动分析和编写一个简单的I2C驱动程序
    – 末片,有专栏内容观看顺序

I2C子系统专栏:

  1. 专栏地址:IIC子系统
  2. 具体芯片的IIC控制器驱动程序分析:i2c-imx.c-CSDN博客
    – 末篇,有专栏内容观看顺序

总线和设备树专栏:

  1. 专栏地址:总线和设备树
  2. 设备树与 Linux 内核设备驱动模型的整合-CSDN博客
    – 末篇,有专栏内容观看顺序

img

目录

  • 1.spi_dac设备的应用程序
    • 1.2 测试示例
      • 1.2.1 使用方法
      • 1.2.2 代码讲解
    • 1.3 编写操作spi_dac设备的应用程序
      • 1.3.1 DAC介绍
      • 1.3.2 时序图
      • 1.3.3 DAC公式
      • 1.3.4 编写
      • 3.3.5 上机
  • 2.编写DAC的驱动程序
    • 2.1 编写设备树
    • 2.2 代码

1.spi_dac设备的应用程序

1.2 测试示例

内核提供的测试程序:tools\spi\spidev_fdx.c 📎spidev_fdx.c(应用程序)

1.2.1 使用方法

编译该程序并生成可执行文件 spidev_test,你可以使用以下命令来与 SPI 设备交互。

  1. 查看设备状态
./spidev_test /dev/spidev0.0
  1. 发送 SPI 消息
./spidev_test -m 16 /dev/spidev0.0
  1. 读取数据
./spidev_test -r 8 /dev/spidev0.0
  1. 启用详细模式
./spidev_test -v /dev/spidev0.0

1.2.2 代码讲解

(1)显示设备属性

static void dumpstat(const char *name, int fd)
{__u8	lsb, bits;__u32	mode, speed;if (ioctl(fd, SPI_IOC_RD_MODE32, &mode) < 0) {  //读取当前的 SPI 模式。perror("SPI rd_mode");return;}if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) { //读取传输是 LSB 先还是 MSB 先。perror("SPI rd_lsb_fist");return;}if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) {  //读取每字传输的位数。perror("SPI bits_per_word");return;}if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) { //读取最大传输速度。perror("SPI max_speed_hz");return;}printf("%s: spi mode 0x%x, %d bits %sper word, %d Hz max\n",name, mode, bits, lsb ? "(lsb first) " : "", speed);  //printf打印出设备的参数
}

通过 ioctl 调用,读取当前 SPI 设备的配置信息(模式、LSB/MSB 顺序、每字传输位数、最大速度等),并将其打印到控制台。

(2)读设备数据

static void do_read(int fd, int len)
{unsigned char	buf[32], *bp;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);//检查并确保读取的数据长度在 2 到 32 字节之间,并通过 read(fd, buf, len) 来从设备读取数据到 buf。if (status < 0) {perror("read");return;}if (status != len) {fprintf(stderr, "short read\n");return;}printf("read(%2d, %2d): %02x %02x,", len, status,buf[0], buf[1]);status -= 2;bp = buf + 2;while (status-- > 0)printf(" %02x", *bp++); // 将读取到的数据打印到控制台。printf("\n");
}

(3)发送消息

static void do_msg(int fd, int len)
{struct spi_ioc_transfer	xfer[2];unsigned char		buf[32], *bp;int			status;memset(xfer, 0, sizeof xfer);memset(buf, 0, sizeof buf);if (len > sizeof buf)len = sizeof buf;buf[0] = 0xaa;xfer[0].tx_buf = (unsigned long)buf;xfer[0].len = 1;xfer[1].rx_buf = (unsigned long) buf;xfer[1].len = len;status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);if (status < 0) {perror("SPI_IOC_MESSAGE");return;}printf("response(%2d, %2d): ", len, status);for (bp = buf; len; len--)printf(" %02x", *bp++);printf("\n");
}

它不是通过调用write函数,进而去调用spidev驱动中的spidev_write,而是通过Ioctl函数来实现,这是可以的,ioctl函数在之前就介绍过是可以用来执行一些复杂的数据传输操作。

(4)主函数

int main(int argc, char **argv)
{int		c;int		readcount = 0;int		msglen = 0;int		fd;const char	*name;while ((c = getopt(argc, argv, "hm:r:v")) != EOF) {switch (c) {case 'm':msglen = atoi(optarg);if (msglen < 0)goto usage;continue;case 'r':readcount = atoi(optarg);if (readcount < 0)goto usage;continue;case 'v':verbose++;continue;case 'h':case '?':
usage:fprintf(stderr,"usage: %s [-h] [-m N] [-r N] /dev/spidevB.D\n",argv[0]);return 1;}}if ((optind + 1) != argc)goto usage;name = argv[optind];fd = open(name, O_RDWR);if (fd < 0) {perror("open");return 1;}dumpstat(name, fd);if (msglen)do_msg(fd, msglen);if (readcount)do_read(fd, readcount);close(fd);return 0;
}
  • 解析命令行参数,支持的选项包括:

    • -m N:发送 N 字节的消息。
    • -r N:读取 N 字节的数据。
    • -v:启用详细模式。
    • -h-?:打印帮助信息。
  • 打开指定的 SPI 设备文件并调用 dumpstat 打印设备的状态。

  • 根据命令行参数调用 do_msg(发送消息)和 do_read(读取数据)函数进行 SPI 传输。

  • 最后关闭设备文件。

1.3 编写操作spi_dac设备的应用程序

使用的驱动程序是内核提供的spidev.

DAC芯片手册:📎TLC5615.pdfc

1.3.1 DAC介绍

DAC(Digital-to-Analog Converter,数字-模拟转换器)是一种将数字信号转换为模拟电压或电流输出的器件。DAC模块常用于音频输出、信号处理、自动控制系统等场合。

img

img

一个典型的 DAC 模块有以下常见的引脚:

  • DIN(Data In,数据输入)

    • 这是数据输入引脚,通过它传入要转换的数字信号。
    • 数据通常以串行方式传输,例如 SPI(Serial Peripheral Interface)通信协议。每次传输的数字信号代表希望生成的模拟输出。
  • SCLK(Serial Clock,串行时钟)

    • 时钟信号引脚,用于同步数据的传输。
    • 通过时钟的上升沿或下降沿(取决于 DAC 的工作模式)将数据从控制器(例如微控制器)发送到 DAC 的数据输入引脚 DIN。SCLK 控制数据传输的时序。
  • CS(Chip Select,片选)

    • 片选信号引脚,用于启用或禁用 DAC。
    • 当 CS 处于低电平时,DAC 会被选中并开始接收数据;当 CS 拉高时,数据传输结束,DAC 停止通信并执行相应的操作(如更新输出电压)。
  • DOUT(Data Out,数据输出)

    • 这是数据输出引脚,一些高级 DAC 模块带有此引脚,用于反馈通信或级联多个 DAC。
    • DOUT 通常用于从 DAC 向主设备返回状态信息,也可以将多个 DAC 模块级联,形成串行数据链。
    • 级联下(也就是多个DAC串行),传输的16bit数据
  • Vdd(电源输入)

    • 为 DAC 提供工作电压的引脚。
    • 典型的工作电压范围为 2.7V 到 5.5V 或 3.3V/5V,具体取决于 DAC 的型号。Vdd 为内部数字和模拟电路供电。
  • OUT(模拟输出)

    • DAC 的模拟电压输出引脚。
    • 根据输入的数字信号,这个引脚会输出相应的模拟信号,通常是电压信号(例如 0V-3.3V 或 0V-5V)。在某些情况下,DAC 可以直接输出电流信号。
    • 其中传入的是16bit,但是输出的10bit,高四位无效,第两位为0
  • REFIN(Reference Input,基准电压输入)

    • 基准电压输入引脚,用于提供 DAC 模块的基准电压。
    • 基准电压决定了 DAC 的输出范围。例如,如果参考电压为 2.5V,DAC 的输出范围可能会是 0V 到 2.5V。外部基准电压可以提高 DAC 的精度和稳定性。
  • AGND(Analog Ground,模拟地)

    • 模拟电路的地线。
    • 与 Vdd 共同提供 DAC 的电源参考电压,确保 DAC 输出的稳定性。AGND 通常用于模拟部分电路,以减少数字噪声的干扰。

需要特别注意的是OUTDOUT,因为这两个的差异,输入的16bit数据其高4位和低2位得都为0才能保证传输正确的数据。这个在时序图讲解的时候再提。

1.3.2 时序图

img

时序图,假设SCLK上升沿的时候读取电平 :

img

记住SPI其实就是彼此数据的置换:

  • img
  • img

CS有效(低电平)期间,DIN(MISO)数据会随着SCLK的每次时钟脉冲被移入从机的移位寄存器,从高位(MSB)开始依次传输到低位(LSB)。同时,DOUT(MOSI)也会将从机中保存的前一次数据从高位(MSB)开始依次移出,传输到主机的移位寄存器中。

在TLC5615的SPI通信中,**DOUT**的第一位对应上一帧(previous frame)的LSB。这是由TLC5615的工作原理和SPI协议的移位寄存器设计决定的。

  • CS信号拉低后,TLC5615进入通信状态,其移位寄存器不会被清零,而是保留上一帧的数据内容。
  • 在通信开始时,从机的移位寄存器会直接输出当前内容中的最高位(MSB)。
  • 但是,因为SPI通信是连续的,上一帧数据的LSB早已移位到移位寄存器的最高位(MSB位置)。
  • 假设上一帧完整的16位数据已经移位完成,寄存器中的最后一个位(LSB)自然会移到最高位(MSB)。
  • 当新的时钟信号(SCLK)到来时,从机移位寄存器的最高位(previous LSB)会最先通过DOUT传出。

SPI协议和TLC5615设计中,移位寄存器在时钟脉冲驱动下始终保持连续性,导致上一帧数据循环至当前帧的最高位。

我觉得主要是得看SPI选择的通信模式吧,像模式0,第一个上升沿就要移入数据,但是此时根本还没有数据,在此之前应该就进行了一次数据的移除。

1.3.3 DAC公式

数字信号怎么转换为模拟信号

img

OUT引脚输出电压:2 * V****refin ***** (n / 1024),其中n为输出的10bit的10进制值

1.3.4 编写

📎dac_test.c

编写设备树:

&ecspi1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_ecspi1>;fsl,spi-num-chipselects = <2>;cs-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>, <&gpio4 24 GPIO_ACTIVE_LOW>;status = "okay";dac: dac {compatible = "spidev";reg = <0>;spi-max-frequency = <20000000>;};
};

img

3.3.5 上机

编译应用程序:

arm-buildroot-linux-gnueabihf-gcc  -o  dac_test  dac_test.c

编译驱动:

img

2.编写DAC的驱动程序

使用之前讲到的编写SPI设备的驱动框架

2.1 编写设备树

&ecspi1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_ecspi1>;fsl,spi-num-chipselects = <2>;cs-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>, <&gpio4 24 GPIO_ACTIVE_LOW>;status = "okay";dac: dac {compatible = "spidev";reg = <0>;spi-max-frequency = <20000000>;};
};

img

img

2.2 代码

📎dac_test.c

📎dac_drv.c

如果spidev没有被编译进内核,那么先执行:

insmod dac_drv.ko

确定设备节点:

ls /dev/100ask_dac

假设设备节点为/dev/100ask_dac,执行测试程序:

./dac_test  /dev/100ask_dac  500
./dac_test  /dev/100ask_dac  600
./dac_test  /dev/100ask_dac  1000
http://www.dtcms.com/wzjs/58868.html

相关文章:

  • 成都学生做网站林哥seo
  • 怎么在电脑上自己做网站如何自己创建网址
  • 网站如何屏蔽ip段厦门百度快照优化排名
  • 横沥镇网站仿做月入百万的游戏代理
  • 深圳哪里有可以做网站跳转的公司seo工具
  • 浏览器代理怎么弄推广优化seo
  • 网站建设经费申请网页设计可以自学吗
  • 淄博市沂源县城乡建设局网站市场营销策划公司排名
  • 大型门户网站建设国外b站推广网站
  • wordpress 中文cms主题seo快速整站上排名教程
  • 谢岗镇网站仿做网站免费推广
  • 网站进入特效营销网站制作公司
  • 哪些网站是jsp做的小程序seo
  • 政府类型网站建设方案专业网站优化推广
  • 做网站深圳win10优化软件哪个好
  • 戒赌网站怎么做怎么做网址
  • 怎么学做电商使用最佳搜索引擎优化工具
  • 合肥大型网站设计郑州seo公司排名
  • seo建站外贸网络营销推广方案3篇
  • 风铃网站代做店铺在百度免费定位
  • 做地方网站德州seo优化
  • 建立网站的主要流程有哪些步骤中国培训网的证书含金量
  • 兴仁企业建站公司北京seo推广外包
  • destoon做众筹网站目前引流最好的平台
  • 昌乐做网站深圳百度开户
  • 有哪些做政府网站的相关公司江苏免费关键词排名外包
  • 百度推广服务费3000元seo优化价格
  • 临沂高端网站建设搜索引擎优化的五个方面
  • 做家常菜的网站网站怎么弄
  • 网站建设金牛万达购买友情链接网站