炬芯(Actions)BLE ATB110X SPI驱动程序

SPI 总线

SPI 总线是同步串行总线接口,速度可以超过 50M。常用来连接 NOR Flash、LCD 等 高速设备。SPI 可以全双工传输数据,同时进行数据的收发。 SPI 总线定义了 4 个逻辑信号:
(1)MOSI – SPI 总线主机输出/ 从机输入(Master Output/Slave Input)
(2)MISO – SPI 总线主机输入/ 从机输出(Master Input/Slave Output)
(3)SCLK – 时钟信号,由主设备产生
(4)CS – 从设备使能信号,由主设备 控制(Chip select)

SPI 总线支持多 slave 连接,通过片选来选择当前读写的 slave 设备.

 

SPI 的 mode:

CPOL 表示时钟极性, 即空闲状态时的电平,低电平(0)或高电平(1)CPOH 表示数 据采样的时钟沿,第一个沿(0)或第二个沿(1) 根据 SPI 的相位 (CPHA) 和极性 (CPOL),对应的 4 种组合构成了 SPI 的 4 种工作模 式:

 
SPI模式


SPI波形对应的波形





另外一个需要注意的是 SPI 每次读写的最小字长。一般有 8、16 和 32bit 几种配置。用 户要根据具体 slave 设备需求来选用。

 

SPI 控制器

ATB110X 带有 3 路独立的 SPI 总线控制器,SPI0 一般接 SPI NOR,用于存储程序。 SPI1 和 SPI2 是通用 SPI 接口,可用来接其它 SPI 接口的外设。
• 支持 master 和 slave 两种模式
• 支持 mode:0/1/2/3
• 只支持 4 线模式

 

驱动接口说明

下面介绍一下 SPI 的具体接口和参数说明
Public API for SPI drivers and applications.

 Defines

SPI_OP_MODE_MASTER
       SPI operational mode.
SPI_OP_MODE_SLAVE
SPI_OP_MODE_MASK
SPI_OP_MODE_GET(_operation_)
SPI_MODE_CPOL
        SPI Polarity & Phase Modes
        Clock Polarity: if set, clock idle state will be 1 and active state will be 0. If untouched, the inverse will be true which is the default.
SPI_MODE_CPHA
        Clock Phase: this dictates when is the data captured, and depends clock’s polarity. When SPI_MODE_CPOL is set and this bit as well, capture will occur on low to high transition and high to low if this bit is not set (default). This is fully reversed if CPOL is not set.
SPI_MODE_LOOP
       Whatever data is transmitted is looped-back to the receiving buffer of the controller. This is fully controller dependent as some may not support this, and can be used for testing purposes only.

SPI_MODE_MASK
SPI_MODE_GET(_mode_)
SPI_TRANSFER_MSB
      SPI Transfer modes (host controller dependent)
SPI_TRANSFER_LSB
SPI_WORD_SIZE_SHIFT
      SPI word size.
SPI_WORD_SIZE_MASK
SPI_WORD_SIZE_GET(_operation_)
SPI_WORD_SET(_word_size_)
SPI_LINES_SINGLE
      SPI MISO lines.
      Some controllers support dual or quad MISO lines connected to slaves. Default is single, which is the case most of the time.
SPI_LINES_DUAL
SPI_LINES_QUAD
SPI_LINES_MASK
SPI_HOLD_ON_CS
      Specific SPI devices control bits.
SPI_LOCK_ON
SPI_EEPROM_MODE


......

驱动使用示例
下面是一个通过 spi 接口来进行数据交互的示例。
IC 的两组 SPI 接口连接在一起, 一 组做 master, 一组做 slave,进行数据交互传输。

 #include 

static struct spi_config spi_master_conf = {
.frequency = 2000000,
.operation = (SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB |SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_MODE_CPOL | SPI_MODE_CPHA),
.vendor = 0,
.slave = 0,
.cs = NULL,
};
static struct spi_config spi_slave_conf = {
.frequency = 2000000,
.operation = (SPI_OP_MODE_SLAVE | SPI_TRANSFER_MSB | SPI_ WORD_SET(8) | SPI_LINES_SINGLE | SPI_MODE_CPOL | SPI_MODE_CPHA),
.vendor = 0,
.slave = 0,
.cs = NULL,
};

#define SPI_MASTER_NAME "spi1"
#define SPI_SLAVER_NAME "spi2"
#define STACK_SIZE 1024

static K_THREAD_STACK_DEFINE(spi_slave_stack, STACK_SIZE);
static struct k_thread spi_slave_thread;

static K_THREAD_STACK_DEFINE(spi_master_stack, STACK_SIZE);

 static struct k_thread spi_master_thread;

static int spi_slave_func(void)
{
struct device *spi_slave_dev;
u8_t buf[4] = {0x81, 0x82, 0x83, 0x84};
struct spi_buf spi_bufs = {buf, 4};

spi_slave_dev = device_get_binding(SPI_MASTER_NAME);
if (!spi_slave_dev)
{
printk("SPI master driver was not found!\n");
return;
}
spi_slave_conf.dev = spi_slave_dev;
printk("slave send:\n");
print_buffer(buf, 1, sizeof(buf), 16, 0);

if (spi_transceive(&spi_slave_conf, &spi_bufs, 1, &spi_bufs, 1) != 0)
{
printk("slave io error\n");
return -EIO;
}
printk("slave receive:\n");
print_buffer(buf, 1, sizeof(buf), 16, 0);
return 0;
}

static int spi_master_func(void)
{
struct device *spi_master_dev;
u8_t buf[4] = {1, 2, 3, 4};
struct spi_buf spi_bufs = {buf, 4};
spi_master_dev = device_get_binding(SPI_SLAVER_NAME);
if (!spi_master_dev)
{
printf("SPI master driver was not found!\n");
return;
}
spi_master_conf.dev = spi_master_dev;
printk("master send:\n");
print_buffer(buf, 1, sizeof(buf), 16, 0);
if (spi_transceive(&spi_master_conf, &spi_bufs, 1,&spi_bufs, 1) != 0)
{
printk("master io error\n");
return -EIO;
}
printk("master receive:\n");
print_buffer(buf, 1, sizeof(buf), 16, 0);
return 0;
}

int test_spi_slave(void)
{
printk("test spi master/slave\n");
k_thread_create(&spi_master_thread,
spi_master_stack,
STACK_SIZE,
(k_thread_entry_t) spi_master_func,
NULL, NULL, NULL, K_PRIO_PREEMPT(8), 0,0);
k_thread_create(&spi_slave_thread, spi_slave_stack,STACK_SIZE,
(k_thread_entry_t) spi_slave_func, NULL, NULL, NULL, K_PRIO_PREEMPT(7), 0, 0); }


 

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论