需提前學(xué)習(xí):MSP430F5529庫函數(shù)學(xué)習(xí)——串口;MSP430F5529庫函數(shù)定時(shí)器A——硬件PWM
目錄
引腳手冊(cè)獲取
實(shí)驗(yàn)?zāi)康?/p>
代碼
代碼解析
串口數(shù)據(jù)發(fā)送部分
數(shù)據(jù)捕獲部分
定時(shí)器部分可選參數(shù)
設(shè)置定時(shí)器部分
捕獲部分可選參數(shù)
設(shè)置捕獲引腳部分
中斷處理
TA2IV_TACCR2解析
TA2IV_TAIFG解析
主函數(shù)解析
實(shí)驗(yàn)現(xiàn)象
引腳手冊(cè)獲取
詳情看MSP430F5529庫函數(shù)定時(shí)器A——硬件PWM獲取引腳手冊(cè)部分。
實(shí)驗(yàn)?zāi)康?/h2>
捕獲波形高電平持續(xù)時(shí)間
代碼
MSP430F5529可以進(jìn)行信號(hào)捕獲。先提供代碼
#include "driverlib.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#define CPU_F ((double)1000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
void UART_printf(uint16_t baseAddress, const char *format,...)
{
uint32_t length;
va_list args;
uint32_t i;
char TxBuffer[128] = {0};
va_start(args, format);
length = vsnprintf((char*)TxBuffer, sizeof(TxBuffer), (char*)format, args);
va_end(args);
for(i = 0; i < length; i++)
USCI_A_UART_transmitData(baseAddress, TxBuffer[i]);
}
//9600
void Usart1_Init()
{
//P4.4=UCA1TXD P4.5=UCA1RXD
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN5+GPIO_PIN4);
USCI_A_UART_initParam param1 = {0};
param1.selectClockSource = USCI_A_UART_CLOCKSOURCE_SMCLK;
param1.clockPrescalar = 6;
param1.firstModReg = 13;
param1.secondModReg = 0;
param1.parity = USCI_A_UART_NO_PARITY; //無校驗(yàn)位
param1.msborLsbFirst = USCI_A_UART_LSB_FIRST; //低位先行
param1.numberofStopBits = USCI_A_UART_ONE_STOP_BIT; //1停止位
param1.uartMode = USCI_A_UART_MODE;
param1.overSampling = USCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION;
if (STATUS_FAIL == USCI_A_UART_init(USCI_A1_BASE, ¶m1)){
return;
}
//Enable UART module for operation
USCI_A_UART_enable(USCI_A1_BASE);
//Enable Receive Interrupt
USCI_A_UART_clearInterrupt(USCI_A1_BASE,USCI_A_UART_RECEIVE_INTERRUPT);
USCI_A_UART_enableInterrupt(USCI_A1_BASE,USCI_A_UART_RECEIVE_INTERRUPT);
}
uint32_t Sign_Counts = 0;
void Timer_A2_Capture_Init()
{
Timer_A_initContinuousModeParam htim = {0};
htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //1048576Hz
htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1; //一分頻,1048576Hz
htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE; //使能TAIE中斷
htim.timerClear = TIMER_A_DO_CLEAR; //把定時(shí)器的定時(shí)計(jì)數(shù)器,分頻計(jì)數(shù)器的計(jì)數(shù)值清零
htim.startTimer = true; //初始化后立即啟動(dòng)定時(shí)器
Timer_A_initContinuousMode(TIMER_A2_BASE, &htim); //設(shè)置為連續(xù)計(jì)數(shù)模式
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN5); //復(fù)用P2.5
Timer_A_initCaptureModeParam capture_htim = {0};
capture_htim.captureRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2; //因?yàn)镻2.5使用的是TA2.2,所以這里是REGISTER_2
capture_htim.captureMode = TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE; //選擇雙邊沿觸發(fā)
capture_htim.captureInputSelect = TIMER_A_CAPTURE_INPUTSELECT_CCIxA; //
capture_htim.synchronizeCaptureSource = TIMER_A_CAPTURE_SYNCHRONOUS; //捕獲源與計(jì)時(shí)器時(shí)鐘同步
capture_htim.captureInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE;
capture_htim.captureOutputMode = TIMER_A_OUTPUTMODE_OUTBITVALUE;
Timer_A_initCaptureMode(TIMER_A2_BASE,&capture_htim);
}
int main(void)
{
//關(guān)閉看門狗
WDT_A_hold(WDT_A_BASE);
//打開輸入捕獲
Timer_A2_Capture_Init();
Usart1_Init();
//interrupts enabled
__bis_SR_register(GIE);
while(1)
{
delay_ms(1000);
//UART_printf(USCI_A1_BASE,"高電平持續(xù)時(shí)間:%f ms",1000.*Sign_Counts/1048576); //注意,這里1000后面必須+'.'表示是浮點(diǎn)運(yùn)算?。。》駝t結(jié)果為0?。?!
UART_printf(USCI_A1_BASE,"高電平持續(xù)時(shí)間:%f ms",1000.*Sign_Counts/UCS_getSMCLK());//UCS_getSMCLK是獲取當(dāng)前SMCLK時(shí)鐘頻率,當(dāng)前SMCLK為1048576HZ
}
}
#pragma vector=TIMER2_A1_VECTOR
__interrupt
void TIMER2_A1_ISR (void)
{
static uint16_t Overflow_Times = 0;
static uint16_t Sign_Begin = 0, Sign_End = 0;
switch(TA2IV)
{
case TA2IV_TACCR2:
if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5)) //獲取P2.5引腳電平,如果為高電平,將當(dāng)前寄存器值存入Sign_Begin
{
Sign_Begin = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);
}
else //獲取P2.5引腳電平,如果為低電平,將當(dāng)前寄存器值存入Sign_End
{
Sign_End = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);
if(!Overflow_Times) //計(jì)算高電平時(shí)間,如果高電平和低電平都在一個(gè)計(jì)數(shù)周期之內(nèi),進(jìn)入
Sign_Counts = Sign_End - Sign_Begin; //如果高低電平在同一個(gè)計(jì)數(shù)周期內(nèi),那么直接相減
else //計(jì)算高電平時(shí)間,如果高電平和低電平不在一個(gè)計(jì)數(shù)周期之內(nèi),進(jìn)入
{
//注意,這里強(qiáng)制類型轉(zhuǎn)換,是因?yàn)閡int16_t 的最大值為65535,此處的Sign_Counts值會(huì)明顯大于65535
Sign_Counts = (uint32_t)(65536 * Overflow_Times + Sign_End - Sign_Begin); //如果高低電平不在同一個(gè)計(jì)數(shù)周期,需要先加上一個(gè)周期的計(jì)數(shù)值
Overflow_Times = 0;
}
}
Timer_A_clearCaptureCompareInterrupt(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);
break;
case TA2IV_TAIFG:
if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5)) //獲取P2.5引腳電平。如果定時(shí)器都溢出中斷了,現(xiàn)在還是高電平,那么表明高電平和低電平不在同一個(gè)定時(shí)周期內(nèi)
{
++Overflow_Times;
}
else //獲取P2.5引腳電平。如果定時(shí)器溢出中斷了,現(xiàn)在不是高電平,那么表明高電平和低電平在同一個(gè)定時(shí)周期內(nèi)
Overflow_Times = 0;
Timer_A_clearTimerInterrupt(TIMER_A2_BASE);
break;
default:
break;
}
}
代碼解析
串口數(shù)據(jù)發(fā)送部分
注意,這部分我就提醒一下。我們是需要進(jìn)行浮點(diǎn)數(shù)據(jù)打印的,所以我們看MSP430F5529庫函數(shù)學(xué)習(xí)——串口的時(shí)候,需要按照浮點(diǎn)數(shù)據(jù)打印這一部分配置!
數(shù)據(jù)捕獲部分
定時(shí)器部分可選參數(shù)
(1)clockSource:選擇時(shí)鐘源
TIMER_A_CLOCKSOURCE_EXTERNAL_TXCLK [Default]
TIMER_A_CLOCKSOURCE_ACLK
TIMER_A_CLOCKSOURCE_SMCLK
TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK
(2)clockSourceDivider:選擇時(shí)鐘分頻次數(shù)
TIMER_A_CLOCKSOURCE_DIVIDER_1 [Default]
TIMER_A_CLOCKSOURCE_DIVIDER_2
TIMER_A_CLOCKSOURCE_DIVIDER_3
TIMER_A_CLOCKSOURCE_DIVIDER_4
TIMER_A_CLOCKSOURCE_DIVIDER_5
TIMER_A_CLOCKSOURCE_DIVIDER_6
TIMER_A_CLOCKSOURCE_DIVIDER_7
TIMER_A_CLOCKSOURCE_DIVIDER_8
TIMER_A_CLOCKSOURCE_DIVIDER_10
TIMER_A_CLOCKSOURCE_DIVIDER_12
TIMER_A_CLOCKSOURCE_DIVIDER_14
TIMER_A_CLOCKSOURCE_DIVIDER_16
TIMER_A_CLOCKSOURCE_DIVIDER_20
TIMER_A_CLOCKSOURCE_DIVIDER_24
TIMER_A_CLOCKSOURCE_DIVIDER_28
TIMER_A_CLOCKSOURCE_DIVIDER_32
TIMER_A_CLOCKSOURCE_DIVIDER_40
TIMER_A_CLOCKSOURCE_DIVIDER_64
TIMER_A_CLOCKSOURCE_DIVIDER_48
TIMER_A_CLOCKSOURCE_DIVIDER_56
(3)timerInterruptEnable_TAIE:使能還是失能定時(shí)器中斷
TIMER_A_TAIE_INTERRUPT_ENABLE //使能定時(shí)器中斷
TIMER_A_TAIE_INTERRUPT_DISABLE //失能定時(shí)器中斷
(4)timerClear:選擇是否把定時(shí)器的定時(shí)計(jì)數(shù)器,分頻計(jì)數(shù)器的計(jì)數(shù)值清零
TIMER_A_DO_CLEAR //清除
TIMER_A_SKIP_CLEAR //不清除
(5)startTimer:選擇初始化之后是否立即啟動(dòng)定時(shí)器
true //初始化后立即啟動(dòng)定時(shí)器
false //初始化后不啟動(dòng)定時(shí)器
設(shè)置定時(shí)器部分
(1)MSP430F5529定時(shí)器時(shí)鐘 TACLK 可以選擇?ACLK,SMCLK?或者來自外部的?TAxCLK。SMCLK系統(tǒng)默認(rèn)?1048576Hz,ACLK系統(tǒng)默認(rèn)為32768Hz。這里我們選擇SMCLK作為時(shí)鐘源
(2)不進(jìn)行分頻,因?yàn)槿绻M(jìn)行輸入捕獲,頻率越高,精確度越大。
(3)因?yàn)閿?shù)據(jù)捕獲實(shí)驗(yàn)是采用的連續(xù)計(jì)數(shù)模式,所以只能使用TAIE中斷。詳情請(qǐng)看MSP430F5529庫函數(shù)定時(shí)器A——定時(shí)中斷的Timer_A_initContinuousMode()函數(shù)介紹。
(4)把定時(shí)器的定時(shí)計(jì)數(shù)器,分頻計(jì)數(shù)器的計(jì)數(shù)值清零。也就是計(jì)數(shù)器從0開始計(jì)數(shù)
(5)初始化之后立即啟動(dòng)定時(shí)器,否則需要之后再去使用Timer_A_startCounter()函數(shù)設(shè)置為連續(xù)計(jì)數(shù)模式啟動(dòng)定時(shí)器
(6)我們開啟定時(shí)器2
Timer_A_initContinuousModeParam htim = {0};
htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //1048576Hz
htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1; //一分頻,1048576Hz
htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE; //使能TAIE中斷
htim.timerClear = TIMER_A_DO_CLEAR; //把定時(shí)器的定時(shí)計(jì)數(shù)器,分頻計(jì)數(shù)器的計(jì)數(shù)值清零
htim.startTimer = true; //初始化后立即啟動(dòng)定時(shí)器
Timer_A_initContinuousMode(TIMER_A2_BASE, &htim); //設(shè)置為連續(xù)計(jì)數(shù)模式
捕獲部分可選參數(shù)
captureRegister:選擇所捕獲引腳的CCRx,如果是CCR2就選擇REGISTER_2
TIMER_A_CAPTURECOMPARE_REGISTER_0
TIMER_A_CAPTURECOMPARE_REGISTER_1
TIMER_A_CAPTURECOMPARE_REGISTER_2
TIMER_A_CAPTURECOMPARE_REGISTER_3
TIMER_A_CAPTURECOMPARE_REGISTER_4
TIMER_A_CAPTURECOMPARE_REGISTER_5
TIMER_A_CAPTURECOMPARE_REGISTER_6
captureMode:選擇捕獲模式
TIMER_A_CAPTUREMODE_NO_CAPTURE //不進(jìn)行捕獲
TIMER_A_CAPTUREMODE_RISING_EDGE //上升沿捕獲
TIMER_A_CAPTUREMODE_FALLING_EDGE //下降沿捕獲
TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE //雙邊沿捕獲
captureInputSelect:選擇捕獲的CCIxA還是CCIxB
TIMER_A_CAPTURE_INPUTSELECT_CCIxA //如果是CCI2A,就選擇這個(gè)。好像基本都是選擇這個(gè)
TIMER_A_CAPTURE_INPUTSELECT_CCIxB //如果是CCI2B,就選擇這個(gè)。這個(gè)好像是跟時(shí)鐘有關(guān)的
TIMER_A_CAPTURE_INPUTSELECT_GND
TIMER_A_CAPTURE_INPUTSELECT_Vcc
synchronizeCaptureSource:捕獲源是否與計(jì)時(shí)器同步,一般設(shè)置為同步
TIMER_A_CAPTURE_ASYNCHRONOUS //不同步
TIMER_A_CAPTURE_SYNCHRONOUS //同步
captureInterruptEnable:是啟用或禁用定時(shí)器capturecompare中斷
TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE //不進(jìn)行定時(shí)器中斷
TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE //開啟定時(shí)器中斷
captureOutputMode:指定輸出模式
TIMER_A_OUTPUTMODE_OUTBITVALUE //因?yàn)槭遣东@模式,所以只能選擇這個(gè)
TIMER_A_OUTPUTMODE_SET
TIMER_A_OUTPUTMODE_TOGGLE_RESET
TIMER_A_OUTPUTMODE_SET_RESET
TIMER_A_OUTPUTMODE_TOGGLE
TIMER_A_OUTPUTMODE_RESET
TIMER_A_OUTPUTMODE_TOGGLE_SET
TIMER_A_OUTPUTMODE_RESET_SET
設(shè)置捕獲引腳部分
(1)因?yàn)槲覀兩厦嬖O(shè)置的是定時(shí)器2,所以我們需要查看引腳圖。選擇具有捕獲功能的,又是定時(shí)器2的引腳。最后選擇了P2.5腳。首先我們需要將他復(fù)用為輸入,因?yàn)槭且M(jìn)行波形捕獲。
?(2)我們看引腳手冊(cè)可知,P2.5對(duì)應(yīng)的是定時(shí)器A的定時(shí)器2的CCR2,所以選擇TIMER_A_CAPTURECOMPARE_REGISTER_2
(3)因?yàn)槲覀冃枰东@高電平持續(xù)時(shí)間,所以需要捕獲上升沿和下降沿
(4)因?yàn)槭荂CI2A所以選擇INPUTSELECT_CCIxA,我查了一下手冊(cè),發(fā)現(xiàn)CCIxB好像都是跟時(shí)鐘有關(guān)的東西。
(5)這個(gè)captureOutputMode是用于設(shè)置輸出的。這個(gè)是PWM輸出的時(shí)候才需要用到的,所以此處設(shè)置為TIMER_A_OUTPUTMODE_OUTBITVALUE,定時(shí)器輸出電平由OUT位控制。詳情看MSP430F5529庫函數(shù)定時(shí)器A——硬件PWM比較輸出模式部分。
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN5); //復(fù)用P2.5
Timer_A_initCaptureModeParam capture_htim = {0};
capture_htim.captureRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2; //因?yàn)镻2.5使用的是TA2.2,所以這里是REGISTER_2
capture_htim.captureMode = TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE; //選擇雙邊沿觸發(fā)
capture_htim.captureInputSelect = TIMER_A_CAPTURE_INPUTSELECT_CCIxA; //因?yàn)槭荂CI2A所以選擇INPUTSELECT_CCIxA
capture_htim.synchronizeCaptureSource = TIMER_A_CAPTURE_SYNCHRONOUS; //捕獲源與計(jì)時(shí)器時(shí)鐘同步
capture_htim.captureInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE; //打開定時(shí)器捕獲中斷
capture_htim.captureOutputMode = TIMER_A_OUTPUTMODE_OUTBITVALUE; //定時(shí)器輸出電平由OUT位控制
Timer_A_initCaptureMode(TIMER_A2_BASE,&capture_htim);
中斷處理
因?yàn)槲覀儾捎玫氖嵌〞r(shí)器2的TALE中斷,所以中斷向量選擇TIMER2_A1_VECTOR。
(1)首先我們需要知道,TAVE中斷向量是具有多個(gè)中斷源的。我們此刻是TA2.2,使用的是CCR2的中斷源,所以需要一個(gè)TA2IV_TACCR2中斷判斷(如果上升沿或者下降沿就觸發(fā)中斷)。
(2)因?yàn)槲覀儾东@的波形不可能是同一個(gè)定時(shí)周期里面,所以還需要一個(gè)TAVE中斷,這樣就不會(huì)因?yàn)楦唠娖匠掷m(xù)時(shí)間太長,導(dǎo)致無法計(jì)算。
#pragma vector=TIMER2_A1_VECTOR
__interrupt
void TIMER2_A1_ISR (void)
{
static uint16_t Overflow_Times = 0;
static uint16_t Sign_Begin = 0, Sign_End = 0;
switch(TA2IV)
{
case TA2IV_TACCR2:
if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5)) //獲取P2.5引腳電平,如果為高電平,將當(dāng)前寄存器值存入Sign_Begin
{
Sign_Begin = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);
}
else //獲取P2.5引腳電平,如果為低電平,將當(dāng)前寄存器值存入Sign_End
{
Sign_End = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);
if(!Overflow_Times) //計(jì)算高電平時(shí)間,如果高電平和低電平都在一個(gè)計(jì)數(shù)周期之內(nèi),進(jìn)入
Sign_Counts = Sign_End - Sign_Begin; //如果高低電平在同一個(gè)計(jì)數(shù)周期內(nèi),那么直接相減
else //計(jì)算高電平時(shí)間,如果高電平和低電平不在一個(gè)計(jì)數(shù)周期之內(nèi),進(jìn)入
{
//注意,這里強(qiáng)制類型轉(zhuǎn)換,是因?yàn)閡int16_t 的最大值為65535,此處的Sign_Counts值會(huì)明顯大于65535
Sign_Counts = (uint32_t)(65536 * Overflow_Times + Sign_End - Sign_Begin); //如果高低電平不在同一個(gè)計(jì)數(shù)周期,需要先加上一個(gè)周期的計(jì)數(shù)值
Overflow_Times = 0;
}
}
Timer_A_clearCaptureCompareInterrupt(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);
break;
case TA2IV_TAIFG:
if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5)) //獲取P2.5引腳電平。如果定時(shí)器都溢出中斷了,現(xiàn)在還是高電平,那么表明高電平和低電平不在同一個(gè)定時(shí)周期內(nèi)
{
++Overflow_Times;
}
else //獲取P2.5引腳電平。如果定時(shí)器溢出中斷了,現(xiàn)在不是高電平,那么表明高電平和低電平在同一個(gè)定時(shí)周期內(nèi)
Overflow_Times = 0;
Timer_A_clearTimerInterrupt(TIMER_A2_BASE);
break;
default:
break;
}
}
如下為TAVE中斷向量里面所含有的中斷方式。?
#pragma vector=TIMER0_A1_VECTOR
__interrupt
void TIMER0_A1_ISR (void)
{
switch(TA0IV)
{
case TA0IV_NONE:
break;
case TA0IV_TACCR1:
break;
case TA0IV_TACCR2:
break;
case TA0IV_TACCR3:
break;
case TA0IV_TACCR4:
break;
case TA0IV_5:
break;
case TA0IV_6:
break;
case TA0IV_TAIFG:
GPIO_toggleOutputOnPin(GPIO_PORT_P4, GPIO_PIN1);
break;
default:
break;
}
}
TA2IV_TACCR2解析
(1)首先是TA2IV_TACCR2中斷,如果P2.5腳捕獲到上升沿或者下降沿將會(huì)進(jìn)入這里。我們先判斷是上升沿還是下降沿,如果是上升沿,那么此時(shí)P2.5將會(huì)是高電平。我們將定時(shí)器的值存入Sign_Begin 中,程序中認(rèn)為,高電平為信號(hào)起始。
(2)如果現(xiàn)在P2.5為低電平,進(jìn)入else語句,表示捕獲已經(jīng)結(jié)束了。將當(dāng)前捕獲的數(shù)據(jù)儲(chǔ)存到,開始進(jìn)行判斷高電平和低電平是否在同一個(gè)定時(shí)周期內(nèi)。
(3)如果Overflow_Times為0,那么表示高電平和低電平在同一定時(shí)周期,只需要把記錄到的低電平時(shí)間減去高電平時(shí)間即可
(4)如果Overflow_Times不為0,那么高低電平不在同一定時(shí)周期。需要先讓記錄的低電平時(shí)間加上Overflow_Times(定時(shí)了幾個(gè)周期)*65536 (定時(shí)器A為16位的定時(shí)器,16bit最大為65535,計(jì)數(shù)65536次,因?yàn)槭菑?開始計(jì)數(shù)),然后再減去記錄的高電平時(shí)間即可。
case TA2IV_TACCR2:
if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5)) //獲取P2.5引腳電平,如果為高電平,將當(dāng)前寄存器值存入Sign_Begin
{
Sign_Begin = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);
}
else //獲取P2.5引腳電平,如果為低電平,將當(dāng)前寄存器值存入Sign_End
{
Sign_End = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);
if(!Overflow_Times) //計(jì)算高電平時(shí)間,如果高電平和低電平都在一個(gè)計(jì)數(shù)周期之內(nèi),進(jìn)入
Sign_Counts = Sign_End - Sign_Begin; //如果高低電平在同一個(gè)計(jì)數(shù)周期內(nèi),那么直接相減
else //計(jì)算高電平時(shí)間,如果高電平和低電平不在一個(gè)計(jì)數(shù)周期之內(nèi),進(jìn)入
{
//注意,這里強(qiáng)制類型轉(zhuǎn)換,是因?yàn)閡int16_t 的最大值為65535,此處的Sign_Counts值會(huì)明顯大于65535
Sign_Counts = (uint32_t)(65536 * Overflow_Times + Sign_End - Sign_Begin); //如果高低電平不在同一個(gè)計(jì)數(shù)周期,需要先加上一個(gè)周期的計(jì)數(shù)值
Overflow_Times = 0;
}
}
Timer_A_clearCaptureCompareInterrupt(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);
break;
TA2IV_TAIFG解析
(1)因?yàn)椴东@的波形高電平持續(xù)時(shí)間不一定會(huì)完整的被一共定時(shí)周期捕獲,所以需要建立一個(gè)?Overflow_Times 來統(tǒng)計(jì)高電平到底跨越了幾個(gè)定時(shí)周期。
(2)我們先判斷P2.5引腳電平,如果P2.5為高電平,表示高電平還在持續(xù),這個(gè)跨度超過了一共定時(shí)周期。
(3)如果現(xiàn)在P2.5為低電平,就說明高電平和低電平在同一個(gè)定時(shí)周期內(nèi)。將Overflow_Times置0。
case TA2IV_TAIFG:
if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5)) //獲取P2.5引腳電平。如果定時(shí)器都溢出中斷了,現(xiàn)在還是高電平,那么表明高電平和低電平不在同一個(gè)定時(shí)周期內(nèi)
{
++Overflow_Times;
}
else //獲取P2.5引腳電平。如果定時(shí)器溢出中斷了,現(xiàn)在不是高電平,那么表明高電平和低電平在同一個(gè)定時(shí)周期內(nèi)
Overflow_Times = 0;
Timer_A_clearTimerInterrupt(TIMER_A2_BASE);
break;
主函數(shù)解析
(1)我們需要關(guān)閉看門狗,否則你不即使喂狗,會(huì)導(dǎo)致程序一致復(fù)位——>執(zhí)行一點(diǎn)點(diǎn)程序——>執(zhí)行一點(diǎn)點(diǎn)程序。最后你調(diào)試的時(shí)候,會(huì)有一種程序卡死的感覺。
(2)打開捕獲和串口,使能總中斷。
(3)我們每過1S給電腦發(fā)送一次高電平持續(xù)時(shí)間。我們需要知道HZ,1S所變化的次數(shù),如果時(shí)鐘為1048576HZ,那么定時(shí)器+1,就是1/1048576秒。所以這里需要/1048576。因?yàn)檫@里是以ms為單位,所以需要乘以1000。如果我們不知道當(dāng)前時(shí)鐘的頻率,可以使用UCS_getSMCLK()函數(shù),獲取當(dāng)前SMCLK的頻率。為什么是獲取SMCLK的頻率,是因?yàn)槲覀冊(cè)O(shè)置的定時(shí)器時(shí)鐘源是SMCLK。
注意:1000后面一定一定要加一個(gè)小數(shù)點(diǎn)'.',因?yàn)?1048576之后,如果一個(gè)波形周期內(nèi),高電平持續(xù)時(shí)間<1S,那么算出來的值一定會(huì)小于1。如果是整型運(yùn)算,那么結(jié)果一定會(huì)只是0?。。〖由闲?shù)點(diǎn)'.'后,變成浮點(diǎn)運(yùn)算。
//關(guān)閉看門狗
WDT_A_hold(WDT_A_BASE);
//打開輸入捕獲
Timer_A2_Capture_Init();
Usart1_Init();
//interrupts enabled
__bis_SR_register(GIE);
while(1)
{
delay_ms(1000);
UART_printf(USCI_A1_BASE,"高電平持續(xù)時(shí)間:%f ms",1000.*Sign_Counts/1048576); //注意,這里1000后面必須+'.'表示是浮點(diǎn)運(yùn)算!?。》駝t結(jié)果為0?。?!
}
實(shí)驗(yàn)現(xiàn)象
我用自己的手持式示波器產(chǎn)生一共100HZ的,占空比為50%的方波。給單片機(jī)測量,結(jié)果如下
?文章來源:http://www.zghlxwxcb.cn/news/detail-545418.html
?如果沒有信號(hào)發(fā)生器,可以自己利用定時(shí)器產(chǎn)生一共PWM。不會(huì)的,可以看這位大佬的MSP430F5529 DriverLib 庫函數(shù)學(xué)習(xí)筆記(五)定時(shí)器A,只需要看輸入捕獲模式測量脈寬長度部分即可??次覍懙腗SP430F5529庫函數(shù)定時(shí)器A——硬件PWM,也可以。???????文章來源地址http://www.zghlxwxcb.cn/news/detail-545418.html
到了這里,關(guān)于MSP430F5529庫函數(shù)定時(shí)器A——捕獲實(shí)驗(yàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!