geralt1114 0 Posted June 13, 2020 Share Posted June 13, 2020 Hello guys,i have a question for my project im using the msp430g2231 microcontroller and i want to measure frequencies up to 10Mhz.Im new to microcontrollers(not programming),and im not sure how to make the overflow work void main(void) { WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation delay(100); // delay 100mS until next screen refresh /*** Timer_A Set-Up ***/ TA0CCR0 = SampleTuneTime; TA0CCTL0 |= CCIE; // Interrupt enable TA0CTL |= TASSEL_1 + ID_3; // SMCLK TA0CCTL1 |= CCIE + CCIS_0 + CM_1 + CAP; // Interrupt enable, capture select CCIxA, Positive edge, capture mode TA0CTL |= TASSEL_1; //SMCLK _BIS_SR(GIE); // Enter LPM0 with interrupts enabled while(1) { TA0CTL |= MC0; // Start timer up mode.Timer counts up to TACCR0 TA0CTL |= MC1; // Start timer //while(CounterValue != 400); // Wait while CounterValue is not equal to 400 TA0CTL &= ~MC0; // Stop timer mode TA0CTL &= ~MC1; // Stop timer Result >>= 2; // Divide Result by 4 calc_freq(); //convert long into frequency char buffer[8]= { 0, }; unsigned long toLCD = Frequency; // int Base = 10; itoa(toLCD,buffer); //convert decimal lcd_init(); send_string("FREQUENCY IS"); send_command(0xC0); send_string(buffer); send_command(0xC8); send_string("HZ"); Result = 0; // Zero Result CounterValue = 0; // Zero CounterValue StoredCount = 0; // Zero StoredCount TA0R = 0; // Zero Timer_A0 register } } #pragma vector=TIMER0_A0_VECTOR __interrupt void Timer0_A0(void) { TA0CTL &= ~MC0; // Stop timer TA0CTL &= ~MC1; // Stop timer CounterValue++; // Increment CounterValue if (CounterValue >= (NumberSamples +1)) // Reset values if NumberSamples +1 is reached { CounterValue = 0; // Zero CountValue StoredCount = 0; // Zero StoredCount } Result += StoredCount; // Store accumulated count in Result StoredCount = 0; // Zero StoredCount TA0CTL |= MC1; // Start timer TA0CTL |= MC0; // Start timer StoredCount++; // Increment StoredCount } this is the main code of the program im using custom made function for the itoa and the communication with the LCD.I have two questions 1.) Can i make the frequency meter up to 10Mhz cuz the g2231 has one timer and 1Mhz calibration available. 2.)Can i somehow check if the code is working cuz i dont have any way to send frequency right now,like counting the internal frequency or something like that. Thank you for your time. Quote Link to post Share on other sites
enl 227 Posted June 13, 2020 Share Posted June 13, 2020 Several things here: where are/what are the declarations for the variables you are using? The types matter here. You seem to be using the capture mode, but you are not ever pulling the captured value from the TACCRx in the interrupt handler. A capture event copies the value from the count register to the CCR Please explain a bit about what your method is here. (as an aside, much of the documentation you have is not useful- it should express what the statements mean in terms of the solution. For example: "CounterValue++; // Increment CounterValue" What does countervalue represent? What are you counting? The next line, same. and so on. Good docs make it a LOT easier to help) As to the questions: What do you mean "make overflow work"? "Can i make the frequency meter up to 10Mhz". Sure. With high enough system clock. It will have poor resolution at the high end if you are doing it by timing from edge to edge (what capture mode will let you do). At low frequency, this is very effective. At higher frequency, it is better to count edges for a fixed period, but that needs to be done with hardware counting, as the interrupt latency, even at 16MHz system clock, will limit you to less than about 1MHz counting in software, and that is tough to hit. This would require a device that has two timer modules (one to time an interval, the other to count using INCLK (TASSEL_3-not available on the g2231) "Can i somehow check if the code is working" Easiest if you find a means to provide a test signal to the input pin. There are a lot of ways (555 timer circuit, leach a 32768Hz signal if that is available on board, 50 or 60Hz grid frequency with the appropriate signal conditioning, a phototransistor in front of a flickering light source, like a PWM'd LED,and so on), but without knowing more about what you have available, I really can't tell you any more than that. Quote Link to post Share on other sites
geralt1114 0 Posted June 13, 2020 Author Share Posted June 13, 2020 Hello,thank you for the reply #define DR P1OUT = P1OUT | BIT4 // define RS high #define CWR P1OUT = P1OUT & (~BIT4) // define RS low #define READ P1OUT = P1OUT | BIT5 // define Read signal R/W = 1 for reading #define WRITE P1OUT = P1OUT & (~BIT5) // define Write signal R/W = 0 for writing #define ENABLE_HIGH P1OUT = P1OUT | BIT6 // define Enable high signal #define ENABLE_LOW P1OUT = P1OUT & (~BIT6) // define Enable Low signal unsigned int i; unsigned int j; volatile unsigned int CounterValue = 0; volatile unsigned int StoredCount = 0; unsigned int Result = 0; const int NumberSamples = 4; unsigned int Frequency = 0; unsigned int SampleTuneTime = 10000; so these are the values i have declared,about the code my idea was that on the rising edge of the signal i turn on the counter i store it in a variable and on falling edge i stop it and read it.I load a value into TA0CCR0 so that TA0 can count up to it,after that TA0CCR0 intrerrupt triggers and increments CounterValue.StoredCount is the number of positive edges seen in the desired frequency.Im havent set a fixed frequency yet because i was still experimenting float SampTime = 0.03; // 30mS sample time Frequency = Result / SampTime; // Divide the averaged sampled result by the sample time to gain the frequency i calculate the frequency like this i convert the value stored in Frequency to a string with the itoa function and send it to the LCD like this And about the overflow thing,sinse i think the SMCLK is only 1 MHz and i need 10 from what i understanded the overflow lets you go higher but i need to read more about it. void send_string(char *s) { while(*s) { send_data(*s); s++; } } Of course what i did could be completely wrong sinse its my very first msp430 project and things are still confusing for me/ Quote Link to post Share on other sites
enl 227 Posted June 13, 2020 Share Posted June 13, 2020 Lets work through a few things here... Frequency is the number of complete cycles per second. This can be determined a number of ways. The scheme you seem to be going for is to time a cycle. This would be from an edge to the next instance of the same type edge- rising to rising, for example. This will produce a count that is a time. The base unit may be microseconds at a 1MHz clock, but it is a time- the period of the signal. The frequency unit will be the reciprocal of this. Lets say that the count is 140. This means that 140microseconds (140E-6 seconds) lapsed from one rising edge to the next rising edge. The frequency will be 1000000/140 (1E6 clocks/second / 140 clocks to get the unit 1/second, or Hz) = 7143Hz. That's the concept. The code you have does not do this. When the interrupt occurs in CAPture mode, the count in the timer is copied to the CCR. This is what you need to pull. As long as this has not rolled over, the count tells you the period of the measured signal. You never read this. You have: Result += StoredCount; // Store accumulated count in Result StoredCount = 0; // Zero StoredCount TA0CTL |= MC1; // Start timer TA0CTL |= MC0; // Start timer StoredCount++; // Increment StoredCount This has several issues, including: you set storedcount to zero every interrupt, then increment it. The net result is that the value will be 1 at the end of the handler, every time, and 1 when the handler is entered, every time except if it has be set elsewhere.. Also, you generally would not want to stop and start the timer in the handler like this. The external signal goes on. The timer stops. The acquired time will be wrong. An outline of what you might do (copied directly from the documents for a system I implemented last year. The system is safety critical in a manufacturing plant and was reviewed and tested exhaustively) Up count the timer interrupt on overflow: this is so you can detect the overflow and deal with it, either with an overflow count or as an out-of-range. This interrupt is hardware supported for just such a purpose Interrupt on capture: grab the value of the CCR and store it in your volatile. Exit sleep mode so your loop in main can grab the stored value and do it's thing. If counting overflows, the overflow counter gets copied at the same time, and reset. No need to reset the CCR. You don't look at it anywhere else. You do NOTHING on overflow except increment the overflow count. There are several ways to go about maintaining the counter. You can reset it when the CCR capture occurs, or you can let it free run, and the ACTUAL value to use is the difference between the current capture and the prior one. There is a little more work if you are counting overflows. Resetting in code introduces synch error. If it is not supported by hardware- I can't remember (and am too lazy to look up) if the 2231 can do the reset of the timer count on CAPture events- the differencing option is the better choice. Quote Link to post Share on other sites
geralt1114 0 Posted June 14, 2020 Author Share Posted June 14, 2020 Thank you for your help currently working on a new code hope it works Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.