如何在SPI1、CS1上正确使用MAX5144 DAC IC的PiSPISetupMode接线?

问题描述 投票:0回答:1

我正在致力于在 Raspberry Pi (SPI1、CS1) 上使用 SPI 通信连接 MAX5144 DAC。下面是我的主程序和我的SPI测试程序。

主程序初始化DAC并设置输出值,但遇到以下错误:

wiringPiSPI: Invalid SPI number/channel (need wiringPiSPIxSetupMode before read/write)

SPI测试程序运行成功,确认SPI1和CS1设置正确。

Cmake:

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;
}

MAX5144.cpp:

#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() {}

SPI 测试程序(正常工作):

#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;
}

附加信息:

  1. 硬件测试结果:DAC 在使用 Python 控制时工作完美,因此 SPI 设置或 MAX5144 IC 不存在与硬件相关的问题。

  2. 观察到的错误:主程序中的错误表明 SPI 通道初始化 (wiringPiSPISetupMode) 存在问题,但 SPI 测试程序验证 SPI1 和 CS1 是否按预期运行。

问题:

  1. 为什么主程序失败并出现有关wiringPiSPI的错误?
  2. SPI测试程序工作正常,那么我如何配置MAX5144类有问题吗?
  3. 对于 SPI1,
    wiringPiSPIDataRW(1, ...)
    方法中使用
    MAX5144::setDacOutput
    是否正确?
c++ raspberry-pi spi dac wiringpi
1个回答
0
投票

答案:在SPI1、CS1上成功使用
wiringPiSPIxSetupMode
与MAX5144

在彻底调查问题并尝试各种配置后,我成功地使用 SPI1 和 CS1 上的

wiringPiSPIxSetupMode
与 Raspberry Pi 连接 MAX5144 DAC。下面是该方法和解决方案的详细分解。


背景与挑战

  1. 设备概述
    MAX5144 DAC需要SPI通信来进行数模转换。 SPI 参数必须符合以下条件:

    • 模式:SPI 模式 0(CPOL = 0,CPHA = 0)。
    • 速度:最大 10 MHz(出于可靠性考虑,我选择 500 kHz)。
    • 数据格式:16位传输,14位左对齐DAC值。
  2. 问题陈述
    最初尝试使用

    wiringPiSPISetupMode
    导致了错误:

    wiringPiSPI: Invalid SPI number/channel (need wiringPiSPIxSetupMode before read/write)
    

    此错误表示磁带库和硬件配置之间的设置不正确或不一致。

  3. 遇到的挑战

    • 多个 SPI 通道:配置 SPI1(总线)和 CS1(通道)并非易事,因为
      wiringPiSPISetupMode
      默认为 SPI0。
    • CS 引脚控制:同步低电平有效 CS 信号对于避免 SPI 传输期间的不稳定行为至关重要。
    • 数据传输:正确格式化 14 位 DAC 数据需要仔细对齐和验证。

解决方案

通过利用支持多总线 SPI 配置的

wiringPiSPIxSetupMode
解决了该问题。下面是重构后的实现。

MAX5144驱动代码

#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;
}

要点

  1. 多总线 SPI 支持:
    wiringPiSPIxSetupMode
    与正确的 SPI 总线 (
    1
    ) 和通道 (
    1
    ) 一起使用解决了初始化问题。
  2. CS 引脚同步:
    正确控制 CS 引脚可确保 MAX5144 不间断地接收 SPI 命令。
  3. 迭代调试:
    使用
    gdb
    等工具进行调试并使用示波器验证 SPI 通信有助于识别时序问题。

CMake 配置

对于初学者来说,配置 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 与嵌入式系统通信的更多见解或问题! 🎉

© www.soinside.com 2019 - 2024. All rights reserved.