Last active
December 10, 2024 12:44
-
-
Save patrickelectric/a2751a4e622ef84473364ebc36bcda87 to your computer and use it in GitHub Desktop.
Test SPI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <sys/ioctl.h> | |
#include <linux/gpio.h> | |
#include <linux/spi/spidev.h> | |
#include <cstring> | |
#define GPIO_CHIP_PATH "/dev/gpiochip4" | |
#define SPI_DEVICE_PATH "/dev/spidev1.0" | |
#define GPIO_CS_LINE 16 | |
int main() { | |
int chip_fd = open(GPIO_CHIP_PATH, O_RDWR | O_CLOEXEC); | |
if (chip_fd < 0) { | |
perror("Failed to open GPIO chip"); | |
return -1; | |
} | |
// Request the GPIO line using the GPIO v2 interface | |
struct gpio_v2_line_request req; | |
memset(&req, 0, sizeof(req)); | |
req.offsets[0] = GPIO_CS_LINE; // The GPIO line offset | |
req.num_lines = 1; | |
req.config.flags = GPIO_V2_LINE_FLAG_OUTPUT; | |
req.config.num_attrs = 0; | |
if (ioctl(chip_fd, GPIO_V2_GET_LINE_IOCTL, &req) < 0) { | |
perror("Failed to get line handle"); | |
close(chip_fd); | |
return -1; | |
} | |
int spi_fd = open(SPI_DEVICE_PATH, O_RDWR); | |
if (spi_fd < 0) { | |
perror("Failed to open SPI device"); | |
close(req.fd); | |
close(chip_fd); | |
return -1; | |
} | |
// Configure SPI settings | |
uint8_t mode = SPI_MODE_0; | |
if (ioctl(spi_fd, SPI_IOC_WR_MODE, &mode) < 0) { | |
perror("Failed to set SPI mode"); | |
close(spi_fd); | |
close(req.fd); | |
close(chip_fd); | |
return -1; | |
} | |
uint8_t bits_per_word = 8; | |
if (ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &bits_per_word) < 0) { | |
perror("Failed to set bits per word"); | |
close(spi_fd); | |
close(req.fd); | |
close(chip_fd); | |
return -1; | |
} | |
uint32_t speed = 1000000; | |
if (ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) { | |
perror("Failed to set max speed Hz"); | |
close(spi_fd); | |
close(req.fd); | |
close(chip_fd); | |
return -1; | |
} | |
// Prepare to control the CS line | |
struct gpio_v2_line_values values; | |
memset(&values, 0, sizeof(values)); | |
values.mask = 1 << 0; // Only one line, line 0 in our request | |
// Pull CS low | |
values.bits = 0; // Set line 0 to 0 (CS low) | |
if (ioctl(req.fd, GPIO_V2_LINE_SET_VALUES_IOCTL, &values) < 0) { | |
perror("Failed to set CS low"); | |
close(spi_fd); | |
close(req.fd); | |
close(chip_fd); | |
return -1; | |
} | |
// Prepare SPI transfer buffers | |
uint8_t tx_buffer[2]; | |
uint8_t rx_buffer[2]; | |
tx_buffer[0] = 0x75 | 0x80; // Read command for WHO_AM_I register | |
tx_buffer[1] = 0x00; // Dummy byte to receive data | |
struct spi_ioc_transfer spi_transfer; | |
memset(&spi_transfer, 0, sizeof(spi_transfer)); | |
spi_transfer.tx_buf = reinterpret_cast<unsigned long>(tx_buffer); | |
spi_transfer.rx_buf = reinterpret_cast<unsigned long>(rx_buffer); | |
spi_transfer.len = 2; | |
spi_transfer.speed_hz = speed; | |
spi_transfer.bits_per_word = bits_per_word; | |
spi_transfer.delay_usecs = 0; | |
// Perform the SPI transfer | |
int ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &spi_transfer); | |
if (ret < 1) { | |
perror("Failed to perform SPI transfer"); | |
close(spi_fd); | |
close(req.fd); | |
close(chip_fd); | |
return -1; | |
} | |
// Pull CS high | |
values.bits = 1 << 0; // Set line 0 to 1 (CS high) | |
if (ioctl(req.fd, GPIO_V2_LINE_SET_VALUES_IOCTL, &values) < 0) { | |
perror("Failed to set CS high"); | |
close(spi_fd); | |
close(req.fd); | |
close(chip_fd); | |
return -1; | |
} | |
// Read and verify the WHO_AM_I register | |
uint8_t who_am_i = rx_buffer[1]; | |
std::cout << "WHO_AM_I register value: 0x" << std::hex << static_cast<int>(who_am_i) << std::dec << std::endl; | |
if (who_am_i == 0x12) { | |
std::cout << "WHO_AM_I value is correct." << std::endl; | |
} else { | |
std::cout << "WHO_AM_I value is incorrect." << std::endl; | |
} | |
// Cleanup | |
close(spi_fd); | |
close(req.fd); | |
close(chip_fd); | |
return 0; | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdint> | |
#include <cstdio> | |
#include <cstring> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <sys/ioctl.h> | |
#include <linux/spi/spidev.h> | |
int main() { | |
int fd = open("/dev/spidev1.2", O_RDWR); | |
if (fd < 0) return -1; | |
uint8_t mode = SPI_MODE_3; // Try SPI_MODE_3 if SPI_MODE_0 returns 0x00 | |
ioctl(fd, SPI_IOC_WR_MODE, &mode); | |
uint8_t bits = 8; | |
ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); | |
uint32_t speed = 1000000; | |
ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); | |
// WHO_AM_I register: 0x75. For read: set MSB = 1 (0x80) | |
uint8_t tx[2], rx[2]; | |
memset(tx, 0, sizeof(tx)); | |
memset(rx, 0, sizeof(rx)); | |
tx[0] = 0x75 | 0x80; | |
tx[1] = 0x00; // dummy byte | |
struct spi_ioc_transfer tr[2] = {}; | |
// Send address | |
tr[0].tx_buf = (unsigned long)&tx[0]; | |
tr[0].rx_buf = (unsigned long)&rx[0]; | |
tr[0].len = 1; | |
tr[0].speed_hz = speed; | |
tr[0].bits_per_word = bits; | |
// Read data | |
tr[1].tx_buf = (unsigned long)&tx[1]; | |
tr[1].rx_buf = (unsigned long)&rx[1]; | |
tr[1].len = 1; | |
tr[1].speed_hz = speed; | |
tr[1].bits_per_word = bits; | |
// Perform transaction | |
if (ioctl(fd, SPI_IOC_MESSAGE(2), &tr) < 1) { | |
close(fd); | |
return -1; | |
} | |
close(fd); | |
printf("WHO_AM_I: 0x%02X\n", rx[1]); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment