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.

[参考译文] MSP430FR5994:通过 UART 进行数据传输时出现问题

Guru**** 2587365 points
Other Parts Discussed in Thread: MSP430FR5994

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/820611/msp430fr5994-problem-with-data-transmissions-via-uart

器件型号:MSP430FR5994

您好!

因此、我遇到了一个问题、就是我要通过 UART 将 ADC 数据发回计算机。 我有11个用于 ADC 的通道、我需要知道我接收的数据的计算机侧是哪个通道。 我似乎无法找到一种巧妙的解决方案、问题是如何知道数据的通道。  

ADC 数据在0x0FFF 和0x0000之间输出。 在计算机侧、我检查2个字节以查看 MSByte (最高有效字节)中是否有0、如果没有、则数据会翻转。 如果我改为使用 MSByte 中的该0来执行0-B 来执行通道指定、那么我不知道哪一个是正确的前两个字节。 如果我发送一个任意的两个字节、那么我将无法判断它是 ADC 结果还是实际通道指定。 有什么想法吗? 我将 python 与 PySerial 一起用于与 MSP430FR5994通信。

谢谢!

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

    您好、Msega、

    感谢您的发帖。

    我们将为您研究这个问题、尽快返回。

    谢谢、

    是的

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

    是否有更新?

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

    您好、Msega、

    您是否考虑使用 ADC ISR 发送数据? 为了让计算机知道发送数据的 ADC、您可以在 发送数据之前为通道指定发送额外的字节、总共3个字节。 这将使计算机能够识别信道并检查数据是否翻转、因为 MSbyte 不再用于检查信道。 在 ADC 通道的 ISR 中、您可以有一条 switch 语句、其中包含每个通道的 case、在每个 case 中、发送相应的代号和数据。  

    请告诉我这是否有帮助。

    祝你一切顺利、

    Colin Adema

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

    我认为这是可行的。 此外、我还有另一个问题(我不确定是否应该发布新帖子、但希望这应该是一个快速的答案)。 因此、我实际上有一个在一个通道(具体来说是通道12)上运行的 ADC、并且我有4个选择。 我在公共引脚上连接了一个16-1多路复用器。 选择引脚2.6-2.3。 它们都已正确连接。 当运行我的代码并单步执行程序时、通道0是 ADC 结果的通道0。 当我让程序以正常速度运行时、现在它在 CCS 中为我提供通道10结果(来自硬件)作为通道0。 您是否对这种情况的发生有任何想法? 如果需要更多信息(例如设置/代码)、我可以提供所有这些信息。 我将在连接到 launchpad eZ-FET 的原型板上使用 msp430fr5994。  

    编辑:也感谢您的帮助!

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

    您好!

    我将对此进行研究、但为了确保我了解该问题、您在引脚2.6-2.3上放置了十进制10 (因此是二进制1010)、而不是在输出上看到通道10、而是看到通道0?

    如果您有一些代码会显示设置和执行该代码、这将是一大帮助。

    祝你一切顺利、

    Colin Adema

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

    我有一个计数器(在我的例子中为"J")、通过执行 P2OUT =(j<3)来将0-10输出至 P2OUT。 当它到达 j = 10时、它会写入 ADC_Holder[j]、其中 j 应该是10、但由于某种原因、它会写入 ADC_Holder[0]。 明天早上、我将能够发送代码、我必须在几分钟内离开工作。 但是、是的、基本上您所说的是正确的。 我明天将发布设置和代码。

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

    是否在不同数字下观察到类似行为? 例如、如果 j = 11、它不是写入 ADC 11、而是写入 ADC 1?

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

    我刚才测试了它。 如果我将 ADC_Holder 的大小增加到了11、则调整 ADC 值将第11个发送到数组的第10个位置的代码。 它实际上只是将第11个 ADC 通道写入 ADC_Holder[0]。 这种行为非常奇怪、除非我只是忽略一些简单的东西。  

    这是代码(我删除了与 UART 有关的任何内容、因为我正在使用引脚 PJ.4和 PJ.5中的振荡器、并且我的原型板上当前没有这些内容)。

    #include 
    
    
    /********
    *文件:********
    *作者:*********
    *日期:*********
    *说明:
    通过 UART 接收每个* 11引脚的外部电压要求。 然后将这些计时器引脚的输出电压
    *设置为分配的电压。 运行 ADC 以确保所需的电压
    *与外部电路密切相关。
    *设置:
    * PWM 输出-> 1k 电阻-> ADC 引脚-> 47uF 电容-> GND
    /
    
    
    int TimerVal[11]={400、400、400、400、400、400、400、400、400、400、400、400};
    volatile int adc_Holder[11];
    int PowConv[11];
    unsigned int i = 0;
    unsigned int j = 0;
    unsigned int
    l = 0;
    unsigned int m = 0;
    unsigned int
    int = 0;partint flag = 0;unsigned int
    
    int cat1、cat2;
    接收到的 int [44];
    int UART_transmit;
    
    void ADC_Setup (void);
    void Timer_Setup (void);
    void Pin_Setup (void);
    无符号连接(无符号、无符号);
    void UART_receev_Vals (void);
    void UART_Setup (void);
    void Timer_Setter (void);
    
    void main (void)
    {
    WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
    Pin_Setup ();
    //UART_Setup ();
    ADC_Setup ();
    Timer_Setup ();
    __bis_SR_register (GIE);
    
    //while (i<44){}/Turn on
    I = 0;
    //uart_receeve_Vals ();/Turn on
    ADC12CTL0 |=(ADC12ENC | ADC12SC);
    
    for (n = 0;n<11;n++)
    {
    PowConv[n]= 2048;
    }
    _delay_cycles (1000);
    
    while (1)
    {
    _DELAY_CYCLES (20000);
    
    if (adc_Holder[m]> PowConv[m]+5 && TimerVal[m]> 0)//如果 ADC 结果大于所需的功率降低占空比
    TimerVal[m]-= 1;
    否则、如果(ADC_Holder[m]< PowConv[m]-5 && TimerVal[m]< 1000)//如果 ADC 结果低于所需的功率增加占空比
    TimerVal[m]+= 1;
    Timer_Setter();
    /*UART_Transmit = ADC_Holder[m];
    Part1 = UART_Transmit & 0x00FF;
    Part2 =(UART_Transmit & 0xFF00)>> 8;
    while (!(UCA3IFG & UCTXIFG));
    UCA3TXBUF = part2;
    while (!(UCA3IFG & UCTXIFG));
    UCA3TXBUF = part1;
    if (i ==44)
    {
    UART_receev_Vals ();
    I=0;
    }*/
    M++;
    如果(m ==11)
    {
    M = 0;
    }
    }
    }//
    
    接收半字并将递增计数器
    /*#pragma vector = EUSCI_A3_vector
    __interrupt void USCI_A3_ISR (void)
    {
    开关(UCA3IV)
    {
    USCI_NONE 案例:中断;
    USCI_UART_UCRXIFG 案例:
    while (!(UCA3IFG&UCTXIFG));
    接收到的[i]= UCA3RXBUF;
    i++;
    中断;
    案例 USCI_UART_UCTXIFG:中断;
    案例 USCI_UART_UCSTTIFG:中断;
    案例 USCI_UART_UCTXCPTIFG:中断;
    默认值:break;
    }
    }*/
    
    //将更改多路复用器选择并执行 ADC 测量,并确定 TimerVal 是否需要
    //递增或递减
    #pragma vector = ADC12_B_vector
    __interrupt void ADC12_ISR (void)
    {
    P2OUT =(j << 3);
    ADC_Holder[j]= ADC12MEM12;
    J++;
    if (j==11)
    {
    J=0;
    }
    
    ADC12IFGR0 &=~ADC12IFG12;
    }
    
    //ADC 设置-在函数
    void ADC_Setup (void)
    {中读取注释
    ADC12CTL0 = ADC12SHT0_2 | ADC12ON | ADC12MSC; //采样时间、S&H=16、ADC12打开
    ADC12CTL1 = ADC12PDIV_3 | ADC12DIV_7 | ADC12SHP | ADC12CONSEQ_2 | ADC12SSEL_3;//使用采样计时器;单通道
    ADC12CTL2 |= ADC12RES_2; // 12位转换结果
    ADC12CTL3 |= ADC12CSTARTADD_12; //启动 ADC 通道为 ch0
    ADC12MCTL12 |= ADC12INCH_12; //A2 ADC 输入选择;Vref=AVCC
    ADC12IER0 |= ADC12IE12; //通道0的中断使能
    }
    
    //引脚设置
    无效 PIN_SETUP (void)
    {
    //////////////////////////////////////// 多路复用器选择
    P2DIR |= BIT6 | BIT5 | BIT4 | BIT3;
    
    //////////////////////////////////////// ADC
    P3SEL1 |= BIT0;
    P3SEL0 |= BIT0;
    P3DIR &=~BIT0;
    //////////////////////////////////////// 计时器
    P1DIR |= BIT7 | BIT6 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0;
    P1SEL0 |= BIT7 | BIT6 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0;
    P1SEL1 &=~BIT7;
    
    P2DIR |= BIT0;
    P2SEL0 |= BIT0;
    
    P3DIR |= BIT6;
    P3SEL0 |= BIT6;
    P3SEL1 &=~BIT6;
    
    P5DIR |= BIT7;
    P5SEL1 |= BIT7;
    //////////////////////////////////////// UART
    //P6SEL1 &=~(BIT0 | BIT1);
    //P6SEL0 |=(BIT0 | BIT1); // USCI_A3 UART 操作
    //PJSEL0 |= BIT4 | BIT5; //表示 XT1
    
    PM5CTL0 &=~LOCKLPM5;
    }
    
    //将定时器周期设置为1000个周期,
    void Timer_Setup (void)
    {
    TBCCR0 = 1000-1;
    TA0CCR0 = 1000-1;
    TA1CCR0 = 1000-1;
    TA4CCR0 = 1000-1;
    
    TBCCTL1 = OUTMOD_7;//复位/置位
    TBCCTL2 = OUTMOD_7;
    TBCCTL3 = OUTMOD_7;
    TBCCTL4 = OUTMOD_7;
    TBCCTL5 = OUTMOD_7;
    TBCCTL6 = OUTMOD_7;
    TA0CCTL1 = OUTMOD_7;
    TA0CCTL2 = OUTMOD_7;
    TA1CCTL1 = OUTMOD_7;
    TA1CCTL2 = OUTMOD_7;
    TA4CCTL1 = OUTMOD_7;
    
    Timer_Setter();
    
    TBCTL = tassel_2 | MC_1 | TBCLR;//SMCLK、向上计数模式、定时器清零
    TA0CTL = tassel_2 | MC_1 | TACLR;
    TA1CTL = tassel_2 | MC_1 | TACLR;
    TA4CTL = tassel_2 | MC_1 | TACLR;
    }
    
    void UART_Setup (void)
    {
    // XT1设置
    CSCTL0_H = CSKKEY_H; //解锁 CS 寄存器
    CSCTL2 = SELA_LFXTCLK | SELESS__DCOCLK | SELM_DCOCLK;
    CSCTL3 = DIVA__1 | DIVM_1 | DIVM__1;//设置所有分频器
    CSCTL4 &=~LFXTOFF;
    操作
    {
    CSCTL5 &=~LFXTOFFG; //清除 XT1故障标志
    SFRIFG1 &=~OFIFG;
    } while (SFRIFG1和 OFIFG); //测试振荡器故障标志
    CSCTL0_H = 0; //锁定 CS 寄存器
    
    //将 USCI_A3配置为 UART 模式
    UCA3CTLW0 = UCSWRST; //将 eUSCI 置于复位状态
    UCA3CTLW0 |= UCSSEL_ACLK; // CLK = ACLK
    UCA3BRW = 3; // 9600波特
    UCA3MCTLW |= 0x5300; // 32768/9600 - INT (32768/9600)=0.41
    // UCBRSx 值= 0x53 (请参阅 UG)
    UCA3CTLW0 &=~UCSWRST; //初始化 eUSCI
    UCA3IE |= UCRXIE; //启用 USCI_A3 RX 中断
    }
    无符号连接(无符号 x、无符号 y)
    {
    返回 x * 10 + y;//连接数字
    }
    
    //将两个半字组合成一个完整的4位数字(十六进制)
    void UART_receeve_Vals (void)
    {
    L = 0;
    对于(k = 0;k < 44;k+=4)
    {
    CAT1 =连接状态(接收[k]、接收[k+1]);
    CAT2 =连接数据(cat1、接收到的[k+2]);
    PowConv[l]=连接(cat2、接收[k+3]);
    L++;
    }
    }
    
    //将定时器捕获控制寄存器设置为定时器值
    void Timer_Setter (void)
    {
    TBCCR1 =定时器 Val[0];
    TBCCR2 =定时器 Val[1];
    TBCCR3 =定时器 Val[2];
    TBCCR4 =定时器 Val[3];
    TBCCR5 =定时器 Val[4];
    TBCCR6 =定时器 Val[5];
    TA0CCR1 =定时器 Val[6];
    TA0CCR2 =定时器 Val[7];
    TA1CCR1 =定时器 Val[8];
    TA1CCR2 =定时器 Val[9];
    TA4CCR1 =定时器 Val[10];
    }
    

    此外、这里还有一些设置图片。  

    设置说明:以这种方式设置11个电路(PWM 输出引脚-> 1k 电阻-> ADC 输入+ 47uF 电容-> GND)。  

    我们目前不使用 TA2.1、因为使用它需要软件 PWM、我们不想再使将另一个 ISR 投入代码变得复杂。  

    P2.6为多路复用器选择器3、P2.5多路复用器选择器2、P2.4多路复用器选择器1、P2.3多路复用器选择器0

    显示了 VCC、EN 和 GND 连接以及选择。 (我们没有任何摩擦酒精来去除助焊剂、因此有点凌乱)

    希望您可以看到焊点未跳接。 也通过 X 射线进行了确认。  

      

    MSP430的连接。

    总体设置:从顶部向下是左侧的通道0-10。 试验电路板上的所有电源轨和 GND 轨均按预期设置。  

    谢谢!

    编辑:此外、我认为选择信号可能有问题或类似问题、我将逻辑分析仪连接到了4个选择、并看到它将从0开始、并按预期计数到10。 这里也是它的图片。  

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

    感谢提供的所有信息! 我将开始把它分开、看看可能会出现什么问题。

    此致、

    Colin Adema

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

    您好!

    进行一些测试后、我注意到 ADC 值始终滞后并存储在下一个数组点、即7存储在8中、10存储在0中、如您所见 我目前正在研究这种情况的原因。

    祝你一切顺利、

    Colin Adema

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

    是的、我也注意到了这一点。 我完全忘记了。 很抱歉。  

    感谢您的深入故障排除!

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

    我可以收到这条警告吗?

    "警告#10421-D:对于运行频率高于8MHz 的 FRAM 器件、需要相应地配置 FRAM 等待状态。"

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

    不幸的是,这没有解决这个问题。 这是我从 MSP430FR5x9x 演示-将 MCLK 配置为16MHz 运行中获得的代码

    void FRAM_Setup (void)
    {
    //根据 MCLK 的器件数据表的要求配置一个 FRAM 等待状态
    //在配置时钟系统之前在8MHz 以上运行。
    FRCTL0 = FRCTLPW | NWAITS_1;
    
    //时钟系统设置
    CSCTL0_H = CSKKEY_H; //解锁 CS 寄存器
    CSCTL1 = DCOFSEL_0; //将 DCO 设置为1MHz
    //设置 SMCLK = MCLK = DCO、ACLK = VLOCLK
    CSCTL2 = SELA_VLOCLK | SELESS__DCOCLK | SELM_DCOCLK;
    //每个器件勘误表在将频率更改为之前将分频器设置为4
    //防止因过冲瞬态而超出规格运行
    CSCTL3 = DIVA__4 | DIVM_4;//针对勘误表将所有相应的时钟源设置为4分频
    CSCTL1 = DCOFSEL_4 | DCORSEL; //将 DCO 设置为16MHz
    //延迟~10us 以使 DCO 稳定。 60个周期= 20个周期缓冲器+(10us /(1/4MHz))
    _DELAY_CYCLLES (60);
    CSCTL3 = DIVA__1 | DIVM_1 | DIVM__1;//针对16MHz 运行将所有分频器设置为1
    CSCTL0_H = 0; //锁定 CS 寄存器
    } 

    仍然观察到通道10进入通道0时出现相同的问题、其余问题向上移动。

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

    因此我发现了这个问题、主要是在对 ADC ISR 进行编码时、出于某种愚蠢的原因、我认为 ADC 会在读取存储器数据时进行转换。 而它应该转换->将标志设置为高电平->进入 ISR。 因此、在对通道进行采样之前、P2OUT 应该已经改变。 因此、在启动 ADC 之前、必须初始化 P2OUT 以将位6至3清零。 此外、ADC ISR 代码被更改为:  

    #pragma vector = ADC12_B_vector
    __interrupt void ADC12_ISR (void)
    {
    ADC_Holder[j]= ADC12MEM12;
    J++;
    P2OUT =(j << 3);
    ADC_Flag = 1;
    if (j==11)
    {
    J=0;
    P2OUT =(j << 3);
    }
    
    ADC12IFGR0 &=~ADC12IFG12;
    } 

    这可确保在下一个 ADC 转换发生前 P2OUT 被改变。 感谢 Colin 的帮助。 如果其他人找到此代码并决定使用它、我尚未确保代码100%正常工作、尽管此代码前面已介绍过修复了此错误。

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

    Msega、

    很高兴听到您让它正常工作。 如果您有任何其他问题和/或希望通过 UART 发送数据时提供其他输入、请告诉我。

    祝你一切顺利、

    Colin Adema