This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C123GH6PM:连接 DAC0840S

Guru**** 2765995 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/924857/tm4c123gh6pm-interfacing-with-dac0840s

器件型号:TM4C123GH6PM

我正在使用 SSI0中的 SPI 协议将 DAC084SO 连接到 Tiva C 系列 Launch Pad。

我向 所有4个通道写入相同的输入值(使用带计数器的 while 环路的三角波形)、并在通道2、3和4中获得所需的输出。 但是、我的输出通道1中的输出中断。

我粘贴了下面3个工作输出和1个中断输出的示波器屏幕截图:

我粘贴了以下代码:

#include 
#include 
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "utils/uartdio.h"
#include "utils/uartdio.h"


//! 尝试使 DAC SSI 084正常工作。 4通道。
//!
//! 此示例使用以下外设和 I/O 信号。 您必须
//! 查看这些内容并根据您自己的董事会需要进行更改:
//! - SSI0外设
//! - GPIO 端口 A 外设(用于 SSI0引脚)
//! SSI0Clk - PA2
//! - SSI0Fss - PA3
//! - SSI0Rx - PA4
//! - SSI0Tx - PA5
#define NUM_SSI_DATA 3

int
main (void)
{

uint8_t loopCount = 0;
uint16_t dacAaddress_dontUpdate = 0b0000;//写入寄存器00 A,直到 D 被写入才会更新
uint16_t dacBaddress_dontUpdate = 0b0100;//写入寄存器01 B、直到 D 被写入才会更新
uint16_t dacCaddress_dontUpdate = 0b1000;//写入寄存器10 C、直到 D 被写入才会更新
uint16_t dacDaddress_doUpdate = 0b1101;//写入寄存器11 D、更新写 D 的所有输出

//移动地址并在内部更新位8位,以便您可以使用 OR 运算符来写入最后8位
dacAdaddress_dontUpdate = dacAdaddress_dontUpdate <8;
dacBaddress_dontUpdate = dacBaddress_dontUpdate <8;
dacCaddress_dontUpdate = dacCaddress_dontUpdate <8;
dacDaddress_doUpdate = dacDaddress_doUpdate <8;

SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHz);

//必须启用 SSI0外设才能使用。
SysCtlPeripheralEnable (SYSCTL_Periph_SSI0);

//对于本示例,SSI0与 Porta[5:2]一起使用。
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);

//为端口 A2、A3、A4和 A5上的 SSI0功能配置引脚复用。
GPIOPinConfigure (GPIO_PA2_SSI0CLK);
GPIOPinConfigure (GPIO_PA3_SSI0FSS);
GPIOPinConfigure (GPIO_PA4_SSI0RX);
GPIOPinConfigure (GPIO_PA5_SSI0TX);

//配置 SSI 引脚的 GPIO 设置。 该函数也会提供
将这些引脚的//控制到 SSI 硬件。 请参阅中的数据表
//查看每个引脚分配的函数。
//引脚分配如下:
// PA5 - SSI0Tx
// PA4 - SSI0Rx
// PA3 - SSI0Fss
// PA2 - SSI0CLK
GPIOPinTypeSSI (GPIO_Porta_base、GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |GPIO_PIN_2);

//为 TI 主控模式配置和启用 SSI 端口。 使用 SSI0系统
//时钟电源、主控模式、1MHz SSI 频率和16位数据。
//位速率必须为2MHz 或更高
SSIConfigSetExpClk (SSI0_BASE、SysCtlClockGet ()、SSI_FRF_TI、SSI_MODE_MASTER、1000000、16);

//启用 SSI0模块。
SSIEnable (SSI0_BASE);


while (1){
//现在使用 OR 运算符将您的控制值放入输入位中
//循环计数是一个8位值。 因此仅修改父级的最后8位。

//现在将所有输入变量进一步移入4位内部。
// DAC048S 的输入变量为16位,最后4位应该是无用的。
//如果不移入内部,现在12位字的最后8位将被忽略!


SSIDataPut (SSI0_BASE、((dacAaddress_dontUpdate | loopCount)<<4);
SSIDataPut (SSI0_BASE、((dacBaddress_dontUpdate | loopCount)<<4);
SSIDataPut (SSI0_BASE、((dacCaddress_dontUpdate | loopCount)<<4);
SSIDataPut (SSI0_BASE、((dacDaddress_doUpdate | loopCount)<<4);

while (SSIBusy (SSI0_BASE)){}


loopCount++;
if (loopCount=255)
loopCount=0;
}

}
// UART 中断处理程序,主程序中的定义
//简单地说,由于我们将它放在启动 CCS 文件的 NVIC 表中,所以必须在这里执行操作。
空 UARTIntHandler (空)
{
}

是否有任何帮助说明为什么一个通道不能正常工作?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

     我不会发现您的代码有任何问题。 首先、您是否有另一个可以尝试的备用 DAC 器件? 我建议您做一些实验。 其次、仅测试第一个通道、暂时不测试其他3个通道。 您会遇到相同的问题吗? 由于您有示波器(逻辑分析仪会更好)、因此您可以查看 MCU 的 SPI 输出、看看它是否输出正确的串行数据。 如果串行数据正确、但 DAC 的输出电压与输入值无关、则需要将您的问题发布到 https://e2e.ti.com/support/data-converters/f/73上的数据转换器论坛。 我只能支持 MCU、而不能支持 DAC 器件。 同样、如果您有额外的器件、请先在第二部分尝试您的程序。 如果第二部分给出相同的结果、则很可能与您的代码有关。 在这种情况下、只关注未给出正确结果的通道。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Charles 和 Balaji、您好!

    这只是第67行中 SSI 协议选择的一个考虑。  在 API (FRF_TI)中选择了所谓的 TI 帧协议。

    选择摩托罗拉 SPI 协议之一是否可以缓解 CH_A 情况?

    我曾遇到过类似的情况、也许这个想法对您的案例有所帮助。

    此致、

    P.S.

    以下是 TI 文档中的 API 选择可能性:

    ui32Protocol 参数定义了数据帧格式。 ui32Protocol 参数

    可以是以下值之一:SSI_FRF_MOTO_MODE_0、SSI_FRF_MOTO_MODE_1、

    SSI_FRF_MOTO_MOTO_MODE_2、SSI_FRF_MOTO_MODE_3、SSI_FRF_TI 或 SSI_FRF_NMW。

    请注意、SSI_FRF_NMW 选项仅在某些器件上可用。 请参阅器件

    数据表、以确定特定器件是否支持 MICROWIRE 格式。 穆-

    Torola 帧格式编码以下极性和相位配置:

    极性相位模式

    0 0 SSI_FRF_MOTO_MODE_0

    0 1 SSI_FRF_MOTO_MODE_1

    1 0 SSI_FRF_MOTO_MODE_2

    1 1 SSI_FRF_MOTO_MODE_3

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Otto、

     感谢您的建议。 我昨天阅读了数据表、认为 TI 的帧格式是正确的。 此外、它还适用于其他三个通道。 当然、海报可以尝试飞思卡尔格式、看看这是否会有所不同。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢你的答复。 我将与替代 DAC 进行核对、然后返回给您。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢你的答复。

    我将检查使用其他 SSI 模式并返回给您。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Charles、

    1) 1)     我尝试使用另一个 DAC IC。 结果是相同的。 通道 A 无法正常工作、其他3个工作正常。

    2)     2)我禁用了其他3个通道、并仅运行通道 A使用 while 循环中的以下代码立即更新输出。 在此设置中、通道 A 工作正常。

    SSIDataPut (SSI0_BASE、((0b000100000000| loopCount)<<4));
    /SSIDataPut (SSI0_BASE、((dacBaddress_dontUpdate | loopCount)<<4));
    /SSIDataPut (SSI0_BASE、 (((dacCaddress_dontUpdate | loopCount)<<4));
    //SSIDataPut (SSI0_BASE、((dacDaddress_doUpdate | loopCount)<<4)); 

    3)     3)然后、我使用以下代码尝试使用4个通道中的2个、并在每次 SSI 写入后立即更新输出。 通道 A 受到干扰、而通道 B 外观良好。

     

    SSIDataPut (SSI0_BASE、(0b000100000000| loopCount)<<4);
    
    SSIDataPut (SSI0_BASE、(0b010100000000| loopCount)<<4));
    
    /SSIDataPut (SSI0_BASE、 (((dacBaddress_dontUpdate | loopCount)<<4));
    
    // SSIDataPut (SSI0_BASE、((dacCaddress_dontUpdate | loopCount)<<4));
    
    // SSIDataPut (SSI0_BASE、(((dacDaddress_doUpdate | loopCount))<4); 

        接下来,我再次执行了2个通道,但这次仅在写入通道 B 数据后更新了两个输出。 现在、通道 A 中的干扰看起来持续时间较长。 通道 B 同样正常。

          SSIDataPut (SSI0_BASE、((0b0000000000000000 | loopCount)<<4));

          SSIDataPut (SSI0_BASE、((0b010100000000|循环计数)<<4);

          //SSIDataPut (SSI0_BASE、((dacBaddress_dontUpdate | loopCount)<<4);

          //SSIDataPut (SSI0_BASE、((dacCaddress_dontUpdate | loopCount)<<4);

          //SSIDataPut (SSI0_BASE、((dacDaddress_doUpdate  | loopCount)<<4);

     

    4)     4)作为另一次尝试、我使用了全部4个、并在写入数据后更新了每个通道 A 单独受到更高频率波动的干扰、这可能是由于立即更新造成的。

     

          SSIDataPut (SSI0_BASE、((0b000100000000|循环计数)<<4);

          SSIDataPut (SSI0_BASE、((0b010100000000|循环计数)<<4);

          SSIDataPut (SSI0_BASE、((0b100000000| loopCount)<<4);

          SSIDataPut (SSI0_BASE、(0b110100000000|循环计数)<<4);

     

    我认为、向其他通道提供数据后进行更新可以在通道 A 的波动之间提供更大的间距

    请提出任何建议?

     

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Otto、

    我尝试了您提到的不同的帧格式。

    // SSIConfigSetExpClk (SSI0_BASE、SysCtlClockGet ()、SSI_FRF_TI、SSI_MODE_MASTER、1000000、16); // 4个中有3个正在工作。
    // SSIConfigSetExpClk (SSI0_BASE、SysCtlClockGet ()、SSI_FRF_NMW、SSI_MODE_MASTER、1000000、16); //不起作用
    // SSIConfigSetExpClk (SSI0_BASE、SysCtlClockGet ()、SSI_FRF_MOTO_MOTO_MODE_3、SSI_MODE_MASTER、1000000、16); //不起作用
    SSIConfigSetExpClk (SSI0_BASE、SysCtlClockGet ()、SSI_FRF_MOTO_MOTO_MODE_2、SSI_MODE_MASTER、1000000、16); //都在工作
    // SSIConfigSetExpClk (SSI0_BASE、SysCtlClockGet ()、SSI_FRF_MOTO_MOTO_MODE_1、SSI_MODE_MASTER、1000000、16); //不起作用
    // SSIConfigSetExpClk (SSI0_BASE、SysCtlClockGet ()、SSI_FRF_MOTO_MOTO_0、SSI_MODE_MASTER、1000000、16); //在所有4个通道上提供乱码输出
    

    在向第四个寄存器写入数据后更新输出时、MOto 模式2格式可在所有4个通道中提供干净的输出。 感谢您的建议。