本帖最后由 刘洋讲单片机 于 2017-1-11 14:47 编辑
第17讲.STM8定时器.zip
(438.55 KB)
众拳【剑齿虎STM8】开发板学习笔记分享
点击此处查看全部资料
第17讲 STM8(TIM1)定时器
目 录
17.1概述 2
17.1.1 定时器特点 3
17.1.2 TIM1功能特点 3
17.1.3 TIM1预分频器的实现 3
17.1.4 向上计数模式 4
17.1.5 向下计数模式 5
17.1.6 中央对齐模式( 向上/ 向下计数) 5
17.1.7 定时器使用重点 5
17.2程序文件设计 6
17.2.1 lib文件中内容分析 6
17.2.2 main.c文件中的程序 7
17.2.3 tim.c文件中的程序 8
17.2.4 tim.h文件中的程序 9
17.2.5 stm8s_it.c文件中的程序 9
17.2.6 led.c文件中的程序 9
17.2.7 led.h文件中的程序 11
17.1概述
STM8S提供三种类型的TIM定时器:高级控制型(TIM1)、通用型(TIM2/TIM3/TIM5)和基本型定时器(TIM4/TIM6)。它们虽有不同功能但都基于共同的架构。此共同的架构使得采用各个定时器来设计应用变得非常容易与方便(相同的寄存器映射,相同的基本功能)。
17.1.1 定时器特点
TIM1—16位高级控制定时器
TIM2,TIM3—16位通用定时器
TIM4—8位基本定时器
17.1.2 TIM1功能特点
这是一个为广范围控制应用而设计的高端定时器,带有互补输出、死区控制和中心对齐的PWM功能,这个领域的应用包括马达控制、照明和半桥驱动等。
● 带有16位预分频的16位递增、递减和双向(递增/递减) 自动重载计数器
● 4个独立的捕获/比较通道(CAPCOM),可配置成输入捕获、输出比较、PWM产生(边沿或中心对齐模式)和单脉冲模式输出。
● 用来控制带有外部信号的定时器的同步模式
● 强制定时器输出进入预定状态的Break输入
● 可调整死区时间3个互补输出
● 编码器模式
● 中断源:3个输入捕获/输出比较中断,1个溢出/更新中断,1个break中断
17.1.3 TIM1预分频器的实现
TIM1的预分频器基于一个由16位寄存器(TIM1_PSCR)控制的16位计数器。由于这个控制寄存器带有缓冲器,因此它能够在运行时被改变。预分频器可以将计数器的时钟频率按1到65536之间的任意值分频。
计数器的频率可以由下式计算:
fCK_CNT=fCK_PSC/(PSCR[15:0]+1)
预分频器的值由预装载寄存器写入,保存了当前使用值的影子寄存器在低位(LS)写入时被载入。
需两次单独的写操作来写16位寄存器,高位(MS)先写。不要使用先写低位(LS)的LDW指令。
新的预分频器的值在下一次更新事件到来时被采用。
对TIM1_PSCR寄存器的读操作通过预装载寄存器完成,因此不需要特别的关注。
17.1.4 向上计数模式
在向上计数模式中,计数器从0计数到用户定义的比较值(TIMx_ARR寄存器的值),然后重新从0开始计数并产生一个计数器溢出事件,同时,如果TIM1_CR1寄存器的UDIS位是0,将会产生一个更新事件(UEV)。
置位TIMx_EGR寄存器的UG位(通过软件方式或者使用从模式控制器)也同样可以产生一个更新事件。
使用软件置位TIMx_CR1寄存器的UDIS位,可以禁止更新事件,这样可以避免在更新预装载寄存器时更新影子寄存器。在UDIS位被清除之前,将不产生更新事件。但是在应该产生更新事件时,计数器仍会被清0,同时预分频器的计数也被清0(但预分频器的数值不变)。此外,如果设置了TIMx_CR1寄存器中的URS位(选择更新请求),设置UG位将产生一个更新事件UEV,但硬件不设置UIF标志(即不产生中断请求)。这是为了避免在捕获模式下清除计数器时,同时产生更新和捕获中断。
当发生一个更新事件时,所有的寄存器都被更新,硬件同时(依据URS位)设置更新标志位(TIMx_SR寄存器的UIF位):
自动装载影子寄存器被重新置入预装载寄存器的值(TIMx_ARR)。
预分频器的缓存器被置入预装载寄存器的值(TIMx_PSC寄存器的内容)。
17.1.5 向下计数模式
在向下模式中,计数器从自动装载的值(TIMx_ARR寄存器的值)开始向下计数到0,然后再从自动装载的值重新开始计数,并产生一个计数器向下溢出事件。如果TIM1_CR1寄存器的UDIS位被清除,还会产生一个更新事件(UEV)。
17.1.6 中央对齐模式( 向上/ 向下计数)
在中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)-1,产生一个计数器溢出事件,然后向下计数到0并且产生一个计数器下溢事件;然后再从0开始重新计数。
装载
17.1.7 定时器使用重点
1.预分频值;
2.计数模式,三种模式选择;
3.自动重装载值;
4.重复计数器值;
5.中断入口;
17.2程序文件设计
17.2.1 lib文件中内容分析
我们建立一个“Lib”文件夹,把引用系统本身定义好的库函数添加在其中,我们使用到哪个外设功能,直接引用到此文件夹中即可。一般情况下下面这四个文件都得引用。
图17.1 stm8s_conf.h头文件内部选择
本节实验及以后的实验我们都是用到库文件,其中 stm8s_conf.h头文件包含了所有外设的声明头文件,在本试验中我们使用到时钟外设和GPIO端口外设。所以#include "stm8s_clk.h"、#include "stm8s_tim1.h"和#include "stm8s_gpio.h"需要“打开”(就是把语句前面的双斜线注释符号删除即可,参考图17.1)。Stm8s_gpio.c库函数包含了所有管脚初始化功能和具体的执行操作;Stm8s_clk.c库函数主要包含了内部时钟和外部时钟设置,在主函数中规定了具体的执行方法,在这个函数中就有具体相关的执行步骤;Stm8s_tim1.c库函数主要包含了定时器1相关寄存器设置和tim1库函数具体执行过程。
17.2.2 main.c文件中的程序
主程序就实现初始化和调用驱动程序,这样主程序控制思路清晰,流程简单。要想了解全面详实的程序,请大家参考光盘(网盘)中程序及程序注释。
/***********************************************************************
* 说 明: STM8定时器
* 开发平台: 剑齿虎STM8开发板
* 关注微信公众平台微信号:"zxkj-ly",免费获取STM8资料。
* STM8技术交流QQ群【335123291】
* 哈尔滨卓恩科技开发有限公司
*
* 作 者: 刘洋 张殿东
* 版 本: V1.0
* 日 期: 2016-05-03
*
* IAR开发环境 版本 V2.20.1
* ST库函数 版本 V2.2.0
***********************************************************************/
#include "pbdata.h"//引入自定义公共头文件
void BSP_Configuration(void);//硬件初始化函数声明
/***********************************************************************
* 函 数 名: main
* 功能说明: c程序入口
* 形 参:无
* 返 回 值: 错误代码(无需处理)
***********************************************************************/
int main(void)
{
BSP_Configuration();//硬件驱动初始化函数
while(1)//主程序循环,反复执行循环体里的语句
{
}
}
/***********************************************************************
* 函 数 名: BSP_Configuration
* 功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
* 形 参:无
* 返 回 值: 无
***********************************************************************/
void BSP_Configuration(void)
{
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//时钟速度为内部16M,1分频,
LED_Init();//调用LED初始化函数
Tim1_Init();
rim();//打开总中断
}
/*断言函数:它的作用是在编程的过程中为程序提供参数检查*/
#ifdef USE_FULL_ASSERT
void assert_failed(u8* file,u32 line)
{
while(1)
{
}
}
#endif
17.2.3 tim.c文件中的程序
#include "pbdata.h"
/**************************************************************************
* 函 数 名: Tim1_Init
* 功能说明: 初始化高级定时器1
* 形 参:无
* 返 回 值: 无
**************************************************************************/
void Tim1_Init(void)
{
TIM1_TimeBaseInit(15,TIM1_COUNTERMODE_UP,1000,0);//初始化定时器1
TIM1_ARRPreloadConfig(ENABLE);//使能自动重装
TIM1_ITConfig(TIM1_IT_UPDATE , ENABLE);//数据更新中断
TIM1_Cmd(ENABLE);//开定时器
}
17.2.4 tim.h文件中的程序
#ifndef _TIM_H//宏定义,定义文件名称
#define _TIM_H
#include "stm8s.h"
/*--------------------------函数声明--------------------------------*/
void Tim1_Init(void);//初始化定时器1
17.2.5 stm8s_it.c文件中的程序
中断和中断处理子程序建立关系必须在stm8s_it.c文件中对应位置中建立。关于定时器1的中断处理子程序要写在事先定义好的入口之内。“INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11)”,所以中断处理子程序入口地址必须放在TIM1中断处理中,请看下面程序语句。
INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11)
{
static u16 i=0; //定义变量 i 类型为 u16 static 定义了 变量i的生存周期
if(i<1000)//判断 i当前的数值是否小于1000
{
i++;//计数器 i 加1 也可以写成 i=i+1;
}
else//如果大于等于100 执行下面这个分支
{
i=0;//计数器 i 清零
LED1_R;//PE0引脚电平取反,高电平时LED1发光二极管(熄灭),底电平时LED1发光二极管(发光)
LED2_R;//PA3引脚电平取反,高电平时LED2发光二极管(熄灭),底电平时LED2发光二极管(发光)
LED3_R;//PA6引脚电平取反,高电平时LED3发光二极管(熄灭),底电平时LED3发光二极管(发光)
}
TIM1_ClearITPendingBit(TIM1_IT_UPDATE);//清除更新标志位
}
17.2.6 led.c文件中的程序
#include "pbdata.h"
/***************************************************************************
* 函 数 名: LED_Init
* 功能说明: LED的GPIO管脚初始化
* 形 参:无
* 返 回 值: 无
***************************************************************************/
void LED_Init(void)
{
GPIO_Init(LED1_PORT, LED1_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);//初始化LED1管脚为低速开漏输出高阻态
GPIO_Init(LED2_PORT, LED2_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);//初始化LED2管脚为低速开漏输出高阻态
GPIO_Init(LED3_PORT, LED3_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);//初始化LED3管脚为低速开漏输出高阻态
}
/***************************************************************************
* 函 数 名: LED_Demo1
* 功能说明: 闪烁例程,间隔时间为1秒。
* 形 参:无
* 返 回 值: 无
***************************************************************************/
void LED_Demo1(void)
{
LED1_L;//拉低PE0引脚,LED1发光二极管(发光)
LED2_L;//拉低PA3引脚,LED2发光二极管(发光)
LED3_L;//拉低PA6引脚,LED3发光二极管(发光)
delay_ms(1000);//延时1秒
LED1_H;//拉高PE0引脚,LED1发光二极管(熄灭)
LED2_H;//拉高PA3引脚,LED2发光二极管(熄灭)
LED3_H;//拉高PA6引脚,LED3发光二极管(熄灭)
delay_ms(1000);//延时1秒
}
/***************************************************************************
* 函 数 名: LED_Demo2
* 功能说明: 闪烁例程,间隔时间为1秒。
* 形 参:无
* 返 回 值: 无
***************************************************************************/
void LED_Demo2(void)
{
LED1_R;//PE0引脚电平取反,高电平时LED1发光二极管(熄灭),底电平时LED1发光二极管(发光)
LED2_R;//PA3引脚电平取反,高电平时LED2发光二极管(熄灭),底电平时LED2发光二极管(发光)
LED3_R;//PA6引脚电平取反,高电平时LED3发光二极管(熄灭),底电平时LED3发光二极管(发光)
delay_ms(1000);//延时1秒
}
17.2.7 led.h文件中的程序
/***********************************************************************
* 剑齿虎STM8开发板硬件连接
* LED1-PE0
* LED2-PA3
* LED3-PA6
************************************************************************/
#ifndef _LED_H //宏定义,定义文件名称
#define _LED_H
/*---------------------------头文件引用--------------------------------------*/
#include "stm8s.h"//引用STM8头文件
/*---------------------------宏定义声明--------------------------------------*/
#define LED1_PIN GPIO_PIN_0 //定义GPIO_PIN_0引脚为LED1_PIN,相当于重新命名。
#define LED2_PIN GPIO_PIN_3 //定义GPIO_PIN_3引脚为LED2_PIN,相当于重新命名。
#define LED3_PIN GPIO_PIN_6 //定义GPIO_PIN_6引脚为LED3_PIN,相当于重新命名。
#define LED1_PORT GPIOE //定义GPIOE端口为LED1_PORT,相当于重新命名。
#define LED2_PORT GPIOA //定义GPIOA端口为LED2_PORT,相当于重新命名。
#define LED3_PORT GPIOA //定义GPIOA端口为LED3_PORT,相当于重新命名。
//如果想用其他管脚控制LED,那么只需更改上面对应的端口与引脚编号即可
#define LED1_L GPIO_WriteLow(LED1_PORT,LED1_PIN); //定义LED1_L,调用LED1_L命令,PE0引脚输出低电平
#define LED1_H GPIO_WriteHigh(LED1_PORT,LED1_PIN); //定义LED1_H,调用LED1_H命令,PE0引脚输出低高平
#define LED1_R GPIO_WriteReverse(LED1_PORT,LED1_PIN); //定义LED1_R,调用LED1_R命令,PE0引脚输出电平状态取反
#define LED2_L GPIO_WriteLow(LED2_PORT,LED2_PIN); //定义LED2_L,调用LED2_L命令,PA3引脚输出低电平
#define LED2_H GPIO_WriteHigh(LED2_PORT,LED2_PIN); //定义LED2_H,调用LED2_H命令,PA3引脚输出低高平
#define LED2_R GPIO_WriteReverse(LED2_PORT,LED2_PIN); //定义LED2_R,调用LED2_R命令,PA3引脚输出电平状态取反
#define LED3_L GPIO_WriteLow(LED3_PORT,LED3_PIN); //定义LED3_L,调用LED2_L命令,PA6引脚输出低电平
#define LED3_H GPIO_WriteHigh(LED3_PORT,LED3_PIN); //定义LED3_H,调用LED2_H命令,PA6引脚输出低高平
#define LED3_R GPIO_WriteReverse(LED3_PORT,LED3_PIN); //定义LED3_R,调用LED2_R命令,PA6引脚输出电平状态取反
/*---------------------------函数声明--------------------------------------*/
void LED_Init(void); //LED初始化函数
void LED_Demo1(void); //闪烁例程1,间隔时间为1秒
void LED_Demo2(void); //闪烁例程2,间隔时间为1秒
#endif //定义文件名称结束
|