RK3568+Linux+buildroot+RC522的C语言代码
·
为了利用rk3568读取rfid卡的信息,首先需要修改设备树,利用spi1,cs和rst利用普通io,这里利用uart4。
gpio在/sys/class/gpio下,可以利用echo num的方式启动gpio。
然后利用`aarch64-linux-gnu-gcc -o mfrc522_app main.c mfrc522.c spi.c gpio_sysfs.c` 编译生成 mfrc522_app,
file mfrc522_app
```c
file mfrc522_app mfrc522_app: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[sha1]=6daf69a465681b87904146da8b9fa5535368cbe5, not stripped
```
执行./mfrc522_app
代码如下:
gpio_sysfs.c```c
#include "gpio_sysfs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define SYSFS_GPIO_PATH "/sys/class/gpio"
static int gpio_write_file(const char *path, const char *value)
{
FILE *fp = fopen(path, "w");
if (!fp)
return -1;
fprintf(fp, "%s", value);
fclose(fp);
return 0;
}
static int gpio_read_file(const char *path, char *buf, size_t size)
{
FILE *fp = fopen(path, "r");
if (!fp)
return -1;
if (fgets(buf, size, fp) == NULL) {
fclose(fp);
return -1;
}
fclose(fp);
return 0;
}
int gpio_export(int gpio_num)
{
char path[64];
snprintf(path, sizeof(path), "%s/export", SYSFS_GPIO_PATH);
char val[8];
snprintf(val, sizeof(val), "%d", gpio_num);
// 如果已经导出,直接返回成功
char check_path[64];
snprintf(check_path, sizeof(check_path), "%s/gpio%d", SYSFS_GPIO_PATH, gpio_num);
if (access(check_path, F_OK) == 0)
return 0;
return gpio_write_file(path, val);
}
int gpio_unexport(int gpio_num)
{
char path[64];
snprintf(path, sizeof(path), "%s/unexport", SYSFS_GPIO_PATH);
char val[8];
snprintf(val, sizeof(val), "%d", gpio_num);
return gpio_write_file(path, val);
}
int gpio_set_direction(int gpio_num, const char *direction)
{
char path[64];
snprintf(path, sizeof(path), "%s/gpio%d/direction", SYSFS_GPIO_PATH, gpio_num);
return gpio_write_file(path, direction);
}
int gpio_set_value(int gpio_num, int value)
{
char path[64];
snprintf(path, sizeof(path), "%s/gpio%d/value", SYSFS_GPIO_PATH, gpio_num);
char val[2];
snprintf(val, sizeof(val), "%d", value ? 1 : 0);
return gpio_write_file(path, val);
}
int gpio_get_value(int gpio_num)
{
char path[64];
snprintf(path, sizeof(path), "%s/gpio%d/value", SYSFS_GPIO_PATH, gpio_num);
char buf[4];
if (gpio_read_file(path, buf, sizeof(buf)) < 0)
return -1;
return atoi(buf);
}
```
GPIO_SYSFS.h
```c
#ifndef GPIO_SYSFS_H
#define GPIO_SYSFS_H
int gpio_export(int gpio_num);
int gpio_unexport(int gpio_num);
int gpio_set_direction(int gpio_num, const char *direction);
int gpio_set_value(int gpio_num, int value);
int gpio_get_value(int gpio_num);
#endif
main.c
#include <stdio.h>
#include <unistd.h>
#include "mfrc522.h"
int main()
{
unsigned char id[4];
unsigned char status;
int ret;
// 使用 spidev1.0,CS=106,RST=105
ret = mfrc522_init("/dev/spidev1.0", 106, 105);
if (ret != 0) {
printf("mfrc522_init failed!\n");
return -1;
}
mfrc522_reset();
mfrc522_config_iso_type('A');
while (1) {
status = mfrc522_pcd_request(PICC_REQALL, id);
if (status == MI_OK)
break;
usleep(100000); // 0.1s
}
if (status == MI_OK) {
printf("request card successfully!\n");
if (mfrc522_anticoll(id) == MI_OK)
printf("card uid = %02X%02X%02X%02X\n", id[0], id[1], id[2], id[3]);
}
mfrc522_exit();
return 0;
}
```c
mfrc522.c
#include "mfrc522.h"
#include "spi.h"
#include "gpio_sysfs.h"
static spi_handle_t *mfrc522_spi;
static int g_rst_gpio_num = -1; // 复位 GPIO 编号
// 写寄存器
static void mfrc522_write_reg(unsigned char reg, unsigned char value)
{
unsigned char send_buf[2];
send_buf[0] = (reg << 1) & 0x7E;
send_buf[1] = value;
spi_write_nbyte_data(mfrc522_spi, send_buf, sizeof(send_buf));
}
// 读寄存器
static unsigned char mfrc522_read_reg(unsigned char reg)
{
unsigned char send_buf[2];
unsigned char recv_buf[2] = {0};
send_buf[0] = ((reg << 1) & 0x7E) | 0x80;
send_buf[1] = 0x00;
spi_write_and_read(mfrc522_spi, send_buf, sizeof(send_buf), recv_buf);
return recv_buf[1];
}
// 置位掩码
static void mfrc522_set_bit_mask(unsigned char reg, unsigned char mask)
{
unsigned char temp = mfrc522_read_reg(reg);
mfrc522_write_reg(reg, temp | mask);
}
// 清除掩码
static void mfrc522_clr_bit_mask(unsigned char reg, unsigned char mask)
{
unsigned char temp = mfrc522_read_reg(reg);
mfrc522_write_reg(reg, temp & (~mask));
}
// 复位引脚控制
static void mfrc522_rst_enabled(void)
{
gpio_set_value(g_rst_gpio_num, 0); // 低电平复位
}
static void mfrc522_rst_disabled(void)
{
gpio_set_value(g_rst_gpio_num, 1); // 高电平正常工作
}
// MFRC522 复位
void mfrc522_reset(void)
{
mfrc522_rst_disabled();
usleep(1);
mfrc522_rst_enabled();
usleep(1);
mfrc522_rst_disabled();
usleep(1);
mfrc522_write_reg(CommandReg, PCD_RESETPHASE);
while (mfrc522_read_reg(CommandReg) & 0x10)
;
usleep(1);
mfrc522_write_reg(ModeReg, 0x3D);
mfrc522_write_reg(TReloadRegL, 30);
mfrc522_write_reg(TReloadRegH, 0);
mfrc522_write_reg(TModeReg, 0x8D);
mfrc522_write_reg(TPrescalerReg, 0x3E);
mfrc522_write_reg(TxAutoReg, 0x40);
}
// 天线开关
void mfrc522_antenna_on(void)
{
unsigned char temp = mfrc522_read_reg(TxControlReg);
if (!(temp & 0x03))
mfrc522_set_bit_mask(TxControlReg, 0x03);
}
void mfrc522_antenna_off(void)
{
mfrc522_clr_bit_mask(TxControlReg, 0x03);
}
// 设置ISO类型
void mfrc522_config_iso_type(unsigned char type)
{
if (type == 'A') {
mfrc522_clr_bit_mask(Status2Reg, 0x08);
mfrc522_write_reg(ModeReg, 0x3D);
mfrc522_write_reg(RxSelReg, 0x86);
mfrc522_write_reg(RFCfgReg, 0x7F);
mfrc522_write_reg(TReloadRegL, 30);
mfrc522_write_reg(TReloadRegH, 0);
mfrc522_write_reg(TModeReg, 0x8D);
mfrc522_write_reg(TPrescalerReg, 0x3E);
usleep(2);
mfrc522_antenna_on();
}
}
// 通过RC522和ISO14443卡通讯
unsigned char mfrc522_to_card(unsigned char command, unsigned char *send_buf, unsigned char send_buf_len, unsigned char *recv_buf, unsigned int *recv_buf_len)
{
unsigned char status = MI_ERR;
unsigned char irq_en = 0x00;
unsigned char wait_irq = 0x00;
unsigned char last_bits;
unsigned char n;
unsigned int i = 0;
switch (command) {
case PCD_AUTHENT: {
irq_en = 0x12;
wait_irq = 0x10;
break;
}
case PCD_TRANSCEIVE: {
irq_en = 0x77;
wait_irq = 0x30;
break;
}
default:
break;
}
mfrc522_write_reg(ComIEnReg, irq_en | 0x80);
mfrc522_clr_bit_mask(ComIrqReg, 0x80);
mfrc522_write_reg(CommandReg, PCD_IDLE);
mfrc522_set_bit_mask(FIFOLevelReg, 0x80);
for (i = 0; i < send_buf_len; i++)
mfrc522_write_reg(FIFODataReg, send_buf[i]);
mfrc522_write_reg(CommandReg, command);
if (command == PCD_TRANSCEIVE)
mfrc522_set_bit_mask(BitFramingReg, 0x80);
do {
n = mfrc522_read_reg(ComIrqReg);
usleep(1000);
i++;
} while ((i != 50) && !(n & 0x01) && !(n & wait_irq));
mfrc522_clr_bit_mask(BitFramingReg, 0x80);
if (i != 50) {
if (!(mfrc522_read_reg(ErrorReg) & 0x1B)) {
status = MI_OK;
if (n & irq_en & 0x01)
status = MI_NOTAGERR;
if (command == PCD_TRANSCEIVE) {
n = mfrc522_read_reg(FIFOLevelReg);
last_bits = mfrc522_read_reg(ControlReg) & 0x07;
if (last_bits)
*recv_buf_len = (n - 1) * 8 + last_bits;
else
*recv_buf_len = n * 8;
if (n == 0)
n = 1;
if (n > MFRC522_MAX_LEN)
n = MFRC522_MAX_LEN;
for (i = 0; i < n; i++)
recv_buf[i] = mfrc522_read_reg(FIFODataReg);
}
} else {
status = MI_ERR;
}
}
mfrc522_set_bit_mask(ControlReg, 0x80);
mfrc522_write_reg(CommandReg, PCD_IDLE);
return status;
}
// 防冲撞
unsigned char mfrc522_anticoll(unsigned char *snr)
{
char status;
uint8_t i, snr_check = 0;
uint8_t com_mfrc522_buf[MFRC522_MAX_LEN];
uint32_t len;
mfrc522_clr_bit_mask(Status2Reg, 0x08);
mfrc522_write_reg(BitFramingReg, 0x00);
mfrc522_clr_bit_mask(CollReg, 0x80);
com_mfrc522_buf[0] = 0x93;
com_mfrc522_buf[1] = 0x20;
status = mfrc522_to_card(PCD_TRANSCEIVE, com_mfrc522_buf, 2, com_mfrc522_buf, &len);
if (status == MI_OK) {
for (i = 0; i < 4; i++) {
*(snr + i) = com_mfrc522_buf[i];
snr_check ^= com_mfrc522_buf[i];
}
if (snr_check != com_mfrc522_buf[i])
status = MI_ERR;
}
mfrc522_set_bit_mask(CollReg, 0x80);
return status;
}
// 寻卡
char mfrc522_pcd_request(unsigned char req_code, unsigned char *tag_type)
{
char status;
unsigned char com_buf[MFRC522_MAX_LEN];
unsigned int len;
mfrc522_clr_bit_mask(Status2Reg, 0x08);
mfrc522_write_reg(BitFramingReg, 0x07);
mfrc522_set_bit_mask(TxControlReg, 0x03);
com_buf[0] = req_code;
status = mfrc522_to_card(PCD_TRANSCEIVE, com_buf, 1, com_buf, &len);
if ((status == MI_OK) && (len == 0x10)) {
*tag_type = com_buf[0];
*(tag_type + 1) = com_buf[1];
} else {
status = MI_ERR;
}
return status;
}
// 初始化
int mfrc522_init(const char *spi_dev, int cs_gpio_num, int rst_gpio_num)
{
if (!spi_dev)
return -1;
// 初始化 SPI(传入CS GPIO编号)
mfrc522_spi = spi_handle_alloc(spi_dev, SPIMODE0, S_1M, cs_gpio_num);
if (!mfrc522_spi) {
printf("spi_handle_alloc failed!\n");
return -1;
}
// 初始化复位 GPIO(导出并设置为输出,高电平)
if (gpio_export(rst_gpio_num) < 0) {
printf("Failed to export RST GPIO %d\n", rst_gpio_num);
spi_handle_free(mfrc522_spi);
return -1;
}
if (gpio_set_direction(rst_gpio_num, "out") < 0) {
printf("Failed to set direction for RST GPIO %d\n", rst_gpio_num);
gpio_unexport(rst_gpio_num);
spi_handle_free(mfrc522_spi);
return -1;
}
gpio_set_value(rst_gpio_num, 1); // 默认高电平(非复位状态)
g_rst_gpio_num = rst_gpio_num;
return 0;
}
// 反初始化
void mfrc522_exit(void)
{
if (g_rst_gpio_num >= 0) {
gpio_unexport(g_rst_gpio_num);
g_rst_gpio_num = -1;
}
if (mfrc522_spi) {
spi_handle_free(mfrc522_spi);
mfrc522_spi = NULL;
}
}
```c
mfrc522.h
MFRC522.H
#ifndef MFRC522_H
#define MFRC522_H
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#define MI_OK 0
#define MI_NOTAGERR 1
#define MI_ERR 2
#define MFRC522_MAX_LEN 18
/* MFRC522 REG */
// Page 0 - Command and Status
#define RFU00 0x00
#define CommandReg 0x01
#define ComIEnReg 0x02
#define DivlEnReg 0x03
#define ComIrqReg 0x04
#define DivIrqReg 0x05
#define ErrorReg 0x06
#define Status1Reg 0x07
#define Status2Reg 0x08
#define FIFODataReg 0x09
#define FIFOLevelReg 0x0A
#define WaterLevelReg 0x0B
#define ControlReg 0x0C
#define BitFramingReg 0x0D
#define CollReg 0x0E
#define RFU0F 0x0F
// Page 1 - Command
#define RFU10 0x10
#define ModeReg 0x11
#define TxModeReg 0x12
#define RxModeReg 0x13
#define TxControlReg 0x14
#define TxAutoReg 0x15
#define TxSelReg 0x16
#define RxSelReg 0x17
#define RxThresholdReg 0x18
#define DemodReg 0x19
#define RFU1A 0x1A
#define RFU1B 0x1B
#define MifareReg 0x1C
#define RFU1D 0x1D
#define RFU1E 0x1E
#define SerialSpeedReg 0x1F
// Page 2 - CFG
#define RFU20 0x20
#define CRCResultRegM 0x21
#define CRCResultRegL 0x22
#define RFU23 0x23
#define ModWidthReg 0x24
#define RFU25 0x25
#define RFCfgReg 0x26
#define GsNReg 0x27
#define CWGsCfgReg 0x28
#define ModGsCfgReg 0x29
#define TModeReg 0x2A
#define TPrescalerReg 0x2B
#define TReloadRegH 0x2C
#define TReloadRegL 0x2D
#define TCounterValueRegH 0x2E
#define TCounterValueRegL 0x2F
// Page 3 - TestRegister
#define RFU30 0x30
#define TestSel1Reg 0x31
#define TestSel2Reg 0x32
#define TestPinEnReg 0x33
#define TestPinValueReg 0x34
#define TestBusReg 0x35
#define AutoTestReg 0x36
#define VersionReg 0x37
#define AnalogTestReg 0x38
#define TestDAC1Reg 0x39
#define TestDAC2Reg 0x3A
#define TestADCReg 0x3B
#define RFU3C 0x3C
#define RFU3D 0x3D
#define RFU3E 0x3E
#define RFU3F 0x3F
/* MFRC522 CMD */
#define PCD_IDLE 0x00
#define PCD_AUTHENT 0x0E
#define PCD_RECEIVE 0x08
#define PCD_TRANSMIT 0x04
#define PCD_TRANSCEIVE 0x0C
#define PCD_RESETPHASE 0x0F
#define PCD_CALCCRC 0x03
/* IC-S50 CMD */
#define PICC_REQIDL 0x26
#define PICC_REQALL 0x52
#define PICC_ANTICOLL1 0x93
#define PICC_ANTICOLL2 0x95
#define PICC_AUTHENT1A 0x60
#define PICC_AUTHENT1B 0x61
#define PICC_READ 0x30
#define PICC_WRITE 0xA0
#define PICC_DECREMENT 0xC0
#define PICC_INCREMENT 0xC1
#define PICC_RESTORE 0xC2
#define PICC_TRANSFER 0xB0
#define PICC_HALT 0x50
/* 函数声明 */
int mfrc522_init(const char *spi_dev, int cs_gpio_num, int rst_gpio_num);
void mfrc522_reset(void);
void mfrc522_antenna_on(void);
void mfrc522_antenna_off(void);
void mfrc522_config_iso_type(unsigned char type);
unsigned char mfrc522_to_card(unsigned char command, unsigned char *send_buf, unsigned char send_buf_len, unsigned char *recv_buf, unsigned int *recv_buf_len);
unsigned char mfrc522_anticoll(unsigned char* ser_num);
char mfrc522_pcd_request(unsigned char req_code, unsigned char *tag_type);
void mfrc522_exit(void);
#endif
spi.c
```c
spi.h
#include "spi.h"
#include "gpio_sysfs.h"
/*******************************
* @brief : SPI同时发送数据和接收数据
*******************************/
void spi_write_and_read(spi_handle_t *spi, unsigned char *send_buf, unsigned int send_buf_len, unsigned char *recv_buf)
{
struct spi_ioc_transfer xfer[1];
int status;
if (spi == NULL || send_buf == NULL || recv_buf == NULL)
return;
memset(xfer, 0, sizeof(xfer));
xfer[0].tx_buf = (unsigned long)send_buf;
xfer[0].rx_buf = (unsigned long)recv_buf;
xfer[0].len = send_buf_len;
pthread_mutex_lock(&(spi->mutex));
gpio_set_value(spi->cs_gpio_num, 0); // CS 低电平
status = ioctl(spi->fd, SPI_IOC_MESSAGE(1), xfer);
if (status < 0)
printf("SPI_IOC_MESSAGE failed!\n");
gpio_set_value(spi->cs_gpio_num, 1); // CS 高电平
pthread_mutex_unlock(&(spi->mutex));
}
/*******************************
* @brief : SPI先发送后接收
*******************************/
void spi_write_then_read(spi_handle_t *spi, unsigned char *send_buf, unsigned int send_buf_len, unsigned char *recv_buf, unsigned int recv_buf_len)
{
struct spi_ioc_transfer xfer[2];
int status;
if (spi == NULL || send_buf == NULL || recv_buf == NULL)
return;
memset(xfer, 0, sizeof(xfer));
xfer[0].tx_buf = (unsigned long)send_buf;
xfer[0].len = send_buf_len;
xfer[1].rx_buf = (unsigned long)recv_buf;
xfer[1].len = recv_buf_len;
pthread_mutex_lock(&(spi->mutex));
gpio_set_value(spi->cs_gpio_num, 0);
status = ioctl(spi->fd, SPI_IOC_MESSAGE(2), xfer);
if (status < 0)
printf("SPI_IOC_MESSAGE failed!\n");
gpio_set_value(spi->cs_gpio_num, 1);
pthread_mutex_unlock(&(spi->mutex));
}
/*******************************
* @brief : SPI发送一个字节
*******************************/
void spi_write_byte_data(spi_handle_t *spi, unsigned char data)
{
unsigned char buff[1] = {data};
if (spi == NULL)
return;
pthread_mutex_lock(&(spi->mutex));
gpio_set_value(spi->cs_gpio_num, 0);
write(spi->fd, buff, 1);
gpio_set_value(spi->cs_gpio_num, 1);
pthread_mutex_unlock(&(spi->mutex));
}
/*******************************
* @brief : SPI发送多个字节
*******************************/
void spi_write_nbyte_data(spi_handle_t *spi, unsigned char *send_buf, unsigned int send_buf_len)
{
struct spi_ioc_transfer xfer[2];
unsigned char recv_buf[send_buf_len];
int status;
if (spi == NULL || send_buf == NULL)
return;
memset(xfer, 0, sizeof(xfer));
memset(recv_buf, 0, send_buf_len);
xfer[0].tx_buf = (unsigned long)send_buf;
xfer[0].rx_buf = (unsigned long)recv_buf;
xfer[0].len = send_buf_len;
pthread_mutex_lock(&(spi->mutex));
gpio_set_value(spi->cs_gpio_num, 0);
status = ioctl(spi->fd, SPI_IOC_MESSAGE(1), xfer);
if (status < 0)
printf("SPI_IOC_MESSAGE failed!\n");
gpio_set_value(spi->cs_gpio_num, 1);
pthread_mutex_unlock(&(spi->mutex));
}
/*******************************
* @brief : 分配并初始化SPI设备句柄
*******************************/
spi_handle_t *spi_handle_alloc(const char *spi_dev, SPI_MODE spi_mode, SPI_SPEED spi_speed, int cs_gpio_num)
{
int ret, fd;
char spi_bits = 8;
uint32_t speed = (uint32_t)spi_speed;
if (!spi_dev)
return NULL;
fd = open(spi_dev, O_RDWR);
if (fd < 0) {
printf("open %s failed!\n", spi_dev);
return NULL;
}
spi_handle_t *spi = (spi_handle_t *)malloc(sizeof(spi_handle_t));
if (!spi) {
printf("spi_handle_t allocation failed!\n");
close(fd);
return NULL;
}
memset(spi, 0, sizeof(*spi));
spi->fd = fd;
spi->cs_gpio_num = cs_gpio_num;
// 配置 SPI 模式、字长、速度
ret = ioctl(spi->fd, SPI_IOC_WR_MODE, &spi_mode);
if (ret < 0) {
printf("SPI_IOC_WR_MODE failed!\n");
goto err;
}
ret = ioctl(spi->fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits);
if (ret < 0) {
printf("SPI_IOC_WR_BITS_PER_WORD failed!\n");
goto err;
}
ret = ioctl(spi->fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret < 0) {
printf("SPI_IOC_WR_MAX_SPEED_HZ failed!\n");
goto err;
}
spi->dev_name = (char *)malloc(strlen(spi_dev) + 1);
if (!spi->dev_name) {
printf("dev_name allocation failed!\n");
goto err;
}
strcpy(spi->dev_name, spi_dev);
ret = pthread_mutex_init(&spi->mutex, NULL);
if (ret != 0) {
printf("pthread_mutex_init failed!\n");
free(spi->dev_name);
goto err;
}
// 导出并设置 CS GPIO 为输出,初始高电平(不选中)
if (gpio_export(cs_gpio_num) < 0) {
printf("Failed to export CS GPIO %d\n", cs_gpio_num);
goto err_mutex;
}
if (gpio_set_direction(cs_gpio_num, "out") < 0) {
printf("Failed to set direction for CS GPIO %d\n", cs_gpio_num);
gpio_unexport(cs_gpio_num);
goto err_mutex;
}
gpio_set_value(cs_gpio_num, 1); // 默认高电平
return spi;
err_mutex:
pthread_mutex_destroy(&spi->mutex);
free(spi->dev_name);
err:
free(spi);
close(fd);
return NULL;
}
/*******************************
* @brief : 释放SPI设备句柄
*******************************/
void spi_handle_free(spi_handle_t *spi)
{
if (!spi)
return;
// 释放 CS GPIO
if (spi->cs_gpio_num >= 0) {
gpio_unexport(spi->cs_gpio_num);
}
if (spi->dev_name)
free(spi->dev_name);
pthread_mutex_destroy(&spi->mutex);
close(spi->fd);
free(spi);
}
#ifndef _SPI_H
#define _SPI_H
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <linux/spi/spidev.h>
#include <pthread.h>
typedef struct spi_handle
{
char *dev_name;
int fd;
pthread_mutex_t mutex;
int cs_gpio_num; // 片选 GPIO 编号(sysfs)
} spi_handle_t;
typedef enum
{
SPIMODE0 = SPI_MODE_0,
SPIMODE1 = SPI_MODE_1,
SPIMODE2 = SPI_MODE_2,
SPIMODE3 = SPI_MODE_3,
} SPI_MODE;
typedef enum
{
S_1M = 1000000,
S_6_75M = 6750000,
S_8M = 8000000,
S_13_5M = 13500000,
S_27M = 27000000,
} SPI_SPEED;
spi_handle_t *spi_handle_alloc(const char *spi_dev, SPI_MODE spi_mode, SPI_SPEED spi_speed, int cs_gpio_num);
void spi_write_and_read(spi_handle_t *spi, unsigned char *send_buf, unsigned int send_buf_len, unsigned char *recv_buf);
void spi_write_then_read(spi_handle_t *spi, unsigned char *send_buf, unsigned int send_buf_len, unsigned char *recv_buf, unsigned int recv_buf_len);
void spi_write_byte_data(spi_handle_t *spi, unsigned char data);
void spi_write_nbyte_data(spi_handle_t *spi, unsigned char *send_buf, unsigned int send_buf_len);
void spi_handle_free(spi_handle_t *spi);
#endif
更多推荐

所有评论(0)