不用库:完全底层代码(使用 spidev 和 sysfs)
main.c(完全底层,不依赖任何库)
// build: sudo make
// run: sudo ./ads1263#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/spi/spidev.h>
#include <sys/ioctl.h>
#include <time.h>
#include <errno.h>/********* 引脚(BCM 编号) *********/
#define PIN_DRDY 17 // 输入
#define PIN_RESET 18 // 输出
#define PIN_CS 22 // 输出(软CS)/********* ADS1263 命令与寄存器 *********/
#define CMD_RESET 0x06
#define CMD_START1 0x08
#define CMD_STOP1 0x0A
#define CMD_RDATA1 0x12
#define CMD_RREG 0x20
#define CMD_WREG 0x40
#define REG_MODE2 0x05
#define REG_INPMUX 0x06
#define REG_REFMUX 0x0F// 参考:AVDD-AVSS
#define REF_AVDD 0x24
// 单端:AINx+ 对 AINCOM-
#define AINCOM 0x0A/********* SPI 配置 *********/
static const char *SPI_PATH = "/dev/spidev0.0";
static const uint32_t SPI_SPEED = 1000000; // 1 MHz
static const uint8_t SPI_BITS = 8;
static uint8_t SPI_MODE = SPI_MODE_1 | SPI_NO_CS; // 模式1,禁用硬件CS,用GPIO22做软CS
static int spi_fd = -1;/********* sysfs GPIO 工具函数 *********/
static int gpio_export(int pin){int fd = open("/sys/class/gpio/export", O_WRONLY);if(fd<0) return -1;char buf[16];int n = snprintf(buf,sizeof(buf),"%d",pin);write(fd, buf, n);close(fd);// 等待目录就绪char path[64];for(int i=0;i<50;i++){snprintf(path,sizeof(path),"/sys/class/gpio/gpio%d/direction",pin);if(access(path,F_OK)==0) return 0;usleep(2000);}return 0;
}
static void gpio_unexport(int pin){int fd = open("/sys/class/gpio/unexport", O_WRONLY);if(fd<0) return;char buf[16];int n = snprintf(buf,sizeof(buf),"%d",pin);write(fd, buf, n);close(fd);
}
static int gpio_set_dir(int pin, const char* dir){char path[64];snprintf(path,sizeof(path),"/sys/class/gpio/gpio%d/direction",pin);int fd = open(path, O_WRONLY);if(fd<0) return -1;write(fd, dir, strlen(dir));close(fd);return 0;
}
static int gpio_write(int pin, int val){char path[64];snprintf(path,sizeof(path),"/sys/class/gpio/gpio%d/value",pin);int fd = open(path, O_WRONLY);if(fd<0) return -1;if(val) write(fd,"1",1); else write(fd,"0",1);close(fd);return 0;
}
static int gpio_read(int pin){char path[64];char v='1';snprintf(path,sizeof(path),"/sys/class/gpio/gpio%d/value",pin);int fd = open(path, O_RDONLY);if(fd<0) return -1;read(fd,&v,1);close(fd);return (v=='0')?0:1;
}/********* 微延时 *********/
static inline void delay_us(unsigned int us){struct timespec ts;ts.tv_sec = us/1000000;ts.tv_nsec = (us%1000000)*1000;nanosleep(&ts,NULL);
}/********* SPI 基础 *********/
static int spi_open(){spi_fd = open(SPI_PATH, O_RDWR);if(spi_fd<0){ perror("open spidev"); return -1; }if(ioctl(spi_fd, SPI_IOC_WR_MODE, &SPI_MODE)<0){ perror("SPI_IOC_WR_MODE"); return -1; }if(ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &SPI_BITS)<0){ perror("SPI_IOC_WR_BITS"); return -1; }if(ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &SPI_SPEED)<0){ perror("SPI_IOC_WR_SPEED"); return -1; }return 0;
}
static void spi_close(){if(spi_fd>=0) close(spi_fd);spi_fd=-1;
}
static int spi_xfer(uint8_t *tx, uint8_t *rx, uint32_t len){struct spi_ioc_transfer tr = {0};tr.tx_buf = (unsigned long)tx;tr.rx_buf = (unsigned long)rx;tr.len = len;tr.speed_hz = SPI_SPEED;tr.bits_per_word = SPI_BITS;int ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);if(ret<0){ perror("SPI_IOC_MESSAGE"); return -1; }return 0;
}/********* 片选 *********/
static inline void cs_low(){ gpio_write(PIN_CS, 0); }
static inline void cs_high(){ gpio_write(PIN_CS, 1); }/********* ADS1263 基础 *********/
static int write_cmd(uint8_t cmd){uint8_t tx[1] = { cmd };cs_low();int r = spi_xfer(tx, NULL, 1);cs_high();delay_us(50);return r;
}
static int write_reg(uint8_t reg, uint8_t val){uint8_t tx[3] = { (uint8_t)(CMD_WREG | reg), 0x00, val };cs_low();int r = spi_xfer(tx, NULL, 3);cs_high();delay_us(50);return r;
}
static int wait_drdy(double timeout_s){const uint64_t deadline_ns = (uint64_t)(timeout_s*1e9);struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);uint64_t t0 = (uint64_t)ts.tv_sec*1000000000ull + ts.tv_nsec;for(;;){int lev = gpio_read(PIN_DRDY);if(lev==0) return 0;delay_us(100);clock_gettime(CLOCK_MONOTONIC, &ts);uint64_t now = (uint64_t)ts.tv_sec*1000000000ull + ts.tv_nsec;if(now - t0 > deadline_ns) break;}return -1;
}// RDATA1 返回顺序:STATUS(1) + DATA(4) + CRC(1)
// 我们发送 1+6 共7字节,rx[1..5] 有效,其中 rx[2..5] 是 32bit 数据
static int32_t read_data(){uint8_t tx[7] = { CMD_RDATA1, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF };uint8_t rx[7] = {0};cs_low();spi_xfer(tx, rx, 7);cs_high();int32_t val = ((int32_t)rx[2]<<24) | ((int32_t)rx[3]<<16) | ((int32_t)rx[4]<<8) | ((int32_t)rx[5]);return val;
}static void select_single_ended(uint8_t pos_ain){write_reg(REG_REFMUX, REF_AVDD);write_reg(REG_INPMUX, (uint8_t)((pos_ain<<4) | AINCOM));delay_us(20); // MUX 建立时间
}static void ads_reset_pulse(){// RESET 为低脉冲再拉高gpio_write(PIN_RESET, 0);delay_us(1000);gpio_write(PIN_RESET, 1);delay_us(5000);
}static void init_ads1263(){ads_reset_pulse();write_cmd(CMD_RESET);usleep(50000);// MODE2:0x8D(高数据率/低延迟,保持与参考算法一致)write_reg(REG_MODE2, 0x8D);
}/********* 算法:码->电压 *********/
static inline double code_to_volt(int32_t code, double vref, int gain){// 32位有符号,参考算法:code / 2^31 * (vref/gain)return ((double)code / 2147483648.0) * (vref / gain);
}int main(void){// 导出并配置 GPIOgpio_export(PIN_DRDY);gpio_export(PIN_RESET);gpio_export(PIN_CS);gpio_set_dir(PIN_DRDY, "in");gpio_set_dir(PIN_RESET, "out");gpio_set_dir(PIN_CS, "out");gpio_write(PIN_CS, 1);gpio_write(PIN_RESET, 1);// 打开 SPIif(spi_open()<0){fprintf(stderr,"open spidev failed\n");return 1;}printf("ADS1263 initialized.\n");init_ads1263();printf("Reset complete.\n");const double vref = 5.32; // 按你的实际 AVDD 或外参电压const int gain = 1;// 预选通道并启动select_single_ended(0);write_cmd(CMD_START1);printf("Started sampling...\n");// 丢弃第一帧if(wait_drdy(0.5)==0) (void)read_data();int32_t code[4]={0};for(;;){// AIN0..3 轮询for(int ch=0; ch<4; ch++){select_single_ended((uint8_t)ch);if(wait_drdy(0.5)==0) code[ch] = read_data();}double v0 = code_to_volt(code[0], vref, gain);double v1 = code_to_volt(code[1], vref, gain);double v2 = code_to_volt(code[2], vref, gain);double v3 = code_to_volt(code[3], vref, gain);printf("\rAIN0= %.6f V AIN1= %.6f V AIN2= %.6f V AIN3= %.6f V ", v0,v1,v2,v3);fflush(stdout);// 轻微节流usleep(1000);}// 不会到达write_cmd(CMD_STOP1);spi_close();gpio_unexport(PIN_DRDY);gpio_unexport(PIN_RESET);gpio_unexport(PIN_CS);return 0;
}
makefile
CC = gcc
CFLAGS = -Wall -O2
LDFLAGS=TARGET = ads1263
SRC = main.c
OBJ = $(SRC:.c=.o)all: $(TARGET)$(TARGET): $(OBJ)$(CC) $(OBJ) -o $@ $(LDFLAGS)%.o: %.c$(CC) $(CFLAGS) -c $< -o $@clean:rm -f $(OBJ) $(TARGET)

pigpio 库 (兼容性一般)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pigpio.h>
#include <time.h>// 引脚定义 (BCM)
#define PIN_DRDY 17 // BCM17 (Data Ready)
#define PIN_RESET 18 // BCM18 (Reset)
#define PIN_CS 22 // BCM22 (Chip Select)// 命令与寄存器
#define CMD_RESET 0x06
#define CMD_START1 0x08
#define CMD_STOP1 0x0A
#define CMD_RDATA1 0x12
#define CMD_RREG 0x20
#define CMD_WREG 0x40
#define REG_MODE2 0x05
#define REG_INPMUX 0x06
#define REG_REFMUX 0x0F// 参考选择:AVDD-AVSS
#define REF_AVDD 0x24
// AIN 编码
#define AINCOM 0x0A// 初始化 SPI 设置
#define SPI_CHANNEL 0
#define SPI_SPEED 500000 // 500 kHz(适当减慢 SPI 时钟频率)
#define SPI_BITS 8// 初始化 ADS1263
void init_ads1263(int spi_handle){uint8_t tx[3] = {CMD_RESET, 0x00, 0x00};gpioWrite(PIN_CS, 0);spiWrite(spi_handle, (char*)tx, 3);gpioWrite(PIN_CS, 1);gpioDelay(50000); // 延时50000微秒,等待重置完成
}// 选择单端模式
void select_single_ended(int spi_handle, uint8_t pos_ain){uint8_t tx[3] = {REG_REFMUX, REF_AVDD, 0x00};gpioWrite(PIN_CS, 0);spiWrite(spi_handle, (char*)tx, 3);gpioWrite(PIN_CS, 1);tx[0] = REG_INPMUX;tx[1] = (pos_ain << 4) | AINCOM;gpioWrite(PIN_CS, 0);spiWrite(spi_handle, (char*)tx, 3);gpioWrite(PIN_CS, 1);gpioDelay(20000); // MUX切换延时
}// 读取数据
int32_t read_data(int spi_handle){uint8_t tx[7] = {CMD_RDATA1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};uint8_t rx[7];gpioWrite(PIN_CS, 0);spiXfer(spi_handle, (char*)tx, (char*)rx, 7);gpioWrite(PIN_CS, 1);int32_t val = ((int32_t)rx[2] << 24) | ((int32_t)rx[3] << 16) |((int32_t)rx[4] << 8) | ((int32_t)rx[5]);return val;
}// 计算电压
double calculate_voltage(int32_t raw_data, double vref, int gain) {return ((double)raw_data / 2147483648.0) * (vref / gain);
}// 等待数据准备好
int wait_drdy(double timeout_s){uint64_t t0 = gpioTick();while(1){if (gpioRead(PIN_DRDY) == 0) {printf("Data is ready!\n"); // Debug: Data is readyreturn 0;}if ((gpioTick() - t0) > (timeout_s * 1000000)) break;}printf("Timeout while waiting for data!\n"); // Debug: Timeoutreturn -1;
}int main(void){if (gpioInitialise() < 0) {printf("GPIO initialization failed\n");return 1;}// 设置引脚gpioSetMode(PIN_DRDY, PI_INPUT);gpioSetMode(PIN_RESET, PI_OUTPUT);gpioSetMode(PIN_CS, PI_OUTPUT);gpioWrite(PIN_CS, 1); // 拉高CSgpioWrite(PIN_RESET, 1); // 拉高RESET// 打开SPI通道int spi_handle = spiOpen(SPI_CHANNEL, SPI_SPEED, 0);if (spi_handle < 0) {printf("Failed to open SPI\n");gpioTerminate();return 1;}printf("ADS1263 initialized.\n");init_ads1263(spi_handle);printf("Reset complete.\n");// 参考电压和增益const double vref = 3.3; // 确保参考电压为 5Vconst int gain = 1; // 假设增益为1// 选择 AIN0 并启动select_single_ended(spi_handle, 0);uint8_t tx[1] = {CMD_START1};gpioWrite(PIN_CS, 0);spiWrite(spi_handle, (char*)tx, 1);gpioWrite(PIN_CS, 1);printf("Started sampling...\n");// 丢弃第一帧if (wait_drdy(0.5) == 0) (void)read_data(spi_handle);// 采集数据并计算电压int32_t code = read_data(spi_handle);double voltage = calculate_voltage(code, vref, gain);// 输出电压printf("AIN0 Voltage: %.6f V\n", voltage);// 停止采样tx[0] = CMD_STOP1;gpioWrite(PIN_CS, 0);spiWrite(spi_handle, (char*)tx, 1);gpioWrite(PIN_CS, 1);spiClose(spi_handle);gpioTerminate();return 0;
}