第一步:TIM1概述
STM8S提供三种类型的 TIM 定时器:高级控制型(TIM1)、通用型(TIM2/TIM3/TIM5)和基本型定时器(TIM4/TIM6)。它们虽有不同功能但都基于共同的架构。此共同的架构使得采用各个定时器来设计应用变得非常容易与方便(相同的寄存器映射,相同的基本功能)。STM8S系列的定时器TIM1,TIM5和TIM6之间没有共享任何资源,但是它们可以TIM5/TIM6定时器的同步中的描述来同步和连接。在拥有TIM1,TIM2,TIM3和TIM4定时器的STM8S系列产品中,定时器是没有连接在一起的。
可以看到TIM1是可以向上、向下、向上/向下自动装载的。分频系数为1~65535之间的任意数值。
预分频器的实现:
TIM1 的预分频器基于一个由16位寄存器(TIM1_PSCR)控制的16位计数器。由于这个控制寄存器带有缓冲器,因此它能够在运行时被改变。预分频器可以将计数器的时钟频率按1 到65536之间的任意值分频。计数器的频率可以由下式计算:fCK_CNT = fCK_PSC / (PSCR[15:0] + 1)。
预分频器的值由预装载寄存器写入,保存了当前使用值的影子寄存器在低位(LS)写入时被载入。需两次单独的写操作来写16位寄存器,高位(MS)先写。不要使用先写低位(LS)的LDW指令。新的预分频器的值在下一次更新事件到来时被采用。
对TIM1_PSCR寄存器的读操作通过预装载寄存器完成,因此不需要特别的关注。
第二步:配置TIM1
stm8的定时器属于stm8的一个外设,其时钟可以单独开启和关闭。我们需要使用TIM1,只需要把第七位置1即可。
由于系统主时钟选择的是HSI 8分频,即2MHz,所以TIM1计数器的频率可以由下式计算:fCK_CNT = fCK_PSC / (PSCR[15:0] + 1)。
向上计数时,当计数器从0计数到TIM1_ARR时,产生溢出。
第三步:具体实现
/*定时时间 = (TIM1_ARRL + 1) * 10ms */ void Timer1_init(void) { CLK_PCKENR1 |= 0x80; //打开TIM1时钟 = Fmaster = 2MHz asm("sim"); // 关全局中断 TIM1_PSCRH = 0x4E; TIM1_PSCRL = 0x20; //时钟20000分频,2MHz/20000 = 100Hz = 10ms TIM1_ARRH=0; //自动重装载 TIM1_ARRL=9; TIM1_IER |= 0X01; //允许更新中断 TIM1_EGR |= 0x01; //产生更新事件 TIM1_CR1 |= 0x01; //开计数器 asm("rim"); // 开全局中断 是不是像51里面的EA = 1;O(∩_∩)O~ } 好了下面开始编写主函数和中断服务函数了。 int main( void ) { System_Init(); Gpio_Init(); Timer1_init(); //100ms中断一次 while (1); } #pragma vector=TIM1_OVR_UIF_vector //0x0D __interrupt void TIM1_OVF_IRQHandler(void) { TIM1_SR1=0x00; //清除中断标志位 该位由软件清零 PE_ODR^=0x20; //PE5取反 }
打开头文件IOSTM8S105K4.h,在第4637行找到stm8的中断向量号Interrupt vector numbers;我们可以看见TIM1_OVR_UIF_vector中断向量号是0x0D。
我们看到TIM1的溢出中断向量号是11,这里的0x0D是13,为什么?我们再看上图表16中断映射表,里面的复位和软件中断是没有中断向量号的,IAR已经处理了,,要依次+2,所以这里我们使用的是0x0D 。