SPI
介绍
对于不同底层驱动的spi操作实现,统一封装成本文所述spi hal接口。 hal相关头文件位于目录:include/aos/hal hal相关实现位于具体的mcu目录下,如:platform/mcu/stm32f1xx/hal
API列表
函数名称 | 功能描述 |
---|---|
hal_spi_init | 初始化指定SPI端口 |
hal_spi_send | 从指定的SPI端口发送数据 |
hal_spi_recv | 从指定的SPI端口接收数据 |
hal_spi_send_recv | 从指定的SPI端口发送并接收数据 |
hal_spi_send_and_recv | 从指定的SPI端口发送后接收数据 |
hal_spi_send_and_send | 从指定的SPI端口发送后再次发送数据 |
hal_spi_finalize | 关闭指定SPI端口 |
API详情
相关宏定义
#define HAL_SPI_MODE_MASTER 1 /* spi communication is master mode */
#define HAL_SPI_MODE_SLAVE 2 /* spi communication is slave mode */
相关结数据结构
spi_dev_t
typedef struct {
uint8_t port; /* spi port */
spi_config_t config; /* spi config */
void *priv; /* priv data */
} spi_dev_t;
spi_config_t
/* Define spi config args */
typedef struct
{
spi_role_e role; /* spi communication mode */
spi_firstbit_e firstbit;
spi_work_mode_e mode;
spi_transfer_mode_e t_mode;
uint32_t freq; /* communication frequency Hz */
uint16_t serial_len; /* serial frame length, necessary for SPI running as Slave */
spi_data_size_e data_size;
spi_cs_e cs;
} spi_config_t;
spi_role_e
typedef enum
{
SPI_ROLE_SLAVE,
SPI_ROLE_MASTER,
} spi_role_e;
spi_firstbit_e
typedef enum
{
SPI_FIRSTBIT_MSB,
SPI_FIRSTBIT_LSB,
} spi_firstbit_e;
spi_work_mode_e
typedef enum
{
SPI_WORK_MODE_0, // CPOL = 0; CPHA = 0
SPI_WORK_MODE_2, // CPOL = 1; CPHA = 0
SPI_WORK_MODE_1, // CPOL = 0; CPHA = 1
SPI_WORK_MODE_3, // CPOL = 1; CPHA = 1
} spi_work_mode_e;
spi_transfer_mode_e
typedef enum
{
SPI_TRANSFER_DMA,
SPI_TRANSFER_NORMAL,
} spi_transfer_mode_e;
spi_data_size_e
/* size of single spi frame data */
typedef enum
{
SPI_DATA_SIZE_4BIT = 4,
SPI_DATA_SIZE_5BIT,
SPI_DATA_SIZE_6BIT,
SPI_DATA_SIZE_7BIT,
SPI_DATA_SIZE_8BIT,
SPI_DATA_SIZE_9BIT,
SPI_DATA_SIZE_10BIT,
SPI_DATA_SIZE_11BIT,
SPI_DATA_SIZE_12BIT,
SPI_DATA_SIZE_13BIT,
SPI_DATA_SIZE_14BIT,
SPI_DATA_SIZE_15BIT,
SPI_DATA_SIZE_16BIT,
} spi_data_size_e;
spi_cs_e
/* cs signal to active for transfer */
typedef enum
{
SPI_CS_DIS,
SPI_CS_EN,
} spi_cs_e;
spi_attribute_t
typedef struct{
spi_work_mode_e work_mode;
}spi_attribute_t;
hal_spi_init
初始化指定SPI端口
函数原型
int32_t hal_spi_init(spi_dev_t *spi)
参数
参数名称 | 出入参 | 参数描述 | 参数示例 |
---|---|---|---|
spi_dev_t *spi | 入参 | SPI设备描述,定义需要初始化的SPI参数 | 用户自定义一个spi_dev_t结构体 |
返回值
返回成功或失败, 返回0表示SPI初始化成功,非0表示失败
调用示例
#define SPI1_PORT_NUM 1
/* define dev */
spi_dev_t spi1;
/* spi port set */
spi1.port = SPI1_PORT_NUM;
/* spi attr config */
spi1.config.mode = HAL_SPI_MODE_MASTER;
spi1.config.freq = 30000000;
ret = hal_spi_init(&spi1);
hal_spi_send
从指定的SPI端口发送数据
函数原型
int32_t hal_spi_send(spi_dev_t *spi, const uint8_t *data, uint16_t size, uint32_t timeout)
参数
参数名称 | 出入参 | 参数描述 | 参数示例 |
---|---|---|---|
spi_dev_t *spi | 入参 | SPI设备描述 | 使用hal_spi_init初始化时传入值 |
const uint8_t *data | 入参 | 指向要发送数据的数据指针 | char spi_data_buf[10] |
uint16_t size | 入参 | 要发送的数据字节数 | 10 |
uint32_t timeout | 入参 | 超时时间(单位ms),如果希望一直等待设置为HAL_WAIT_FOREVER | 50 |
返回值
返回成功或失败, 返回0表示SPI数据发送成功,非0表示失败
调用示例
#define SPI_BUF_SIZE 10
#define SPI_TX_TIMEOUT 50
/* data buffer */
char spi_data_buf[SPI_BUF_SIZE];
ret = hal_spi_send(&spi1, spi_data_buf, SPI_BUF_SIZE, SPI_TX_TIMEOUT);
hal_spi_recv
从指定的SPI端口发送并接收数据
函数原型
int32_t hal_spi_recv(spi_dev_t *spi, uint8_t *data, uint16_t size, uint32_t timeout)
参数
参数名称 | 出入参 | 参数描述 | 参数示例 |
---|---|---|---|
spi_dev_t *spi | 入参 | SPI设备描述 | 使用hal_spi_init初始化时传入值 |
const uint8_t *data | 入参 | 指向接收缓冲区的数据指针 | char spi_data_buf[10] |
uint16_t size | 入参 | 期望接收的数据字节数 | 10 |
uint32_t timeout | 入参 | 超时时间(单位ms),如果希望一直等待设置为HAL_WAIT_FOREVER | 50 |
返回值
返回成功或失败, 返回0表示成功接收size个数据,非0表示失败
调用示例
#define SPI_BUF_SIZE 10
#define SPI_RX_TIMEOUT 50
/* data buffer */
char spi_data_buf[SPI_BUF_SIZE];
ret =hal_spi_recv(&spi1, spi_data_buf, SPI_BUF_SIZE, SPI_RX_TIMEOUT);
hal_spi_send_recv
从指定的SPI端口发送并接收数据
函数原型
int32_t hal_spi_send_recv(spi_dev_t *spi, uint8_t *tx_data, uint8_t *rx_data, uint16_t size, uint32_t timeout)
参数
参数名称 | 出入参 | 参数描述 | 参数示例 |
---|---|---|---|
spi_dev_t *spi | 入参 | SPI设备描述 | 使用hal_spi_init初始化时传入值 |
uint8_t *tx_data | 入参 | 指向发送缓冲区的数据指针 | char spi_send_buf[10] |
uint8_t *rx_data | 入参 | 指向接收缓冲区的数据指针 | char spi_recv_buf[10] |
uint16_t size | 入参 | 要发送和接收数据字节数 | 10 |
uint32_t timeout | 入参 | 超时时间(单位ms),如果希望一直等待设置为HAL_WAIT_FOREVER | 50 |
返回值
返回成功或失败, 返回0表示成功发送和接收size个数据,非0表示失败
调用示例
#define SPI_BUF_SIZE 10
#define SPI_RX_TIMEOUT 50
/* data buffer */
char spi_send_buf[SPI_BUF_SIZE] = {0};
char spi_recv_buf[SPI_BUF_SIZE] = {0};
ret =hal_spi_send_recv(&spi1, spi_send_buf, spi_recv_buf,SPI_BUF_SIZE, SPI_RX_TIMEOUT);
hal_spi_send_and_recv
从指定的SPI端口发送后接收数据
函数原型
int32_t hal_spi_send_and_recv(spi_dev_t *spi, uint8_t *tx_data, uint16_t tx_size, uint8_t *rx_data,
uint16_t rx_size, uint32_t timeout);
参数
参数名称 | 出入参 | 参数描述 | 参数示例 |
---|---|---|---|
spi_dev_t *spi | 入参 | SPI设备描述 | 使用hal_spi_init初始化时传入值 |
uint8_t *tx_data | 入参 | 指向发送缓冲区的数据指针 | char spi_send_buf[10] |
uint16_t tx_size | 入参 | 要发送数据字节数 | 10 |
uint8_t *rx_data | 出参 | 指向接收缓冲区的数据指针 | char spi_recv_buf[10] |
uint16_t rx_size | 入参 | 要发送和接收数据字节数 | 10 |
uint32_t timeout | 入参 | 超时时间(单位ms),如果希望一直等待设置为HAL_WAIT_FOREVER | 50 |
返回值
返回成功或失败, 返回0表示成功,非0表示失败
调用示例
#define SPI_BUF_SIZE 10
#define SPI_TRX_TIMEOUT 50
/* data buffer */
char spi_send_buf[SPI_BUF_SIZE] = {0};
char spi_recv_buf[SPI_BUF_SIZE] = {0};
ret =hal_spi_send_recv(&spi1, spi_send_buf, SPI_BUF_SIZE, spi_recv_buf,SPI_BUF_SIZE, SPI_TRX_TIMEOUT);
hal_spi_send_and_send
从指定的SPI端口发送后再次发送数据
函数原型
int32_t hal_spi_send_and_send(spi_dev_t *spi, uint8_t *tx1_data, uint16_t tx1_size, uint8_t *tx2_data,
uint16_t tx2_size, uint32_t timeout);
参数
参数名称 | 出入参 | 参数描述 | 参数示例 |
---|---|---|---|
spi_dev_t *spi | 入参 | SPI设备描述 | 使用hal_spi_init初始化时传入值 |
uint8_t *tx1_data | 入参 | 指向发送缓冲区的数据指针 | char spi_send_buf1[10] |
uint16_t tx1_size | 入参 | 要发送数据字节数 | 10 |
uint8_t *tx2_data | 入参 | 指向发送缓冲区的数据指针 | char spi_send_buf2[10] |
uint16_t tx2_size | 入参 | 要发送数据字节数 | 10 |
uint32_t timeout | 入参 | 超时时间(单位ms),如果希望一直等待设置为HAL_WAIT_FOREVER | 50 |
返回值
返回成功或失败, 返回0表示成功,非0表示失败
调用示例
#define SPI_BUF_SIZE 10
#define SPI_TX_TIMEOUT 50
/* data buffer */
char spi_send_buf[SPI_BUF_SIZE] = {0};
char spi_recv_buf[SPI_BUF_SIZE] = {0};
ret =hal_spi_send_recv(&spi1, spi_send_buf1, SPI_BUF_SIZE, spi_send_buf2, SPI_BUF_SIZE, SPI_TX_TIMEOUT);
hal_spi_finalize
关闭指定SPI端口
函数原型
int32_t hal_spi_finalize(spi_dev_t *spi)
参数
参数名称 | 出入参 | 参数描述 | 参数示例 |
---|---|---|---|
spi_dev_t *spi | 入参 | SPI设备描述 | 使用hal_spi_init初始化时传入值 |
返回值
类型:int 返回成功或失败, 返回0表示SPI关闭成功,非0表示失败。
调用示例
ret =hal_spi_finalize(&spi1);
使用
添加该组件
在相应的platform/mcu的mk内,添加对应hal文件的编译包含。
包含头文件
#include "aos/hal/spi.h"
使用示例
#include <aos/hal/spi.h>
#define SPI1_PORT_NUM 1
#define SPI_BUF_SIZE 10
#define SPI_TX_TIMEOUT 10
#define SPI_RX_TIMEOUT 10
/* define dev */
spi_dev_t spi1;
/* data buffer */
char spi_data_buf[SPI_BUF_SIZE];
int application_start(int argc, char *argv[])
{
int count = 0;
int ret = -1;
int i = 0;
int rx_size = 0;
/* spi port set */
spi1.port = SPI1_PORT_NUM;
/* spi attr config */
spi1.config.mode = HAL_SPI_MODE_MASTER;
spi1.config.freq = 30000000;
/* init spi1 with the given settings */
ret = hal_spi_init(&spi1);
if (ret != 0) {
printf("spi1 init error !\n");
}
/* init the tx buffer */
for (i = 0; i < SPI_BUF_SIZE; i++) {
spi_data_buf[i] = i + 1;
}
/* send 0,1,2,3,4,5,6,7,8,9 by spi1 */
ret = hal_spi_send(&spi1, spi_data_buf, SPI_BUF_SIZE, SPI_TX_TIMEOUT);
if (ret == 0) {
printf("spi1 data send succeed !\n");
}
/* scan spi every 100ms to get the data */
while(1) {
ret = hal_spi_recv(&spi1, spi_data_buf, SPI_BUF_SIZE, SPI_RX_TIMEOUT);
if (ret == 0) {
printf("spi1 data received succeed !\n");
}
/* sleep 100ms */
aos_msleep(100);
};
}
注:port为逻辑端口号,其与物理端口号的对应关系见具体的对接实现
移植说明
新建hal_spi_xxmcu.c和hal_spi_xxmcu.h的文件,并将这两个文件放到platform/mcu/xxmcu/hal目录下。在hal_spi_xxmcu.c中实现所需要的hal函数,hal_spi_xxmcu.h中放置相关宏定义。<br /> 参考platform/mcu/stm32l4xx/src/STM32L496G-Discovery/hal/hal_spi_stm32l4.c