发布: 06_使用spidev操作SPI_DAC模块
109
IMX6ULL/doc_pic/11_SPI/06_使用spidev操作SPI_DAC模块.md
Normal 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:
|
||||
|
||||

|
||||
|
||||
STM32MP157:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
原理图:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 1.2 连接
|
||||
|
||||
#### 1.2.1 IMX6ULL
|
||||
|
||||
DAC模块接到IMX6ULL扩展板的SPI_A插座上:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
#### 1.2.2 STM32MP157
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 2. DAC操作原理
|
||||
|
||||
### 2.1 内部框图
|
||||
|
||||

|
||||
|
||||
操作过程为:
|
||||
|
||||
* 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 时序图
|
||||
|
||||

|
||||
|
||||
使用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公式
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
```shell
|
||||
输出电压 = 2 * VREFIN * n / 1024 = 2 * 2.048 * n / 1024
|
||||
其中: n为10位数值
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 3. 编写APP
|
||||
|
||||
源码在GIT仓库里,这2个位置里的源码是一样的:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
BIN
IMX6ULL/doc_pic/11_SPI/06_使用spidev操作SPI_DAC模块.tif
Normal file
144
IMX6ULL/doc_pic/11_SPI/07_DAC模块上机实验.md
Normal 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:
|
||||
|
||||

|
||||
|
||||
STM32MP157:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
原理图:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 1.2 连接
|
||||
|
||||
#### 1.2.1 IMX6ULL
|
||||
|
||||
DAC模块接到IMX6ULL扩展板的SPI_A插座上:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
#### 1.2.2 STM32MP157
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 2. DAC操作原理
|
||||
|
||||
### 2.1 内部框图
|
||||
|
||||

|
||||
|
||||
操作过程为:
|
||||
|
||||
* 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 时序图
|
||||
|
||||

|
||||
|
||||
使用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公式
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
```shell
|
||||
输出电压 = 2 * VREFIN * n / 1024 = 2 * 2.048 * n / 1024
|
||||
其中: n为10位数值
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 3. 编写设备树
|
||||
|
||||
确认SPI时钟最大频率:
|
||||
|
||||

|
||||
|
||||
```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个位置里的源码是一样的:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
BIN
IMX6ULL/doc_pic/11_SPI/TLC5615.pdf
Normal file
BIN
IMX6ULL/doc_pic/11_SPI/pic/33_imx6ull_dac.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
IMX6ULL/doc_pic/11_SPI/pic/34_stm32mp157_dac.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
IMX6ULL/doc_pic/11_SPI/pic/35_dac_sch.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
IMX6ULL/doc_pic/11_SPI/pic/36_dac_block.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
IMX6ULL/doc_pic/11_SPI/pic/37_dac_timing_diagram.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
IMX6ULL/doc_pic/11_SPI/pic/38_dac_value.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
IMX6ULL/doc_pic/11_SPI/pic/39_dac_time_param.png
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
IMX6ULL/doc_pic/11_SPI/pic/40_dac_on_imx6ull.png
Normal file
|
After Width: | Height: | Size: 602 KiB |
BIN
IMX6ULL/doc_pic/11_SPI/pic/41_dac_app_use_spidev.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
IMX6ULL/doc_pic/11_SPI/pic/42_dac_app_use_spidev.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
70
IMX6ULL/source/11_SPI/02_dac_use_spidev/dac_test.c
Normal 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;
|
||||
}
|
||||
|
||||
@@ -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. 联系方式
|
||||
|
||||
109
STM32MP157/doc_pic/11_SPI/06_使用spidev操作SPI_DAC模块.md
Normal 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:
|
||||
|
||||

|
||||
|
||||
STM32MP157:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
原理图:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 1.2 连接
|
||||
|
||||
#### 1.2.1 IMX6ULL
|
||||
|
||||
DAC模块接到IMX6ULL扩展板的SPI_A插座上:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
#### 1.2.2 STM32MP157
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 2. DAC操作原理
|
||||
|
||||
### 2.1 内部框图
|
||||
|
||||

|
||||
|
||||
操作过程为:
|
||||
|
||||
* 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 时序图
|
||||
|
||||

|
||||
|
||||
使用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公式
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
```shell
|
||||
输出电压 = 2 * VREFIN * n / 1024 = 2 * 2.048 * n / 1024
|
||||
其中: n为10位数值
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 3. 编写APP
|
||||
|
||||
源码在GIT仓库里,这2个位置里的源码是一样的:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
BIN
STM32MP157/doc_pic/11_SPI/06_使用spidev操作SPI_DAC模块.tif
Normal file
144
STM32MP157/doc_pic/11_SPI/07_DAC模块上机实验.md
Normal 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:
|
||||
|
||||

|
||||
|
||||
STM32MP157:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
原理图:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 1.2 连接
|
||||
|
||||
#### 1.2.1 IMX6ULL
|
||||
|
||||
DAC模块接到IMX6ULL扩展板的SPI_A插座上:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
#### 1.2.2 STM32MP157
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 2. DAC操作原理
|
||||
|
||||
### 2.1 内部框图
|
||||
|
||||

|
||||
|
||||
操作过程为:
|
||||
|
||||
* 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 时序图
|
||||
|
||||

|
||||
|
||||
使用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公式
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
```shell
|
||||
输出电压 = 2 * VREFIN * n / 1024 = 2 * 2.048 * n / 1024
|
||||
其中: n为10位数值
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 3. 编写设备树
|
||||
|
||||
确认SPI时钟最大频率:
|
||||
|
||||

|
||||
|
||||
```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个位置里的源码是一样的:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
BIN
STM32MP157/doc_pic/11_SPI/TLC5615.pdf
Normal file
BIN
STM32MP157/doc_pic/11_SPI/pic/33_imx6ull_dac.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
STM32MP157/doc_pic/11_SPI/pic/34_stm32mp157_dac.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
STM32MP157/doc_pic/11_SPI/pic/35_dac_sch.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
STM32MP157/doc_pic/11_SPI/pic/36_dac_block.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
STM32MP157/doc_pic/11_SPI/pic/37_dac_timing_diagram.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
STM32MP157/doc_pic/11_SPI/pic/38_dac_value.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
STM32MP157/doc_pic/11_SPI/pic/39_dac_time_param.png
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
STM32MP157/doc_pic/11_SPI/pic/40_dac_on_imx6ull.png
Normal file
|
After Width: | Height: | Size: 602 KiB |
BIN
STM32MP157/doc_pic/11_SPI/pic/41_dac_app_use_spidev.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
STM32MP157/doc_pic/11_SPI/pic/42_dac_app_use_spidev.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
70
STM32MP157/source/A7/11_SPI/02_dac_use_spidev/dac_test.c
Normal 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;
|
||||
}
|
||||
|
||||
BIN
STM32MP157/开发板配套资料/原理图/04_Extend_modules(外设模块)/dac/TLC5615.pdf
Normal file
BIN
STM32MP157/开发板配套资料/原理图/04_Extend_modules(外设模块)/dac/dac.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |