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_slave
或demo_hosal_spi_slave
启动从机,在主机串口中输入demo_hosal_spi_dma_master
或demo_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_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);