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.

[参考译文] MSP430F5438A:MSP430F5438A ADC 和 UART

Guru**** 2589265 points
Other Parts Discussed in Thread: MSP430F5438A, Z-STACK

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/768670/msp430f5438a-msp430f5438a-adc-and-uart

器件型号:MSP430F5438A
Thread 中讨论的其他器件: Z-stack

您好、先生、  

我使用的是具有~1kHz 采样频率和115200 UART 波特率的12位 ADC。 当使用 UART 接收 ADC 数据时、我会得到一个额外的字符(符号)、如图所示。 这与数据一起出现的原因是代码中存在任何错误、请检查一次。

谢谢

#include "msp430f5438A.h"
#include 
#include 
#include 


void adcfunction (void);
void adcInit (void);

char buffer[10]='\0';
static int SavedADC12MEM1;

#pragma vector=ADC12_vector
_ interrupt void ADC12_ISR (void)
{

SavedADC12MEM1 = ADC12MEM0;

P5SEL |= BCC1CL0







= UCC1 = UCT1;UCC1 = UCC1 = UCT1 = UCC1;UCC1 = UCC1 = UCT1 = UCC1 = UCC1;UCC1 = UCT1 = UCT1 = UCC1 = UCC1 = UCT1;UCC1 = UCT1 = UCC1 = UCT1 = UCC1 + UCC1 ~

int k=0;

sprintf (buffer、"\r\n%d"、SavedADC12MEM1);

while (buffer[k])
{
while (!(UCA1IFG&UCTXIFG));
UCA1TXBUF = buffer[k++];
}

while (!(UCA1IFG&UCTXIFG);
UCA1TXBUF='\n';

while (!(UCA1IFG&UCTXIFG));
UCA1TXBUF='\r\n';

__BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);
}

void adcInit (


~

STR){P6SEL |= BFC127 + ADC12+ ADC12+ ADC12+ ADC12+ ADC12+ ADC0 = ADC12+ ADC12+ ADC12+ ADC0 + ADC12+ ADC12+ ADC12+ ADC12+ ADC0 + ADC12+ ADC12+ ADC12+ ADC0 + ADC12+ ADC12+ ADC0 + ADC12+ ADC12+ ADC12+ ADC0 + ADC12+ ADC12+ ADC0 + ADC12+ ADC12+ ADC0 + ADC12+ ADC0 + ADC12+ ADC12+ ADC0 + ADC12ADC0 + ADC12ADC12+ ADC0 + ADC12ADC12+









void adcfunction (void)
{
ADC12CTL0 |= ADC12ENC | ADC12SC;

_ bis_SR_register (LPM0_bits+GIE);
_ no_operation ();
}


int main (void)
{
WDTCTL = WDTPW + WDTHOLD;
adcInit


();while (1

+ GPM0);}_ function (void)+ GSR)



  

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

    嗨、Shiva、

    大多数人都避免使用 MSP430中的 printf()函数,因为它们对于嵌入式环境来说可能非常大并且效率较低。 我想知道它是在向您的字符串中添加 null 还是其他内容。

    我相信您可以将其设置为显示原始十六进制。 我会这样做、以查看接收到的确切数据是什么。 我还建议在第45行周围放置一个断点、以便您可以将收到的内容与缓冲区中的内容进行比较。

    谢谢、
    JD

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    1) 1)您正在为每个样本重置 UART、特别是在 ADC ISR 中。
    2) 2)您使用的是 CONSEQ=2和 MSC=1、它连续且非常快地进行采样。
    3) 3)由于以115.2kbps 写入9个字节、ADC ISR 需要很长时间。

    由于(2)+(3)、ADC ISR 退出后立即重新进入-它永远不会(作为一个实际问题)返回到 main。 这种情况发生得非常快、而最后一个 UART 字节仍在发送中。 然后您将重置 UART (1),它会破坏最终字节。 我建议:

    a)使用 CONSEQ=0、因此 ADC 按 main (adcfunction)起搏。
    b)在 main 的开头初始化 UART 一次

    将 sprintf()和 TXBUF 写入 main 是一个很好的做法,但是只要这个程序受到 UART 速度的限制,它就不会产生实际的影响。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、先生、  

    感谢您的建议。 我已经进行了更改、现在结果即将到来。

    ADC 频率=时钟源频率/分频器预分频器

    ADC 采样频率= ADC 频率/转换周期+采样保持周期


    我使用示波器计算出 SMCLK 时钟频率、频率为1048576 SO、 1048576/1*1 = 1048576

    采样频率= 1048576/13+1024 = 1011khz  

    #include "msp430f5438A.h"
    #include
    #include
    #include


    void adcfunction (void);
    void adcInit (void);


    char buffer[10];
    静态 Int16_t SavedADC12MEM1;

    #pragma vector=ADC12_vector
    _interrupt void ADC12_ISR (void)


    SavedADC12MEM1 = ADC12MEM0;

    _BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);

    void adcInit (void)

    P6SEL |= BIT7;
    P6DIR &=~BIT7;

    REFCTL0 |= REFMSTR+REFVSEL_2+REFON+REFTCOFF;

    ADC12CTL0 = ADC12ON + ADC12SHT0_12 + ADC12MSC;
    ADC12CTL1 = ADC12SHP + ADC12CONSEQ_2 + ADC12SSEL_0 + ADC12DIV_0;
    ADC12CTL2 = ADC12RES_2;

    ADC12MCTL0 = ADC12INCH_7+ ADC12SREF_1;
    ADC12IE = BIT0;

    void adcfunction (void)(空)

    ADC12CTL0 |= ADC12ENC | ADC12SC;

    _bis_SR_register (LPM0_bits+GIE);
    __no_operation();

    int main (空)

    WDTCTL = WDTPW + WDTHOLD;

    P11DIR |= 0x07;
    P11SEL |= 0x07;

    P5SEL |= BIT6 + BIT7;
    UCA1CTL1 |= UCSWRST;
    UCA1CTL1 |= UCSSEL_SMCLK;
    UCA1BR0 = 109;
    UCA1BR1 = 0;

    UCA1MCTL = UCBRS_0;

    UCA1CTL1 &=~UCSWRST;

    adcInit();
    while (1)

    adcfunction();
    int k=0;

    sprintf (buffer、"\n\r\n%d"、SavedADC12MEM1);
    while (缓冲区[k])

    while (!(UCA1IFG&UCTXIFG));
    UCA1TXBUF =缓冲器[k++];

    }}

    1) ADC 采样频率计算公式是否正确?  

    2) 2)我的 ADC 设置(基准、时钟、采样保持周期)是否正确?

    3) 3)我正在使用 Matlab 中的串行值绘制波形、我通过将输入(0.5Hz 至100Hz)变为5Hz 来从函数发生器提供输入(正弦波)我通过增加无法获取正弦波的频率来获得精确正弦波。 采样频率以及采样保持周期选择是否存在任何错误。 plz 澄清

    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您的 ADC 时钟(ADC12SSEL=0)比1MHz 更接近5MHz、因此您的实际采样率(CONSEQ=2、MSC=1、SHT=1024)更接近5ksps。

    但是,有效的采样率(通过 UART 传输到 PC 的原因)受到9600bps (apx 960字节/秒)的 UART 速度的限制。 由于每个样本发送大约6个字节、因此速率降低到960/6=160个样本/秒(对于 sprintf、减去一点)。 其他样本会丢失。

    在某些(正弦)频率下、您的(视觉)保真度将开始消失、但如果您收集足够的样本、您仍可以对其进行分析。 在80Hz 正弦频率下、您将通过奈奎斯特。

    您能否加快 UART 的速度?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、先生、
    我更改了波特率115200、即115200/6 = 19ksps、即使我无法获得正确的正弦波。
    因此、我使用 UCS UCSCTL2 = FLLD_1 + 374将 SMCLK 时钟频率更改为12MHz;我能够以968khz 的采样频率绘制高达40Hz 的正弦波。 ADC12CTL0 = ADC12ON + ADC12SHT0_12 + ADC12MSC;
    ADC12CTL1 = ADC12SHP + ADC12CONSEQ_2 + ADC12SSEL_3 + ADC12DIV_2;
    ADC12CTL2 = ADC12PDIV+ADC12RES_0;
    在这种情况下、我使用的波特率为460800 (12MHz 时钟)。
    为什么会发生这种情况?

    谢谢、
    Shiva
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    >为什么会发生这种情况?
    什么是"这"? 您已经介绍了许多成功和失败的测试案例。

    另外:如果您没有看到正确的正弦波、您会看到什么?

    只需明确一下您现在所拥有的:ADC12SSEL=3、PDIV=1、DIV=2、您的 ADC 时钟为12MHz/(3*4)=1MHz。 SHT0=12、RES=0给出一个(1024+9+1)或者大约1000个 ADC 时钟、大约1ksps 的采样时间。 将 UART 速度提高到115200会使吞吐率达到115200/10/6 = 1.9ksps (对于 sprintf 和 LPM 偏斜则略为减去)。 ADC 现在是限速器。

    在1ksps 时、40Hz 输入信号每周期获得约1000/40=25个样本、因此它看起来应该模糊地像一个正弦波。

    通过使用 SHTs 来驱动采样率(CONSEQ=2、MSC=1)、采样电容器需要花费很长的时间(1ms)进行积分。 随着输入频率的增加、我预计这会导致一定程度的失真。 我仍然建议使用具有较低 SHT0设置的 CONSEQ=0、因此采样直接按 UART 速度进行、您可以获得信号的实际快照。 (实际上、我建议使用计时器触发器、但此时这是一个额外的复杂程度。)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢先生的快速回答。
    对于我们的项目、我们需要持续对数据进行采样、这就是我们分配 CONSEQ=2并启用 MSC 的原因。
    现在、我们的计算如下:

    8位 ADC
    ADC 频率=时钟源频率/分频器 X 预分频器;ADC 频率=12MHz/4*3 = 1MHz。
    转换周期=分辨率+1 = 8+1 = 9。
    采样保持周期= 1024。
    ADC 采样频率= ADC 频率/转换周期+采样保持周期;1MHz/9+1024 = 968hz =~968sps。

    现在我们的问题如下:

    1) 1)根据我们的计算、我们应该得到~968sps。 我们正在尝试使用 UART (460800)读取这些样本、方法是将 ADC12MEM0值传输到 UCA1TXBUF、python 程序正在从串行端口读取这些值。 但是、我们无法获得~968sps、仅显示290sps 最大值。 如果我们在 Z-stack (Z-stack 2.5 EXP5438)中包含相同的 ADC 代码、并将该值从终端设备传输到协调器、并使用 UART 和使用 Python 程序读取接收到的值。 通过这种方法、我们得到的结果是~968 SPS。
    现在、我们的问题是、我们为什么不获得没有 Z-stack 的计算样本? 我们是否应该使用缓冲器来存储该值?

    2)如何在 Z-stack 中提供的简单 ADC 程序中定义字节数据类型?

    3) 3)如果我们将 ADC12MEM0值分配为十六进制格式的整数类型变量、是否会丢失实际值?

    注意:先生、根据您之前的建议、我们删除了 sprintf 函数并将 UCA1TXBUF 保留在 main 中。

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

    我必须推迟到 Z-Stack 上的其他人。 也许在10年前、我对它进行了研究、然后忘记了一切。

    我也不清楚您在数据链中放置 Z-Stack 的位置。 它现在运行的是 ADC 吗? 还是仅仅是 UART 桥?

    1) 1)我不知道为什么您只能看到290sps。 您可能会看到 LPM 偏斜(在 ADC 完成后进入 LPM、因此它会等待1ms 直到下一个采样)、但我认为最坏的情况是系数2、而不是3。 或者、sprintf 所花费的时间可能比我们想象的要长得多。 此时、我将(a)探测 UART Tx 线和/或(b)在代码中的重要时刻弄杂 GPIO、并测量示波器上的起搏。

    3) 3)如果使用十六进制表示法、则每个样本可存储在3个字节中。 您也可以使用'\r\n'而不是使用这两种方法来离开。 这会将您的"数据包"从(2+4)字节减少到(1+3)字节。 但是、根据您的说法、您的 UART 速度不是(现在)限制。

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

    您是否能够进行充分优化以获得您期望的吞吐量?

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

    您好、先生、

    主席先生,我的问题是否可以转介到其他地方?

    谢谢主席先生

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

    我也不熟悉 Z 堆栈或它在做什么不同。 您的代码中的某个内容似乎会使吞吐量下降到瓶子里、但不清楚它是什么。

    我认为 Bruce 给出了一些非常好的建议。 我认为您的下一步是监控 UART 总线以查看原始数据、并在代码中切换某些 GPIO 以确定导致您看到的瓶子坏死的原因。

    如果我们有更多有关导致瓶颈的确切原因的信息、我们可能能够提供更具体的反馈。

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

    Bruce 先生和 JD 先生,您好!

    1) 1)如果我设置采样频率为124hz (时钟= smclk (1.04Mhz)、SHTs cycles = 256、div+prediv=32)、那么我将获得正确的样本数、因为我们将采样频率增加到250Hz 以上、那么样本开始丢失。 UART 波特率为115200。

    请注意:ADC12MEM0数据以十六进制格式传输、该格式为1字节到 UART。 不使用 sprintf。

    在 ADC_ISR 内部
    数据= ADC12MEM0;
    while (!(UCA1IFG&UCTXIFG));
    UCA1TXBUF = data;
    
    void adcfunction (void)
    {
    ADC12CTL0 |= ADC12ENC | ADC12SC;
    __bis_SR_register (GIE);
    __no_operation();
    }
    
    while (1)
    {
    
    adcfunction();
    
    } 

    谢谢、此致
    Shiva

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

    不幸的是、我们在这里没有真正的方法来识别您的瓶颈。 如前所述、我将开始测量固件的所有不同部分。 基本上、我会在 UART 上放置一个逻辑分析仪、在进行 ADC 转换时切换引脚、可能还有其他一些地方。

    然后、在一次清晰的捕获中、您应该能够看到正在采集的 ADC 样本、通过 UART 发出的样本、并查看代码中是否有需要花费大量时间的东西。

    至于 ADC 设置、为什么采样保持时间这么长? 您的 ADC 似乎在以巨大的采样保持时间不断转换。 通常情况下、ADC 可以对信号使用更短的采样保持时间、并且会根据需要在环路中进行调用。

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

    您好、先生、

    我们已根据以下信息调整了周期数。

    请澄清一下、我的行为是否正确?

    谢谢、此致

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

    嗨、Shiva、

    您能否共享该主题的链接、以便我可以阅读上下文?  

    Bruce 和我所说的是您极长的采样保持时间。  这一行代码让您在每个采样之间等待1000多个 ADC 时钟周期。  通过降低 ADC12SHT0、您可以提高 ADC 的速度、使 UART 成为瓶颈。   

    ADC12CTL0 = ADC12ON + ADC12SHT0_12 + ADC12MSC; 

    谢谢、

    JD

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

    主席先生,

    对于 SMCLK = 12MHz、我使用了1024个 SHTs 周期。  

    1) 1)如果我在75us 延迟和75us 延迟下降低 SHTs 周期、则仅针对以下代码获得~190至220个样本(SMCLK = 1048576Hz)

    1) 1)您能告诉我参考结算是否需要75美元延迟?

    2) 2)如何检查我获得的样本数是否符合指定的采样频率?  要检查样本的否。我正在使用不带 python 的 python、如何检查?

    e2e.ti.com/.../404798

    #include "msp430f5438A.h"
    #include 
    #include 
    #include 
    
    typedef unsigned char 字节;
    void adcfunction (void);
    void adcInit (void);
    uint8_t 数据;
    
    unsigned char 电压;
    
    int 样本;
    //unsigned int count=0;
    
    #if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
    #pragma vector = ADC12_vector
    __interrupt void ADC12_ISR (void)
    #Elif defined (__GISR__)
    void __attribute__(interrupt (interrupt (void (void) ADC12_ISR
    
    )#vector (void)#ADC12_void!错误!
    #endif
    {
    
    data = ADC12MEM0;
    
    _BIC_SR_REGISTER_ON_EXIT (GIE);
    __NO_OPERATION ();
    
    }
    void adcInit (void)
    {
    P6SEL |= BIT7; //引脚7.6和7.7是从加速计到 ADC 的输入=>它们被配置为 ADC
    P6DIR 的输入&=~BIT7;
    REFCTL0 |= REFMSTR+REFVSEL_2+REFON+REFTCOFF;//
    
    ADC12CTL0 = ADC12ON + ADC12SHT0_4 + ADC12MSC; //+ADC12REF2_5V +ADC12REFON;
    ADC12CTL1 = ADC12SHP + ADC12CONSEQ_2 + ADC12SSEL_3 + ADC12DIV_7;
    // ADC12CTL1 = ADC12CONSEQ_2 + ADC12SSEL_3 + ADC12DIV_7;// ADC12CTL1
    = ADC12CONSEQ0 + ADC12RSD_0;ADC12C12RSD_ADC12R=0 //+ADC12TCOFF; //分辨率=08位,9个时钟周期转换时间
    
    ADC12MCTL0 = ADC12INCH_7+ ADC12SREF_1;
    ADC12IE = BIT0;
    
    //_delay_cycles (75);
    }
    void adcfunction (void)
    {
    ADC12CTL0 |= ADC12ENC | ADC12SC;
    __ bis_SR_register (GIE);
    __ no_operation ();
    }
    void uartInit (void)
    {
    P5SEL |= BIT6 + BIT7; // P5.6、7 = USCI_A1 TXD/RXD
    UCA1CTL1 |= UCSWRST; //**将状态机置于重置中**
    UCA1CTL1 |= UCSSEL_2;
    UCA1BR0 = 9; //
    UCA1BR1 = 0; //
    
    UCA1MCTL = UCBRS_0;
    
    UCA1CTL1 &=~UCSWRST; //**初始化 USCI 状态机**
    }
    
    int main (void)
    {
    WDTCTL = WDTPW + WDTHOLD;//停止 WDT
    
    adcInit();
    uartInit();
    while (1)
    {
    
    adcfunction();
    
    while (!(UCA1IFG&UCTXIFG));
    UCA1TXBUF = data;
    
    }
    
    }
    
    
    

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

    嗨、Shiva、

    75us 仅供 ADC 电压基准稳定。  所以、这仅在您首次初始化 ADC 时进行、而不是每次转换时进行。   

    代码的运行方式是、您只能通过 UART 发送尽可能多的样本、因此您的 python 程序将告诉您。  您的程序将尽快运行、并将每个单独的测量值流式传输出来。   

    因此、不清楚您的采样频率是多少。  当然、您必须 进一步深入、并使用计时器以指定的速率触发采样。   

    谢谢、

    JD