各位专家、您好!
我想使用 MSP430FR5969上的外部计时器捕获频率。 我该怎么做? 欢迎提出任何建议。
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
各位专家、您好!
我想使用 MSP430FR5969上的外部计时器捕获频率。 我该怎么做? 欢迎提出任何建议。
您好 Kostas、
您的理解是正确的、我需要捕获外部频率我已将时钟源设置为 SMCLK 至8MHz 以下是我的完整代码、如果我混淆了任何内容、请更正
#include
#define NUMBER_TIMER_CAPTURES 40.
volatile unsigned int timerAcaptureValues[number_timer_capturs];
unsigned int timerAcapturePointer = 0;
int main (空)
{
WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器
P1OUT &=~0x01;
P1DIR |= 0x01;
P1DIR |= BIT2; // P1.2
P1SEL0 |= BIT2;
P2DIR |= BIT0;
P2SEL0 |= BIT0; //输出 ACLK
P2SEL1 |= BIT0;
P3DIR |= BIT4;
P3SEL0 |= BIT4; //输出 SMCLK
P3SEL1 |= BIT4;
PJSEL0 |= BIT4 | BIT5 | BIT6 | BIT4; //用于 XT1和 XT2
PM5CTL0 &=~LOCKLPM5;
//时钟系统设置
CSCTL0_H = CSKEY >> 8; //解锁 CS 寄存器
CSCTL1 = DCOFSEL_6; //将 DCO 设置为8MHz
CSCTL2 = SELA_LFXTCLK | SELS__HFXTCLK | SELM_DCOCLK;
/CSCTL2 = SELA_VLOCLK | SELS_DCOCLK | SELM_DCOCLK;
CSCTL3 = DIVA__1 | DIVM_1 | DIVM__1; //将所有分频器设置为1
CSCTL4 |= LFXTDRIVE_3 | HFXTDRIVE_3;
CSCTL4 &=~(LFXTOFF | HFXTOFF);
操作
{
CSCTL5 &=~(LFXTOFFG | HFXTOFFG); //清除 XT1和 XT2故障标志
SFRIFG1 &=~OFIFG;
} while (SFRIFG1&OFIFG); //测试振荡器故障标志
CSCTL0_H = 0;
__DELAY_CYCLES (1000); //时钟初始化延迟
TA0CCTL2 = CM_1 | CCIS_1 | SCS | CAP | CCIE;
TA0CTL = tassel_SMCLK | MC__Continuous;
_bis_SR_register (LPM0_bits | GIE);
__no_operation();
}
// Timer0_A3 CC1-4,TA 中断处理程序
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector = TIMER0_A1_vector
_interrupt void Timer0_A1_ISR (void)
#Elif defined (_GNU_)
void __attribute__((中断(TIMER0_A1_vector)) Timer0_A1_ISR (void)
其他
错误编译器不受支持!
#endif
{
switch (__evo_in_range (TA0IV、TA0IV_TAIFG)){
案例 TA0IV_TA0CCR1:
中断;
案例 TA0IV_TA0CCR2:
timerAcaptureValues[timerAcapturePointer++]= TA0CCR2;
if (timerAcapturePointer >= 40){
while (1){
P1OUT ^= 0x01; //切换 P1.0 (LED)
_DELAY_CYCLES (100000);
}
}
中断;
案例 TA0IV_TA0IFG:
中断;
默认值:
中断;
}
}
大家好、Kostas 和所有专家、
我需要问一个简单的问题、我已将 SMCLK 上的器件配置为8MHz、我需要捕获从示波器测得的外部频率、大约为390Khz、我的代码是否能够测量该频率? 下面是我的代码、请给出任何建议、因为我无法继续。 我将感谢这一行动。 这是我的代码。
#include <MSP430FR5969.h>
#define NUMBER_TIMER_CAPTURES 40.
volatile unsigned int timerAcaptureValues[number_timer_capturs];
unsigned int timerAcapturePointer = 0;
int main (空)
{
WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器
P1OUT &=~0x01;
P1DIR |= 0x01;
P1DIR |= BIT2; // P1.2
P1SEL0 |= BIT2;
P2DIR |= BIT0;
P2SEL0 |= BIT0; //输出 ACLK
P2SEL1 |= BIT0;
P3DIR |= BIT4;
P3SEL0 |= BIT4; //输出 SMCLK
P3SEL1 |= BIT4;
PJSEL0 |= BIT4 | BIT5 | BIT6 | BIT4; //用于 XT1和 XT2
PM5CTL0 &=~LOCKLPM5;
//时钟系统设置
CSCTL0_H = CSKEY >> 8; //解锁 CS 寄存器
CSCTL1 = DCOFSEL_6; //将 DCO 设置为8MHz
CSCTL2 = SELA_LFXTCLK | SELS__HFXTCLK | SELM_DCOCLK;
/CSCTL2 = SELA_VLOCLK | SELS_DCOCLK | SELM_DCOCLK;
CSCTL3 = DIVA__1 | DIVM_1 | DIVM__1; //将所有分频器设置为1
CSCTL4 |= LFXTDRIVE_3 | HFXTDRIVE_3;
CSCTL4 &=~(LFXTOFF | HFXTOFF);
操作
{
CSCTL5 &=~(LFXTOFFG | HFXTOFFG); //清除 XT1和 XT2故障标志
SFRIFG1 &=~OFIFG;
} while (SFRIFG1&OFIFG); //测试振荡器故障标志
CSCTL0_H = 0;
__DELAY_CYCLES (1000); //时钟初始化延迟
TA0CCTL2 = CM_1 | CCIS_1 | SCS | CAP | CCIE;
TA0CTL = tassel_SMCLK | MC__Continuous;
_bis_SR_register (LPM0_bits | GIE);
__no_operation();
}
// Timer0_A3 CC1-4,TA 中断处理程序
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector = TIMER0_A1_vector
_interrupt void Timer0_A1_ISR (void)
#Elif defined (_GNU_)
void __attribute__((中断(TIMER0_A1_vector)) Timer0_A1_ISR (void)
其他
错误编译器不受支持!
#endif
{
switch (__evo_in_range (TA0IV、TA0IV_TAIFG)){
案例 TA0IV_TA0CCR1:
中断;
案例 TA0IV_TA0CCR2:
timerAcaptureValues[timerAcapturePointer++]= TA0CCR2;
if (timerAcapturePointer >= 40){
while (1){
P1OUT ^= 0x01; //切换 P1.0 (LED)
_DELAY_CYCLES (100000);
}
}
中断;
案例 TA0IV_TA0IFG:
中断;
默认值:
中断;
}
}
如果我错了、请纠正我的理解。
尝试在8MHz 频率下直接捕获390kHz 信号是不可行的、因为这只能为您提供20个 CPU 时钟来处理每次捕获。
推荐的快速信号方法是通过将信号连接到计时器的时钟输入来进行频率计数。
也许您已经知道这一点、因为此计划中已经存在用于执行此操作的大多数基础架构。 但您尚未为 TACLK 设置 TA0、因此您需要:
>P1DIR |= BIT2; // P1.2
>P1SEL0 |= BIT2;
应为:
根据 SLAS704G 表6-49、> P1DIR &=~BIT2;// P1.2作为 TA0CLK
> P1SEL1 |= BIT2;
和
>TA0CTL = tassel_SMCLK | MC__Continuous;
应为:
> TA0CTL = tassel_TACLK | MC__Continuous;//来自 P1.2的时钟(TA0CLK)
对于考古学家:这里发生的是 TA0从外部信号计时、捕捉(CCIS=1)在 ACLK 上触发、每隔~32usec。 捕获计数可用于在相当短的固定周期内测量输入频率。 该程序具有大约(8MHz 时为32us)=256个 CPU 时钟来处理每个捕捉。
----------
您是否正在使用 Launchpad? 在交付时、高频晶振(Y1)未被组装。 您的程序是否可能一直等待(永远) HFXT 启动?
Manish、您好!
我同意 Bruce 在上面所说的话。
但是、这是我发送给您的 Link1中实现的、已经两次了。 您应该已经了解过这一点。 此处介绍了该实现。
以下是我在 P1.3引脚上使用250kHz 外部信号进行测试的示例代码。
您也可以使用 P1.2输入、如 Bruce 所述。
========================================================================
// MSP430FR5969
// P1.3上的外部频率捕捉
#include
#define NUMBER_TIMER_CAPTURES 20.
volatile unsigned int timerAcaptureValues[number_timer_capturs];
unsigned int timerAcapturePointer = 0;
unsigned int result = 0;
int main (空)
{
WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器
//配置 GPIO
P1DIR &=~BIT3; //使用计时器 A1和 CCR 2寄存器
P1SEL1 &=~BIT3; //将 P1.3设置为输入方向
P1SEL0 |= BIT3; //(TA1.CCI2A)
//使用计时器 A1和 CCR 2寄存器
//可选的到引脚的 SMCLK 输出
P3DIR |= BIT4; // P3.4设置为方向输出(DS 表6-57)
P3SEL1 |= BIT4; //为 SMCLK 选择输出
//禁用 GPIO 上电默认高阻抗模式以激活
//先前配置的端口设置
PM5CTL0 &=~LOCKLPM5;
//时钟系统设置:设置 DCO 频率。 为 ACLK、SMCLK、MCLK 设置分频器和源
CSCTL0_H = CSKEY >> 8; //解锁 CS 寄存器
CSCTL1 = DCOFSEL_6; //将 DCO 频率设置为选项6:->8MHz
CSCTL2 = SELA_VLOCLK | SELS__DCOCLK | SELM_DCOCLK; //设置 SMCLK 的源= MCLK = DCO、ACLK = VLOCLK
CSCTL3 = DIVA__1 | DIVM_1 | DIVM__1; //将所有分频器设置为1
CSCTL0_H = 0; //锁定 CS 模块(使用字节模式到高字节)
_DELAY_CYCLLES (1000); //允许时钟系统稳定
// Timer0_A3设置
TA1CTL = tassel_SMCLK | MC__Continous; //使用 SMCLK 作为时钟源、
//在连续模式中启动计时器
TA1CCTL2 = CM_1 | CCIS_0 | SCS | CAP | CCIE;//(计时器 A1、CC 块2)
// CM_1:捕获模式上升沿、
// CCIS_0:使用 CC 输入 CCI2A=P1.3、请参阅 DS
// SCS:同步捕捉、
// cap:模式1->Capture,0->Compare,启用捕获模式,
// CCIE:启用捕捉中断
_bis_SR_register (LPM0_bits | GIE); //启用 LPM 和通用中断
__no_operation();
}
// Timer1_A3 CC1-4,TA 中断处理程序
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector = Timer1_A1_vector
_interrupt void Timer1_A1_ISR (void)
#Elif defined (_GNU_)
void __attribute__((中断(Timer1_A1_vector)) Timer1_A1_ISR (void)
其他
错误编译器不受支持!
#endif
{
开关(__evo_in_range (TA1IV、TA1IV_TAIFG))
{
案例 TA1IV_TA1CCR1:
中断;
案例 TA1IV_TA1CCR2:
timerAcaptureValues[timerAcapturePointer++]= TA1CCR2; //将值存储在数组中
if (timerAcapturePointer == 20)
{
timerAcapturePointer = 0;
// 计算两个连续值的示例
结果=((timerAcaptureValues[11])-(timerAcaptureValues[10]));
__no_operation(); //在此处设置断点
}
中断;
案例 TA1IV_TA1IFG:
中断;
默认值:
中断;
}
}
我希望这有助于解决您的问题。
此致
Kostas
应有的尊重:不同。 Link1示例(上面)使用 tassel=SMCLK 和 CCIS=CCI2A (信号引脚)、这是我提到的"直接"方法、我认为在390kHz 时不可行(在250kHz 时、我有点惊讶它成功)。
我的建议是反转、tassel=TACLK、CCIS=CCI2B (ACLK)。 这会使用输入信号为计时器计时、并以固定(ACLK)间隔(更悠闲的节奏)收集计数。 算术略有不同、但并不复杂。