为了利用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


 

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐