stm8s根据定时器写延时函数始终不成功,定时无问题

时间:2021-06-29 23:36:56
测试时候发现。
全局时钟初始化,定时器初始化,中断处理函数,中断向量结构,全局中断都没问题。
下面是定时中断处理函数。

@far @interrupt void irq_10ms_flag(void)
 {
TIM5_SR1 = 0X0; //置位中断
freq =~freq;
 //PF_ODR = ~PF_ODR;   -----------------问题一
count_10ms--;
if (count_10ms <= 0)
  count_10ms = 0;
time_freq++;
if (time_freq > 100) //修改time_freq为int
{
//PF_ODR = ~PF_ODR;           --------------问题二
time_freq = 0; //为1000时处理时间,一秒处理一次
}
 }

这个函数是没有问题的,但是我考虑到通用性,想通过在定时器中断处理函数中设置flag的方法,来延时。
于是,我屏蔽上面的问题一,问题二。
重新写了几个个函数。
函数一。

void delay_10ms(void)
{
  unsigned char temp = freq;
  while (temp == freq)
_asm("nop");
}

函数二。

void delay_10ms(unsigned char ten_ms)
{
  count_10ms = ten_ms;
  while (count_10ms)
_asm("nop");
}

再在主函数中写入

while(1)
{
PF_ODR = ~PF_ODR;
delay_10ms();
//delay_10ms(100);
}


这两个函数,不论哪一个都没有起到延时的作用。无论是上面的10ms还是下面的1秒,示波器显示全是稳定高电平。
如果将延时函数提到前面,就稳定低电平,也就是说delay_10ms这个函数死循环了。

5 个解决方案

#1


time_freq    
count_10ms;
定义为 
volatile signed char count_10ms;
volatile signed char time_freq;

#2


引用 1 楼 wangfan027 的回复:
time_freq    
count_10ms;
定义为 
volatile signed char count_10ms;
volatile signed char time_freq;


测试了,没用。
经过其他测试,我在程序开始把time_freq = 0; freq = 0;
发现程序运行后,两者恒等于0。
换句话说,中断是运行的(PF_ODR = ~PF_ODR写在中断处理函数中没问题)。
中断函数中赋值给freq这两个全局变量也是没问题的,主楼问题二可以运行,说明计数没有问题。
但是退出中断处理函数后却没有保存。就是freq是个静态static变量一样。但是略有区别。

总结猜测就是
中断处理函数中的freq和我定义的全局freq虽然名字一样,但是却是不同的变量……

STVD4.3.5  + comic 

#3


问题解决,我初始化了两个时间不同的溢出中断,TIM5,TIM6,
当初始化寄存器的时候,如果把TIM6_IER 和TIM6_CR1同时使能的话。会导致上面的问题。
贴出源码,看看是不是个例。
===========
mian.c

/* MAIN.C file
 * 
 * Copyright (c) 2002-2005 STMicroelectronics
 */
//#include "STM8S903K.h"
#include "config.h"

/*
* 全局变量定义
*/
volatile unsigned char count_10ms;
volatile char freq;
//volatile char time_freq;

void gpio_init(void)
{
/*
* 开背光,PF4,写1
*/
PF_DDR |=0X10;
PF_CR1 |=0X10;
PF_ODR |=0X10;
}

void clk_init(void)
{

/*对于内部高速时钟HSI[16MHz],其逻辑关系是HSI---[HSIDIV分频]---[时钟选择门]---
* 主时钟Fmaster---{[CPUDIV分频]---Fcpu时钟;其他外设时钟}
*/
CLK_ICKR = 0x01; //Internal clock control register。复位值,使能HSI时钟,快速唤醒禁止
CLK_ECKR = 0x00; //External clock control register。禁止。
CLK_SWR  = 0xE1; //Clock master switch register。选择HSI为主时钟。
CLK_SWCR = 0x00; //Clock switch control register。时钟切换,中文数据手册似乎有误
/*Clock divider register。分频Fmaster和Fcpu。
* 默认是8和1,现在是2和1,因此Fmaster=8M,Fcpu=8M */
CLK_CKDIVR = 0x08;
CLK_PCKENR1 = 0xFF; //Peripheral clock gating register 1。Fmaster与外设时钟连接
CLK_PCKENR2 = 0x0; //同上
CLK_CSSR = 0x0; //Clock security system register。时钟安全检测关
CLK_CCOR = 0x0; //Configurable clock control register。时钟输出关闭
}



void var_init(void)
{
  count_10ms = 0;
  freq=0;
  //time_freq =0;
}
void init(void)
{
gpio_init();
clk_init();
irq_init();
var_init();
}

void delay_10ms(unsigned char ten_ms)
{
  count_10ms = ten_ms;
while(count_10ms);
}
main()
{
_asm("rim" );
init();
while (1)
{
  delay_10ms(100);
  PF_ODR = ~PF_ODR;
}
}
   


====stm8_interrupt_vector.c===

//#include "STM8S903K.h"
#include "config.h"
extern volatile unsigned char count_10ms;
extern volatile char freq;

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;
}

void irq_init(void)
{
/*TIM5是16位简单定时器*/
/*HSI=16MHZ,Fcpu=Fmaster=8MHZ=Fck_psc*/
/*定时器时钟Fck_cnt由Fck_psc分频而来*/
TIM5_PSCR = 0X03; //分频8,计数器一次计数1us
TIM5_CNTRH = 0x0; //定时器计数值
TIM5_CNTRL = 0X0;
TIM5_ARRH  = 0x27; //10000=0x2710,10ms中断一次
TIM5_ARRL = 0x10;

TIM5_IER  = 0X01; //更新中断使能
TIM5_CR1  = 0X05; //使能计数器,使能溢出计数器
TIM5_EGR  = 0X01; //立即开始一次中断

#if 0
/*TIM6是8位简单定时器*/
/*HSI=16MHZ,Fcpu=Fmaster=8MHZ=Fck_psc*/
//TIM6_PSCR = 0X06; //分频64,计数器一次计数8 ms
//TIM6_CNTR = 0x0; //定时器计数值
//TIM6_ARR  = 0x3e; //125次1毫秒,

TIM6_IER  = 0X01; //更新中断使能
TIM6_CR1  = 0X01; //使能计数器,使能溢出计数器
//TIM6_EGR  = 0X01; //立即开始一次中断
#endif 
}

 /************************************************************************/
/* 功能:定时溢出中断处理,10ms一次的稳定中断
 * 形参:无
 * 返回:无
 * 修改:2014-11-14
 * 缘由:各种奇怪的问题                                */ 
/************************************************************************/
@far @interrupt void irq_10ms_flag(void)
 { 

freq++;
if(freq == 100)
  freq =0;
count_10ms--;
TIM5_SR1 &= ~0X01; //置位中断
 }

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, NonHandledInterrupt}, /* irq11 */
{0x82, NonHandledInterrupt}, /* irq12 */
{0x82, irq_10ms_flag}, /* 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 */
};


config.h是头文件和函数变量声明

#ifndef _CONFIG_H
#define _CONFIG_H


///////////////////////官方库文件///////////////////////////////////
#include "STM8S903K.h"

@far @interrupt void irq_10ms_flag(void);
void irq_init(void);
#endif


原因未知。。。

#4


/**虽然怪怪的,但程序逻辑没有问题,不确认楼主开启中断后再去初始化行不行,但正常是这样的初始化**/
main()
{   
    _asm("sim" );           //禁止中断
    init();                           
    _asm("rim" );     
    while (1)
    {   
      delay_10ms(100);
      PF_ODR = ~PF_ODR;
    }
}
    

#5


//我这么写一点问题都没有。
#pragma vector=TIM4_OVR_UIF_vector
__interrupt void TIM4_OVR_UIF_IRQHandler(void)
{
TIM4_SR=0x00;
count_250us++; 
if(count_250us%4==0){
ms_count++;
}
if(count_250us==4000){
System_Time++;          //+1/s
count_250us=0;
}
}
void delay_ms(unsigned int time)
{
ms_count=0;
while(ms_count<time);
}

#1


time_freq    
count_10ms;
定义为 
volatile signed char count_10ms;
volatile signed char time_freq;

#2


引用 1 楼 wangfan027 的回复:
time_freq    
count_10ms;
定义为 
volatile signed char count_10ms;
volatile signed char time_freq;


测试了,没用。
经过其他测试,我在程序开始把time_freq = 0; freq = 0;
发现程序运行后,两者恒等于0。
换句话说,中断是运行的(PF_ODR = ~PF_ODR写在中断处理函数中没问题)。
中断函数中赋值给freq这两个全局变量也是没问题的,主楼问题二可以运行,说明计数没有问题。
但是退出中断处理函数后却没有保存。就是freq是个静态static变量一样。但是略有区别。

总结猜测就是
中断处理函数中的freq和我定义的全局freq虽然名字一样,但是却是不同的变量……

STVD4.3.5  + comic 

#3


问题解决,我初始化了两个时间不同的溢出中断,TIM5,TIM6,
当初始化寄存器的时候,如果把TIM6_IER 和TIM6_CR1同时使能的话。会导致上面的问题。
贴出源码,看看是不是个例。
===========
mian.c

/* MAIN.C file
 * 
 * Copyright (c) 2002-2005 STMicroelectronics
 */
//#include "STM8S903K.h"
#include "config.h"

/*
* 全局变量定义
*/
volatile unsigned char count_10ms;
volatile char freq;
//volatile char time_freq;

void gpio_init(void)
{
/*
* 开背光,PF4,写1
*/
PF_DDR |=0X10;
PF_CR1 |=0X10;
PF_ODR |=0X10;
}

void clk_init(void)
{

/*对于内部高速时钟HSI[16MHz],其逻辑关系是HSI---[HSIDIV分频]---[时钟选择门]---
* 主时钟Fmaster---{[CPUDIV分频]---Fcpu时钟;其他外设时钟}
*/
CLK_ICKR = 0x01; //Internal clock control register。复位值,使能HSI时钟,快速唤醒禁止
CLK_ECKR = 0x00; //External clock control register。禁止。
CLK_SWR  = 0xE1; //Clock master switch register。选择HSI为主时钟。
CLK_SWCR = 0x00; //Clock switch control register。时钟切换,中文数据手册似乎有误
/*Clock divider register。分频Fmaster和Fcpu。
* 默认是8和1,现在是2和1,因此Fmaster=8M,Fcpu=8M */
CLK_CKDIVR = 0x08;
CLK_PCKENR1 = 0xFF; //Peripheral clock gating register 1。Fmaster与外设时钟连接
CLK_PCKENR2 = 0x0; //同上
CLK_CSSR = 0x0; //Clock security system register。时钟安全检测关
CLK_CCOR = 0x0; //Configurable clock control register。时钟输出关闭
}



void var_init(void)
{
  count_10ms = 0;
  freq=0;
  //time_freq =0;
}
void init(void)
{
gpio_init();
clk_init();
irq_init();
var_init();
}

void delay_10ms(unsigned char ten_ms)
{
  count_10ms = ten_ms;
while(count_10ms);
}
main()
{
_asm("rim" );
init();
while (1)
{
  delay_10ms(100);
  PF_ODR = ~PF_ODR;
}
}
   


====stm8_interrupt_vector.c===

//#include "STM8S903K.h"
#include "config.h"
extern volatile unsigned char count_10ms;
extern volatile char freq;

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;
}

void irq_init(void)
{
/*TIM5是16位简单定时器*/
/*HSI=16MHZ,Fcpu=Fmaster=8MHZ=Fck_psc*/
/*定时器时钟Fck_cnt由Fck_psc分频而来*/
TIM5_PSCR = 0X03; //分频8,计数器一次计数1us
TIM5_CNTRH = 0x0; //定时器计数值
TIM5_CNTRL = 0X0;
TIM5_ARRH  = 0x27; //10000=0x2710,10ms中断一次
TIM5_ARRL = 0x10;

TIM5_IER  = 0X01; //更新中断使能
TIM5_CR1  = 0X05; //使能计数器,使能溢出计数器
TIM5_EGR  = 0X01; //立即开始一次中断

#if 0
/*TIM6是8位简单定时器*/
/*HSI=16MHZ,Fcpu=Fmaster=8MHZ=Fck_psc*/
//TIM6_PSCR = 0X06; //分频64,计数器一次计数8 ms
//TIM6_CNTR = 0x0; //定时器计数值
//TIM6_ARR  = 0x3e; //125次1毫秒,

TIM6_IER  = 0X01; //更新中断使能
TIM6_CR1  = 0X01; //使能计数器,使能溢出计数器
//TIM6_EGR  = 0X01; //立即开始一次中断
#endif 
}

 /************************************************************************/
/* 功能:定时溢出中断处理,10ms一次的稳定中断
 * 形参:无
 * 返回:无
 * 修改:2014-11-14
 * 缘由:各种奇怪的问题                                */ 
/************************************************************************/
@far @interrupt void irq_10ms_flag(void)
 { 

freq++;
if(freq == 100)
  freq =0;
count_10ms--;
TIM5_SR1 &= ~0X01; //置位中断
 }

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, NonHandledInterrupt}, /* irq11 */
{0x82, NonHandledInterrupt}, /* irq12 */
{0x82, irq_10ms_flag}, /* 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 */
};


config.h是头文件和函数变量声明

#ifndef _CONFIG_H
#define _CONFIG_H


///////////////////////官方库文件///////////////////////////////////
#include "STM8S903K.h"

@far @interrupt void irq_10ms_flag(void);
void irq_init(void);
#endif


原因未知。。。

#4


/**虽然怪怪的,但程序逻辑没有问题,不确认楼主开启中断后再去初始化行不行,但正常是这样的初始化**/
main()
{   
    _asm("sim" );           //禁止中断
    init();                           
    _asm("rim" );     
    while (1)
    {   
      delay_10ms(100);
      PF_ODR = ~PF_ODR;
    }
}
    

#5


//我这么写一点问题都没有。
#pragma vector=TIM4_OVR_UIF_vector
__interrupt void TIM4_OVR_UIF_IRQHandler(void)
{
TIM4_SR=0x00;
count_250us++; 
if(count_250us%4==0){
ms_count++;
}
if(count_250us==4000){
System_Time++;          //+1/s
count_250us=0;
}
}
void delay_ms(unsigned int time)
{
ms_count=0;
while(ms_count<time);
}