完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1.题目具体内容:按键控制跑马灯停止,按下按键二跑马灯停止,所有灯熄灭,再按按键一跑马灯
从头开始运行。 使用定时器控制跑马灯,里面有一个参数相当于开关,当参数为1时启动流水灯,当参数为其他时流水灯熄灭。 按键控制参数,达到本题要求。 1.LED灯宏定义 按键宏定义 #define LED1_ON() GPIO_ResetBits(GPIOA , GPIO_Pin_8); //PA8 输出低电平,使其发光 #define LED1_OFF() GPIO_SetBits(GPIOA , GPIO_Pin_8); //PA8 输出高电平,使其灭 #define LED2_ON() GPIO_ResetBits(GPIOB , GPIO_Pin_1); //PB1 输出低电平,使其发光 #define LED2_OFF() GPIO_SetBits(GPIOB , GPIO_Pin_1); //PB1 输出高电平,使其灭 #define LED3_ON() GPIO_ResetBits(GPIOA , GPIO_Pin_7); //PA7 输出低电平,使其发光 #define LED3_OFF() GPIO_SetBits(GPIOA , GPIO_Pin_7); //PA7 输出高电平,使其灭 #define LED4_ON() GPIO_ResetBits(GPIOB , GPIO_Pin_2); //PB2 输出低电平,使其发光 #define LED4_OFF() GPIO_SetBits(GPIOB , GPIO_Pin_2); //PB2 输出高电平,使其灭 #define KEY1() GPIO_ReadInputDataBit(GPIOB , GPIO_Pin_5) #define KEY2() GPIO_ReadInputDataBit(GPIOB , GPIO_Pin_0) #define KEY3() GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_6) 2.LED灯初始化 按键初始化 定时器初始化 void LED_Pin_Init() { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB , ENABLE); //使能PAPB端口时钟 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8; //LED1--》PA8 LED3--》PA7端口配置, 推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 ; //LED2--》PB1 , LED4--》PB2端口配置, 推挽输出 GPIO_Init(GPIOB, &GPIO_InitStructure); LED1_OFF(); LED2_OFF(); LED3_OFF(); LED4_OFF(); } void KEY_Pin_Init() { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); //使能PAPB端口时钟 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_0; //KEY1--》PB5 KEY2--》PB0端口配置 GPIO_Init(GPIOB, &GPIO_InitStructure); //IO口速度为50MHz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 ; //KEY3--》PA6端口配置 GPIO_Init(GPIOA, &GPIO_InitStructure); } //初始化TIM2控制引脚及配置其中断方式、优先级 void TIM2_Int_Init(u16 arr , u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定时器2时钟 TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到2000为2ms TIM_TimeBaseStructure.TIM_Prescaler = psc; //设置用来作为TIMx时钟频率除数的预分频值 1Mhz的计数频率 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 TIM_ITConfig(TIM2 , TIM_IT_Update , ENABLE ); //使能指定的TIM2中断,允许更新中断 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 TIM_Cmd(TIM2, ENABLE); //使能TIM2外设,开始计数 } 3.编写中断服务函数即开关 设定三个变量,一个是开关mode,一个是tim2_count,由于定时器是每2ms运行一次,为达到流水灯的效果,令4000ms执行一次LED灯循环;最后一个为tim2_stats,令1000ms执行一次一个灯亮起 //TIM2中断服务处理函数 void TIM2_IRQHandler() { if(TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET) //检查指定的TIM2中断发生与否:TIM 中断源 { TIM_ClearITPendingBit(TIM2 , TIM_IT_Update ); //清除TIM2的中断待处理位:TIM 中断源 if(mode==1) { tim2_count++; //对2毫秒中断进行累加,累计到1000毫秒即500次, if(tim2_count 》= 500) { tim2_count = 0; tim2_stats++; //对1秒时间进行累加 if (tim2_stats % 4 == 1 ) { LED1_ON(); LED2_OFF(); LED3_OFF(); LED4_OFF(); } else if(tim2_stats % 4 == 2) { LED1_OFF(); LED2_ON(); LED3_OFF(); LED4_OFF(); } else if(tim2_stats % 4 == 3) { LED1_OFF(); LED2_OFF(); LED3_ON(); LED4_OFF(); } else if(tim2_stats % 4 == 0) { LED1_OFF(); LED2_OFF(); LED3_OFF(); LED4_ON(); } } } else { LED1_OFF(); LED2_OFF(); LED3_OFF(); LED4_OFF(); } } } 最后一步就是编写主函数,通过按键控制mode即控制开关 #include “stm32f10x.h” #include “delay.h” int main() { u8 key1stat = 0; delay_init(); //调用精确延时初始化函数 LED_Pin_Init(); //调用LED引脚控制初始化函数 KEY_Pin_Init(); TIM2_Int_Init(2000 , 72 - 1); //调用定时器2初始化函数,配置计数2000,进行72预分频 while(1) //无限循环,等待TIM4中断产生 { if(KEY1() == 0) //判断KEY1是否已按下 { delay_ms(3); //延时消抖 while(KEY1() == 0); //等待KEY1松手 delay_ms(3); //再次延时消抖 mode=1; tim2_stats=0; } if(KEY2()==0) { mode=0; } } } 由于本题是按下KEY1流水灯从头开始,所以不要忘了将tim2_stats清零达到重新来过的效果呀 本题感悟: 题主在写本题时曾想用主函数是流水灯,令外部中断控制流水灯,可是外部中断只能控制一次流水灯就清除标志位了,无法达到永久的效;或者是在外部中断中编写流水灯,但是当中断发生时只能执行一次流水灯也被清除标志位了。这两种方法都是使用死循环来控制流水灯。从而达不到想要的效果,因为是两个永久,流水灯永久循环,消失永久循环。而定时器可以达到通过执行时间来控制流水灯,每两毫秒执行一次中断,达到流水灯循环的效果,并且也可以永久保存mode值,直到下一次按键改变mode才会改变。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1632 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1559 浏览 1 评论
985 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
688 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1605 浏览 2 评论
1869浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
652浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
522浏览 3评论
539浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
508浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 10:21 , Processed in 0.689724 second(s), Total 48, Slave 41 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号