Tool/software: Code Composer Studio
Hi everyone, I've been trying for many hours to modify an already working code that allows me to send/receive characters and strings via UART. The modification I'm trying to add is that this time I want to implement interrupts to do the same task. I've looked many related posts but still can't do it.
My code is as follows: it has a UART_init function that setup the proper configuration for the UART, including the configuration and enable of interrupts. I also have 4 functions to send/receive a single char and a string (recepcion of strings is done with a Ring buffer).
So my doubt is how should I modify this functions in order to implement the interrupts, and also, how do I have to implement a ISR for this. I've been told that I shouldn't have a while(wait for flag) in these functions. I also want to implement a ISR to detect if a button has been pushed/released, clearly this can be solved easily if the previous problem is solved. In the main function I just initialize the UART by calling UART_init and then play with the transmission and recepcion of chars and string.
CODE can be found in file example_code.c
#include <msp430.h> #include <string.h> // Have a look at both the .h and the .c file, there is code missing. #include "USART_implement_me.h" #define BufferSize 16 //for the ring buffer /* The main function */ int main(void){ WDTCTL = WDTPW + WDTHOLD; // You already lerned how to configure that button, remember? P1DIR = 0x01; // Set P1.0 (led) as output and P1.1 as intput (botón en cero) P1REN |= 0x02; // Enable pull-up resistor on P1.1 (evita que la entrada flote) P1OUT = 0x02; //fijamos P1.1 como HIGH (en 1). struct USART_configuration config_57600_8N1 = {57600, 8, 0, 1}; // This time you should also configure and enable(!) some interrupts. USART_Init(config_57600_8N1); // Print a welcome message USART_Transmit_char("G"); USART_Transmit_String("Please send some characters from your terminal.\r\n"); //TEST char c = USART_Receive_char(); USART_Transmit_String("I received an "); USART_Transmit_char(c); USART_Transmit_String(".\r\n\r\n"); //END TESTEO // // while(1){ // // Your program will only ask *if* a string was received. If yes, it will display this string. // // If not, it will just skip and do other stuff until it is time to ask again. // // Here you could do all kinds of other cool things. Remember, the step above // // will be skipped in most iterations, so you have plenty of processing time here.... // } } // Add a ISR for a button here! NOT WORKING #pragma vector=USCI_A1_VECTOR __interrupt void USCI_A1_ISR(void){ volatile unsigned int t; static const int DelaySum = 15000; if( !(P1IN & 0x02)){ //if the button is pushed USART_Transmit_String("The button was pushed.\r\n"); for(t = DelaySum; t>0; t--); if ((P1IN & 0x02)){ //if the button is released USART_Transmit_String("The button was released.\r\n"); for(t = DelaySum; t>0; t--); } } } volatile unsigned int i; int retardo = 10000; #include "USART_implement_me.h" // Returns zero in case of success, non-zero for errors. void USART_Init(struct USART_configuration config){ // Expected values const unsigned int BR = 57600; const int DL = 8; const int Par = 0; const int SB = 1; // Given Values unsigned int BaudR = config.BaudRate; unsigned int DataL = config.DataLength; unsigned int Parity = config.Parity; unsigned int StopB = (config.StopBit -1); // Basic config UCA1CTL0 = UCMODE_0; // USCI mode: UART. By default. P4SEL |= BIT4 + BIT5; // Set P4.4 as UCA1TXD, P4.5 as UCA1RXD UCA1CTL1 |= UCSWRST; // Put eUSCI in reset. Allows to modify UCAxTL0. UCA1CTL1 |= UCSSEL_2; // SMCLK (1048576MHz) (_0 es ACLK = 32768) UCA1BR1 = 0; //Specific config if (BaudR == 57600){ if (DataL == 8){ // Only 8 bits accepted for USART mode. 7 bits reserved for SPI communication mode. if (StopB == 0){ // 0 for 1 SP, 1 for 2 SP. if (Parity == 0){ UCA1MCTL |= UCBRS_2; // From DataSheet: modulation and over sampling for this clk y BaudRate. UCA1BR0 = 18; UCA1CTL0 = !UC7BIT | !UCSPB | !UCPEN; // 8bit + 0 stop bits + parity disabled. purely ornament. These are the default values. UCA1CTL1 &= ~UCSWRST; // **Initialize USCI state machine** // UCA1CTL1 = ~UCRXEIE; /*NTERRUPTIONS*/ UCA1IE |= UCRXIE + UCTXIE; // Enable USCI_A1 RX interrupt __bis_SR_register(GIE); // Interrupts enabled. LPM0_bits: para modo LPM0 for(i = retardo; i>0; i--); } else{ printf( "This communication channel is exclusively configured for no parity. Please enter a %d on the third argument \r\n", Par); } } else{ printf( "This communication channel is exclusively configured for one stop bit. Please enter a %d on the fourth argument \r\n", SB); } } else{ printf( "This communication channel is exclusively configured for eight bits length. Please enter an %d on the second argument \r\n", DL); } } else{ printf( "This communication channel is exclusively configured for %d baud rate. Please enter %d on the first argument \r\n", BR, BR); } } // Receives a single character. char USART_Receive_char(void){ char singleC; if(UCA1IFG & UCRXIFG){ /* Receive data */ singleC = UCA1RXBUF; } return singleC; // A nice hint: With interrupts, your microcontroller can inform you whenever // a character comes in. There is an interrupt called UCRXIFG for that. // If such an interrupt would fill a buffer with the received data, this // function here could return you one character from this buffer. You would no // longer need to 'wait for the byte to arrive', but could just fetch it out // of this buffer at any later point. And of course you've got a buffer, // right? // If the buffer is actually empty, you could maybe return a 0 or so to // indicate that to the user? } // Transmits a single character void USART_Transmit_char(uint8_t dato){ if(UCA1IFG & UCTXIFG ){ UCA1TXBUF = dato; /* Clear the interrupt flag */ UCA1IFG &= ~UCTXIFG; } // A nice hint: With interrupts, you can send bytes whenever the register UCA1TXBUF // is free. And there is an interrupt called UCTXIFG that *tells you* // whenever UCA1TXBUF is free. // This requires you to have some bytes in the buffer that you would like to // send, of course. You have a buffer, don't you? } //Transmits a given string void USART_Transmit_String(char *string){ if (string != NULL ) { int length = strlen(string); int i; for(i=0;i<length;i++,string++){ USART_Transmit_char(*string); } } } //build for strings ending with \n. char USART_Receive_StringRING(void){ unsigned int j = 0, p = 0, BufSiz = BufferSize; char *string; /*Case 1: the buffer is not full*/ while (j < BufSiz){ char caracterr = USART_Receive_char(); if (caracterr != '\n'){ string[j] = caracterr; } else if(caracterr == '\n'){ //If we receive a \n the master wants to end string[j] = '\0'; //Overwrites the \n with \0 return string; } j++; } /*Case 2: the buffer is full*/ if ( j == BufSiz){ while(p < BufSiz){ char caracter = USART_Receive_char(); if (caracter != '\n'){ string[ p ] = caracter; } else if (caracter == '\n'){ *(string+BufSiz) = '\0'; rotleftmem(string, BufSiz, p); break; } j++, p++; if (p == BufSiz){ p = 0; } } } return string; } void rotleftmem(char *p, size_t len, size_t lshift){ //rotate a string unsigned char *d; size_t start; size_t dx, sx; size_t todo; unsigned char x; if (!len) return; lshift %= len; if (!lshift) return; d = p; todo = len; for (start = 0; todo; start++) { x = d[start]; dx = start; while (1) { todo--; sx = dx + lshift; if (sx >= len || sx < dx /*overflow*/) sx -= len; if (sx == start) { d[dx] = x; break; } d[dx] = d[sx]; dx = sx; } } }