今天又进行了SPI的相关测试,化简了测试代码,分别写了上位机的测试代码与下位机的接收代码,当前可以收到SPI的数据,但是CS片选没有起作用,两个STM32同时向总线发送数据,导致数据错误。如果仅使用一个STM32,则两个SPI接收的数据相同。
其中STM32的代码略去了不相干的部分,具体代码可以查看我的仓库1和仓库2
#include <cmath>
#include <iostream>
#include <unistd.h>
#include <byteswap.h>
#include <math.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <linux/spi/spidev.h>
unsigned char spi_mode = SPI_MODE_0; // 时钟极性0,时钟相位0
unsigned char spi_bits_per_word = 8; // 每个字8字节
unsigned int spi_speed = 6000000; // 6M
uint8_t lsb = 0x01;
int spi_1_fd = -1;
int spi_2_fd = -1;
/*!
* Compute SPI message checksum
* @param data : input
* @param len : length (in 32-bit words)
* @return
*/
uint32_t xor_checksum(uint32_t* data, size_t len)
{
uint32_t t = 0;
for (size_t i = 0; i < len; i++)
t = t ^ data[i];
return t;
}
/*!
* Open SPI device
* 启动spi设备
*/
int spi_open()
{
// 打开spi
printf("[RT SPI] Open\n");
int rv = 0; // receive value
// 通过打开文件的方式打开设备吗? fd=file device
spi_1_fd = open("/dev/spidev0.0", O_RDWR); // O_RDWR :文件可读可写
if (spi_1_fd < 0)
perror("[ERROR] Couldn't open spidev 2.0");
spi_2_fd = open("/dev/spidev0.1", O_RDWR);
if (spi_2_fd < 0)
perror("[ERROR] Couldn't open spidev 2.1");
// ioctl:Input output control.设置一些io信息
// spi_mode 设置极性与相位
rv = ioctl(spi_1_fd, SPI_IOC_WR_MODE, &spi_mode);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_wr_mode (1)");
rv = ioctl(spi_2_fd, SPI_IOC_WR_MODE, &spi_mode);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_wr_mode (2)");
rv = ioctl(spi_1_fd, SPI_IOC_RD_MODE, &spi_mode);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_rd_mode (1)");
rv = ioctl(spi_2_fd, SPI_IOC_RD_MODE, &spi_mode);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_rd_mode (2)");
// 设置每个字有几个字节
rv = ioctl(spi_1_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_wr_bits_per_word (1)");
rv = ioctl(spi_2_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_wr_bits_per_word (2)");
rv = ioctl(spi_1_fd, SPI_IOC_RD_BITS_PER_WORD, &spi_bits_per_word);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_rd_bits_per_word (1)");
rv = ioctl(spi_2_fd, SPI_IOC_RD_BITS_PER_WORD, &spi_bits_per_word);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_rd_bits_per_word (2)");
// 设置spi通信速度 6M
rv = ioctl(spi_1_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_wr_max_speed_hz (1)");
rv = ioctl(spi_2_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_wr_max_speed_hz (2)");
rv = ioctl(spi_1_fd, SPI_IOC_RD_MAX_SPEED_HZ, &spi_speed);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_rd_max_speed_hz (1)");
rv = ioctl(spi_2_fd, SPI_IOC_RD_MAX_SPEED_HZ, &spi_speed);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_rd_max_speed_hz (2)");
// 采用lsb模式
rv = ioctl(spi_1_fd, SPI_IOC_RD_LSB_FIRST, &lsb);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_rd_lsb_first (1)");
rv = ioctl(spi_2_fd, SPI_IOC_RD_LSB_FIRST, &lsb);
if (rv < 0)
perror("[ERROR] ioctl spi_ioc_rd_lsb_first (2)");
return rv;
}
void spi_close()
{
close(spi_1_fd);
close(spi_2_fd);
}
std::string hex2str(const uint8_t* str, int len)
{
static const char hexTable[17] = "0123456789ABCDEF";
std::string result;
for (int i = 0; i < len; ++i)
{
result += "0x";
result += hexTable[(unsigned char)str[i] / 16];
result += hexTable[(unsigned char)str[i] % 16];
result += " ";
}
return result;
}
int transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
{
struct spi_ioc_transfer tr = {
.tx_buf = (uint64_t)tx,
.rx_buf = (uint64_t)rx,
.len = len,
.speed_hz = spi_speed,
.delay_usecs = 0,
.bits_per_word = spi_bits_per_word,
.cs_change = 1,
};
int ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
printf("can't send spi message\n");
return ret;
}
int main()
{
spi_open();
uint8_t tx[16];
uint8_t rx_1[16];
uint8_t rx_2[16];
for (int i = 0; i < 16; ++i)
{
tx[i] = i;
}
int rv = transfer(spi_1_fd, tx, rx_1, 16);
(void)rv;
auto str = hex2str(rx_1, 16);
std::cout << "[SPI1]" << str << std::endl;
rv = transfer(spi_2_fd, tx, rx_2, 16);
(void)rv;
str = hex2str(rx_2, 16);
std::cout << "[SPI2]" << str << std::endl;
spi_close();
return 0;
}
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int state = 1;
static uint8_t tx[16];
static uint8_t rx[16];
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_CAN1_Init();
MX_CAN2_Init();
MX_SPI1_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
for(int i = 0; i < 16; ++i)
{
tx[i] = 16 - i;
}
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, state);
HAL_SPI_TransmitReceive_IT(&hspi1, tx, rx, 16);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//HAL_SPI_TransmitReceive(&hspi1, tx, rx, 16, 10);
//HAL_UART_Transmit(&huart2, "hello", 6, 100);
HAL_Delay(1000);
}
/* USER CODE END 3 */
}
/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == SPI_CS_Pin)
{
if(HAL_GPIO_ReadPin(SPI_CS_GPIO_Port, SPI_CS_Pin) == GPIO_PIN_RESET)
{
state = !state;
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, state);
HAL_SPI_TransmitReceive_IT(&hspi1, tx, rx, 16);
}
}
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
// TX Done .. Do Something ...
}
/* USER CODE END 4 */