【南航嵌入式系统原理与应用】第6章作业

第六章作业

【6.3】

一基于 STM32F10x 微控制器的嵌入式应用系统使用的 GPIO 情况如图 6.24 所示,PA0 接 一按键,PC4 通过光耦驱动一个 VDD=24V DC 的继电器,继电器触点做为可控制的开关,连接到 220VAC 工作的喇叭,当 PC4 输出 0 逻辑时,光耦发光而使继电器得电闭合,喇叭发声。PD2 连接 LED 发光二极管,PD2 输出逻辑 0 时发光管亮。PB1 产生 200Hz~1KHz 方波,假设已经按照第 5 章的有关内容初始化 PA0 为输入高阻输入,PD2、PC4 和 PB1 为 2MHz 推挽输出。

image-20220401163120373

(1)利用定时计数器 3(TIM3)定时 10ms,每当 10ms 中断一次,在中断服务程序中判断按键,当按键按下超过 0.5 秒小于 1 秒时称为短按,按下超过 3 秒时为长按。试用 C 语言写出定时器 3(TIM3)定时 10ms 的初始化函数; 当短按奇数次按键时,让 LED 发光,短按偶数按键时,让 LED 熄灭,长按偶数次按键时让喇叭发声报警,长按奇数次按键时停止发声,写入定时器 3(TIM3)的中断服务程序。

(2)利用PWM的捕获功能确定按键按下,通过PWM1(PB1:TIM3_CH4)输出200Hz~1KHz占空比为 50%的方波,由按键控制频率的改变,起始频率 200Hz,频率增加 1Hz。当达到 1KHz 时让 LED 亮,再按一次按键则回到 200Hz,当频率小于 950Hz 时让 LED 灭。试编程实现

解答:

(1)利用定时计数器 3(TIM3)定时 10ms,每当 10ms 中断一次,在中断服务程序中判断按键,当按键按下超过 0.5 秒小于 1 秒时称为短按,按下超过 3 秒时为长按。试用 C 语言写出定时器 3(TIM3)定时 10ms 的初始化函数; 当短按奇数次按键时,让 LED 发光,短按偶数按键时,让 LED 熄灭,长按偶数次按键时让喇叭发声报警,长按奇数次按键时停止发声,写入定时器 3(TIM3)的中断服务程序。

void NVIC_Configuration(void)//定时器中断配置 
{
    NVIC_InitTypeDef NVIC_InitStructure; 
    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0000);     
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
    NVIC_Init(&NVIC_InitStructure); 
}
void TIM_Configuration(void) //配置定时器 3
{ 
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); ;/*使能 TIM3 对应时钟*/ 
    TIM_TimeBaseStructure.TIM_Period = 10*10-1; /*定时 10ms */ 
    TIM_TimeBaseStructure.TIM_Prescaler = SystemCoreClock/10000-1; 
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); /* 初始化 TIM3*/ 
    /* TIM Interrupts enable */ 
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);/*使能 TIM3 更新中断*/ 
    TIM_Cmd(TIM3, ENABLE);/*启动 TIM3 计数器*/ 
}
extern u32 TP1,TP2,Times;
int main(void) 
{ 
    SystemInit(); 
    GPIO_Configuration(); 
    TIM_Configuration();     /* 初始化 TIMx 定时器 */ 
    NVIC_Configuration(); 
    LCD_Init();     /* LCD 初始化 */ 
    Welcome(); /* 显示主界面 */ 
    LED1(1);LED2(1);LED3(1);LED4(1); 
    while(1) 
    { 
        if (Times>=300) 
        {
            if (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11)==0) 
                    TP2++; 
            if (TP2&1)
            {
                GPIO_SetBits(GPIOC,GPIO_Pin_4);
                Times=0;
            }//停止报警 
            else 
            {
                GPIO_ResetBits(GPIOC,GPIO_Pin_4);
                Times=0;
            }//报警 
        } 
        else if ((Times>=50)&&(Times<=150)) 
        {
            TP1++;
            Delay_ms(10); 
            if (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11)==1) 
            {
                    if (TP1&1) {GPIO_ResetBits(GPIOD,GPIO_Pin_2);
                               Times=0;
              }//LED1 亮 
            else 
            {
                GPIO_SetBits(GPIOD,GPIO_Pin_2);
                Times=0;
            }//LED1 灭 
        }                                                                                   
    } 
} 

u32 Times=0,TP1=0,TP2; 
void TIM3_IRQHandler(void) 
{ 
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) /*判断是否是更新中断*/ 
    { 
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update); /*清除中断标志*/ 
        if (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11)==0) 
            Times++;//按下键计 10ms 倍数 
    } 
}

(2)利用PWM的捕获功能确定按键按下,通过PWM1(PB1:TIM3_CH4)输出200Hz~1KHz占空比为 50%的方波,由按键控制频率的改变,起始频率 200Hz,频率增加 1Hz。当达到 1KHz 时让 LED 亮,再按一次按键则回到 200Hz,当频率小于 950Hz 时让 LED 灭。试编程实现

void PWM_GPIO_Init(void) 
{ 
    GPIO_InitTypeDef GPIO_InitStructure; //定义一个 GPIO 结构体变量 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE); 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //PB1 TIM3 CH4 通道引脚 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用输出推挽 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //配置端口速度为 50M 
    GPIO_Init(GPIOB, &GPIO_InitStructure); //将端口 GPIOD 进行初始化配置 
}
void TIM2_Cap_Init(u16 arr,u16 psc)//TIM2 CH1 捕获方式 PA0 
{ 
    GPIO_InitTypeDef GPIO_InitStructure; 
    TIM_ICInitTypeDef TIM2_ICInitStructure; 
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
    NVIC_InitTypeDef NVIC_InitStructure; 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); /*使能 TIM2 时钟*/ 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);/*使能 GPIOA 时钟*/ 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; /*PA0 引脚 */ 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; /*PA0 上拉输入 */ 
    GPIO_Init(GPIOA, &GPIO_InitStructure); 
    GPIO_SetBits(GPIOA,GPIO_Pin_0); /*初始化 TIM2 输入捕获参数*/ 
    TIM_TimeBaseStructure.Tim_Period = arr;
    TIM_TimeBaseStructure.Tim_Prescalar = psc;
    TIM_TimeBaseStructure.Tim_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.Tim_CounyerMode = TIM_ConnterMode_UP;
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
    TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1; /*选择输入端 IC1 映射到 TI1 上*/ 
    TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; /*下升沿捕获*/ 
    TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; /*映射到 TI1 上*/ 
    TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; /*配置输入不分频*/ 
    TIM2_ICInitStructure.TIM_ICFilter = 0x00; /*配置输入不滤波*/ 
    TIM_ICInit(TIM2, &TIM2_ICInitStructure); /*中断分组初始化*/ 
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; /*TIM2 中断*/ 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; /*先占优先级 2 级*/ 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /*从优先级 0 级*/ 
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /*IRQ 通道被使能*/ 
    NVIC_Init(&NVIC_InitStructure); 
    TIM_ITConfig(TIM2, TIM_IT_CC1,ENABLE);/*允许 CC1IE 捕获中断*/ 
    TIM_Cmd(TIM2,ENABLE ); /*使能定时器 2*/ 
}
void Init_PWM(uint16_t Dutyfactor)
{
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCStructureInit(&TIM_OCInitStructure);
    TIM_OCInitstructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitstructure.TIM_Pulse = Dutyfactor;
    TIM_OCInitstructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitstructure.TIM_OutPutState = TIM_OutPutState_Enable;
    TIM_OC3Init(TIM2,&TIM_OCInit_OCInitStructure);
    TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Enanble);
    TIM_CtrlPWMOutputs(TIM2,Enable);
}

void change(u16 arr)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
    TIM_TimeBaseStructure.Tim_Period = arr;
    TIM_TimeBaseStructure.Tim_Prescalar = 0;
    TIM_TimeBaseStructure.Tim_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.Tim_CounyerMode = TIM_ConnterMode_UP;
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
}
//设预分频器值为0
void TIM2_IRQHandler(void)
{
    u16 period,arr = 0;
    if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
    {
        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
        period = TIM_TimeBaseStructure.TIM_Period;
        if((period<=359999)&(period>71999))//即200Hz-1KHz
        {
            arr = (72*10^6*(period+1))/(72*10^6+period+1)-1;
            change(arr);
            if(arr = 71999)
            {
                GPIOD->ODR&=~(1<<2);
            }
        }
        else if(period == 71999)
        {
            arr = 35999;
            change(arr);
        }
        if((arr<=359999)&(arr>75788))//即200Hz<= <950Hz
        {
            GPIOD->ODR |= (1<<2);
        }
    }
}

int main()
{
    SystemInit();
    PWM_GPIO_Init();
    TIM2_Cap_Init(359999,0);
    Init_PWM(360000*0.5);
    while(1)
    {

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NUAA_Peter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值