SPI

总览

本示例主要介绍spi的使用方法。

准备及使用步骤

  • 使用步骤:
  • 插入将板子的USB电源线;
  • 编译 customer_app/periperal/demo_spi 工程并下载工程;
  • 打开一个串口终端窗口(波特率为2000000,用于接收和发送uart消息)。
  • 可以用一个开发板环回发送接收,demo中miso和mosi分别为pin0,pin1,将pin0和pin1连接起来,代表自己发给自己
  • 串口终端输入 demo_hosal_spi_dma_master ,会打印发送和接收的数据,可以看到发送和接收一一对应。
  • 也可以用两个开发板,一个作主机一个作从机,都下载该工程,在从机串口中输入 demo_hosal_spi_dma_slavedemo_hosal_spi_slave 启动从机,在主机串口中输入 demo_hosal_spi_dma_masterdemo_hosal_spi_master 启动主机,注意从机需要先启动才能正确接收数据。

应用实例

  • 示例代码
/* 主机端(dma模式和中断模式仅仅是dma_enable设置不同) */
#include <stdio.h>
#include <cli.h>
#include <hosal_spi.h>
#include <blog.h>
/* About Pin:
 * if pin % 4 is 0 ===> this pin can be used as spi miso function
 * if pin % 4 is 1 ===> this pin can be used as spi mosi function
 * if pin % 4 is 2 ===> this pin can be used as spi cs   function
 * if pin % 4 is 3 ===> this pin can be used as spi sclk function
 * such as: GLB_GPIO_PIN_0 ===> miso
 *          GLB_GPIO_PIN_1 ===> mosi
 *          GLB_GPIO_PIN_2 ===> cs
 *          GLB_GPIO_PIN_3 ===> sclk
 * about cs pin: for master device, user can use hardware cs pin like pin2,and can also use software to select any pin for cs , for slave device ,user can only use hardwrae cs
 * about mosi and miso pin: mosi can be used as miso when miso can be uesd as mosi
 */
 uint8_t send_data[6];
 uint8_t recv_data[6];
/* spi callback */
void spi_master_cb(void *arg)
{
    for (int i = 0; i < sizeof(send_data)/sizeof(send_data[0]); i++) {
        blog_info("master send is %d\r\n",send_data[i]);
        blog_info("master recv is %d\r\n",recv_data[i]);
    }
    blog_info("master complete\r\n");
}

void demo_hosal_spi_dma_master(void)
{

    hosal_spi_dev_t spi;
    /* spi port set */
    spi.port = 0;
    /* spi master mode */
    spi.config.mode  = HOSAL_SPI_MODE_MASTER;

    /* 1: enable dma, 0: disable dma */
    spi.config.dma_enable = 1;

     /* 0: phase 0, polarity low
      * 1: phase 1, polarity low
      * 2: phase 0, polarity high
      * 3: phase 0, polarity high
      */
    spi.config.polar_phase= 0;
    /* 0 ~ 40M */
    spi.config.freq= 100000;
    spi.config.pin_clk = 3;
    /* hardware cs now is pin 2 */
    spi.config.pin_mosi= 1;
    spi.config.pin_miso= 0;
    /* init spi device */
    hosal_spi_init(&spi);

    /* register dma irq callback */
    hosal_spi_irq_callback_set(&spi, spi_master_cb, (void*)&spi);
    memset(recv_data, 0, 6);

    /* prepara send buf */
    for (int i = 0; i < sizeof(send_data)/sizeof(send_data[0]); i++) {
      send_data[i] = i + 2;
    }
    /* software set pin4 as cs pin and set cs low to select slave */
    hosal_spi_set_cs(4, 0);
    /*send and recv data, timeout is 10s */
    hosal_spi_send_recv(&spi, (uint8_t *)send_data, (uint8_t *)recv_data, 6, 10000);
    /* set cs high, release slave */
    hosal_spi_set_cs(4, 1);
    hosal_spi_finalize(&spi);
}
/* 从机端(dma模式和中断模式仅仅是dma_enable设置不同) */
#include <stdio.h>
#include <cli.h>
#include <hosal_spi.h>
#include <blog.h>
/* About Pin:
 * if pin % 4 is 0 ===> this pin can be used as spi miso function
 * if pin % 4 is 1 ===> this pin can be used as spi mosi function
 * if pin % 4 is 2 ===> this pin can be used as spi cs   function
 * if pin % 4 is 3 ===> this pin can be used as spi sclk function
 * such as: GLB_GPIO_PIN_0 ===> miso
 *          GLB_GPIO_PIN_1 ===> mosi
 *          GLB_GPIO_PIN_2 ===> cs
 *          GLB_GPIO_PIN_3 ===> sclk
 * about cs pin: for master device, user can use hardware cs pin like pin2,and can also use software to select any pin for cs , for slave device ,user can only use hardwrae cs
 * about mosi and miso pin: mosi can be used as miso when miso can be uesd as mosi
 */
 uint8_t send_data[6];
 uint8_t recv_data[6];
/* spi dma callback */
void spi_slave_cb(void *arg)
{
    for (int i = 0; i < sizeof(send_data)/sizeof(send_data[0]); i++) {
        blog_info("slave send is %d\r\n",send_data[i]);
        blog_info("slave recv is %d\r\n",recv_data[i]);
    }
    blog_info("slave complete\r\n");
}

void demo_hosal_spi_dma_master(void)
{
    hosal_spi_dev_t spi;
    /* spi port set */
    spi.port = 0;
    /* spi master mode */
    spi.config.mode  = HOSAL_SPI_MODE_SLAVE;

    /* 1: enable dma, 0: disable dma */
    spi.config.dma_enable = 1;

     /* 0: phase 0, polarity low
      * 1: phase 1, polarity low
      * 2: phase 0, polarity high
      * 3: phase 0, polarity high
      */
    spi.config.polar_phase= 0;
    /* 0 ~ 40M */
    spi.config.freq= 100000;
    spi.config.pin_clk = 3;
    /* pin cs now must be pin 2 */
    spi.config.pin_mosi= 1;
    spi.config.pin_miso= 0;
    /* init spi device */
    hosal_spi_init(&spi);

    /* register dma irq callback */
    hosal_spi_irq_callback_set(&spi, spi_slave_cb, (void*)&spi);
    memset(recv_data, 0, 6);

    /* prepara send buf */
    for (int i = 0; i < sizeof(send_data)/sizeof(send_data[0]); i++) {
      send_data[i] = i + 2;
    }
    /* send data ,timeout is 10s */
    //hosal_spi_send(&spi, (uint8_t *)send_data, sizeof(send_data)/sizeof(send_data[0]),10000);
    /*send and recv data, timeout is 10s */
    hosal_spi_send_recv(&spi, (uint8_t *)send_data, (uint8_t *)recv_data, 6, 10000);

    hosal_spi_finalize(&spi);
}
  • 通过 hosal_spi_dev_t 定义一个spi设备,设置相关属性,调用 hosal_spi_init 初始化spi。
hosal_spi_dev_t spi;
spi.port = 0;
/* 设置成主机 */
spi.config.mode = HOSAL_SPI_MODE_MASTER;
/* 设置成从机 */
//spi.config.mode = HOSAL_SPI_MODE_SLAVE
/* 使能dma模式,当为0时使用中断方式传输 */
spi.config.dma_enable = 1;
/* 设置时钟极性和相位 */
/* 0: phase 0, polarity low
 * 1: phase 1, polarity low
 * 2: phase 0, polarity high
 * 3: phase 0, polarity high
 */
spi.config.polar_phase= 0;
/* 0 ~ 40M */
spi.config.freq= 100000;
spi.config.pin_clk = 3;
/* user do not need to set cs for slave */
spi.config.pin_mosi= 1;
spi.config.pin_miso= 0;
hosal_spi_init(&spi);
  • 通过 hosal_spi_irq_callback_set 设置传输完成回调函数。
hosal_spi_irq_callback_set(&spi, spi_dma_master_cb, (void*)&spi);
  • 通过 hosal_spi_set_cs 来设置主机的cs引脚
hosal_spi_set_cs(4, 0);
  • 通过 hosal_spi_send_recv 同时发送接收数据,同时也提供 hosal_spi_sendhosal_spi_recv 来只发或者只接收数据。
hosal_spi_send_recv(&spi, (uint8_t *)send_data, (uint8_t *)recv_data, 6, 10000);
  • 通过 hosal_spi_finalize 结束spi的使用
hosal_spi_finalize(&spi);