Write a pulse frequency measurement program
First
determine
the frequency measurement method--pulse filling method
Measured
signal
____
|
|
___________| |_____
Filled
pulses
||
...
Since the MSP430G2553 device cannot be used during simulation, it is difficult to determine the capture input pin. You can download the information of MSP430F2132 online. This time, the information of msp430f2132 has been attached to the compressed package. You should learn to download it yourself when you need the information in the future.
After consulting the information, it is determined that P1.3 can be used as CCI2A signal.
3. Program design ideas
According to the principle of frequency measurement, two captures are required to measure the frequency of an input signal. Therefore, two variables should be defined to save the results of two captures. The variable is an unsigned integer variable (matching the word length of the capture register). The
input signal and the CPU work are asynchronous, so when designing the program, it is unknown when there is a capture input. There are two ways for the program to handle when the capture occurs
One is the query method. After the capture event occurs, the timer hardware will set the capture interrupt to indicate CCIF is 1. The program can continuously query this flag in the main loop to determine whether a capture event has occurred. The
second is the timer interrupt method. When a capture event occurs, a timer interrupt must be generated, and the capture register can be read in the interrupt.
The query method is not a good programming method because the query will occupy the CPU, so that the CPU can no longer do other tasks. The interrupt method is somewhat difficult for beginners. That is, how the interrupt program communicates with the main program (exchanges information). It is more difficult to understand interrupts and design interrupt service programs. The program gives the interrupt method and the query method for beginners to compare.
Define 2 variables
unsigned int capture1, capture2;
unsigned period;
the value of the first capture is placed in capture1, and the value of the second capture is placed in capture2. The subtraction of the two captured values is the period of the measured signal.
Start designing the source code of the program step by step
1. System clock module initialization
The main clock MCLK=8Mhz, the subsystem clock SMCLK=1Mhz, use DCO to generate the CPU clock.
Clock initialization program
void BCSplus_init(void)
{
BCSCTL2 = SELM_0 + DIVM_0 + DIVS_3; //SELM_0 selects DCO, DIVM_0, MCLK is not divided, DIVS_3, SMCLK is divided by 8
if (CALBC1_8MHZ != 0xFF) {
DCOCTL = 0x00;
BCSCTL1 = CALBC1_8MHZ; /* Set DCO to 8MHz */
DCOCTL = CALDCO_8MHZ;
}
BCSCTL1 |= XT2OFF + DIVA_0; //Turn off XT2, ACLK is not divided
BCSCTL3 = XT2S_0 + LFXT1S_2 + XCAP_1; //XT2S_0: XT2 0.4~1Mhz, LFXT1S_2: VCLOCK is used as ACLK, XCAP_1: 6pf capacitor
}
Initialization procedure of P1 port
void gpio_init(void)
{
P1SEL |= BIT3;
P1SEL2 |= BIT3; //P1.3 is used as CCI2A signal, capture input of timer 0
}
Timer initialization procedure
void timer0_init(void)
{
TA0CTL |= TASSEL_2+ID_0+MC_2; //Select SMCLK as timer clock, no frequency division, continuous counting mode.
TA0CCR2 |= CM_1+CCIS_0+SCS+CAP+CCIE; //Rising edge capture, CCI2A is used as capture input, synchronous mode, capture mode, capture interrupt is allowed.
}
Interrupt service program
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A1_ISR_HOOK(void)
{
if(TAIV==0x04)//CCR2 capture occurred
{
capture1=TA0CCR2; //Read TA0CCR2
if(capture1>capture2)//Data processing, if capture1>capture2, then directly subtract
{
period=capture1-capture2;
}
else //Otherwise
{
period=65536-(capture2-capture1);
}
capture2=capture1; //capture2 is the previous capture value
}
}
During simulation, it was found that the LCD could not display normally. After single-step debugging, it was found that when the program used P1.3 as the capture input pin, P1.7 also became the capture pin. P1.7 is the data line of the original LCD. At this time, the LCD could not work properly. In the class on Friday, when the AD conversion and PWM output were working at the same time, the LCD could not display normally. The reason was the same. This was a bug in the proteus simulation software, so the LCD driver had to be selected as P3out port.
The program needs further improvement
1. Each capture1-capture2 is more troublesome, and the judgment is more verbose. It is also difficult to judge and handle when the timer overflows.
Improvement: After reading the capture value in the interrupt service program, immediately clear the timer, so that there is no need to do subtraction. However, there is a period of time from the start of the interrupt response to the timer clearing. This time can be compensated by software.
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A1_ISR_HOOK(void)
{
if(TAIV==0x04)//CCR2 capture occurs
{
period=TA0CCR2;//Read TA0CCR2
TA0CTL |=TA0CLR;
if(TA0CCTL2&COV)
period +=65536;
}
}
2. Improve measurement accuracy
Perform single-step debugging in proteus, set a breakpoint in the timer interrupt service program, observe the value of TAR when entering the interrupt, and when the program clears TA0 and goes through several timing counting cycles, add this cycle to period to compensate.
Increasing the kernel running speed can improve accuracy.
The example program has been compensated.
When the input signal frequency is high, the error is large. Why?
|