SPI外设是我们常用的外设功能之一,CSK6 SDK支持SPI外设功能,本章节通过示例介绍SPI外设的基本使用方法。
CSK6 芯片有两组SPI硬件外设,SPI0和SPI1。
CSK6 SPI驱动功能特性如下:
当CSK6 作为从模式时,单次最大能接收512字节数据,超过512字节数据时主发送端需要拆包发送。
读取spi设备的数据
int spi_read(const struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *rx_bufs
);
返回0表示成功,返回非0表示失败。
参数说明
字段 | 说明 |
---|---|
dev | 指向spi Device的指针 |
config | 指向spi的配置属性的指针 |
rx_bufs | 指向spi接收buf的结构指针 |
向spi设备写入数据
int spi_write(const struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs);
返回0表示成功,返回非0表示失败。
参数说明
字段 | 说明 |
---|---|
dev | 指向spi Device的指针 |
config | 指向spi的配置属性的指针 |
tx_bufs | 指向spi写入buf的结构指针 |
向spi设备写入/读取数据
int spi_transceive(const struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs);
这个函数可以实现同时读写功能,spi_write与spi_read都基于这个函数实现,spi_write在调用时候会将rx设置为空,而spi_read调用时会将tx设置为空。返回0表示成功,返回非0表示失败。
参数说明
字段 | 说明 |
---|---|
dev | 指向spi Device的指针 |
config | 指向spi的配置属性的指针 |
tx_bufs | 指向spi写入buf的结构指针 |
rx_bufs | 指向spi接收buf的结构指针 |
更多SPI API接口请查看zephyr官网SPI Interface。
SDK 中提供了 SPI Master 的示例。
使用芯片上的一组 SPI 引脚往外发送数据,可通过示波器或者逻辑分析仪去抓取 SPI 数据。
{SDK}\.sdk\csk\samples\driver\spi_master
适用开发板:大模型开发套件
编译版型:csk6_duomotai_devkit
使用引脚:
在 SDK 根目录(duomotai_ap
)下可通过执行以下指令进行对该示例工程的编译:
lisa zep build -b csk6_duomotai_devkit .sdk\csk\samples\driver\spi_master -p
编译完成后,编译产物二进制文件位于 build\zephyr\zephyr.bin
使用 Type-C 数据线连接开发套件的 DAP_USB
接口,选中以下其中一种方式对固件进行烧录:
cskburn desktop
是一款聆思推出的桌面烧录工具,在下载并安装 cskburn desktop 烧录工具后,双击图标运行软件:
1.点击串口下拉框,选择连接开发套件后识别到的串口编号;
2.将编译输出的.bin
文件拖拽进烧录区域;
3.点击开始烧录,等待烧录完成。
若您已按照 《环境搭建》 教程完成开发环境的安装,可在编译完成后执行 lisa zep exec cskburn
指令完成烧录。
lisa zep exec cskburn -s \\.\COMxx -C 6 -b 1500000 0x000000 --verify-all .\build\zephyr\zephyr.bin
请将命令行中的的 COMx 替换为开发套件在 PC 上对应的串口号(可通过设备管理器查看)。例如:
COM3
。
lisa zep exec cskburn -s PORT -C 6 0x000000 --verify-all ./build/zephyr/zephyr.bin -b 1500000
请将命令行中的 PORT 替换为开发套件连接在 PC 上对应的串口号。例如:
/dev/ttyUSB0
。
烧录完成后,连接串口终端,可看到串口有对应的信息输出。可通过示波器或者逻辑分析仪去抓取 SPI 数据。
以下代码与注释已省略一部分非关键接口代码,主要呈现示例的主业务流程与主要接口的使用。
在工程目录prj.conf
文件中需配置以下模块:
CONFIG_GPIO=y
CONFIG_SPI=y
CONFIG_HEAP_MEM_POOL_SIZE=10240
设备树文件csk6_duomotai_devkit.overlay
配置如下:
/*
* SPDX-License-Identifier: Apache-2.0
*/
&pinctrl {
/* SPIC alternate function */
pinctrl_spi0_cs_default: spi0_cs_default{
pinctrls = <SPI0_CS_N_GPIOA_12>;
};
pinctrl_spi0_miso_default: spi0_miso_default{
pinctrls = <SPI0_MISO_GPIOA_13>;
};
pinctrl_spi0_mosi_default: spi0_mosi_default{
pinctrls = <SPI0_MOSI_GPIOA_14>;
};
pinctrl_spi0_sclk_default: spi0_sclk_default{
pinctrls = <SPI0_CLK_GPIOA_11>;
};
};
1.从设备树获取SPI设备spi0的设备指针
spi = DEVICE_DT_GET(DT_NODELABEL(spi0));
2.配置SPI为主设备模式,设置数据位为8位,最低位优先,频率设置为10 MHz
3.分配内存以存储10个SPI缓冲区的数组
struct spi_buf *tx_package = k_calloc(tx_package_num, sizeof(struct spi_buf));
4.在无限循环中,周期性地发送数据并在每次发送后暂停1000毫秒
spi_write(spi, &spi_cfg, &tx_set);
按下开发板复位按钮,运行程序,观察示波器或逻辑分析仪抓取的数据。
…
int main(void)
{
…
// 从设备树获取 SP I设备 spi0 的设备指针
spi = DEVICE_DT_GET(DT_NODELABEL(spi0));
…
// 配置 SPI 为主设备模式,设置数据位为 8 位,最低位优先,频率设置为 10 MHz
struct spi_config spi_cfg = {0};
/* spi master 8bit, LSB first*/
spi_cfg.operation = SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_TRANSFER_LSB;
spi_cfg.frequency = 10 * 1000000UL;
…
// 分配内存以存储10个SPI缓冲区的数组
/* Make spi transaction package buffers */
const int tx_package_num = 10;
struct spi_buf *tx_package = k_calloc(tx_package_num, sizeof(struct spi_buf));
…
while (1) {
printk("spi master sending data ...\n");
// 发送数据
spi_write(spi, &spi_cfg, &tx_set);
k_msleep(1000);
}
}
SDK 中提供了 SPI Master Slave 的示例。
使用芯片上的一组SPI引脚往外发送数据,可以设置主模式或者从模式,可通过示波器或者逻辑分析仪去抓取SPI数据。
{SDK}\.sdk\csk\samples\driver\spi_master_slave
适用开发板:大模型开发套件
编译版型:csk6_duomotai_devkit
使用引脚:
2个csk6_duomotai_devkit
开发板
分别烧录主/从模式固件 (修改代码main.c
#define MASTER_MODE 0或1)
使用杜邦线将主从设备 SPI1_CS_N,SPI1_MISO,SPI1_MOSI,SPI1_CLK
连接,接线方式如下图所示:
在 SDK 根目录(duomotai_ap
)下可通过执行以下指令进行对该示例工程的编译:
lisa zep build -b csk6_duomotai_devkit .sdk\csk\samples\driver\spi_master_slave -p
编译完成后,编译产物二进制文件位于 build\zephyr\zephyr.bin
使用 Type-C 数据线连接开发套件的 DAP_USB
接口,选中以下其中一种方式对固件进行烧录:
cskburn desktop
是一款聆思推出的桌面烧录工具,在下载并安装 cskburn desktop 烧录工具后,双击图标运行软件:
1.点击串口下拉框,选择连接开发套件后识别到的串口编号;
2.将编译输出的.bin
文件拖拽进烧录区域;
3.点击开始烧录,等待烧录完成。
若您已按照 《环境搭建》 教程完成开发环境的安装,可在编译完成后执行 lisa zep exec cskburn
指令完成烧录。
lisa zep exec cskburn -s \\.\COMxx -C 6 -b 1500000 0x000000 --verify-all .\build\zephyr\zephyr.bin
请将命令行中的的 COMx 替换为开发套件在 PC 上对应的串口号(可通过设备管理器查看)。例如:
COM3
。
lisa zep exec cskburn -s PORT -C 6 0x000000 --verify-all ./build/zephyr/zephyr.bin -b 1500000
请将命令行中的 PORT 替换为开发套件连接在 PC 上对应的串口号。例如:
/dev/ttyUSB0
。
烧录完成后,连接串口终端,可看到串口有对应的信息输出。可通过示波器或者逻辑分析仪去抓取 SPI 数据。
主设备日志:
从设备日志:
以下代码与注释已省略一部分非关键接口代码,主要呈现示例的主业务流程与主要接口的使用。
在工程目录prj.conf
文件中需配置以下模块:
CONFIG_GPIO=y
CONFIG_SPI=y
CONFIG_LOG=y
CONFIG_HEAP_MEM_POOL_SIZE=10240
CONFIG_SPI_COMPLETION_TIMEOUT_TOLERANCE=10000
设备树文件csk6_duomotai_devkit.overlay
配置如下:
/*
* SPDX-License-Identifier: Apache-2.0
*/
&pinctrl {
/* SPIC alternate function */
pinctrl_spi0_cs_default: spi0_cs_default{
pinctrls = <SPI0_CS_N_GPIOB_08>;
};
pinctrl_spi0_miso_default: spi0_miso_default{
pinctrls = <SPI0_MISO_GPIOB_07>;
};
pinctrl_spi0_mosi_default: spi0_mosi_default{
pinctrls = <SPI0_MOSI_GPIOB_06>;
};
pinctrl_spi0_sclk_default: spi0_sclk_default{
pinctrls = <SPI0_CLK_GPIOB_09>;
};
pinctrl_spi1_sclk_default: spi1_sclk_default{
pinctrls = <SPI1_CLK_GPIOA_08>;
};
pinctrl_spi1_mosi_default: spi1_mosi_default{
pinctrls = <SPI1_MOSI_GPIOA_07>;
};
pinctrl_spi1_miso_default: spi1_miso_default{
pinctrls = <SPI1_MISO_GPIOA_10>;
};
pinctrl_spi1_cs_default: spi1_cs_default{
pinctrls = <SPI1_CS_N_GPIOA_09>;
};
};
&spi1 {
pinctrl-0 = <&pinctrl_spi1_sclk_default &pinctrl_spi1_mosi_default &pinctrl_spi1_miso_default &pinctrl_spi1_cs_default>;
pinctrl-names = "default";
status = "okay";
};
以下以主模式进行讲解
1.从设备树获取SPI设备spi1的设备指针
spi = DEVICE_DT_GET(DT_NODELABEL(spi1));
2. 配置SPI为主设备模式,设置数据位为8位,最低位优先,频率设置为10 MHz
spi_cfg.operation = SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB;
spi_cfg.frequency = 10 * 1000000UL;
3. 分配内存以存储接收缓冲区的数据
rx_buff = k_malloc(BUF_SIZE);
4. 在无限循环中,周期性地发送和接收数据,并在每次发送后暂停100毫秒
while (1) {
k_msleep(100);
memset(rx_buff, 0, BUF_SIZE);
spi_transceive(spi_master, &spi_cfg, &tx, &rx);
printk("[主设备]接收:");
for (uint8_t i = 0; i < BUF_SIZE; i++) {
printk("0x%02x ", rx_buff[i]);
}
printk("\n");
}
按下开发板复位按钮,运行程序,观察示波器或逻辑分析仪抓取的数据。
int main(void)
{
int ret = 0;
printk("SPI test start \n");
#if MASTER_MODE
ret = spi_master_init();
#else
ret = spi_slave_init();
#endif
if(ret != 0){
return -1;
}
//创建主线程/从线程
int pri = k_thread_priority_get(k_current_get());
#if MASTER_MODE
k_thread_create(&master_thread_data, master_stack_area,
K_THREAD_STACK_SIZEOF(master_stack_area), master_thread, NULL, NULL, NULL,
pri, 0, K_NO_WAIT);
#else
k_thread_create(&slave_thread_data, slave_stack_area,
K_THREAD_STACK_SIZEOF(slave_stack_area), slave_thread, NULL, NULL, NULL,
pri, 0, K_NO_WAIT);
#endif
printk("SPI thread created\n");
while (1) {
k_msleep(10);
}
return 0;
}