1,2,5,6,9,12
1.一个基本的 I/O 接口,一般包含哪些寄存器?这些寄存器的作用分别是什么?
控制寄存器和数据寄存器。
- 数据寄存器用于设置输出数据或读取输入数据;
- 控制寄存器决定 GPIO 的方向,即 GPIO 工作于输入还是输出状态。
2. 一个 GPIO 引脚作为输入、输出使用时,有哪几种常用具体配置?各种配置的特点和应用场合?
常见配置有标准输入、上/下拉输入、输入禁用的推拉输出、上/下拉输出、复位或模拟 I/O。
- 标准输入:GPIO 被配置为标准输入时,为了防止 MCU 读到不确定的输入状态,该 GPIO 必须被外部电路驱动,即输入不能悬空。
- 上/下拉输入:上拉就是将不确定的信号通过一个电阻钳位在高电平,电阻同时起限流作用,下拉就是将不确定的信号通过一个电阻钳位在低电平。
- 输入禁用的推拉输出:推拉电路由两个二极管组成,这两个二极管始终处于一个导通、一个截止的状态,对于负载而言,就好像是一个在推、一个在拉,共同完成电流输出任务。推拉电路的输出对外部电路具有驱动能力。
- 上/下拉输出:这种模式相当于在推拉输出时串接了一个电阻,限制了输出电流,可以保护 GPIO 引脚,适合于外部弱驱动要求的应用。
- 复位或模拟 I/O:一般芯片复位时,GPIO 会被自动配置成这种模式。
5,设计编写一个程序,用中断方式来读取一个按键状态,并控制一个 LED 的亮和灭。即按一下灯亮、再按一下灯灭,可重复操作,要求每次操作执行可靠
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include <stdint.h>
#include <stdbool.h>
int main(void)
{
MAP_WDT_A_holdTimer();
MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1);
MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1);
MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);
MAP_Interrupt_enableInterrupt(INT_PORT1);
MAP_SysCtl_enableSRAMBankRetention(SYSCTL_SRAM_BANK1);
MAP_Interrupt_enableMaster();
while (1)
{
MAP_PCM_gotoLPM3();
}
}
void PORT1_IRQHandler(void)
{
uint32_t status;
status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);
MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status);
if(status & GPIO_PIN1)
{
MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
}
}
6.简述定时器的一般结构及其扩展功能(输入捕获、输出比较、PWM 等)。
定时器主要由控制寄存器、状态寄存器、初始值寄存器、输出寄存器和计
数器组成
- 输入捕获功能可以用于测量周期。只要捕获两次脉冲,然后相减就能得到两次脉冲的间隔时间
- 输出比较功能可以用于产生特定波形。当计数器的值与比较寄存器的值相等时,可在输出引脚输出指定信号
- PWM 是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,其原理是冲量相等而形状不同的窄脉冲加在具有惯性的环节上时,其效果基本相同
9 设计编写一个程序,实现一个“呼吸灯”的功能。就是 LED 灯的亮度慢慢变亮、再慢慢变暗,周而复始不断循环,要求亮度变化感觉柔和,循环周期与人的呼吸周期差不多
通过之前的实验自主尝试
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
void myDelay(int time)
{
int i = 500 * time;
while (i--);
}
int main() {
GPIO_setAsOutputPin(led1);
int level[17] = { 32,28,24,20,16,12,8,4,0,4,8,12,16,20,24,28,32 };
int len = sizeof(level) / sizeof(int);
while (1)
{
int times = 0
for (int i = 0;i < len;i++)
{
while(time++ < 20)
{
GPIO_setOutputHighOnPin(GPIO_PORT_P2,GPIO_PIN0);
myDelay(i);
GPIO_setOutputLowOnPin(GPIO_PORT_P2,GPIO_PIN0);
myDelay(32 - i);
}
}
}
}
参考网上资料找到的另一种写法
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include <stdint.h>
#include <stdbool.h>
uint32_t flag = 1;
Timer_A_PWMConfig pwmConfig =
{
TIMER_A_CLOCKSOURCE_SMCLK,
TIMER_A_CLOCKSOURCE_DIVIDER_1,
320,
TIMER_A_CAPTURECOMPARE_REGISTER_1,
TIMER_A_OUTPUTMODE_RESET_SET,
2
};
const uint8_t port_mapping[] =
{
//port2,use red led
PM_TA0CCR1A,PM_NONE,PM_NONE,PM_NONE,PM_NONE,PM_NONE,PM_NONE,
PM_NONE
};
int main(void)
{
MAP_WDT_A_holdTimer();
MAP_CS_setReferenceOscillatorFrequency(CS_REFO_128KHZ);
MAP_CS_initClockSignal(CS_MCLK, CS_REFOCLK_SELECT,
CS_CLOCK_DIVIDER_1);
MAP_CS_initClockSignal(CS_SMCLK, CS_REFOCLK_SELECT,
CS_CLOCK_DIVIDER_2);
MAP_PCM_setPowerState(PCM_AM_LF_VCORE0);
//configure port mapping
MAP_PMAP_configurePorts((const uint8_t *)
port_mapping,PMAP_P2MAP,1,PMAP_DISABLE_RECONFIGURATION);
MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2,GPIO_PIN0|GPI
O_PIN1|GPIO_PIN2,GPIO_PRIMARY_MODULE_FUNCTION);
MAP_SysTick_enableModule();
MAP_SysTick_setPeriod(3000);
MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
MAP_SysTick_enableInterrupt();
MAP_Interrupt_enableSleepOnIsrExit();
MAP_Interrupt_enableMaster();
GPIO_setOutputLowOnPin(GPIO_PORT_P2,GPIO_PIN0);
GPIO_setOutputLowOnPin(GPIO_PORT_P2,GPIO_PIN1);
GPIO_setOutputLowOnPin(GPIO_PORT_P2,GPIO_PIN2);
while (1)
{
MAP_PCM_gotoLPM0();
}
}
void SysTick_Handler(void)
{
if(flag)
{
if(pwmConfig.dutyCycle <= 288)
{
pwmConfig.dutyCycle += 2;
}
else
{
flag = 0;
pwmConfig.dutyCycle -= 2;
}
}
else
{
if(pwmConfig.dutyCycle >= 2)
{
pwmConfig.dutyCycle -= 2;
}
else
{
flag = 1;
pwmConfig.dutyCycle += 2;
}
}
MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
}
通过和同学讨论之后,发现其实可以不使用中断,可以直接延迟处理,修改版如下
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include <stdint.h>
#include <stdbool.h>
void myDelay(int time)
{
int i = 500 * time;
while (i--);
}
uint32_t flag = 1;
Timer_A_PWMConfig pwmConfig =
{
TIMER_A_CLOCKSOURCE_SMCLK,
TIMER_A_CLOCKSOURCE_DIVIDER_1,
320,
TIMER_A_CAPTURECOMPARE_REGISTER_1,
TIMER_A_OUTPUTMODE_RESET_SET,
32
};
const uint8_t port_mapping[] =
{
PM_TA0CCR1A,PM_NONE,PM_NONE,PM_NONE,PM_NONE,PM_NONE,PM_NONE,
PM_NONE
};
int main(void) {
MAP_WDT_A_holdTimer();
MAP_CS_setReferenceOscillatorFrequency(CS_REFO_128KHZ);
MAP_CS_initClockSignal(CS_MCLK, CS_REFOCLK_SELECT,
CS_CLOCK_DIVIDER_1);
MAP_CS_initClockSignal(CS_SMCLK, CS_REFOCLK_SELECT,
CS_CLOCK_DIVIDER_2);
MAP_PCM_setPowerState(PCM_AM_LF_VCORE0);
MAP_PMAP_configurePorts((const uint8_t*)
port_mapping, PMAP_P2MAP, 1, PMAP_DISABLE_RECONFIGURATION);
MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION);
MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);
GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);
GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN2);
while (1) {
myDelay(10);
if (pwmConfig.dutyCycle == 288)
flag = 0;
if (pwmConfig.dutyCycle == 32)
flag = 1;
if (flag)
pwmConfig.dutyCycle += 32;
else
pwmConfig.dutyCycle -= 32;
MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
}
}
12 简述看门狗定时器的基本概念及其使用方法。
看门狗定时器是一个特殊的定时器,可以通过对系统进行复位来防止系统故障,主要功能是看门狗功能和普通定时器功能。
- WDT 设置一定的计时时间,使能后,计数器开始计数。当计时时间到后,则触发系统复位
- 如果在定时时间到达之前,进行喂狗(计数器重装) 动作,则不会引起系统复位。
- 看门狗的定时时间可以由用户设定,可以根据需要在指定的时间内复位系统