STM8S903K3基于ST Visual Develop开发定时器1中断示例

STM8S903K3基于ST Visual Develop开发定时器1中断示例


  • 🎉在基于STVP环境下和IAR环境下,如果都使用寄存器操作,那么差异不大,主要在中断函数的书写上有差异。

📝本示例基于定时器1定时,产生中断来控制闪烁间隔时间,led引脚在PD7上。

📋定时器配置基本步骤

  1. 配置定时器工作模式以及系统时钟频率。
  2. 配置定时器中断。
  3. 时钟分频系数设置。
  4. 计数值上限设置。
  5. 开启计数器。

🚩重装载值说明

如果是基于STVD寄存器开发,那么在写重装载寄存器的值时推荐将高低寄存器分开写,具体为什么,可以查看头文件寄存器地址具体位置就可以知道。

	TIM5_ARRH = 0x00; // 自动重载寄存器ARR=0x007c
   TIM5_ARRL = 0x7c; // 每1ms中断一次
TIM5_ARR = 0x7c;//自动重装的值,变成了每隔524ms一次了达不到预期。
  • 头文件寄存器地址:

例如TIM5重装载寄存器,的高8位寄存器的地址和TIM5_ARR是相同的,如果直接赋值那相当于将重装载值直接赋值给了高8位的寄存器TIMx_ARRH。这一点特别需要注意!

/* TIM5 Auto-reload register */
DEF_16BIT_REG_AT(TIM5_ARR,0x530f);
/* Data bits High */
DEF_8BIT_REG_AT(TIM5_ARRH,0x530f);
/* Data bits Low */
DEF_8BIT_REG_AT(TIM5_ARRL,0x5310);
  • ⚡TIM1也是如此
/* TIM1 Auto-reload register */
DEF_16BIT_REG_AT(TIM1_ARR,0x5262);
/* Data bits High */
DEF_8BIT_REG_AT(TIM1_ARRH,0x5262);
/* Data bits Low */
DEF_8BIT_REG_AT(TIM1_ARRL,0x5263);

🌼示例一

🔖使用外部8MHz时钟源定时,500ms,让PD7引脚led状态翻转。

#include"stm8s903k3.h"
unsigned char i=0;

void Init_Timer1(void)
{
	CLK_ECKR = 0x01; //开启外部时钟寄存器
  CLK_SWR = 0xb4; //HSE外部时钟源作为主时钟源
  CLK_CKDIVR = 0x00;//不分频
		TIM1_CR1=0x01;//enable 使能计数器
  //TIM1_IER=0x00;//disable TIMER
		TIM1_IER=0x01;//更新中断使能
		TIM1_EGR=0x01;
		TIM1_CNTR=255;//计数器值
		TIM1_ARR=255;//自动重装的值,相当于**TIM1_ARRH**高位是0xff
		TIM1_PSCR=0x07;//分频值:2^7=128分频;T=128/8MHz=16us,16us*255*122=500ms

}
void Init_GPIO(void)
{
		PD_DDR |=0x80;
	  PD_CR1 |=0x80;
	  PD_CR2 |=0x00;
}
void main()
{
	
	Init_GPIO();
	Init_Timer1();
	_asm("rim");

	while (1);
}

@far @interrupt void TIM1_UPD_OVF_IRQHandler (void)
{
      i++;
      TIM1_SR1=0x00;// 清除更新中断标记,这步不能漏掉
      if(i==122)
      {
					PD_ODR ^= 0x80;
					i=0;
      }
      return;
}


  • 📈逻辑分析仪采集的波形
    在这里插入图片描述

🌻示例二

🍁使用内部16MHz时钟源,定时1s,,让PD7引脚led状态翻转。

/* MAIN.C file
 * 
 * Copyright (c) 2002-2005 STMicroelectronics
 */
#include"stm8s903k3.h"
unsigned char i=0;

void Init_Timer1(void)
{
//	CLK_ECKR = 0x01; //开启外部时钟寄存器
//  CLK_SWR = 0xb4; //HSE外部时钟源作为主时钟源
//  CLK_CKDIVR = 0x00;//不分频
  CLK_ICKR |= 0X01; //使能内部高速时钟 HSI
     CLK_CKDIVR = 0x08; // 2分频
    while(!(CLK_ICKR&0x02)); //HSI准备就绪
      CLK_SWR =0xE1;//HSI内部时钟源作为主时钟源(复位值)  
       
  //TIM1_IER=0x00;//disable TIMER
  CLK_PCKENR1 |=0x80; //外设时钟门控寄存器
		TIM1_EGR=0x01;//计数器更新,可省略
		TIM1_PSCR=0x07;//分频值:8
		TIM1_CNTR=255;//计数器值
		TIM1_ARR=255;//自动重装的值
		TIM1_CR1=0x01;//enable 使能计数器
		TIM1_IER=0x01;//更新中断使能

}
void Init_GPIO(void)
{
	  PD_DDR |=0x80;
	  PD_CR1 |=0x80;
	  PD_CR2 |=0x00;
}
void main()
{
	_asm("sim");    //disable all interrupt
	Init_GPIO();
	Init_Timer1();
	_asm("rim");//enable all interrupt

	while (1);
}

@far @interrupt void TIM1_UPD_OVF_IRQHandler (void)
{
      i++;
      TIM1_SR1=0x00;// 清除更新中断标记,这步不能漏掉
      if(i==122)
      {
					PD_ODR ^= 0x80;
					i=0;
      }
      return;
}


  • 📈逻辑分析仪采集的波形
    在这里插入图片描述

  • 两个示例中的stm8_interrupt_vector.c代码相同,都是采用的TIM1,中断号:11

typedef void @far (*interrupt_handler_t)(void);

struct interrupt_vector {
	unsigned char interrupt_instruction;
	interrupt_handler_t interrupt_handler;
};

@far @interrupt void NonHandledInterrupt (void)
{
	/* in order to detect unexpected events during development, 
	   it is recommended to set a breakpoint on the following instruction
	*/
	
	return;
}
extern @far @interrupt void TIM1_UPD_OVF_IRQHandler (void);
extern void _stext();     /* startup routine */

struct interrupt_vector const _vectab[] = {
	{0x82, (interrupt_handler_t)_stext}, /* reset */
	{0x82, NonHandledInterrupt}, /* trap  */
	{0x82, NonHandledInterrupt}, /* irq0  */
	{0x82, NonHandledInterrupt}, /* irq1  */
	{0x82, NonHandledInterrupt}, /* irq2  */
	{0x82, NonHandledInterrupt}, /* irq3  */
	{0x82, NonHandledInterrupt}, /* irq4  */
	{0x82, NonHandledInterrupt}, /* irq5  */
	{0x82, NonHandledInterrupt}, /* irq6  */
	{0x82, NonHandledInterrupt}, /* irq7  */
	{0x82, NonHandledInterrupt}, /* irq8  */
	{0x82, NonHandledInterrupt}, /* irq9  */
	{0x82, NonHandledInterrupt}, /* irq10 */
	{0x82, TIM1_UPD_OVF_IRQHandler}, /* irq11 */
	{0x82, NonHandledInterrupt}, /* irq12 */
	{0x82, NonHandledInterrupt}, /* irq13 */
	{0x82, NonHandledInterrupt}, /* irq14 */
	{0x82, NonHandledInterrupt}, /* irq15 */
	{0x82, NonHandledInterrupt}, /* irq16 */
	{0x82, NonHandledInterrupt}, /* irq17 */
	{0x82, NonHandledInterrupt}, /* irq18 */
	{0x82, NonHandledInterrupt}, /* irq19 */
	{0x82, NonHandledInterrupt}, /* irq20 */
	{0x82, NonHandledInterrupt}, /* irq21 */
	{0x82, NonHandledInterrupt}, /* irq22 */
	{0x82, NonHandledInterrupt}, /* irq23     */
	{0x82, NonHandledInterrupt}, /* irq24 */
	{0x82, NonHandledInterrupt}, /* irq25 */
	{0x82, NonHandledInterrupt}, /* irq26 */
	{0x82, NonHandledInterrupt}, /* irq27 */
	{0x82, NonHandledInterrupt}, /* irq28 */
	{0x82, NonHandledInterrupt}, /* irq29 */
};

示例二效果方式二(推荐)

与上面的主要的差异在于将分配寄存器进行高8位低8位进行了拆解。

#include"stm8s903k3.h"
void Init_Timer1(void)
{
//	CLK_ECKR = 0x01; //开启外部时钟寄存器
//  CLK_SWR = 0xb4; //HSE外部时钟源作为主时钟源
//  CLK_CKDIVR = 0x00;//不分频
  CLK_ICKR |= 0X01; //使能内部高速时钟 HSI
     CLK_CKDIVR = 0x08; // 16M,2分频后8MHz
    while(!(CLK_ICKR&0x02)); //HSI准备就绪
      CLK_SWR =0xE1;//HSI内部时钟源作为主时钟源(复位值)  
			
  //TIM1_IER=0x00;//disable TIMER
		CLK_PCKENR1 |=0x80; //外设时钟门控寄存器
		TIM1_EGR=0x01;//计数器更新,可省略
		TIM1_PSCRH = 0x1F; // 8M系统时钟经预分频f=fck/(PSCR+1)
    TIM1_PSCRL = 0x3F; // PSCR=0x1F3F,f=8M/(0x1F3F+1)=1000Hz,每个计数周期1ms
    TIM1_ARRH = 0x03; // 自动重载寄存器ARR=0x01F4=500;0X03E8=1000
    TIM1_ARRL = 0xE8; // 每记数500次产生一次中断,即500ms

	  TIM1_RCR = 0x00;    //重复计数器值
    TIM1_SR1 = ( ~0x01 );          //清除更新中断标志
		TIM1_CR1=0x01;//enable 使能计数器
		TIM1_IER=0x01;//更新中断使能
		
		

}
void Init_GPIO(void)
{
		PD_DDR |=0x80;// 配置PD端口的方向寄存器PD7输出
	  PD_CR1 |=0x80;// 设置PD7为推挽输出
	  PD_CR2 |=0x00;
}
void main()
{
	_asm("sim");    //disable all interrupt
	Init_GPIO();
	Init_Timer1();
	_asm("rim");

	while (1);
}

@far @interrupt void TIM1_UPD_OVF_IRQHandler (void)
{

      TIM1_SR1 =0x00;// 清除更新中断标记,这步不能漏掉
	 PD_ODR ^= 0x80;
   
}

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值