全国大学生电子竞赛单片机培训与任务记录

目录

前言

按键控制流水灯 

总结


前言

刚刚接触培训的我一开始肯定是茫然的,但是经过了两周的培训,第一次任务已经完美完成了。现在把自己的心得记录一下。

首先本次培训的内容很简单:

1.介绍了STM32F407的使用方法,以及如何查看其相关数据手册。

2.介绍了基于keli5的基本程序编译,调用正点原子库函数中的跑马灯进行演示。

3.介绍了一个完整的单片机程序包括但不限于主函数中的循环部分,中断函数的中断条件以及中断语句中的执行。

4.串口的使用,以及串口的调试方法。

5.如何调试单片机程序以及一些同学遇到的问题。

这些内容都很碎片化,并且很抽象,对于笔者这种单片机新手来说是很不友好的。但是之后我根据老师布置的任务一步一步学习,最后总结了一下,发现还是收获颇丰。

下面先介绍一下任务详情:

(1) 按键控制流水灯:KEY0按一下,开启流水灯,再按一下,LED灯熄灭
(2) 产生频率可调的方波(采用定时器Timer的方法实现):KEY1控制方波频 率在500Hz、100Hz、1Hz切换(方波输出管脚自行在开发板的引出管脚 上选择,用杜邦线引出,在示波器上观察)
(3) 串口(UART)发送:通过串口将单片机工作状态发送到PC的串口调试助 手,比如:流水灯正在工作、输出500Hz的方波信号等。
提高要求:
(4) 串口(UART)接收:PC端通过串口调试助手发送信息控制方波频率的 切换
(5) AD模块:使用单片机的AD模块测量直流信号电平(将信号源的方波信 号频率设为最低,峰峰值不超过3.3V。不允许接电源输出作为单片机AD 输入)。测到的电平值可以通过串口发送到PC显示或者显示到板上的液 晶屏上。
这次我先介绍任务(1)的思考流程以及程序,之后再慢慢介绍其他的。在介绍中,希望能够帮助你找到你需要的内容。

按键控制流水灯 

(以下全部程序都是在正点原子的库函数中的程序加以引用和改动)

KEY0按一下,开启流水灯,再按一下,LED灯熄灭。

看上去很简单的一个功能,但就是这样简单一个功能让我纠结了1个晚上。

一开始我的想法是不使用中断(因为当时还不是很熟练),就用简单的flag奇偶判断,于是我在主函数里写道:

int main()
...//一些初始化
while(1)
if(key1==0)
{
    delay_ms(10);//按键消抖
    flag++;
}
if(flag%2==0)//判断为偶,则两个灯都灭
{
    led1=0;
    led2=0;
}
if(flag%2==1)//判断为奇,则开始流水灯
{
    led1=~led1;
    delay_ms(100);//延时100ms,不然两个灯闪的太快,下面同理
    led2=~led2;
    delay_ms(100);
}

但是烧入程序后我发现流水灯只能用一次,之后再按开关就没有用了,我以为是循环的问题,于是将控制流水灯启动的条件里面加了个while死循环,之后就不用说了......自然是流水灯一直在闪烁,无法关闭。

就在我一筹莫展时,我想到了中断系统这一单片机神奇的功能,因为单片机的中断系统将迫使暂停CPU正在执行的程序,转而去进行中断事件的处理;中断处理完毕后。又返回被中断的程序处,继续执行下去。于是我将外部中断的库函数也加入了进来:

void EXTIX_Init(void)
{
	NVIC_InitTypeDef   NVIC_InitStructure;
	EXTI_InitTypeDef   EXTI_InitStructure;
	
	KEY_Init(); 
 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
	
 
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);
	

  EXTI_InitStructure.EXTI_Line = EXTI_Line0;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; 
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
	

	EXTI_InitStructure.EXTI_Line = EXTI_Line2 | EXTI_Line3 | EXTI_Line4;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);

	
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	   
}

之后就是在中断函数里写中断条件以及中断后执行的语句了

void EXTI4_IRQHandler(void)	
{
	delay(1);//注意这里要在中断函数里重新定义一个delay函数,如果用库函数里自带的会导致程序卡死	
	if(KEY0==0)	 
	{	
		Num++;
	}					 
	 EXTI_ClearITPendingBit(EXTI_Line4); 
}

然后就是在主函数里写入功能循环

int main(void)
...//一些初始化
extern u8 Num;
while(1)
{
		if(Num%2==1)
	{
	    GPIO_ResetBits(GPIOF,GPIO_Pin_9);    //相当于LED0=0,LED0对应引脚拉低  
	    GPIO_SetBits(GPIOF,GPIO_Pin_10);     //相当于LED1=1,LED1对应引脚拉高   
	    delay_ms(100);  		  		     //延时100ms				
	    GPIO_SetBits(GPIOF,GPIO_Pin_9);      //相当于LED0=1,LED0对应引脚拉高	   
	    GPIO_ResetBits(GPIOF,GPIO_Pin_10);   //相当于LED1=0,LED1对应引脚拉低 
	    delay_ms(100);                       //延时100ms
	}
	    if(Num%2==0)
	{
		    LED0=1;
		    LED1=1;
	}
}

烧入程序,发现流水灯可以完美执行,一次开关按下启动,再次按下开关关闭。


总结

就如同我开头所写的那样,一个完整的单片机程序中是肯定的包括主函数和中断函数的(除非特别简单的),所以当你发现你的程序在单片机里运行起来就无法打断时,可以试一试中断系统。希望能够通过这一个简单的程序帮助到你之后“玩”单片机。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Thresh My Dream

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

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

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

打赏作者

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

抵扣说明:

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

余额充值