Hello,
I am using TimerA to implement a software UART but when CCIFG is set to 1 in TACCTL0 I assume that it has entered that interrupt, however during the interrupt I do TACCTL0 &= ~CCIFG to reset it back to 0, but it does not reset so I'm not sure if its actually entering the interrupt even though the flag is set. Can anyone help?
Here is the code:
/****************************************************************** Copyright (C) 2006-2007 Texas Instruments, Inc.*ShreHarsha Rao - RFID Systems*----------------------------------------------------------------* All software and related documentation is provided "AS IS" and* without warranty or support of any kind and Texas Instruments* expressly disclaims all other warranties, express or implied,* including, but not limited to, the implied warranties of* merchantability and fitness for a particular purpose. Under no* circumstances shall Texas Instruments be liable for any* incidental, special or consequential damages that result from* the use or inability to use the software or related* documentation, even if Texas Instruments has been advised of* the liability.** Unless otherwise stated, software written and copyrighted by* Texas Instruments is distributed as "freeware". You may use* and modify this software without any charge or restriction.* You may distribute to others, as long as the original author* is acknowledged.*****************************************************************///--------------------------------------//Program with hardware USART and//paralel communication interface//with TIR reader chip.////PORT 4.0-4.7 - (IO0-IO7) for parallel interface with reader chip//PORT3.4 - PORT3.5 - USCI_A0 ---> USB/UART control signals//PORT2.1 - IRQ//PORT3.3 - DATA_CLK//PORT1.7 - PORT1.3 - signaling LEDs//--------------------------------------#define DBG 0#include <MSP430x23x0.h> #include <stdlib.h> //Processor specific definitions#include <stdio.h>#include "hardware.h"#include "parallel.h"#include "anticollision.h"#include "globals.h"#include "tiris.h"#include "14443.h"#include "host.h"#include "epc.h"#include "automatic.h"// =======================================================================char rxdata; //RS232 RX data byteunsigned char buf[BUF_LENGTH];signed char RXTXstate; //used for transmit recieve byte countunsigned char flags; //stores the mask value (used in anticollision)unsigned char RXErrorFlag;unsigned char RXflag; //indicates that data is in bufferunsigned char i_reg; //interrupt registerunsigned char counter;unsigned char CollPoss;#include "msp430g2231.h"#include "stdbool.h"#define TXD BIT1 // TXD on P1.1#define RXD BIT2 // RXD on P1.2#define Bit_time 104 // 9600 Baud, SMCLK=1MHz (1MHz/9600)=104#define Bit_time_5 52 // Time for half a bit.unsigned char BitCnt; // Bit count, used when transmitting byteunsigned int TXByte = 1; // Value sent over UART when Transmit() is calledunsigned int RXByte = 1; // Value recieved once hasRecieved is setbool isReceiving; // Status for when the device is receivingbool hasReceived; // Lets the program know when a byte is received// =========================================================================// Main function with init and an endless loop//void Transmit(void);// void main(void) { // initialize peripherals WDTCTL = WDTPW + WDTHOLD; // Stop WDT UARTset(); EnableSet; TRFDisable; delay_ms(1); TRFEnable; delay_ms(1); BCSCTL1 = CALBC1_1MHZ; // Set rangeDCOCTL = CALDCO_1MHZ; // SMCLK = DCO = 1MHzP4SEL |= BIT4;P4DIR |= BIT4;P1IES |= RXD; // RXD Hi/lo edge interruptP1IFG &= ~RXD; // Clear RXD (flag) before enabling interruptP1IE |= RXD; // Enable RXD interrupt isReceiving = false; // Set initial valueshasReceived = false;while(1){Transmit();} __bis_SR_register(GIE); // interrupts enabledwhile(1){if (hasReceived) // If the device has recieved a value{hasReceived = false; // Clear the flagTXByte = RXByte; // Load the recieved byte into the byte to be transmittedTransmit();}if (~hasReceived) // Loop again if another value has been received __bis_SR_register(CPUOFF + GIE);// LPM0, the ADC interrupt will wake the processor up. This is so that it does not// endlessly loop when no value has been Received.} //Add logic for SPI/parallel selection. if (SPIMODE) { //Set Port Functions for Serial Mode EnableSet; irqPINset; irqEDGEset; /* rising edge interrupt */ LEDallOFF; LEDportSET; } else PARset(); //Set Port Functions for Parallel Mode /* Use the DCO to program the SPI first*/ if (SPIMODE) { #ifndef SPI_BITBANG USARTset(); //Set the USART */ #else SlaveSelectPortSet // P3.0 - Slave Select SlaveSelectHIGH // Slave Select - inactive ( high) SIMOSet clkPOUTset; #endif }//test code TRFDisable; TRFEnable; delay_ms(1);//end test code InitialSettings(); // Set MCU Clock Frequency to 13.56 MHz and OOK Modulation /*Now switch from DCO to external 13.56 MHz clock*/ OSCsel(0x00); //set the oscilator delay_ms(10); /*Re-configure the USART with this external clock*/ if (SPIMODE) { #ifndef SPI_BITBANG USARTEXTCLKset(); //Set the USART */ #endif } EnableInterrupts; // General enable interrupts delay_ms(10); LEDpowerON; OOKdirIN; //set OOK port tristate ENABLE = 1; POLLING = 1; FindTags(0x00);}void Transmit(){ while(isReceiving); // Wait for RX completion CCTL0 = OUT; // TXD Idle as Mark TACTL = TASSEL_2 + MC_2; // SMCLK, continuous mode BitCnt = 0xA; // Load Bit counter, 8 bits + ST/SP CCR0 = TAR; // Initialize compare register CCR0 += Bit_time; // Set time till first bit TXByte |= 0x100; // Add stop bit to TXByte (which is logical 1) TXByte = TXByte << 1; // Add start bit (which is logical 0) CCTL0 = CCIS0 + OUTMOD0 + CCIE; // Set signal, intial value, enable interrupts while ( CCTL0 & CCIE ); // Wait for previous TX completion}// === end of main =====================================================#pragma vector=PORT1_VECTOR__interrupt void Port_1(void){isReceiving = true;P1IE &= ~RXD; // Disable RXD interruptP1IFG &= ~RXD; // Clear RXD IFG (interrupt flag) TACTL = TASSEL_2 + MC_2; // SMCLK, continuous mode CCR0 = TAR; // Initialize compare register CCR0 += Bit_time_5; // Set time till first bitCCTL0 = OUTMOD1 + CCIE; // Dissable TX and enable interruptsRXByte = 1; // Initialize RXByteBitCnt = 0x9; // Load Bit counter, 8 bits + ST}// Timer A0 interrupt service routine#pragma vector=TIMERA0_VECTOR__interrupt void Timer_A (void){ CCTL0 &= ~CCIFG;if(!isReceiving){CCR0 += Bit_time; // Add Offset to CCR0if ( BitCnt == 0) // If all bits TXed{ TACTL = TASSEL_2; // SMCLK, timer off (for power consumption)CCTL0 &= ~ CCIE ; // Disable interrupt}else{CCTL0 |= OUTMOD2; // Set TX bit to 0if (TXByte & 0x01)CCTL0 &= ~ OUTMOD2; // If it should be 1, set it to 1TXByte = TXByte >> 1;BitCnt --;}}else{CCR0 += Bit_time; // Add Offset to CCR0if ( BitCnt == 0){ TACTL = TASSEL_2; // SMCLK, timer off (for power consumption)CCTL0 &= ~ CCIE ; // Disable interruptisReceiving = false;P1IFG &= ~RXD; // clear RXD IFG (interrupt flag)P1IE |= RXD; // enabled RXD interruptif ( (RXByte & 0x201) == 0x200) // Validate the start and stop bits are correct{RXByte = RXByte >> 1; // Remove start bitRXByte &= 0xFF; // Remove stop bithasReceived = true;} __bic_SR_register_on_exit(CPUOFF); // Enable CPU so the main while loop continues}else{if ( (P1IN & RXD) == RXD) // If bit is set?RXByte |= 0x400; // Set the value in the RXByteRXByte = RXByte >> 1; // Shift the bits downBitCnt --;}}}
James
I'm not sure what your problem/quesiton is.
Where do you look at CCIFG? How do ou know it is set?Doe syour code not work? If so what doesn't work?
If you set a breakpoint inside the TIMERA0 _VECTOR, teh CCIF Gbit in TACCR0 is automatically cleared when teh ISR is entered. However, at the moment the debugger has fetched all data to present it to you, chances are that another interrupt has been already triggered in the meantime. The world doesn't stop turning just because the debugger hit a breakpoint.
Even in main it is possible that an 'if (CCR=&CCIFG)' block in main is entered even though any possible interrupt should be handled by the ISR.It may be that the check was performed the very moment the IFG bit was set. So the ISR will be triggered and executed right after the check - however, the check was positive, even if only for one MCLK cycle.
And as long as GIE is clear (and it is always clear implicitely while an ISR is executed) no interrupts are executed at all (else an ISR would infinitely interrupt itself)
_____________________________________Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.
I'm using IAR to watch the registers and it shows that once CCIFG gets set it doesn't clear, furthermore the last line of my code in the Transmit() function waits for CCIE to be cleared in the ISR, but when I step through my code it doesn't get past that line which suggests the ISR was never executed.
while ( CCTL0 & CCIE ); // Wait for previous TX completion
James Yuwhile(1){Transmit();} __bis_SR_register(GIE); // interrupts enabled
Your code gets stuck in the while before it reaches the line that sets GIE and enables interrupts. If GIE is clear, interrupts are globally disabled, which is the power-on default.
I didn't read further, so maybe there is more, but my office hours are over now :)
Ah I see! Can't believe I missed that, thanks!