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.
Tool/software: Code Composer Studio
I posted a very similar question to this one a while ago, and I made several adjustments since then. The project I am working on involves a temperature sensor fan controller and the MSP430G2553. ADC values are measured from the sensor, and an error difference between a preset desired temperature and the current temperature are both printed over UART TX to the PC. The fan increases in speed via PWM, dependent on three if-statements that check the ADC10MEM value (i removed many other if-statements for cleaning). I used CoolTerm, by the way, to see the printed values.
The last thing I want to do is send multiple-character commands over UART RX, to set any desired temperature value. Right now, single character commands such as if(UCA0RXBUF == 'a') can set a SetDesiredTemp = 100. Also, I can type any random string of characters over UART RX, and the exact same string will be echoed over UART RX back to PC. This means I can confirm that my MSP430 is able to read a full string of characters and send it back to PC.
Here's where my issue arises. I know UART RX is doing what I want it to do, but using this code below, how can I check the string I sent to RX (or check the string echoed over TX) to see if a string command such as "Set Desired Temperature = " has been entered? And more importantly, how can I then convert the last three characters "100" into an integer that can be plugged into a SetDesiredTemp = 100 line?
I'll post my full code here for all to see. It compiles. I'm mainly hoping where in this code I can do the things described above, debugging for hours has gotten me nowhere.
#include <msp430g2553.h> #include <stdio.h> #include <string.h> //Closed Loop: Temperature Sensor Fan Controller /*** Initialize UART-Related Code ***/ volatile unsigned int current = 0; // store the currently read ADC10MEM at the beginning of the loop. 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); /*** Initialize Temperature Variables ***/ int error = 0; // subtract current from current to determine fan speed. int SETtemperror = 370; //the default room temperature for making the error temperature values. 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) // print to PC over TX one character at a time. { while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = c; // TX } void uart_puts(const char *str) // print any string message to PC with this function. { while(*str) uart_putc(*str++); } void uart_rx_isr(unsigned char c) { // UART RX Commands go here? uart_putc(c); P1OUT ^= BIT0; // toggle P1.0 (red led) switch(c) { case 'a': { SETtemperror = 460; uart_puts((char *)"\n\rDesired Temperature is now: 460\n\r"); } } } 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 = 104; // see baud rate divider above UCA0BR1 = 0; UCA0MCTL = UCBRS0; // modulation UCBRSx = 1 UCA0CTL1 &= ~UCSWRST; // ** initialize USCI state machine ** IE2 |= UCA0RXIE; // Enable USCI_A0 TX interrupt } void UARTSendArray(unsigned char *TxArray, unsigned char ArrayLength) { while(ArrayLength--) { // Loop until StringLength == 0 and post decrement while(!(IFG2 & UCA0TXIFG)); // Wait for TX buffer to be ready for new data UCA0TXBUF = *TxArray; //Write the character at the location specified py the pointer TxArray++; //Increment the TxString pointer to point to the next character } } void init_timer() { TA1CTL |= TACLR; // reset timer TA1CTL = TASSEL_2 // SMCLK + ID_0 // input divider = 1 + MC_2; // continuous mode, interrupt disabled TA1CCTL0 = OUTMOD_2 // compare mode + CCIE // interrupt enabled + CCIFG; /*** Timer0_A Set-Up ***/ DCOCTL = 0; // Select lowest DCO settings BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1 MHz 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) ¤t; // store latest ADC value into address } } int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT init_uart(); init_timer(); /*** GPIO Set-Up ***/ P1DIR |= BIT6; // PWM output P1SEL |= BIT6; P2DIR |= BIT0 + BIT1 + BIT3 + BIT4; /*** ADC10 Set-Up ***/ ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE + REFON + ENC; // ADC10ON, interrupt enabled. enable (but not yet start) conversions ADC10DTC1 = 1; // one block per transfer ADC10CTL1 = INCH_3 + SHS_0 + ADC10DIV_3 + ADC10SSEL_3 + CONSEQ_0; // clock source = SMCLK //ADC10AE0 |= BIT0; // PA.1 ADC option select // register ISR called when data was received uart_set_rx_isr_ptr(uart_rx_isr); // enable interrupts and put the CPU to sleep _bis_SR_register(GIE+LPM0_bits); unsigned char c = UCA0RXBUF; uart_putc(c); // initialize retrieving of characters, initialize printing of characters. uart_puts((char *)"\n\rTemperature Controller: ON and READY\n\r"); // signal that the main block has been initialized unsigned int a = 0, delay = 50000, sec = 0; for (;;) { current = ADC10MEM; error = current - SETtemperror; // Calculate error difference from preset temperature. abs() removed. //a = 0; sec = 0; // Delays to remove LED flickering //while (a < delay) { a++; } //while ((a >= delay) && (sec < 10)) { a = 0; sec++; } if (error < 10) { P2OUT &= ~BIT4; P2OUT &= ~BIT3; P2OUT &= ~BIT1; P2OUT &= ~BIT0; // 0000 TA0CCR1 = 0; // TA0CCR1 = ADC10MEM } if ((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 service routine __interrupt void ADC10_ISR(void) { __bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR) } // INTERRUPT HANDLERS #pragma vector = TIMER1_A0_VECTOR __interrupt void Timer1_A0(void) { timer_count++; if (timer_count > 16) { //default is 16 for 1 second refresh rate. set to 16 for slower data transfer timer_count = 0; start_conversion(); IE2 |= UCA0TXIE; // activate TX interrupt IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt } } #pragma vector = USCIAB0TX_VECTOR __interrupt void USCI0TX_ISR(void) { //P1DIR = 0x01; //P1OUT ^= 0x01; //red led unsigned int i = 0; // iterator pointers sprintf(buffer, "temp measured: %d \n\r", (int)(current)); //output text to PC //uart_puts((char *)"MSP430 harduart\n\r"); while (buffer[i] != '\0') { while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = buffer[i++]; } unsigned int j = 0; // iterator pointers sprintf(buffer2, "Error diff: %d \n\r", (int)(error)); //output text to PC while (buffer2[j] != '\0') { while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = buffer2[j++]; } IE2 &= ~UCA0TXIFG; // reset interrupt flag } #pragma vector=USCIAB0RX_VECTOR __interrupt void USCI0RX_ISR(void) { if(uart_rx_isr_ptr != 0L) { // if there are more characters to send to RX buffer, keep sending characters. (uart_rx_isr_ptr)(UCA0RXBUF); } switch(UCA0RXBUF) { // unsure where exactly the commands would go case 'd': { SETtemperror = 460; uart_puts((char *)"\n\rDesired Temperature is now: 460\n\r"); } } }
Did the method I suggested over here
https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/641968
not work?
This is my re-attempt at getting the program to save the inputting RX string in a global buffer, outside of the RX interrupt. It seems to work already, looking at the image of printed strings. There are portions of code, mainly lines 22-42 and 120-129 and 202-204, that I grabbed from a GitHub page a bit ago, so I am unsure how exactly this code is saving into a global buffer. But I can confirm that a string command i send over RX, say "slkjdflksjdfklsjdklfjsd", the same command "slkjdflksjdfklsjdklfjsd" is echoed over TX back to PC, thus I believe a global buffer is already in this code.
I guess what I am looking to do is, somehow extract / check / read whatever string command I just entered and analyze it with an if-statement or something similar. This string is echoed back over TX, so maybe there is a way to read whatever string command was just echoed back? I'm just too unsure on how to proceed.
I have tried running the code line-by-line in the debugger, and simply nothing is telling me where exactly the code saves the incoming RX data into a string / array, to be fed one character at a time back to TX. This process seems to be happening out of nowhere, and I was hoping to grab that string / array variable name to call it within an if-statement, assuming if-statements can check for something like "if (RXstring[0:25] == 'Set Desired Temperature = ') { SETdesiredtemp = strtoul( RXstring[26:28] ) }; //set desired temp to whatever 3-digit number is after the equals sign". I know the syntax in that if-statement is horrible, but that is precisely what I am looking to do, it seems impossible.
**Attention** This is a public forum