`)
1. 图形化配置界面中打开spi对应内核配置文件1 CONFIG_SPIy 2 CONFIG_SPI_DEBUGy 3 CONFIG_SPI_MASTERy 4 CONFIG_SPI_MEMy 5 CONFIG_SPI_BITBANGy 6 CONFIG_SPI_ROCKCHIPy 7 CONFIG_SPI_SPIDEVy 8 CONFIG_SPI_LOOPBACK_TESTm 9 CONFIG_SPI_SLAVEy 10 CONFIG_SPI_SLAVE_TIMEy 11 CONFIG_SPI_SLAVE_SYSTEM_CONTROLy编译内核rk35568_linux_sdk/下 ./build.sh kernel3. 设备树添加spi节点kernel/arch/arm64/boot/dts/rockchip/rk3568-atk-evb1-ddr4-v10.dtsispi1 { status okay; pinctrl-names default,high_speed; pinctrl-0 spi1m1_pins; pinctrl-1 spi1m1_pins_hs; cs-gpios gpio3 RK_PA1 GPIO_ACTIVE_LOW; // 片选用法与上面同理硬件CS与GPIO CS二选一 spidev0 { compatible linux,spidev; /* 有的主线更严格可用 rohm,dh2228fv 旧兼容ID蹭上 */ reg 0; spi-max-frequency 10000000; status okay; }; };我只用过“linux,spidev”编译、下载boot4. 在/dev中可以看到spidev1.0“linux,spidev”-驱动匹配了字符设备-用户接口dmesg | grep spi*有日志内容内核内核驱动初始化完成5.spi#include stdio.h #include stdlib.h #include unistd.h #include fcntl.h #include sys/ioctl.h #include linux/spi/spidev.h #include stdint.h #include string.h #include math.h // BMP280寄存器地址 #define BMP280_REG_CHIP_ID 0xD0 #define BMP280_REG_RESET 0xE0 #define BMP280_REG_STATUS 0xF3 #define BMP280_REG_CTRL_MEAS 0xF4 #define BMP280_REG_CONFIG 0xF5 #define BMP280_REG_PRESS_MSB 0xF7 #define BMP280_REG_PRESS_LSB 0xF8 #define BMP280_REG_PRESS_XLSB 0xF9 #define BMP280_REG_TEMP_MSB 0xFA #define BMP280_REG_TEMP_LSB 0xFB #define BMP280_REG_TEMP_XLSB 0xFC #define BMP280_REG_CALIB_DATA 0x88 // SPI读写标志 #define SPI_READ_FLAG 0x80 #define SPI_WRITE_FLAG 0x00 // 校准参数结构体 struct bmp280_calib_param { uint16_t dig_T1; int16_t dig_T2; int16_t dig_T3; uint16_t dig_P1; int16_t dig_P2; int16_t dig_P3; int16_t dig_P4; int16_t dig_P5; int16_t dig_P6; int16_t dig_P7; int16_t dig_P8; int16_t dig_P9; int32_t t_fine; }; int spi_init(const char* device, uint32_t speed, uint8_t mode) { int fd open(device, O_RDWR); if (fd 0) { perror(无法打开SPI设备); return -1; } // 设置SPI模式 if (ioctl(fd, SPI_IOC_WR_MODE, mode) 0) { perror(无法设置SPI模式); close(fd); return -1; } // 设置SPI位宽8位 uint8_t bits 8; if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, bits) 0) { perror(无法设置SPI位宽); close(fd); return -1; } // 设置SPI速度 if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, speed) 0) { perror(无法设置SPI速度); close(fd); return -1; } return fd; } // SPI单字节写函数 int spi_write_byte(int fd, uint8_t reg, uint8_t value) { uint8_t tx_buf[2] {reg 0x7F, value}; // 写操作清除最高位 uint8_t rx_buf[2] {0}; struct spi_ioc_transfer tr { .tx_buf (unsigned long)tx_buf, .rx_buf (unsigned long)rx_buf, .len 2, .delay_usecs 0, .speed_hz 1000000, .bits_per_word 8, }; if (ioctl(fd, SPI_IOC_MESSAGE(1), tr) 0) { perror(SPI写操作失败); return -1; } return 0; } // SPI单字节读函数 int spi_read_byte(int fd, uint8_t reg, uint8_t *value) { uint8_t tx_buf[2] {reg | SPI_READ_FLAG, 0x00}; // 读操作设置最高位 uint8_t rx_buf[2] {0}; struct spi_ioc_transfer tr { .tx_buf (unsigned long)tx_buf, .rx_buf (unsigned long)rx_buf, .len 2, .delay_usecs 0, .speed_hz 1000000, .bits_per_word 8, }; if (ioctl(fd, SPI_IOC_MESSAGE(1), tr) 0) { perror(SPI读操作失败); return -1; } *value rx_buf[1]; return 0; } // SPI多字节突发读取重要保证数据一致性 int spi_read_burst(int fd, uint8_t start_reg, uint8_t *buffer, int length) { uint8_t tx_buf[length 1]; uint8_t rx_buf[length 1]; // 设置起始寄存器读模式 tx_buf[0] start_reg | SPI_READ_FLAG; memset(tx_buf[1], 0x00, length); // 填充空数据以产生时钟 struct spi_ioc_transfer tr { .tx_buf (unsigned long)tx_buf, .rx_buf (unsigned long)rx_buf, .len length 1, .delay_usecs 0, .speed_hz 1000000, .bits_per_word 8, }; if (ioctl(fd, SPI_IOC_MESSAGE(1), tr) 0) { perror(SPI突发读取失败); return -1; } // 复制接收到的数据跳过第一个字节 memcpy(buffer, rx_buf[1], length); return 0; } int bmp280_spi_init(int fd, struct bmp280_calib_param *calib) { uint8_t chip_id; // 读取芯片ID确认连接 if (spi_read_byte(fd, BMP280_REG_CHIP_ID, chip_id) 0) { return -1; } if (chip_id ! 0x58) { fprintf(stderr, BMP280未找到芯片ID: 0x%02X\n, chip_id); return -1; } printf(BMP280检测成功芯片ID: 0x%02X\n, chip_id); // 读取校准参数突发读取 uint8_t calib_data[24]; if (spi_read_burst(fd, BMP280_REG_CALIB_DATA, calib_data, 24) 0) { return -1; } // 解析校准参数小端格式 calib-dig_T1 (calib_data[1] 8) | calib_data[0]; calib-dig_T2 (calib_data[3] 8) | calib_data[2]; calib-dig_T3 (calib_data[5] 8) | calib_data[4]; calib-dig_P1 (calib_data[7] 8) | calib_data[6]; calib-dig_P2 (calib_data[9] 8) | calib_data[8]; calib-dig_P3 (calib_data[11] 8) | calib_data[10]; calib-dig_P4 (calib_data[13] 8) | calib_data[12]; calib-dig_P5 (calib_data[15] 8) | calib_data[14]; calib-dig_P6 (calib_data[17] 8) | calib_data[16]; calib-dig_P7 (calib_data[19] 8) | calib_data[18]; calib-dig_P8 (calib_data[21] 8) | calib_data[20]; calib-dig_P9 (calib_data[23] 8) | calib_data[22]; // 软件复位 if (spi_write_byte(fd, BMP280_REG_RESET, 0xB6) 0) { return -1; } usleep(10000); // 等待复位完成 // 配置传感器根据文档第4.3.4和4.3.5节 // 设置测量控制温度4倍过采样压力4倍过采样正常模式 if (spi_write_byte(fd, BMP280_REG_CTRL_MEAS, 0xB7) 0) { // osrs_t2, osrs_p2, mode3 return -1; } // 设置配置standby时间500ms滤波器系数16 if (spi_write_byte(fd, BMP280_REG_CONFIG, 0x94) 0) { // t_sb101, filter100, spi3w_en0 return -1; } calib-t_fine 0; return 0; } // 温度补偿函数文档第3.11.3节 int32_t bmp280_compensate_temperature(struct bmp280_calib_param *calib, int32_t adc_T) { int32_t var1, var2, T; var1 ((((adc_T 3) - ((int32_t)calib-dig_T1 1))) * ((int32_t)calib-dig_T2)) 11; var2 (((((adc_T 4) - ((int32_t)calib-dig_T1)) * ((adc_T 4) - ((int32_t)calib-dig_T1))) 12) * ((int32_t)calib-dig_T3)) 14; calib-t_fine var1 var2; T (calib-t_fine * 5 128) 8; return T; } // 压力补偿函数文档第3.11.3节 uint32_t bmp280_compensate_pressure(struct bmp280_calib_param *calib, int32_t adc_P) { int64_t var1, var2, p; var1 ((int64_t)calib-t_fine) - 128000; var2 var1 * var1 * (int64_t)calib-dig_P6; var2 var2 ((var1 * (int64_t)calib-dig_P5) 17); var2 var2 (((int64_t)calib-dig_P4) 35); var1 ((var1 * var1 * (int64_t)calib-dig_P3) 8) ((var1 * (int64_t)calib-dig_P2) 12); var1 (((((int64_t)1) 47) var1)) * ((int64_t)calib-dig_P1) 33; if (var1 0) { return 0; } p 1048576 - adc_P; p (((p 31) - var2) * 3125) / var1; var1 (((int64_t)calib-dig_P9) * (p 13) * (p 13)) 25; var2 (((int64_t)calib-dig_P8) * p) 19; p ((p var1 var2) 8) (((int64_t)calib-dig_P7) 4); return (uint32_t)p; } int read_bmp280_pressure_spi(int fd, struct bmp280_calib_param *calib, double *pressure_hPa, double *temperature_c) { uint8_t data[6]; // 使用突发读取获取压力和温度数据文档第3.9节 if (spi_read_burst(fd, BMP280_REG_PRESS_MSB, data, 6) 0) { return -1; } // 检查数据是否就绪 uint8_t status; if (spi_read_byte(fd, BMP280_REG_STATUS, status) 0) { return -1; } if (status 0x08) { // 测量进行中 printf(测量进行中等待完成...\n); int timeout 100; while ((status 0x08) timeout 0) { usleep(1000); spi_read_byte(fd, BMP280_REG_STATUS, status); timeout--; } if (timeout 0) { fprintf(stderr, 测量超时\n); return -1; } // 重新读取数据 if (spi_read_burst(fd, BMP280_REG_PRESS_MSB, data, 6) 0) { return -1; } } // 组合20位原始数据 int32_t adc_P ((data[0] 12) | (data[1] 4) | (data[2] 4)); int32_t adc_T ((data[3] 12) | (data[4] 4) | (data[5] 4)); // 补偿计算 int32_t temp_comp bmp280_compensate_temperature(calib, adc_T); uint32_t press_comp bmp280_compensate_pressure(calib, adc_P); // 转换为常用单位 *temperature_c temp_comp / 100.0; *pressure_hPa press_comp / 256.0 / 100.0; return 0; } int main() { int fd; const char *spi_device /dev/spidev1.0; // 根据实际SPI设备调整 struct bmp280_calib_param calib; // 初始化SPI模式0速度1MHz fd spi_init(spi_device, 100000, 0); if (fd 0) { fprintf(stderr, SPI初始化失败\n); return 1; } // 初始化BMP280 if (bmp280_spi_init(fd, calib) 0) { fprintf(stderr, BMP280 SPI初始化失败\n); close(fd); return 1; } printf(BMP280 SPI初始化成功\n); // 连续读取示例 for (int i 0; i 10; i) { double pressure_hPa, temperature_c; if (read_bmp280_pressure_spi(fd, calib, pressure_hPa, temperature_c) 0) { printf(读数 %d: 温度 %.2f°C, 压强 %.2f hPa, 海拔 ≈ %.1f米\n, i 1, temperature_c, pressure_hPa, (1 - pow(pressure_hPa / 1013.25, 0.190284)) * 44307.7); } else { fprintf(stderr, 读取失败\n); } sleep(1); // 每秒读取一次 } close(fd); return 0; }iic#include stdio.h #include stdlib.h #include unistd.h #include fcntl.h #include sys/ioctl.h #include linux/i2c-dev.h #include stdint.h #include math.h // BMP280寄存器地址 #define BMP280_REG_CHIP_ID 0xD0 #define BMP280_REG_RESET 0xE0 #define BMP280_REG_STATUS 0xF3 #define BMP280_REG_CTRL_MEAS 0xF4 #define BMP280_REG_CONFIG 0xF5 #define BMP280_REG_PRESS_MSB 0xF7 #define BMP280_REG_PRESS_LSB 0xF8 #define BMP280_REG_PRESS_XLSB 0xF9 #define BMP280_REG_TEMP_MSB 0xFA #define BMP280_REG_TEMP_LSB 0xFB #define BMP280_REG_TEMP_XLSB 0xFC #define BMP280_REG_CALIB_DATA 0x88 // BMP280校准参数结构体 struct bmp280_calib_param { uint16_t dig_T1; int16_t dig_T2; int16_t dig_T3; uint16_t dig_P1; int16_t dig_P2; int16_t dig_P3; int16_t dig_P4; int16_t dig_P5; int16_t dig_P6; int16_t dig_P7; int16_t dig_P8; int16_t dig_P9; int32_t t_fine; }; // I2C写函数 int i2c_write_byte(int fd, uint8_t reg, uint8_t value) { uint8_t buf[2] {reg, value}; if (write(fd, buf, 2) ! 2) { perror(I2C write failed); return -1; } return 0; } // I2C读函数 int i2c_read_bytes(int fd, uint8_t reg, uint8_t *buf, int len) { if (write(fd, reg, 1) ! 1) { perror(I2C register select failed); return -1; } if (read(fd, buf, len) ! len) { perror(I2C read failed); return -1; } return 0; } int bmp280_init(int fd, struct bmp280_calib_param *calib) { uint8_t chip_id; // 读取芯片ID确认连接 if (i2c_read_bytes(fd, BMP280_REG_CHIP_ID, chip_id, 1) 0) { return -1; } if (chip_id ! 0x58) { fprintf(stderr, BMP280 not found, chip ID: 0x%02X\n, chip_id); return -1; } printf(BMP280 detected, chip ID: 0x%02X\n, chip_id); // 读取校准参数 uint8_t calib_data[24]; if (i2c_read_bytes(fd, BMP280_REG_CALIB_DATA, calib_data, 24) 0) { return -1; } // 解析校准参数小端格式 calib-dig_T1 (calib_data[1] 8) | calib_data[0]; calib-dig_T2 (calib_data[3] 8) | calib_data[2]; calib-dig_T3 (calib_data[5] 8) | calib_data[4]; calib-dig_P1 (calib_data[7] 8) | calib_data[6]; calib-dig_P2 (calib_data[9] 8) | calib_data[8]; calib-dig_P3 (calib_data[11] 8) | calib_data[10]; calib-dig_P4 (calib_data[13] 8) | calib_data[12]; calib-dig_P5 (calib_data[15] 8) | calib_data[14]; calib-dig_P6 (calib_data[17] 8) | calib_data[16]; calib-dig_P7 (calib_data[19] 8) | calib_data[18]; calib-dig_P8 (calib_data[21] 8) | calib_data[20]; calib-dig_P9 (calib_data[23] 8) | calib_data[22]; // 配置传感器文档第4.3.4和4.3.5节 // 设置测量控制温度4倍过采样压力4倍过采样强制模式 if (i2c_write_byte(fd, BMP280_REG_CTRL_MEAS, 0x93) 0) { // osrs_t2, osrs_p2, mode1 return -1; } // 设置配置standby时间500ms滤波器关闭 if (i2c_write_byte(fd, BMP280_REG_CONFIG, 0x00) 0) { // t_sb000, filter000, spi3w_en0 return -1; } calib-t_fine 0; return 0; } int32_t bmp280_compensate_temperature(struct bmp280_calib_param *calib, int32_t adc_T) { int32_t var1, var2, T; var1 ((((adc_T 3) - ((int32_t)calib-dig_T1 1))) * ((int32_t)calib-dig_T2)) 11; var2 (((((adc_T 4) - ((int32_t)calib-dig_T1)) * ((adc_T 4) - ((int32_t)calib-dig_T1))) 12) * ((int32_t)calib-dig_T3)) 14; calib-t_fine var1 var2; T (calib-t_fine * 5 128) 8; return T; // 返回温度值单位0.01°C } uint32_t bmp280_compensate_pressure(struct bmp280_calib_param *calib, int32_t adc_P) { int64_t var1, var2, p; var1 ((int64_t)calib-t_fine) - 128000; var2 var1 * var1 * (int64_t)calib-dig_P6; var2 var2 ((var1 * (int64_t)calib-dig_P5) 17); var2 var2 (((int64_t)calib-dig_P4) 35); var1 ((var1 * var1 * (int64_t)calib-dig_P3) 8) ((var1 * (int64_t)calib-dig_P2) 12); var1 (((((int64_t)1) 47) var1)) * ((int64_t)calib-dig_P1) 33; if (var1 0) { return 0; // 避免除零错误 } p 1048576 - adc_P; p (((p 31) - var2) * 3125) / var1; var1 (((int64_t)calib-dig_P9) * (p 13) * (p 13)) 25; var2 (((int64_t)calib-dig_P8) * p) 19; p ((p var1 var2) 8) (((int64_t)calib-dig_P7) 4); return (uint32_t)p; // 返回压力值单位Pa/256 } int read_bmp280_pressure(int fd, struct bmp280_calib_param *calib, double *pressure_hPa, double *temperature_c) { uint8_t data[6]; // 触发单次测量强制模式 if (i2c_write_byte(fd, BMP280_REG_CTRL_MEAS, 0x93) 0) { return -1; } // 等待测量完成检查状态寄存器 uint8_t status; int timeout 100; // 最大等待100ms do { usleep(1000); // 等待1ms if (i2c_read_bytes(fd, BMP280_REG_STATUS, status, 1) 0) { return -1; } timeout--; } while ((status 0x08) timeout 0); // 检查measuring位文档第4.3.3节 if (timeout 0) { fprintf(stderr, Measurement timeout\n); return -1; } // 读取压力和温度数据文档第3.9节突发读取 if (i2c_read_bytes(fd, BMP280_REG_PRESS_MSB, data, 6) 0) { return -1; } // 组合20位原始数据 int32_t adc_P ((data[0] 12) | (data[1] 4) | (data[2] 4)); int32_t adc_T ((data[3] 12) | (data[4] 4) | (data[5] 4)); // 补偿计算 int32_t temp_comp bmp280_compensate_temperature(calib, adc_T); uint32_t press_comp bmp280_compensate_pressure(calib, adc_P); // 转换为常用单位 *temperature_c temp_comp / 100.0; // 转换为°C *pressure_hPa press_comp / 256.0 / 100.0; // 转换为hPa return 0; } int main() { int fd; const char *i2c_device /dev/i2c-4; // 根据实际I2C总线调整 const int bmp280_addr 0x76; // 或0x77取决于SDO引脚 // 打开I2C设备 if ((fd open(i2c_device, O_RDWR)) 0) { perror(Failed to open I2C device); return 1; } // 设置I2C从设备地址 if (ioctl(fd, I2C_SLAVE, bmp280_addr) 0) { perror(Failed to set I2C address); close(fd); return 1; } struct bmp280_calib_param calib; // 初始化BMP280 if (bmp280_init(fd, calib) 0) { fprintf(stderr, BMP280 initialization failed\n); close(fd); return 1; } printf(BMP280 initialized successfully\n); // 读取压强和温度值 double pressure_hPa, temperature_c; if (read_bmp280_pressure(fd, calib, pressure_hPa, temperature_c) 0) { printf(Temperature: %.2f °C\n, temperature_c); printf(Pressure: %.2f hPa\n, pressure_hPa); printf(Pressure: %.2f mmHg\n, pressure_hPa * 0.750062); } else { fprintf(stderr, Failed to read pressure\n); } close(fd); return 0; }内核源码 .config → 编译 → Image dts源码 dtc工具 → 编译 → dtb 打包 → boot.img