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.

[参考译文] MSP430G2553:有关计时器和中断标志的问题

Guru**** 2124380 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1243983/msp430g2553-question-about-timers-and-interrupt-flags

器件型号:MSP430G2553

大家好、我想先讲一讲 Timer0中断的工作原理。

我没有张贴我的代码,因为在许多尝试后,它不是很整洁,但我可以张贴,如果需要. 我将尝试进行的操作是对电机的 RPM 进行计数、因为这样、我将在电机每次旋转一周时激活一个外部中断。 此部件工作正常。

我得到了计时器旋转所花费的时间、其中计时器检查 TA0R、同时检查了每次计时器溢出时计数器将增加的计数器。 这样、对于 H 桥上的 PWM、我可以在高 CPU 时钟下运行、但仍然测量 RPM 是否较低。 随后、根据轮子的位置(根据达到该位置所需的时间计算得出、我将切换输出)。  

但我遇到了计时器中断问题。 当我进行调试时、我可以看到 TAIFG 永远不会被设置、我可以在 TA0IV 上看到它已溢出、我可以用它正确计算 RPM、但我的问题是在电机达到所需位置时切换输出。  

为此、我将尝试在发生 X 次溢出后在 TA0CCTL1和2上启用 CCIE。 例如、我的电机用了30次计时器溢出来达到1 rpm、我希望输出在180度后稍微开启。 因此、TA0CCR 中断只在 Noverflow=15时发生、从那时起使用定时器开始计数。  

那么、如何才能使 CCR 中断只在一定数量的溢出后发生、而不是始终发生。 在 TA0IV 上、如果 TA0CCTL CCIE 被置位或没有被置位、则定时器每次达到 CCR 值时、就会独立激活。

我觉得我的解释不是很清楚,所以如果有你不理解的东西,请问,我会尝试更详细的阐述。  

作为参考、这是我的代码。 在计时器中断中、由于我一直在尝试执行的操作、因此添加了许多注释。  

#包含
#include "GPIO.h"

/*****
五颗星 定义
* /

#define INTERRUPT_PIN 0x13 //(P1.3)
#define interrupt_bit (1<<3)
#define SPARK_PIN 0x14 //(P1.4)

*/
五颗星 变量定义***********
* /

//转速计的变量
//计时器 A0在2MHz 的频率下工作
无符号长整型 TimeRevolution =0;// Max = 4.294967秒(2^32纳秒)
const unsigned long int TimeOverflow = 32768000;//时间以纳秒为单位(32.768毫秒)
无符号长整型 TimerOverflowCounter = 0;
unsigned long int LastTimerOverflowCounter = 0;
unsigned long int N1 = 0;// PHI 1的溢出计数器
无符号长整型 int N2 = 0;// PHI 2的溢出计数器
unsigned long int TimePhi1 = 0;//曲轴到达 phi1的时间
无符号超长整型 int TimePhi2 = 0;
const unsigned long int TimePerClock = 500;//以纳秒为单位的时间(原始值500)
无符号超长整型 int rpm = 0;

//火花塞的变量
unsigned int phi1 = 230;
unsigned int deltaPHI = 30;
unsigned int phi2 = 260;

*/
五颗星 功能定义***********
* /

空转速计_Init (空){

gpioMode (interrupt_PIN、input_pulldown);//如果需要上拉或下拉
P1IE |= INTERRUPT_BIT;//在引脚 P1.3上启用外部中断
P1IES |= INTERRUPT_BIT;


//转速计使用计时器 A0

//设置计时器
TA0CTL |= TACLR;//复位 TA0

// TA0CTL |= MC_1;//设置 TA0不向上计数模式
TA0CTL |= MC_2;//设置 TA0非连续模式
TA0CTL |= tassel_2 | ID_3;//选择 SMCLK 和分频器/8 ----- >(结果为2MHz)

// TA0CCR0 = 65535;//将周期设置为最大值(0.004096秒)

//TA0CCTL0 = CCIE;//启用 CCR0的计时器溢出中断
TA0CTL |= TAIE;
TA0CTL &&~TAIFG;//清除挂起的中断溢出

//_BIS_SR_(GIE);//常规中断启用
__enable_interrupt ();//常规中断启用
//TA0CCTL0 &=~CCIFG;//清除 CCR0的挂起中断标志
P1IFG &&~interrupt_bit;//清除挂起的中断标志

空 SparkPlugInit (空){
gpioMode (SPARK_PIN、输出);
gpioWrite (SPARK_PIN、LOW);

TA0CCTL1 &=~CCIFG;//清除挂起标志 TA0CCR1/2
TA0CCTL1 &=~CCIFG;

void SparkTime (void){// TimePerRevolution 的单位为纳秒
unsigned long int t1 = 0;//在 TA0CCR1中设置的时间
unsigned long int t2 = 0;//在 TA0CCR2中设置的时间

TimePhi1 =(TimeRevolution /360)* phi1;//曲轴达到 phi1的时间
TimePhi2 =(TimeRevolution /360)* phi2;

N1 = TimePhi1/TimeOverflow;//到达 TimePhi1之前计时器将溢出的次数
n2 = TimePhi2/ TimeOverflow;//到达 TimePhi2之前计时器将溢出的次数

t1 = TimePhi1 - N1*TimeOverflow;//由于 N1是 int,因此我们在这里计算最终溢出中断后应发生的时间
T2 = TimePhi2 - N2*TimeOverflow;

TA0CCR1 = T1/TimePerClock;//每个时钟脉冲为500纳秒。 TA0CCR1计数时钟周期
TA0CCR2 = T2/TimePerClock;


空 CheckTimerOverflow (空){

if (TimerOverflowCounter == N1){

TA0CCTL1 &=~CCIFG;
TA0CCTL1 |= CCIE;//一旦发生正确的溢出量,我们就可以启用中断来计数剩余时间

if (TimerOverflowCounter == N2){

TA0CCTL2 &=~CCIFG;
TA0CCTL2 |= CCIE;//一旦发生正确的溢出量,我们就可以启用中断来计数剩余时间

#pragma vector = Port1_vector
__interrupt void ISR_External (void){
静态 int CONT=0;

P1IFG &&~interrupt_bit;//清除中断标志


/
*旋转1圈的计算时间。 每次计时器溢出(每0.00005秒) TimerOverflowCounter 都会递增。
*我们使用此变量计算旋转一周的时间
*/

TimeRevolution = TimeOverflow*TimerOverflowCounter + TA0R*TimePerClock;//以纳秒为单位的时间
TA0CTL |= TACLR;

LastTimerOverflowCounter = TimerOverflowCounter;//我们保存火花触发器点火时间的最后一个溢出计数器
TimerOverflowCounter = 0;

rpm=(60000000000)/TimeRevolution;//顶部为60 * 1e9、从纳秒变为秒、每分钟转数

cont++;

if (cont=1){
RPM++;
CONT = 0;

SparkTime();//计算点火时间

#pragma vector = TIMER0_A0_Vector
__interrupt void ISR_TA0_CCR0 (void){
//TA0CCTL0 &=~CCIFG;//清除中断标志 CCR0
TA0CTL &=~TAIFG;//清除中断标志

TimerOverflowCounter++;

#pragma vector = TIMER0_A1_Vector
__interrupt void ISR_TA0_CCRx (void){
//我们必须检查中断是否由于 TA0CCR1或 TA0CCR2 (phi1或 phi2)而发生
//unsigned int timer = TA0IV;


if (TA0CTL & TAIFG){
TA0CTL &=~TAIFG;

TimerOverflowCounter++;

/*
开关(_ even_in_range (TA0IV、TA0IV_TAIFG)){
情形2:
if (TA0CCTL1 & 0x10){
TA0CCTL1 &=~CCIE;
P1OUT |= 0x10;

中断;
情形4:
如果(TA0CCTL2 & 0x10){
TA0CCTL2 &=~CCIE;
P1OUT &= 0x10;

中断;
情形10:
TimerOverflowCounter++;
中断;
}*/

/*
if (TA0CCTL1 => 0x0011){//我检查中断是否由于 CCR1 (CCIE 和 CCIFG)而发生

TA0CCTL1 &=~CCIFG;//删除了中断标志
TA0CCTL1 &=~CCIE;//我们必须关闭中断(只有在发生重叠的正确层叠时才会发生)
//打开火花塞(1.4)
P1OUT |= 0x10;

if (TA0CCTL2 => 0x0011){//我检查中断是否由于 CCR2而发生

TA0CCTL2 &=~CCIFG;//删除中断标志
TA0CCTL2 &=~CCIE;//关闭选项
//关闭火花塞
P1OUT &=~0x10;

if (定时器& 0x08){
TimerOverflowCounter++;
}*/

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我对电机控制部分不熟悉、只对您的问题和代码做一些评论。

    // TA0CTL |= MC_1;//设置 TA0不向上计数模式
    TA0CTL |= MC_2;//设置 TA0非连续模式
    TA0CTL |= tassel_2 | ID_3;//选择 SMCLK 和分频器/8 ----- >(结果为2MHz)

    // TA0CCR0 = 65535;//将周期设置为最大值(0.004096秒)

    [/报价]

    由于您将 TA0时钟频率配置为2MHz、计时器的最大周期应为2^16/2M = 0.032768s、而不是 注释中的0.004096秒。  

    [quote userid="568359" url="~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1243983/msp430g2553-question-about-timers-and-interrupt-flags 这样我如何才能使 CCR 中断只发生在一定数量的溢出后、而不是始终发生。 在 TA0IV 上、如果 TA0CCTL CCIE 已设置或未设置、则计时器每次达到 CCR 值时都会独立激活。

      根据 UG、当 TACCR0.CCIE 为零时、TACCR0.CCIFG 不应被置位。 您是否 说  在 TACCR0.CCIE 为零时您将使 TACCR0.CCIFG 置1?

    此致、

    现金豪

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您的代码中有很多错误。 可能比我想找的要多。 从开始:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void ISR_TA0_CCR0(void){
    //TA0CCTL0 &= ~CCIFG; // Clear interrupt flag CCR0
    TA0CTL &= ~TAIFG; // Clear interrupt flag
    TimerOverflowCounter++;
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    在最好的情况下,清除 TAIFG 是毫无意义的,而在最坏的情况下,它是一场比赛。

    在向上计数模式下、当计时器计数到 TACCR0时、将调用该 ISR。 短时间之后、当计数器返回到零时、TAIFG 中断将触发。 计时器时钟为 MCLK/8 (我认为)就会有竞争。 在硬件设置 TAIFG 之前或之后、是否会为计时器中断提供服务并执行清除 TAIFG 的代码? 但这仍然是一种糟糕的做法。 更改计时器时钟、使其运行速度变慢、然后这一点的代码突然中断。

    如果您不想处理 TAIFG 中断、不要设置 TAIE。 或设置 TAIE 而不启用 CCR0中断。 任您选择。