.. _spi-index: SPI ================== 总览 ---------------- 本示例主要介绍spi的使用方法。 准备及使用步骤 ---------------- - 使用步骤: - 插入将板子的USB电源线; - 编译 ``customer_app/periperal/demo_spi`` 工程并下载工程; - 打开一个串口终端窗口(波特率为2000000,用于接收和发送uart消息)。 - 可以用一个开发板环回发送接收,demo中miso和mosi分别为pin0,pin1,将pin0和pin1连接起来,代表自己发给自己 - 串口终端输入 ``demo_hosal_spi_dma_master`` ,会打印发送和接收的数据,可以看到发送和接收一一对应。 .. figure:: imgs/image1.png :alt: - 也可以用两个开发板,一个作主机一个作从机,都下载该工程,在从机串口中输入 ``demo_hosal_spi_dma_slave`` 或 ``demo_hosal_spi_slave`` 启动从机,在主机串口中输入 ``demo_hosal_spi_dma_master`` 或 ``demo_hosal_spi_master`` 启动主机,注意从机需要先启动才能正确接收数据。 .. figure:: imgs/image2.png :alt: 应用实例 ---------------- - 示例代码 :: /* 主机端(dma模式和中断模式仅仅是dma_enable设置不同) */ #include #include #include #include /* 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 #include #include #include /* 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_send`` ,``hosal_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);