发布: 06_使用spidev操作SPI_DAC模块

This commit is contained in:
weidongshan
2022-03-10 12:11:38 +08:00
parent 20954891a3
commit 808b2e8303
34 changed files with 652 additions and 0 deletions

View File

@@ -0,0 +1,109 @@
# 使用spidev操作SPI_DAC模块 #
参考资料:
* 内核驱动:`drivers\spi\spidev.c`
* 内核提供的测试程序:`tools\spi\spidev_fdx.c`
* 内核文档:`Documentation\spi\spidev`
* DAC芯片手册`TLC5615.pdf`
## 1. 硬件
### 1.1 原理图
IMX6ULL:
![image-20220309150927785](pic/33_imx6ull_dac.png)
STM32MP157:
![image-20220309151025637](pic/34_stm32mp157_dac.png)
原理图:
![image-20220309151636533](pic/35_dac_sch.png)
### 1.2 连接
#### 1.2.1 IMX6ULL
DAC模块接到IMX6ULL扩展板的SPI_A插座上
![image-20220309164031109](pic/40_dac_on_imx6ull.png)
#### 1.2.2 STM32MP157
## 2. DAC操作原理
### 2.1 内部框图
![image-20220309155625021](pic/36_dac_block.png)
操作过程为:
* CS为低
* 在SCLK的上升沿从DIN采集16位数据存入上图中的`16-Bit Shift Register`
* 在CS的上升沿`16-Bit Shift Register`中的10位数据传入`10-Bit DAC Register`作为模拟量在OUT引脚输出
**注意**
* 传输的16位数据中高4位是无意义的
* 中间10位才被转换为模拟量
* 最低2位必须是0
### 2.2 时序图
![image-20220309160306094](pic/37_dac_timing_diagram.png)
使用SPI传输的细节
* SCLK初始电平为低
* 使用16个SCLK周期来传输16位数据
* 在SCLK上升沿读取DIN电平
* 在SCLK上升沿发出DOUT信号
* DOUT数据来自`16-Bit Shift Register`
* 第1个数据是上次数据遗留下的LSB位
* 其余15个数据来自`16-Bit Shift Register`的高15位
* `16-Bit Shift Register`的LSB在下一个周期的第1个时钟传输
* LSB必定是0所以当前的周期里读出`16-Bit Shift Register`的15位数据也足够了
### 2.3 DAC公式
![image-20220309162256125](pic/38_dac_value.png)
```shell
输出电压 = 2 * VREFIN * n / 1024 = 2 * 2.048 * n / 1024
其中: n为10位数值
```
## 3. 编写APP
源码在GIT仓库里这2个位置里的源码是一样的
![image-20220310120532411](pic/41_dac_app_use_spidev.png)
![image-20220310120646206](pic/42_dac_app_use_spidev.png)

View File

@@ -0,0 +1,144 @@
# 使用spidev操作SPI_DAC模块 #
参考资料:
* 内核驱动:`drivers\spi\spidev.c`
* 内核提供的测试程序:`tools\spi\spidev_fdx.c`
* 内核文档:`Documentation\spi\spidev`
* DAC芯片手册`TLC5615.pdf`
## 1. 硬件
### 1.1 原理图
IMX6ULL:
![image-20220309150927785](pic/33_imx6ull_dac.png)
STM32MP157:
![image-20220309151025637](pic/34_stm32mp157_dac.png)
原理图:
![image-20220309151636533](pic/35_dac_sch.png)
### 1.2 连接
#### 1.2.1 IMX6ULL
DAC模块接到IMX6ULL扩展板的SPI_A插座上
![image-20220309164031109](pic/40_dac_on_imx6ull.png)
#### 1.2.2 STM32MP157
## 2. DAC操作原理
### 2.1 内部框图
![image-20220309155625021](pic/36_dac_block.png)
操作过程为:
* CS为低
* 在SCLK的上升沿从DIN采集16位数据存入上图中的`16-Bit Shift Register`
* 在CS的上升沿`16-Bit Shift Register`中的10位数据传入`10-Bit DAC Register`作为模拟量在OUT引脚输出
**注意**
* 传输的16位数据中高4位是无意义的
* 中间10位才被转换为模拟量
* 最低2位必须是0
### 2.2 时序图
![image-20220309160306094](pic/37_dac_timing_diagram.png)
使用SPI传输的细节
* SCLK初始电平为低
* 使用16个SCLK周期来传输16位数据
* 在SCLK上升沿读取DIN电平
* 在SCLK上升沿发出DOUT信号
* DOUT数据来自`16-Bit Shift Register`
* 第1个数据是上次数据遗留下的LSB位
* 其余15个数据来自`16-Bit Shift Register`的高15位
* `16-Bit Shift Register`的LSB在下一个周期的第1个时钟传输
* LSB必定是0所以当前的周期里读出`16-Bit Shift Register`的15位数据也足够了
### 2.3 DAC公式
![image-20220309162256125](pic/38_dac_value.png)
```shell
输出电压 = 2 * VREFIN * n / 1024 = 2 * 2.048 * n / 1024
其中: n为10位数值
```
## 3. 编写设备树
确认SPI时钟最大频率
![image-20220309163435541](pic/39_dac_time_param.png)
```shell
T = 25 + 25 = 50ns
F = 20000000 = 20MHz
```
设备树如下:
```shell
dac: dac {
compatible = "spidev";
reg = <0>;
spi-max-frequency = <20000000>;
};
```
### 3.1 IMX6ULL
### 3.2 STM32MP157
## 3. 编写APP
源码在GIT仓库里这2个位置里的源码是一样的
![image-20220310120532411](pic/41_dac_app_use_spidev.png)
![image-20220310120646206](pic/42_dac_app_use_spidev.png)

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -0,0 +1,70 @@
/* 参考: tools\spi\spidev_fdx.c */
#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;
struct spi_ioc_transfer xfer[1];
int status;
unsigned char tx_buf[2];
unsigned char rx_buf[2];
if (argc != 3)
{
printf("Usage: %s /dev/spidevB.D <val>\n", argv[0]);
return 0;
}
fd = open(argv[1], O_RDWR);
if (fd < 0) {
printf("can not open %s\n", argv[1]);
return 1;
}
val = strtoul(argv[2], NULL, 0);
val <<= 2; /* bit0,bit1 = 0b00 */
val &= 0xFFC; /* 只保留10bit */
tx_buf[1] = val & 0xff;
tx_buf[0] = (val>>8) & 0xff;
memset(xfer, 0, sizeof xfer);
xfer[0].tx_buf = tx_buf;
xfer[0].rx_buf = rx_buf;
xfer[0].len = 2;
status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer);
if (status < 0) {
printf("SPI_IOC_MESSAGE\n");
return -1;
}
/* 打印 */
val = (rx_buf[0] << 8) | (rx_buf[1]);
val >>= 1;
printf("Pre val = %d\n", val);
return 0;
}

View File

@@ -510,6 +510,12 @@ git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git
05_spidev的使用(SPI用户态API)
```
* 2021.03.10 发布"SPI子系统"
```shell
06_使用spidev操作SPI_DAC模块
```
## 6. 联系方式

View File

@@ -0,0 +1,109 @@
# 使用spidev操作SPI_DAC模块 #
参考资料:
* 内核驱动:`drivers\spi\spidev.c`
* 内核提供的测试程序:`tools\spi\spidev_fdx.c`
* 内核文档:`Documentation\spi\spidev`
* DAC芯片手册`TLC5615.pdf`
## 1. 硬件
### 1.1 原理图
IMX6ULL:
![image-20220309150927785](pic/33_imx6ull_dac.png)
STM32MP157:
![image-20220309151025637](pic/34_stm32mp157_dac.png)
原理图:
![image-20220309151636533](pic/35_dac_sch.png)
### 1.2 连接
#### 1.2.1 IMX6ULL
DAC模块接到IMX6ULL扩展板的SPI_A插座上
![image-20220309164031109](pic/40_dac_on_imx6ull.png)
#### 1.2.2 STM32MP157
## 2. DAC操作原理
### 2.1 内部框图
![image-20220309155625021](pic/36_dac_block.png)
操作过程为:
* CS为低
* 在SCLK的上升沿从DIN采集16位数据存入上图中的`16-Bit Shift Register`
* 在CS的上升沿`16-Bit Shift Register`中的10位数据传入`10-Bit DAC Register`作为模拟量在OUT引脚输出
**注意**
* 传输的16位数据中高4位是无意义的
* 中间10位才被转换为模拟量
* 最低2位必须是0
### 2.2 时序图
![image-20220309160306094](pic/37_dac_timing_diagram.png)
使用SPI传输的细节
* SCLK初始电平为低
* 使用16个SCLK周期来传输16位数据
* 在SCLK上升沿读取DIN电平
* 在SCLK上升沿发出DOUT信号
* DOUT数据来自`16-Bit Shift Register`
* 第1个数据是上次数据遗留下的LSB位
* 其余15个数据来自`16-Bit Shift Register`的高15位
* `16-Bit Shift Register`的LSB在下一个周期的第1个时钟传输
* LSB必定是0所以当前的周期里读出`16-Bit Shift Register`的15位数据也足够了
### 2.3 DAC公式
![image-20220309162256125](pic/38_dac_value.png)
```shell
输出电压 = 2 * VREFIN * n / 1024 = 2 * 2.048 * n / 1024
其中: n为10位数值
```
## 3. 编写APP
源码在GIT仓库里这2个位置里的源码是一样的
![image-20220310120532411](pic/41_dac_app_use_spidev.png)
![image-20220310120646206](pic/42_dac_app_use_spidev.png)

View File

@@ -0,0 +1,144 @@
# 使用spidev操作SPI_DAC模块 #
参考资料:
* 内核驱动:`drivers\spi\spidev.c`
* 内核提供的测试程序:`tools\spi\spidev_fdx.c`
* 内核文档:`Documentation\spi\spidev`
* DAC芯片手册`TLC5615.pdf`
## 1. 硬件
### 1.1 原理图
IMX6ULL:
![image-20220309150927785](pic/33_imx6ull_dac.png)
STM32MP157:
![image-20220309151025637](pic/34_stm32mp157_dac.png)
原理图:
![image-20220309151636533](pic/35_dac_sch.png)
### 1.2 连接
#### 1.2.1 IMX6ULL
DAC模块接到IMX6ULL扩展板的SPI_A插座上
![image-20220309164031109](pic/40_dac_on_imx6ull.png)
#### 1.2.2 STM32MP157
## 2. DAC操作原理
### 2.1 内部框图
![image-20220309155625021](pic/36_dac_block.png)
操作过程为:
* CS为低
* 在SCLK的上升沿从DIN采集16位数据存入上图中的`16-Bit Shift Register`
* 在CS的上升沿`16-Bit Shift Register`中的10位数据传入`10-Bit DAC Register`作为模拟量在OUT引脚输出
**注意**
* 传输的16位数据中高4位是无意义的
* 中间10位才被转换为模拟量
* 最低2位必须是0
### 2.2 时序图
![image-20220309160306094](pic/37_dac_timing_diagram.png)
使用SPI传输的细节
* SCLK初始电平为低
* 使用16个SCLK周期来传输16位数据
* 在SCLK上升沿读取DIN电平
* 在SCLK上升沿发出DOUT信号
* DOUT数据来自`16-Bit Shift Register`
* 第1个数据是上次数据遗留下的LSB位
* 其余15个数据来自`16-Bit Shift Register`的高15位
* `16-Bit Shift Register`的LSB在下一个周期的第1个时钟传输
* LSB必定是0所以当前的周期里读出`16-Bit Shift Register`的15位数据也足够了
### 2.3 DAC公式
![image-20220309162256125](pic/38_dac_value.png)
```shell
输出电压 = 2 * VREFIN * n / 1024 = 2 * 2.048 * n / 1024
其中: n为10位数值
```
## 3. 编写设备树
确认SPI时钟最大频率
![image-20220309163435541](pic/39_dac_time_param.png)
```shell
T = 25 + 25 = 50ns
F = 20000000 = 20MHz
```
设备树如下:
```shell
dac: dac {
compatible = "spidev";
reg = <0>;
spi-max-frequency = <20000000>;
};
```
### 3.1 IMX6ULL
### 3.2 STM32MP157
## 3. 编写APP
源码在GIT仓库里这2个位置里的源码是一样的
![image-20220310120532411](pic/41_dac_app_use_spidev.png)
![image-20220310120646206](pic/42_dac_app_use_spidev.png)

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -0,0 +1,70 @@
/* 参考: tools\spi\spidev_fdx.c */
#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;
struct spi_ioc_transfer xfer[1];
int status;
unsigned char tx_buf[2];
unsigned char rx_buf[2];
if (argc != 3)
{
printf("Usage: %s /dev/spidevB.D <val>\n", argv[0]);
return 0;
}
fd = open(argv[1], O_RDWR);
if (fd < 0) {
printf("can not open %s\n", argv[1]);
return 1;
}
val = strtoul(argv[2], NULL, 0);
val <<= 2; /* bit0,bit1 = 0b00 */
val &= 0xFFC; /* 只保留10bit */
tx_buf[1] = val & 0xff;
tx_buf[0] = (val>>8) & 0xff;
memset(xfer, 0, sizeof xfer);
xfer[0].tx_buf = tx_buf;
xfer[0].rx_buf = rx_buf;
xfer[0].len = 2;
status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer);
if (status < 0) {
printf("SPI_IOC_MESSAGE\n");
return -1;
}
/* 打印 */
val = (rx_buf[0] << 8) | (rx_buf[1]);
val >>= 1;
printf("Pre val = %d\n", val);
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB