ENGR 2350 - Quiz 2

Q1 定时器计算

对于一个工作在 12 MHz 系统时钟下并且处于“向上模式”的 Timer_A 模块…

Q1.1

要让定时器的溢出周期为 8 ms,需要设置其周期(以计数值表示)为多少?假设定时器的时钟分频器设置为 32

$$\text{Timer clock} = \frac{12,\text{MHz}}{32} = 375000 \text{ Hz}$$ $$N = 375000 \times 0.008 \text{ s} = \boxed{3000} \text{ ticks}$$

Q1.2

要使定时器仍能产生相同的溢出周期,最小的分频器应该是多少?假设定时器的周期(以计数值表示)可以调整。

我们有一个16位的Timer_A(因此它的最大计数值为65536)。我们可以使用以下不等式:

$$ \begin{align*} N_{DIV} &\ge T_{period} \times \frac{f_{SMCLK}}{N_{period}} \\ N_{DIV} &\ge 0.008 \times \frac{12000000}{65536} \\ N_{DIV} &\approx 1.4648 \end{align*} $$

分频器必须是整数,所以我们需要向上取整到 $\boxed{2}$。

Q2 基本 GPIO

请回答以下关于 GPIO 功能和使用的问题,并考虑提供的电路图。

/zh-cn/engr-2350-quiz-02/q2-gpio.avif
Q2 Basic GPIO Pin Out

Q2.1

使用寄存器仅初始化上述图中使用的GPIO,不要修改端口中的其他引脚。

1
2
P6DIR |= 0x10; // for pin 4
P6DIR &= ~0x42; // or 0xBD for 0x40 (pin 6) and 0x02 (pin 1) 
Q2.2

使用 DriverLib 初始化电路图中的 GPIO 引脚。不要修改端口的其他引脚。

1
2
GPIO_setAsInputPin(GPIO_PORT_P6, GPIO_PIN1 | GPIO_PIN6);
GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN4);
Q2.3

使用 寄存器DriverLib,当 PB1 被按下且 PB2 未被按下时,点亮 LED1;否则关闭 LED。

1
2
3
4
5
6
7
8
PB1 = GPIO_getInputPinValue(GPIO_PORT_P6, GPIO_PIN1);
PB2 = GPIO_getInputPinValue(GPIO_PORT_P6, GPIO_PIN6);

if (!PB1 && !PB2){ 
    GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN6);
} else { 
    GPIO_setOutputLowOnPIN(GPIO_PORT_P3, GPIO_PIN6);
}

Q3

将流程图转换为等效的代码段。

 flowchart LR
    A([Start]) --> B{Are a and b
both zero?} B -- Yes --> C([Done]) B -- No --> D[Divide a by 2
and save back into a] D --> E[Multiply b by a
and save back into b] E --> B
1
2
3
4
while (a == 0 && b == 0) {
    a = a / 2;
    b = b * a;
}

Q4 定时器/中断代码

给定下面的完整程序,并且知道 SMCLK 是 12 MHz,回答以下问题。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
void IncA(),IncB(),IncC();
uint8_t A = 0,B = 0,C = 0;
Timer_A_UpModeConfig tim_config;
uint32_t timer = XXXXXXXXX; // Some valid value

void main(){
  SysInit();
  TimerInit();
  while(1){
        // To fill in
  }
}

void TimerInit(){
  tim_config.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;
  tim_config.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_32;
  tim_config.timerPeriod = 12345;
  tim_config.timerClear = TIMER_A_DO_CLEAR;
  tim_config.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE;
  Timer_A_configureUpMode(timer,&tim_config);
  Timer_A_registerInterrupt(timer,TIMER_A_CCRX_AND_OVERFLOW_INTERRUPT,IncC);
  Timer_A_startCounter(timer,TIMER_A_UP_MODE);
}

void IncA(){
  Timer_A_clearInterruptFlag(TIMER_A1_BASE);
  A++;
}

void IncB(){
  Timer_A_clearInterruptFlag(TIMER_A2_BASE);
  B++;
}

void IncC(){
  Timer_A_clearInterruptFlag(TIMER_A3_BASE);
 C++;
}
Q4.1

在给定的代码中,哪个函数会被作为 中断服务例程 调用?给出函数名。

1
IncC()

因为 Timer_A_registerInterrupt(timer, TIMER_A_CCRX_AND_OVERFLOW_INTERRUPT, IncC); 这一行将 IncC() 设置为定时器中断的 ISR。

Q4.2

这个函数被硬件触发的频率是多少?请给出答案并用毫秒为单位。

$$\text{Timer Clock} = \frac{12,\text{MHz}}{32} = 375 \text{ kHz}$$ $$\text{Tick Period} = \frac{1}{375,\text{kHz}} \approx 2.667\,\mu\text{s}$$ $$\text{Interrupt Period} = 12345 \times 2.667,\mu\text{s} \approx \boxed{32.92} \text{ ms}$$

Q4.3

编写一段代码,放在 while(1) 循环中,实现一个 阻塞 的延迟,大约为 5 秒钟,并且不使用 __delay_cycles(),使得每次延迟后打印出消息 “5 seconds"。

$$\text{Period} \approx \frac{12345}{12,\text{MHz}/32} \approx 32.92\text{ ms}$$ $$\frac{5000\text{ ms}}{32.92\text{ ms}} \approx 152$$

1
2
3
C = 0;
while(C < 152) {}
printf("5 seconds\n");
Q4.4

编写一段代码,放在 while(1) 循环中,实现一个 非阻塞 的延迟,大约为 5 秒钟,并且不使用 __delay_cycles(),使得每次延迟后打印出消息 “5 seconds” 并且连续打印出 “not blocked"。

1
2
3
4
5
printf("not blocked");
if (C >= 152) {
    printf("5 seconds");
    C = 0;
}

相关内容

0%