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.

[参考译文] CCS/MSP430G2553:如何检查 If-Statement 中通过 UART RX 发送的字符串命令/通过 UART TX 回显的字符串命令、以及如何将最后三个字符转换为整数?

Guru**** 2606725 points
Other Parts Discussed in Thread: MSP430G2553

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/649547/ccs-msp430g2553-how-to-check-string-command-sent-over-uart-rx-echoed-back-over-uart-tx-in-an-if-statement-and-convert-last-three-characters-into-an-integer

器件型号:MSP430G2553

工具/软件:Code Composer Studio

我曾在一段时间前提出过一个与这个非常相似的问题、此后我进行了几次调整。 我正在处理的项目涉及温度传感器风扇控制器和 MSP430G2553。 ADC 值通过传感器进行测量、预设所需温度和当前温度之间的误差差异都通过 UART TX 打印到 PC。 风扇通过 PWM 增加速度、这取决于检查 ADC10MEM 值的三个 if 语句(我删除了许多其他用于清洁的 if 语句)。 顺便说一下、我使用了 CoolTerm 来查看打印的值。  

我要做的最后一件事是通过 UART RX 发送多字符命令、以设置任何所需的温度值。 现在、诸如 if (UCA0RXBUF ='A')的单字符命令可以设置 SetDesiredTemp = 100。 此外、我可以通过 UART RX 键入任何随机字符串、完全相同的字符串将通过 UART RX 回传到 PC。 这意味着我可以确认我的 MSP430能够读取一整串字符并将其发回 PC。

这是我的问题出现的地方。 我知道 UART RX 正在执行我想要的操作、但使用下面的代码、如何检查发送到 RX 的字符串(或检查通过 TX 回显的字符串)以查看是否输入了字符串命令、例如"Set Desired Temperature ="? 更重要的是、如何将最后三个字符"100"转换为可插入 SetDesiredTemp = 100行的整数?

我将在这里发布完整代码、供大家查看。 它会进行编译。 我主要希望在代码中可以执行上述操作的地方、数小时的调试让我无处可去。

#include 
#include 
#include 

//闭环:温度传感器风扇控制器

/***初始化 UART 相关代码***/
volatile unsigned int current = 0;//将当前读取的 ADC10MEM 存储在循环的开头。
volatile unsigned int timer_count = 0;
static char data;
char buffer[32];
char buffer2[32];
void init_UART ();
void init_timer();
void start_conversion ();
void UARTSendArray (unsigned char * TxArray、unsigned char ArrayLength);

/***初始化温度变量***/
int error = 0;//从电流中减去电流以确定风扇速度。
int SETtemperror = 370;//生成错误温度值的默认室温。

void (* UART_Rx_ISR_PTR)(unsigned char c);

void UART_SET_Rx_ISR_PTR (void (* ISR_PTR)(unsigned char c)
){
UART_Rx_ISR_PTR = ISR_PTR;
}

void UART_putc (unsigned char c) //通过 TX 一次打印一个字符到 PC。
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX 缓冲器就绪?
UCA0TXBUF = c;// TX
}

void UART_PUs (const char * str) //使用此功能将任何字符串消息打印到 PC。
{
while (* str) UART_putc (* str++);
}

void UART_Rx_ISR (unsigned char c){// UART RX 命令转到此处?
UART_putc (c);
P1OUT ^= BIT0;//切换 P1.0 (红色 LED)

开关(c){
案例"A":{
SETtemperror = 460;
UART_PUs ((char *)"\n\rDesirred 温度现在为:460\n");
}
}


void init_UART ()
{
P1SEL = BIT1 + BIT2;// P1.1 = RXD、P1.2 = TXD
P1SEL2 = BIT1 + BIT2;// P1.1 = RXD、P1.2 = TXD
UCA0CTL1 |= UCSSEL_2;// SMCLK
UCA0BR0 = UCA0;参阅上面的波特率分频器0 = UCA0BR0
;/ UCB0BR0 = UCA0 = UCA104;
//调制 UCBRSx = 1
UCA0CTL1 &=~UCSWRST;//**初始化 USCI 状态机**
IE2 |= UCA0RXIE;//启用 USCI_A0 TX 中断
}

空 UARTSendArray (unsigned char * TxArray、unsigned char ArrayLength)
{
while (ArrayLength --){//循环、直至 StringLength = 0且 POST 递减
while (!(IFG2 & UCA0TXIFG));//等待 TX 缓冲区为新数据做好准备

UCA0TXBUF =* TxArray;//在指定的指针的位置写入字符
TxArray++;//使 TxString 指针指向下一个字符
}
}

void init_timer ()
{
TA1CTL |= TACLR;//重置计时器
TA1CTL = tassel_2// SMCLK
+ ID_0//输入分频器= 1
+ MC_2;//连续模式,中断禁用
TA1CCTL0 = OUTMOD_2//比较模式
+ CCIE//中断启用
+ CCIFG

;*** Timer0设置
DCOCTL = 0;//选择最低 DCO 设置
BCSCTL1 = CALBC1_1MHz;//将 DCO 设置为1MHz
DCOCTL = CALDCO_1MHz;
TA0CTL |= TASSEL_2 | MC_1 | ID_3;
TA0CCR0 |= 800;
TA0CCTL1 |= OUTMOD_7;
TA0CCR1 |=0;
}

void start_conversion ()
{
if ((ADC10CTL1 & ADC10BUSY)=0){// if not already converting
//P1OUT ^= 0x40;// green led
ADC10CTL0 |= ADC10SC;
ADC10SA =(unsigned)&current;//将最新的 ADC 值存储到



主地址
中}void (int)
WDTCTL = WDTPW + WDTHOLD; //停止 WDT
init_uart();
init_timer();

/*** GPIO 设置***/
P1DIR |= BIT6;// PWM 输出
P1SEL |= BIT6;
P2DIR |= BIT0 + BIT1 + BIT3 + BIT4;

/*** ADC10设置***/
ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE + REFON + ENC;// ADC10ON、中断被启用。 启用(但尚未启动)转换
ADC10DTC1 = 1;//每次传输一个块
ADC10CTL1 = INCH_3 + SHS_0 + ADC10DIV_3 + ADC10SSEL_3 + CONSEQ_0;//时钟源= SMCLK
//ADC10AE0 |= BIT0; // pa.1 ADC 选项选择

//在接收到数据时调用寄存器 ISR
UART_SET_Rx_ISR_PTR (UART_Rx_ISR);

//启用中断并将 CPU 置于 SLEEP
_Bis_SR_register (GIE+LPM0_Bits);

unsigned char c = UCA0RXBUF;
UART_putc (c); //初始化字符检索,初始化字符打印。

UART_PUT ((char *)"\n\n\r 温度控制器:打开并准备好\n");//发出主块已初始化的信号

unsigned int a = 0、delay = 50000、sec = 0;
对于(;)
{
电流= ADC10MEM;
Error = Current - SETtemperror;//计算与预设温度的误差差异。 ab()已删除。

//a = 0;sec = 0; //延迟以消除 LED 闪烁
//while (A < delay){A++;}
//while ((a >= delay)&&(sec < 10)){A = 0;sec++;}

如果(误差< 10){
P2OUT &=~BIT4;P2OUT &=~BIT3;P2OUT &=~BIT1;P2OUT &=~BIT0;// 0000
TA0CCR1 = 0;// TA0CCR1 = ADC10MEM
}
如果((error >= 10)&&(error < 100)){
P2OUT &=~BIT4;P2OUT |= BIT3;P2OUT |= BIT1;P2OUT &=~BIT0;// 0000
TA0CCR1 = 400;// TA0CCR1 = ADC10MEM
}
if (error >= 100){
P2OUT |= BIT4;P2OUT |= BIT3;P2OUT |= BIT1;P2OUT |= BIT0;// 1111
TA0CCR1 = 800;// TA0CCR1 = ADC10MEM
}
}


#pragma vector=ADC10_vector // ADC10中断服务例程
__interrupt void ADC10_ISR (void)
{
_BIC_SR_REGISTER_ON_EXIT (CPUOFF); //从0 (SR)清除 CPUOFF 位
}

//中断处理程序
#pragma vector = Timer1_A0_vector
__interrupt void Timer1_A0 (void)
{
timer_count++;
if (timer_count > 16){// 1秒刷新率的默认值为16。 对于较慢的数据传输
、设置为16 timer_count = 0;
start_conversion ();

IE2 |= UCA0TXIE;//激活 TX 中断
IE2 |= UCA0RXIE;//启用 USCI_A0 RX 中断
}
#pragma

vector = USCIAB0TX_vector
__interrupt void USCI0TX_ISR (void)
{
//P1DIR = 0x01;
//P1OUT ^= 0x01;//红色 LED

无符号整型 I = 0;//迭代器指针
sprintf (buffer、"temp measured:%d \n\r"、(int)(current));//将文本输出到 PC
//uart_posed (((char *)"MSP430 Harduart\n"while
(int)、(int))、(int)(int)))(while '/uift2
)/u0u./uart!/uart (uif) buffer 0)/u./uart (uift2)/u0u.u.
UCA0TXBUF = buffer[i++];
}

unsigned int j = 0;//迭代器指针
sprintf (buffer2、"Error diff:%d \n\r"、(int)(error)));//将文本输出到 PC
while (buffer2[j]!='\0'){
while (!(IFG2 & TXIFG缓冲区)/ UCA0A0准备就绪
UCA0TXBUF = buffer2[j+];
}
IE2 &&~UCA0TXIFG;//复位中断标志
}

#pragma vector=USCIAB0RX_Vector
__interrupt void USCI0RX_ISR (void)
{
if (UART_Rx_ISR_PTR!= 0L){ //如果有更多字符要发送到 RX 缓冲区,请继续发送字符。
(UART_Rx_ISR_PTR)(UCA0RXBUF);
}

switch (UCA0RXBUF){//不确定命令的确切位置
案例"d":{
SETtemperror = 460;
UART_PUs ((char *)"\n\rDesirred 温度现在为:460\n");
}
}

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

    我在这里建议的方法

    https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/641968

    不起作用?

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

    这是我再次尝试让程序将输入 RX 字符串保存在全局缓冲区中、RX 中断之外。 它似乎已经起作用了,看着印刷字符串的图像。 有部分代码、主要是22-42行、120-129行和202-204行、我是在一个 GitHub 页面上抓取的、因此我不确定该代码是如何保存到全局缓冲区中的。 但我可以确认我通过 RX 发送的字符串命令、例如"slkjdflksjdfklsjdklfjkfjsd"、同一命令"slkjdflksjdfklsjdklkljdklfjsd"在 TX 上回传到 PC、因此我相信此代码中已经有全局缓冲区。  

    我想我要做的是、以某种方式提取/检查/读取我刚刚输入的任何字符串命令、并使用 if 语句或类似的内容对其进行分析。 该字符串通过 TX 回传、因此可能有一种方法来读取刚刚回传的任何字符串命令? 我对如何继续的问题不太确定。

    我已经尝试在调试器中逐行运行代码、只是没有任何信息告诉我代码将传入的 RX 数据保存到字符串/数组中的确切位置、以便每次将一个字符反馈回 TX。 这个过程似乎是在没有地方发生的,我希望抓住该字符串/数组变量名称在 if 语句中调用它,假设 if-statements 可以检查诸如“if (RXstring[0:25]='Set desired Temperature ='){ SETdesedtemp = strtol (RXstrstrstrstring[26:28])}的内容;} //将所需的温度设置为等号后面的3位数字。" 我知道 if 语句的语法很可怕,但这正是我要做的,似乎是不可能的。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我将按如下方式处理该问题:
    1-发送“开始接收值”命令。 这应该会将 RX 状态机设置为将传入字节添加到缓冲区。
    2-一次读取一位字节并递增缓冲区索引(即缓冲区索引0处的"1"、缓冲区索引1处的"0"等)
    3-发送“评估和使用发送的值”命令。 然后、该命令只是数字缓冲器上的"atoi()"函数、用于重置 RX 状态机。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    您是否成功地使 UART 通信正常工作、或者您是否仍有任何未决问题?

    此致、
    Caleb Overbay