5节拍定时器应用.docx

上传人:b****6 文档编号:3729434 上传时间:2022-11-25 格式:DOCX 页数:15 大小:63.48KB
下载 相关 举报
5节拍定时器应用.docx_第1页
第1页 / 共15页
5节拍定时器应用.docx_第2页
第2页 / 共15页
5节拍定时器应用.docx_第3页
第3页 / 共15页
5节拍定时器应用.docx_第4页
第4页 / 共15页
5节拍定时器应用.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

5节拍定时器应用.docx

《5节拍定时器应用.docx》由会员分享,可在线阅读,更多相关《5节拍定时器应用.docx(15页珍藏版)》请在冰豆网上搜索。

5节拍定时器应用.docx

5节拍定时器应用

第五章节拍定时器

5.1节拍定时器概述

STM32F10x内核中有一个节拍定时器。

节拍定时器为一个24位递减计数器,节拍定时器设定初值并使能后,每经过1个系统时钟周期,计数值就减1。

当计数值递减到0时,节拍定时器自动重装初值,并继续向下计数,同时内部的COUNTFLAG标志会置位,触发中断(如果中断使能)。

节拍定时器,其功能简单,只能提供一个节拍定时用,一般作为系统的嘀嗒。

在使用外部晶振为8MHz,9倍频,系统时钟为72MHz,节拍定时器的递减频率可以设为9MHz(如HCLK/8)。

在这个条件下,把系统定时器的初始值设置成90000,就能够产生10ms的时间基值,如果开启中断,则产生10ms的中断。

利用ST的函数库使用systick的方法

1、调用SysTick_CounterCmd()失能SysTick计数器

2、调用SysTick_ITConfig()失能SysTick中断

3、调用SysTick_CLKSourceConfig()设置SysTick时钟源。

4、调用SysTick_SetReload()设置SysTick重装载值。

5、调用SysTick_ITConfig()    使能SysTick中断

6、调用SysTick_CounterCmd()开启SysTick计数器

下面部分我们分别来介绍这几个库函数。

5.2库函数介绍

5.2.1函数SysTick_CLKSourceConfig

SysTick_CLKSourceConfig函数,其功能为设置SysTick时钟源。

表5-2-1.描述了函数SysTick_CLKSourceConfig

函数名

SysTick_CLKSourceConfig

函数原形

voidSysTick_CLKSourceConfig(u32SysTick_CLKSource)

功能描述

设置SysTick时钟源

输入参数

SysTick_CLKSource:

SysTick时钟源

输出参数

返回值

先决条件

被调用函数

表5-2-2列举了SysTick_CLKSource参数允许取值范围

表5-2-2SysTick_CLKSource值

SysTick_CLKSource参数可取的值

描述

SysTick_CLKSource_HCLK_Div8

SysTick时钟源为AHB时钟除以8

SysTick_CLKSource_HCLK

SysTick时钟源为AHB时钟

例:

设置系统定时器时钟为AHB时钟

SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);

5.2.2函数SysTick_SetReload

函数SysTick_SetReload的功能为设置SysTick重装载值。

表5-2-3描述了函数SysTick_SetReload

函数名

SysTick_SetReload

函数原形

voidSysTick_SetReload(u32Reload)

功能描述

设置SysTick重装载值

输入参数

Reload:

重装载值,该参数取值必须在1和0x00FFFFFF之间

输出参数

返回值

先决条件

被调用函数

例:

设定系统定时器的重载值为90000

SysTick_SetReload(90000);

5.2.3函数SysTick_CounterCmd

函数SysTick_CounterCmd的功能为使能或者失能SysTick计数器

表5-2-4.描述了函数SysTick_CounterCmd

函数名

SysTick_CounterCmd

函数原形

voidSysTick_CounterCmd(u32SysTick_Counter)

功能描述

使能或者失能SysTick计数器

输入参数

SysTick_Counter:

SysTick计数器新状态

输出参数

返回值

先决条件

被调用函数

表5-2-5列举了SysTick_Counter参数可取的值。

表5-2-5.SysTick_Counter值

SysTick_Counter参数可取的值

描述

SysTick_Counter_Disable

失能计数器

SysTick_Counter_Enable

使能计数器

SysTick_Counter_Clear

清除计数器值为0

例:

使能系统定时器

SysTick_CounterCmd(SysTick_Counter_Enable);

5.2.4函数SysTick_ITConfig

函数SysTick_ITConfig的功能是使能或者失能SysTick中断。

表5-2-6.描述了函数SysTick_ITConfig

函数名

SysTick_ITConfig

函数原形

voidSysTick_ITConfig(FunctionalStateNewState)

功能描述

使能或者失能SysTick中断

输入参数

NewState:

SysTick中断的新状态,这个参数可以取:

ENABLE或者DISABLE

输出参数

返回值

先决条件

被调用函数

例:

使能系统定时器中断

SysTick_ITConfig(ENABLE);

5.2.5函数SysTick_GetCounter

函数SysTick_GetCounter的功能是获取SysTick计数器的值。

表5-2-7描述了函数SysTick_GetCounter

函数名

SysTick_GetCounter

函数原形

u32SysTick_GetCounter(void)

功能描述

获取SysTick计数器的值

输入参数

输出参数

返回值

SysTick计数器的值

先决条件

被调用函数

例:

获取系统定时器的计数值

u32SysTickCurrentCounterValue;

SysTickCurrentCounterValue=SysTick_GetCounter();

5.3节拍定时器试验1—嘀嗒实例

5.3.1实验要求

利用节拍定时器,每10毫秒中断一次,每500毫秒跳变一次LED8。

5.3.2软件结构

在程序中,需要初始化节拍定时器,使节拍定时器每10ms重载一次,并开启节拍定时器中断。

在中断程序中,每进入一次中断,让一计数变量加1,然后判断是否有50次,如果有50次,则跳变一下LED8灯,同时把计数变量清0。

这样程序运行时LED8灯就不停地闪烁。

图5-3-1是程序的流程图。

图5-3-1软件流程图

5.3.3实例代码

以队列收发数据为基础,来进行添加。

首先创建E:

\OpenM3V开发板测试程序\SysTick\sys_delay文件夹,把E:

\OpenM3V开发板测试程序\USART\USART3文件夹中的工程,复制到E:

\OpenM3V开发板测试程序\SysTick\sys_delay文件夹中,,编译下载,看程序复制是否正确,这一步很关键,在作任何更改前,必须验证前一步的正确和完整性。

对其的态度是,宁愿认为其是错误的,也不要去假设它是正确的。

所有正确的东西,必须要实际测试后才能确定。

有时看似麻烦的东西,却能节省好多时间和精力,并给我们对下一步的信心。

验证通过后,点击

图标,在编辑对话框中出现一个新的空白文档,在这个文档中加入以下这部分内容,然后点击存盘,文件保存在本工程文件所在地文件夹中,命名为systic.c。

这个文件中,存放系统定时器初始化有关的所有程序代码和函数。

同时把这个文件加入到文件组USER中。

下面是systic.c文件中系统定时器初始化的程序清单:

#include"stm32f10x_lib.h"

unsignedcharsys_nub;//系统定时器中断计数变量

//SysTick设置

voidSysTick_Config(void)

{

//失能SysTick定时器

SysTick_CounterCmd(SysTick_Counter_Disable);

//失能SysTick中断

SysTick_ITConfig(DISABLE);

//设置SysTick时钟源

SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);

//设置SysTick重载值,10ms重载一次,在72Mhz时钟下

SysTick_SetReload(90000);

//开SysTick中断

SysTick_ITConfig(ENABLE);

//开SysTick定时器

SysTick_CounterCmd(SysTick_Counter_Enable);

}

点击

图标,在编辑对话框中出现一个新的空白文档,在这个文档中加入以下这部分内容,然后点击存盘,文件保存在本工程文件所在地文件夹中,命名为systic.h。

voidSysTick_Config(void);

externunsignedcharsys_nub;

在stm32f10x_it.c文件中,加入头函数systic.h,在系统中断定时器中断函数voidSysTickHandler(void)中加入以下程序代码:

voidSysTickHandler(void)

{

sys_nub++;//系统定时器中断计数变量加1

if(sys_nub>49)//计数到50时

{

sys_nub=0;//清0计数变量

LED8B();//跳转LED8灯

}

}

在主函数中加入头文件systic.h,并加入系统定时器初始化函数SysTick_Config()。

程序代码分析:

在main函数中,首先启动时钟和初始化嵌套向量中断控制器(NVIC),然后再调用I/O口、串口系统定时器初始化函数。

在系统定时器中断中计数中断次数,当达到50次时,跳转LED8灯。

5.3.4编译下载和调试

通过Project\RebuildAll命令进行编译。

编译通过后,在其工程文件夹下Debug\Exe目录下有一个.HEX后缀的文件,此为可执行文件,使用ST提供的下载工具,以ISP方式把程序下载到芯片中。

复位系统,可以看到LED8每秒钟闪烁一次。

打开串口调试助手,可以看到,PC机发送什么数据,串口也能接收到相同的数据。

 

5.4有实际应用意义的键盘实例

5.4.1实验要求

有了这个节拍定时器实验后,回过头来看前面的按键和串口还有LED灯,下面来做一个把三者结合起来的实验。

实验设计要求是,实现真正的按键功能,每按一次键,系统只识读一次,而不管按多长时间。

前面讲叙的按键识别没有进行防抖处理,在这里,使用系统定时器,来实现键盘防抖功能。

具体要求是:

每按K1键一次,LED1灯翻转一次,同时通过串口1发送0X31这个数据;每按K2键一次,LED2灯翻转一次,同时通过串口发送0X32这个数据;……每按K7键一次,LED7灯翻转一次,同时通过串口1发送0X37这个数据。

5.4.2软件结构

在这个键盘扫描程序的逻辑有点复杂,可以利用串口,把中间变量传出来,查看程序的流程和变量的值,方便调试,找出错误所在。

在这本书中,对于程序的调试,没有使用仿真器调试的方法,使用的是用LED灯指示程序的运行状态,用串口输出程序中的中间变量和过程变量。

这种方法,跟实际的运行结果一样,只是在最终版本中,把串口输出和LED指示部分注销就行,不必做任何的更改,同时能很好的观察到中断的运行情况,也能把程序运行的事件状况如实的表现出来。

由于stm32f10x系列的芯片的FLASH可以烧写上千次(现在的FLASH基本都能达到上千次的烧写),使得我们每次改动都能下载验证,而不必担心FLASH会很快烧坏。

这样对于学习单片机的费用就大大减少,不需要昂贵的仿真器,只需要一个根串口线就可以了。

回到这个实例上来,这个键盘处理逻辑比较复杂。

当一个键按下后,首先要判断是否有键按下,还要判断这个键是否处理过,还要判读是否延时过,只有经过这些判读处理后才能真正实现我们所要的功能。

图5-4-1是键盘扫描的流程图。

图5-4-1按键流程图

5.3.3实例代码

以嘀嗒实例为基础,来进行添加。

首先创建E:

\OpenM3V开发板测试程序\SysTick\key_usart文件夹,把E:

\OpenM3V开发板测试程序\SysTick\sys_delay文件夹中的工程,复制到E:

\OpenM3V开发板测试程序\SysTick\key_usart文件夹中,,编译下载验证,看程序复制是否正确,这一步很关键,在作任何更改前,必须验证前一步的正确和完整性。

在gpio.c文件中,加入键盘扫描函数和按键执行函数,具体函数如下:

voidkey1(void)

{

LED1B();

uart_trx[uart_rx]=0x31;

uart_rx++;

uart_rx&=0xf;

}

voidkey2(void)

{

LED2B();

uart_trx[uart_rx]=0x32;

uart_rx++;

uart_rx&=0xf;

}

voidkey3(void)

{

LED3B();

uart_trx[uart_rx]=0x33;

uart_rx++;

uart_rx&=0xf;

}

voidkey4(void)

{

LED4B();

uart_trx[uart_rx]=0x34;

uart_rx++;

uart_rx&=0xf;

}

voidkey5(void)

{

LED5B();

uart_trx[uart_rx]=0x35;

uart_rx++;

uart_rx&=0xf;

}

voidkey6(void)

{

LED6B();

uart_trx[uart_rx]=0x36;

uart_rx++;

uart_rx&=0xf;

}

voidkey7(void)

{

LED7B();

uart_trx[uart_rx]=0x37;

uart_rx++;

uart_rx&=0xf;

}

 

voidkey_work(void)

{unsignedcharkey_data;

key_data=GPIO_ReadInputData(GPIOE);//读取PE输入端口值

key_data&=0x7f

if(key_data<0x7F)//如果小于0X7F,说明有按键按下

{//LED2ON();//设置一个调试状态指示LED,有键按下亮。

if(!

(key_bit&0x02))//判断按键是否被处理,按键没有被处理,执行IF

{

if(key_bit&0x01)//如果已经延时了

{

key_bit&=~0x01;//清延时标志

key_bit|=0x02;//置位按键已处理标志

//uart_trx[uart_rx]=key_bit;//把标志变量功过串口传出来

//uart_rx++;

//uart_rx&=0x3f;

//uart_trx[uart_rx]=key_data;//把按键值通过串口传出来

//uart_rx++;

//uart_rx&=0x3f;

switch(key_data)

{

case0x7E:

key1();break;//调用key1()函数

case0x7D:

key2();break;//调用key2()函数

case0x7B:

key3();break;//调用key3()函数

case0x77:

key4();break;//调用key4()函数

case0x6F:

key5();break;//调用key5()函数

case0x5F:

key6();break;//调用key6()函数

case0x3F:

key7();break;//调用key7()函数

}

}

else//如果没有延时

{

key_bit|=0x04;//置位要延时标志

}

}

}

else//如果没有键按下,执行else

{

key_bit&=~0x07;//清所有的标志位

//LED2OFF();//无键按下LED灭。

}

}

在系统定时器中断中,加入相应的防抖程序代码,具体如下:

if(key_bit&0x04)//如果允许延时标志被置位的话

{

if(key_bit&0x80)//加入这个判断,只有当两次进入中断后才置位延时标志

{

key_bit|=0x01;//置位延时标志,表明经过延时

key_bit&=~0x04;//清允许延时标志位置位标志位

}

else//如果第7位没有置位,说明是第一次进入中断

{

key_bit|=0x80;//第一次进入时,把key_bit第7位置位。

}

}

在上面的程序中,加入了调试指示灯和中间变量输出部分。

里面有个非常关键的标志变量key_bit,在这个标志变量中,包含着许多信息,充分利用对不同位的判断来解析这些信息,为程序服务。

5.4.4编译下载和调试

通过Project\RebuildAll命令进行编译。

编译通过后,在其工程文件夹下Debug\Exe目录下有一个.HEX后缀的文件,此为可执行文件,使用ST提供的下载工具,以ISP方式把程序下载到芯片中。

复位系统,可以看到LED8每秒钟闪烁一次。

打开串口调试助手,可以看到,PC机发送什么数据,串口也能接收到相同的数据。

同时按K1键LED1灯跳变一次,同时串口有0X31数据输出(如果是ASC码方式,则输出为1),按其他键,则对应的LED等跳变,串口有相应的数据输出。

那么这个比较复杂的程序是不是一气写成的呢,答案是否定的。

下面把我写这个程序的过程向大家介绍一下。

把E:

\OpenM3V开发板测试程序\SysTick\sys_delay文件夹中的工程,复制到E:

\OpenM3V开发板测试程序\SysTick\key_usart文件夹中,下载到实验板中,灯是否闪烁,串口是否有数据输出。

由于需要用串口传出数据,所以串口功能的完善是必须保证的。

首先实现第一步目标是,有键按下时,LED1灯亮,松开时LED1灯灭,同时判断按键处理位,如果没有被处理,则让LED2跳转一次,并置位按键处理标志位。

这样只要按键被处理标志位置位就不会来跳转LED2灯,达到一次按键只处理一次的结果。

具体程序如下:

key_data=GPIO_ReadInputData(GPIOE);//读取PE输入端口值

key_data&=0x7f

if(key_data<0x7F)//如果小于0X7F,说明有按键按下

{

LED1ON();//LED1灯亮

if(!

(key_bit&0x02))//如果按键没有被处理

{

LED2B();//跳转LED2灯

key_bit|=0x02;//置按键处理标志

}

}

else

{

LED1OFF();//LED1灯灭

}

编译下载后,发现按下键后LED1灯亮,松手后就灭。

但不论按多少次,LED2灯就翻转一次。

程序哪里出问题了,很显然,程序没有执行if(!

(key_bit&0x02))语句下的内容,在这条语句前加上串口输出部分,把key_bit的值传出来看看,是什么内容。

加上以下语句。

uart_trx[uart_rx]=key_bit;//把数据写入串口队列中

uart_rx++;

uart_rx&=0x3f;

编译下载,打开串口调试软件,设置成38400,8,N,1,16进制显示,清空接收区域。

连接好串口线,打开实验板电源,按下任一键,可以看到串口出来一大串数据,LED1灯亮,LED2灯跳转一次,松开按键,LED1灯灭,串口也没有数据输出,在串口调试软件接收区,发现满篇都是0X02,我们找到数据头,发现第一个数据是0x00。

扫描多少次键盘,就有多少个串口数据输出。

我们把PC机上的串口调试软件的接收区域清零,然后再按一下任意键,当然LED1灯会亮,松手就灭,可LED2灯不跳转。

我们来看看输出的数据,全为0X02,找到第一个,也是0X02。

也就是说,在这次扫描过程中,按键程序把这次按下的键当作已经处理过。

问题出在哪,出在当松按键时,我们没有及时的清零按键处理标志位。

在else语句中加上以下这句就行了。

key_bit&=~0x02;//清零按键处理标志

编译下载,上面的BUG没有了,程序能按照我们设想去运行了。

在这里我们充分的利用了LED指示灯和中间变量的输出,来分析程序问题。

当然用仿真器单步或断点也会很快找出问题,只是仿真器调试的速度不一定有这里所介绍方法快。

首先我们使用LED2后,可以发现问题,同时可以判断程序错在哪,找出问题在哪,这就解决了一半的问题。

接下来,加入按键的延时防抖部分,思路是,利用系统定时器溢出间隔中断来延时防抖,这样就提高了程序的运行效率,不会在按键程序中死等20MS。

怎样才能很好的利用这个系统定时器来延时呢,如果只是简单在系统定时器中断中置位延时标志位的话,就没有任何意义。

必须得有一个标志位,来允许置延时标志。

第一次扫描到有按键按下时,延时标志肯定为空,那么我们在此置位一个标志位,来允许系统定时器中置位延时标志,这样就解决了这个问题。

软件的逻辑结构是:

如果没有延时,则置位允许延时标志置位标志(这句话有点拗口)。

可以这样理解,首先是置位标志位,那么这个标志位是干什么的呢,如果它置位的话,在系统定时器溢出中断中,就可以置位延时标志位,有点向指向指针的指针的意识。

如果已经延时,处理按键值。

下面这段程序加入了对延时标志判断的处理

if(!

(key_bit&0x02))//如果按键没有被处理

{

if(key_bit&0x01)//如果已经延时了

{

key_bit&=~0x01;//清延时标志位

LED2B();//跳转LED2灯

key_bit|=0x02;//置按键处理标志

}

else//如果没有被延时

{

key_bit|=0x04;//置位允许延时标志位置位标志位

}

}

系统定时器中断函数中加入这句话就行

if(key_bit&0x04)

{

key_bit|=0x01;//置位延时标志,表明经过延时

key_bit&=~0x04;//清允

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1