Files
SOMEIP/source/spi_dev/spi4test.c

165 lines
4.7 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* spi_slave_recv_loop.c - SPI从设备持续接收程序
*
* 功能SoC作为SPI从设备配置与MCU主设备对齐循环接收并打印数据
* MCU每秒发送一帧8字节
*
* MCU主设备配置需对齐
* Mode : SPI_MODE_0 (CPOL=0, CPHA=0)
* Bits/Word : 8
* Speed : 1 MHz
* 发送数据 : {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}
*
* 编译aarch64-linux-gnu-gcc -o spi_slave_recv_loop spi_slave_recv_loop.c
* 运行:./spi_slave_recv_loop
* 退出:按 Ctrl+C
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
/* ========== SPI配置必须与MCU主设备完全一致========== */
#define SPI_DEVICE "/dev/spidev4.0"
#define SPI_MODE SPI_MODE_2 /* CPOL=1, CPHA=1 */
#define SPI_BITS 8
#define SPI_SPEED 1000000 /* 1MHz */
#define FRAME_LEN 128 /* 每帧256字节 */
/* ===================================================== */
static volatile int keep_running = 1;
static int is_all_zero(const uint8_t *buf, int len) {
for (int i = 0; i < len; i++)
if (buf[i] != 0)
return 0;
return 1;
}
void sigint_handler(int sig) {
(void)sig;
keep_running = 0;
printf("\n[INFO] User interrupted, exiting...\n");
}
int main(void)
{
uint8_t rx_buf[FRAME_LEN];
uint8_t tx_buf[FRAME_LEN] = {0xAA, 0xBB, 0xCC, 0xDD};
tx_buf[FRAME_LEN-4] = 0x11;
tx_buf[FRAME_LEN-3] = 0x22;
tx_buf[FRAME_LEN-2] = 0x33;
tx_buf[FRAME_LEN-1] = 0x44;
int fd, ret;
unsigned int frame_count = 0;
/* 注册退出信号 */
signal(SIGINT, sigint_handler);
/* 1. 打开 SPI 设备 */
fd = open(SPI_DEVICE, O_RDWR);
if (fd < 0) {
perror("open " SPI_DEVICE);
return 1;
}
/* 2. 配置 SPI 模式 */
uint8_t mode = SPI_MODE;
mode |= SPI_LSB_FIRST;
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1) {
perror("SPI_IOC_WR_MODE");
close(fd);
return 1;
}
/* 3. 配置每字位数 */
uint8_t bits = SPI_BITS;
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1) {
perror("SPI_IOC_WR_BITS_PER_WORD");
close(fd);
return 1;
}
/* 4. 配置最大时钟频率 */
uint32_t speed = SPI_SPEED;
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1) {
perror("SPI_IOC_WR_MAX_SPEED_HZ");
close(fd);
return 1;
}
/* 5. 回读验证配置 */
ioctl(fd, SPI_IOC_RD_MODE, &mode);
ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
printf("========================================\n");
printf("SPI Slave Config (aligned with MCU)\n");
printf("========================================\n");
printf("Device : %s\n", SPI_DEVICE);
printf("Mode : %d (CPOL=%d, CPHA=%d)\n",
mode, (mode & SPI_CPOL) ? 1 : 0, (mode & SPI_CPHA) ? 1 : 0);
printf("Bits/Word : %d\n", bits);
printf("Max Speed : %d Hz\n", speed);
printf("Frame length: %d bytes\n", FRAME_LEN);
printf("========================================\n");
printf("Waiting for MCU (master) to send data...\n");
printf("Press Ctrl+C to stop.\n\n");
/* 6. 循环接收数据 */
while (keep_running) {
memset(rx_buf, 0, FRAME_LEN);
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx_buf,
.rx_buf = (unsigned long)rx_buf,
.len = FRAME_LEN,
.speed_hz = SPI_SPEED,
.bits_per_word = SPI_BITS,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 0) {
perror("spi transfer");
break;
}
ret = FRAME_LEN; /* transfer 成功则返回 FRAME_LEN */
frame_count++;
/* 只有 tx 或 rx 数据不全为零时才打印 */
if (is_all_zero(tx_buf, FRAME_LEN) && is_all_zero(rx_buf, FRAME_LEN))
continue;
printf("\n========== Frame #%u (%d bytes) ==========\n", frame_count, ret);
if (!is_all_zero(tx_buf, FRAME_LEN)) {
printf("TX HEX: ");
for (int i = 0; i < ret; i++)
printf("0x%02X ", tx_buf[i]);
printf("\n");
}
if (!is_all_zero(rx_buf, FRAME_LEN)) {
printf("RX HEX: ");
for (int i = 0; i < ret; i++)
printf("0x%02X ", rx_buf[i]);
printf("\n");
}
printf("=========================================\n");
}
close(fd);
return 0;
}