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.
我正在尝试在 MSP430FR2676上设置多个计时器。 我知道它有两个定时器:A 和 B。我已经能够成功运行示例代码(见下文)。 但是、我希望能够运行4个单独的计时器来切换4个单独的 LED。 我正在尝试使用带有单独 TB0CCTLn 寄存器的计时器 B 对其进行设置。 我知道每个单独的 TB0CCTLn 寄存器都有一个单独的计数用来产生中断。 在如何识别中断函数中何时发生单独的中断方面、我有点困惑。 是否有寄存器可读取哪个中断触发了事件? ~、我知道发送 TB0CTL &= 1 μ s MC 会停止整个计时器 B。但是、是否有办法可以停止单个 TB0CCTLn 计数以便通过软件停止每个单独的 LED 计时器?
#include <msp430.h> int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop WDT // Configure GPIO P1DIR |= BIT0; // P1.0 output P1OUT |= BIT0; // P1.0 high // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5; TA0CCTL0 |= CCIE; // TACCR0 interrupt enabled TA0CCR0 = 50000; TA0CTL |= TASSEL__SMCLK | MC__CONTINUOUS; // SMCLK, continuous mode __bis_SR_register(LPM0_bits | GIE); // Enter LPM0 w/ interrupts __no_operation(); // For debug } // Timer A0 interrupt service routine #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = TIMER0_A0_VECTOR __interrupt void Timer_A (void) #elif defined(__GNUC__) void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A (void) #else #error Compiler not supported! #endif { P1OUT ^= BIT0; TA0CCR0 = 50000; // Add Offset to TACCR0 }
除了将每个计时器放在一个单独的 TB0CCTLn 寄存器上外、有没有更好的方法可以完成我正在尝试的工作?
我怀疑这不是你想要的。 计时器配置为连续模式、这意味着它会计数到其最大值然后再返回零。 (向上计数模式将在复位之前计数到 CCR0中的值。) 当然、您可以在每个 CCRx 上获得一个中断、但它们发生的速率会是相同的。 相位取决于 CCRx 值。
CCR0中断具有其自己的中断矢量、而其他中断矢量是共享的、并且可以读取 IV 寄存器以指示哪个已触发。 详细说明了这一点。
哦、数据表显示此器件有五个定时器、四个 TimerA 和一个 TimerB。
对您尝试执行的操作的架构不太确定。
每个计时器器件(例如计时器 A0、计时器 A1、计时器 B0)都有其自己的计数器、用于设置 PWM 周期的周期、现在该计数器周期(最多0xFFFF、 或 CCR0指定的某个值、具体取决于 TAxCTL 中的 MC 位-您可以是连续的、因此它会循环到0xFFFF)。 现在有很多比较寄存器正在查看 PWM 计数器 CCR1-n;其中的每个比较寄存器可以在 PWM 计数器经过该点时触发。
比较寄存器通常用作任何 PWM 输出中的占空比、因此它们会在多大比例的 PWM 周期持续时间内进行切换、这些输出都可以针对多大的 PWM 周期持续时间处于活动状态。 因此、将 CCR1设置为0xFF -它通常在0到0xFF 之间处于活动状态、在0x100到0xFFFF 之间处于关闭状态;因此、连接的 LED 仅为总时间的1/256 -因此光线相当暗。
不同的比较寄存器可以有不同的 CCRn 值、因此适合不同的时间百分比。
那么、问题是您要尝试实现什么、是否所有 LED 闪烁都在同一周期、但具有不同的持续时间? 如果是、那么可以使用单个计时器来执行该操作。 如果 LED 完全异步(例如每5s 闪烁一次、每7s 闪烁一次)-那么您可能需要多个计时器。
这有什么用吗? 我不确定我是否真的明白你在想做什么。
只是看了一下代码。 您是否执行了端口映射;因此让计时器明确切换 IO 端口、如果您无法将 LED 连接到这些引脚、则需要将端口映射到 LED 连接的位置? 这意味着您不需要代码来切换 LED 灯、而是由计时器设备执行此操作。
尊敬的 David:
我已经附上了到目前为止我所掌握的最新代码、希望这些代码能够更清楚地说明我正在尝试执行的操作。 从本质上讲、您在评论我正在尝试做什么时描述得非常好。 我正在尝试使用四个单独控制的计时器来分别控制四个 LED。 如果在同一个时钟上对它们进行控制、我就可以了、但我希望它们能够在不同的时间进行设置。 例如、我希望该软件能够在按下某个按钮时启动 LED1计时器来打开 LED1、并在关闭该计时器之前将其保持一定的秒(可以在几毫秒到20秒之间设置)。 在 LED1的计时器运行时、可以按下另一个按钮、以在 LED2关闭之前将其打开并保持不同的时间。 LED 3和4也是如此。 这听起来可能不是最好的方法。 如果是这种情况、我可以自行创建一个独立计数的自定义计时器代码。 但是、我想尝试使用 MSP430已经具有的计时器模块。
//***************************************************************************** // Definitions //***************************************************************************** //***************************************************************************** // //! Timer B is used for the LEDs. //! Register 0 is LED 1. //! Register 1 is LED 2. //! Register 2 is LEDs 3. //! Register 3 is LEDs 4 //! \def TIMER_B_RESET defines a shortcut to set the timer B reset bit. //! \def TIMER_B_CTL_SET defines a shortcut to set the timer B clock to the //! SMCLK divided by 2 (1MHz), the timer B mode to up count, and set the //! max count to 16-bit (65535). //! \def TIMER_B_CTL_STOP defines a shortcut to stop the timer B clocks. //! \def TIMER_B_LED_1_IQR_ENABLE defines a shortcut to set the timer B //! register 0 interrupt enable bit. //! \def TIMER_B_LED_1_IQR_CLEAR defines a shortcut to clear the timer B //! register 0 interrupt bit. //! \def TIMER_B_LED_1_COUNT defines a shortcut to the timer B count //! register 0. //! \def TIMER_B_LED_2_IQR_ENABLE defines a shortcut to set the timer B //! register 1 interrupt enable bit. //! \def TIMER_B_LED_2_IQR_CLEAR defines a shortcut to clear the timer B //! register 1 interrupt bit. //! \def TIMER_B_LED_2_COUNT defines a shortcut to the timer B count //! register 1. //! \def TIMER_B_LED_3_IQR_ENABLE defines a shortcut to set the timer B //! register 2 interrupt enable bit. //! \def TIMER_B_LED_3_IQR_CLEAR defines a shortcut to clear the timer B //! register 2 interrupt bit. //! \def TIMER_B_LED_3_COUNT defines a shortcut to the timer B count //! register 2. //! \def TIMER_B_LED_4_IQR_ENABLE defines a shortcut to set the timer B //! register 3 interrupt enable bit. //! \def TIMER_B_LED_4_IQR_CLEAR defines a shortcut to clear the timer B //! register 3 interrupt bit. //! \def TIMER_B_LED_4_COUNT defines a shortcut to the timer B count //! register 3. // //***************************************************************************** #define TIMER_B_RESET (TB0CTL |= TBCLR) #define TIMER_B_CTL_SET (TB0CTL |= TBSSEL__SMCLK | ID__2 | MC__UP | CNTL__16) #define TIMER_B_CTL_STOP (TB0CTL &= ~MC) #define TIMER_B_LED_1_IQR_ENABLE (TB0CCTL0 |= CCIE) #define TIMER_B_LED_1_IQR_CLEAR (TB0CCTL0 &= ~CCIFG) #define TIMER_B_LED_1_COUNT (TB0CCR0) #define TIMER_B_LED_2_IQR_ENABLE (TB0CCTL1 |= CCIE) #define TIMER_B_LED_2_IQR_CLEAR (TB0CCTL1 &= ~CCIFG) #define TIMER_B_LED_2_COUNT (TB0CCR1) #define TIMER_B_LED_3_IQR_ENABLE (TB0CCTL2 |= CCIE) #define TIMER_B_LED_3_IQR_CLEAR (TB0CCTL2 &= ~CCIFG) #define TIMER_B_LED_3_COUNT (TB0CCR2) #define TIMER_B_LED_4_IQR_ENABLE (TB0CCTL3 |= CCIE) #define TIMER_B_LED_4_IQR_CLEAR (TB0CCTL3 &= ~CCIFG) #define TIMER_B_LED_4_COUNT (TB0CCR3) //***************************************************************************** // Function Implementations //***************************************************************************** void Timer_startLED1Timer(uint16_t usDuration) { // Initialize timer B, if applicable Timer_startTimerB(); // Enable the LED timer 1 interrupt, set the count, and clear the interrupt bit TIMER_B_LED_1_IQR_ENABLE; TIMER_B_LED_1_COUNT = usDuration; TIMER_B_LED_1_IQR_CLEAR; } void Timer_startLED2Timer(uint16_t usDuration) { // Initialize timer B, if applicable Timer_startTimerB(); // Enable the LED 2 timer interrupt, set the count, and clear the interrupt bit TIMER_B_LED_2_IQR_ENABLE; TIMER_B_LED_2_COUNT = usDuration; TIMER_B_LED_2_IQR_CLEAR; } void Timer_startLED3Timer(uint16_t usDuration) { // Initialize timer B, if applicable Timer_startTimerB(); // Enable the LED 3 timer interrupt, set the count, and clear the interrupt bit TIMER_B_LED_3_IQR_ENABLE; TIMER_B_LED_3_COUNT = usDuration; TIMER_B_LED_3_IQR_CLEAR; } void Timer_startLED4Timer(uint16_t usDuration) { // Initialize timer B, if applicable Timer_startTimerB(); // Enable the LED 4 timer interrupt, set the count, and clear the interrupt bit TIMER_B_LED_4_IQR_ENABLE; TIMER_B_LED_4_COUNT = usDuration; TIMER_B_LED_4_IQR_CLEAR; } void Timer_stopLEDTimers(void) { TIMER_B_CTL_STOP; TIMER_B_RESET; } void Timer_startTimerB(void) { // Initialize the timer B peripheral, if the timer is not already running // TODO: Add way to check the status of the timer if (1) { Timer_stopLEDTimers(); TIMER_B_CTL_SET; } } // Interrupt for the LED 1 timer #pragma vector = TIMER0_B0_VECTOR __interrupt void Timer_led1ISR() { // TODO: Toggle LED 1 and stop timer, if applicable } // Interrupt for other LED timers #pragma vector = TIMER0_B1_VECTOR __interrupt void Timer_led2To4ISR() { // TODO: Check which interrupt occurred, toggle appropriate LED, and stop timer, if applicable }
尚未检查代码-但您所描述的内容听起来不像常规计时器逻辑。 计时器设备往往会重复执行某些操作、 例如使 LED 永远闪烁。
那么我怎样想对它进行编码呢、我要设置一个中断进行监控、但按下。 假如您甚至可以通过按下按钮来启动中断、那么您只需要编写代码来捕获该中断。 然后、根据按下按钮的不同、我说它设置警报、并没有在 MSP430上执行此操作、但我希望它具有 RTC 的功能。
因此、当按下一个按钮时、Code 会首先打开相关的 LED。 然后在 LED 必须关闭时设置警报事件、可能 MSP430只能执行一个警报。 因此、您需要一个警报事件表、当您将某些内容添加到该表中时、您可以扫描该表以查找最早的事件、然后确保为最早的事件设置了警报。
当警报响起时、猜测这将被另一个中断和例程捕获。 该例程、然后扫描警报事件表、查看发生的事件、并关闭相关的 LED。 然后扫描表以确定下一个事件的发生、并为该事件设置警报。
我建议阅读手册的 RTC 部分、以及如何在数字 IO 部分(按下按钮)中使用该部分设置中断。
明白了吗?
尊敬的 David:
这是完全正确的。 在前面看了您的所有意见之后、我觉得这似乎是处理此应用的最佳方法。 我将继续介绍。