我正在致力于在 Raspberry Pi (SPI1、CS1) 上使用 SPI 通信连接 MAX5144 DAC。下面是我的主程序和我的SPI测试程序。
主程序初始化DAC并设置输出值,但遇到以下错误:
wiringPiSPI: Invalid SPI number/channel (need wiringPiSPIxSetupMode before read/write)
SPI测试程序运行成功,确认SPI1和CS1设置正确。
cmake_minimum_required(VERSION 3.10)
project(TemperatureControlProject)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS "-g")
# Add custom module path for FindWiringPi.cmake
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
include_directories(include)
# Main project executable
add_executable(TemperatureControlProject src/main.cpp src/MAX5144.cpp)
find_package(WiringPi REQUIRED)
target_link_libraries(TemperatureControlProject ${WIRINGPI_LIBRARY})
# SPI test executable
add_executable(SPITest src/spi_test.cpp)
target_link_libraries(SPITest -lwiringPi)
#include "MAX5144.h"
#include <iostream>
int main() {
try {
MAX5144 dac(1, 17); // SPI channel 1, CS pin GPIO17
dac.setDacOutput(4854); // Set DAC output value
std::cout << "DAC output successfully set." << std::endl;
} catch (const std::exception &e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
#include "MAX5144.h"
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <iostream>
#include <stdexcept>
MAX5144::MAX5144(int spiChannel, int csPin) : csPin(csPin) {
wiringPiSetup();
pinMode(csPin, OUTPUT);
digitalWrite(csPin, HIGH);
if (wiringPiSPISetupMode(spiChannel, 500000, 0) < 0) {
throw std::runtime_error("SPI initialization failed!");
}
}
void MAX5144::setDacOutput(int value) {
if (value < 0 || value >= 16384) {
throw std::invalid_argument("DAC value out of range!");
}
int dataWord = value << 2;
unsigned char msb = (dataWord >> 8) & 0xFF;
unsigned char lsb = dataWord & 0xFF;
digitalWrite(csPin, LOW);
unsigned char buffer[2] = {msb, lsb};
wiringPiSPIDataRW(1, buffer, 2); // SPI channel 1
digitalWrite(csPin, HIGH);
std::cout << "DAC output set to: " << value << std::endl;
}
MAX5144::~MAX5144() {}
#include <wiringPiSPI.h>
#include <iostream>
#include <stdexcept>
int main() {
int spiChannel = 1; // Using SPI1
int speed = 500000; // SPI speed
int mode = 0; // SPI mode 0
if (wiringPiSPISetupMode(spiChannel, speed, mode) < 0) {
throw std::runtime_error("SPI1 initialization failed!");
}
std::cout << "SPI1 initialized successfully!" << std::endl;
unsigned char buffer[2] = {0xFF, 0x00}; // Test data
if (wiringPiSPIDataRW(spiChannel, buffer, 2) < 0) {
throw std::runtime_error("SPI1 data transfer failed!");
}
std::cout << "SPI1 data sent successfully!" << std::endl;
return 0;
}
硬件测试结果:DAC 在使用 Python 控制时工作完美,因此 SPI 设置或 MAX5144 IC 不存在与硬件相关的问题。
观察到的错误:主程序中的错误表明 SPI 通道初始化 (wiringPiSPISetupMode) 存在问题,但 SPI 测试程序验证 SPI1 和 CS1 是否按预期运行。
wiringPiSPIDataRW(1, ...)
方法中使用 MAX5144::setDacOutput
是否正确?wiringPiSPIxSetupMode
与MAX5144在彻底调查问题并尝试各种配置后,我成功地使用 SPI1 和 CS1 上的
wiringPiSPIxSetupMode
与 Raspberry Pi 连接 MAX5144 DAC。下面是该方法和解决方案的详细分解。
设备概述:
MAX5144 DAC需要SPI通信来进行数模转换。 SPI 参数必须符合以下条件:
问题陈述:
最初尝试使用
wiringPiSPISetupMode
导致了错误:
wiringPiSPI: Invalid SPI number/channel (need wiringPiSPIxSetupMode before read/write)
此错误表示磁带库和硬件配置之间的设置不正确或不一致。
遇到的挑战:
wiringPiSPISetupMode
默认为 SPI0。通过利用支持多总线 SPI 配置的
wiringPiSPIxSetupMode
解决了该问题。下面是重构后的实现。
#include "MAX5144.h"
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <stdexcept>
#include <iostream>
// Constructor
MAX5144::MAX5144(int spiNumber, int spiChannel, int csPin, int speed, int mode)
: spiNumber(spiNumber), spiChannel(spiChannel), csPin(csPin) {
// Initialize GPIO for CS
if (wiringPiSetup() < 0) {
throw std::runtime_error("Failed to initialize WiringPi!");
}
pinMode(csPin, OUTPUT);
digitalWrite(csPin, HIGH); // Default to deselected state
// Initialize SPI
if (wiringPiSPIxSetupMode(spiNumber, spiChannel, speed, mode) < 0) {
throw std::runtime_error("SPI initialization failed for SPI" + std::to_string(spiNumber) +
", Channel " + std::to_string(spiChannel));
}
std::cout << "SPI initialized on SPI" << spiNumber << ", Channel " << spiChannel << std::endl;
}
// Set DAC Output
void MAX5144::setDacOutput(int value) {
if (value < 0 || value > 16383) {
throw std::invalid_argument("DAC value out of range! Must be between 0 and 16383.");
}
// Prepare data
int dataWord = value << 2; // Align 14-bit value
unsigned char buffer[2] = {
static_cast<unsigned char>((dataWord >> 8) & 0xFF), // MSB
static_cast<unsigned char>(dataWord & 0xFF) // LSB
};
// SPI Transfer
digitalWrite(csPin, LOW); // Select chip
if (wiringPiSPIxDataRW(spiNumber, spiChannel, buffer, 2) < 0) {
throw std::runtime_error("SPI data transfer failed!");
}
digitalWrite(csPin, HIGH); // Deselect chip
std::cout << "DAC output set to: " << value << std::endl;
}
// Destructor
MAX5144::~MAX5144() {
wiringPiSPIClose(spiChannel); // Close SPI channel
}
#include "MAX5144.h"
#include <iostream>
int main() {
try {
MAX5144 dac(1, 1, 17); // SPI1, Channel 1, CS Pin GPIO17
dac.setDacOutput(12345); // Set an example DAC value
std::cout << "DAC successfully configured and output set." << std::endl;
} catch (const std::exception &e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
return 0;
}
wiringPiSPIxSetupMode
与正确的 SPI 总线 (1
) 和通道 (1
) 一起使用解决了初始化问题。gdb
等工具进行调试并使用示波器验证 SPI 通信有助于识别时序问题。对于初学者来说,配置 CMake 可能是一个挑战。以下是用于此项目的
CMakeLists.txt
文件:
cmake_minimum_required(VERSION 3.10)
project(MAX5144_Project)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-g")
# Include directories
include_directories(include)
# Executables
add_executable(MAX5144_TEC_Control src/main.cpp src/MAX5144.cpp)
target_link_libraries(MAX5144_TEC_Control wiringPi)
该实现成功将MAX5144 DAC与Raspberry Pi上的SPI1和CS1集成,实现了TEC应用的精确控制。该解决方案展示了了解硬件要求和有效利用库功能的重要性。
随时分享有关 SPI 与嵌入式系统通信的更多见解或问题! 🎉