打印
[STM8]

STM8S的通用定时器问题!!

[复制链接]
6613|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
逻辑很简单,使用通用定时器2,设置每10us产生一次中断,然后在定时器中断里面设置IO口翻转,用示波器观察IO口的翻转频率
硬件上STM8S使用内部16MHZ使用,没有使用外部晶振。定时器2由f(master)二分频,即为2MHZ/2=1MHZ,即每1us计数一次。
设置ARR寄存器值为10,则应该是每10us产生一次中断,中断里面翻转IO,则IO的频率应该是1s/(10us*2)=50KHZ
然后实际测试发现ARR寄存器设置到150以下频率就不能再上去了,即1s/(150us*2)=3.3KHZ
ARR设置到150以上的所有测试波形都与理论计算符合,150以下所有的测试波形都为3.3KHZ!!!
请问是怎么回事呢??
沙发
insect2006|  楼主 | 2015-11-26 16:37 | 只看该作者
IO口的设置模式是:GPIO_MODE_OUT_PP_LOW_FAST 换了几种IO模块波形一样

定时器的配置函数:
/*通用定时器2配置函数*/
void TIM2_Config(void)
{
  asm("sim");         //sim是禁止中断
  
  TIM2_PrescalerConfig(TIM2_PRESCALER_2,TIM2_PSCRELOADMODE_IMMEDIATE);              //f(master)/2=2MHZ/2=1MHZ=1us/count  
  TIM2_SetCounter(0);
  TIM2_SetAutoreload(200);                                                                              
  TIM2_ITConfig(TIM2_IT_UPDATE,ENABLE);         
  TIM2_Cmd(ENABLE);
  asm("rim");        //rim使能中断
}

使用特权

评论回复
板凳
insect2006|  楼主 | 2015-11-26 16:38 | 只看该作者
然后没有用到其他外设和中断,只用了定时器2和一个IO口

使用特权

评论回复
地板
insect2006|  楼主 | 2015-11-26 16:45 | 只看该作者
换了其他IO口也是一样的现象

使用特权

评论回复
5
insect2006|  楼主 | 2015-11-26 16:46 | 只看该作者
更改定时器2的分频系数也一样,只要频率是低于3.3KHZ的全部没问题,高于3.3KHZ的全部只能到3.3KHZ

使用特权

评论回复
6
insect2006|  楼主 | 2015-11-26 17:00 | 只看该作者
要崩溃鸟~~~没有大神来指点迷津吗??

使用特权

评论回复
7
chenpads| | 2015-11-26 17:53 | 只看该作者
为使系统快速启动,复位后时钟控制器自动使用HSI的8分频(HSI/8)做为主时钟。其原因为HSI的稳定时间短,而8分频可保证系统在较差的VDD条件下安全启动。
要16MHZ,初始要 CLK_CKDIVR =0 ;

使用特权

评论回复
8
chenpads| | 2015-11-26 17:57 | 只看该作者
中断响应要时间,主时钟不能太慢。

使用特权

评论回复
9
HARRY007| | 2015-11-27 15:01 | 只看该作者
你在主函数里面用另外一个I/O取反。ARR寄存器设置到150以下的时候,如果主函数里面的I/O频率为0,那可能原因就是I/O取反还没结束呢,10us到了……

使用特权

评论回复
10
insect2006|  楼主 | 2015-11-27 15:54 | 只看该作者
经过7楼那位兄弟的提醒,我把f(master)的频率设置为不分频,即为16MHZ,果然速度上去了,然而最高也只能到46KHZ左右

通过直接操作寄存器的方式在main函数中直接取反IO,其他啥也不干,发现IO翻转的极限速率是46KHZ左右

也就是说16MHZ的主时钟下,IO的速度设置2MHZ和10MHZ根本就没鸟用~~

使用特权

评论回复
11
insect2006|  楼主 | 2015-11-27 15:57 | 只看该作者
HARRY007 发表于 2015-11-27 15:01
你在主函数里面用另外一个I/O取反。ARR寄存器设置到150以下的时候,如果主函数里面的I/O频率为0,那可能原因 ...

16MHZ的主时钟,翻转一次IO居然要us级的时间???

使用特权

评论回复
12
HARRY007| | 2015-11-28 13:27 | 只看该作者
本帖最后由 HARRY007 于 2015-11-28 13:29 编辑

定时器2由f(master)二分频,即为2MHZ/2=1MHZ,你都说了f(master) = 2MHZ了。一个反转指令在C语言上就是一句话,到汇编上了就是几条指令。
/*******************************************************************************
* 名称: Sysclock_Init
* 功能: 设置系统时钟频率
* 形参: 无
* 返回: 无
* 说明: 时钟选择
         如果选择外部24MHz主时钟的,外部不是24M的话
         把#define HSE_24M  HSE_VALUE注释掉即可,
         如果不需要切换到外部时钟,把#define __HSE_VALUE  HSE_VALUE
         注释掉即可
******************************************************************************/
void SystemClock_Init(void)
{
    CLK_HSICmd(ENABLE);//启用内部高速时钟
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//配置HSI时钟分频系数为1,16MHZ供给CPU
      /* CLK_HSECmd(ENABLE);                     //外部时钟使能
       CLK_HSICmd(ENABLE);//开启内部高速时钟 16MHz
       CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);//时钟分频设置系统时钟16M不分频
       CLK_ClockSwitchCmd(ENABLE);
       CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE); */
}

这是我的时钟配置,我Main里取了个反,还有其他任务执行……,我测I/O的频率是99.20Khz~
while(1)
    {     
              
       // Led_SystemRun();//系统指示灯
         GPIO_WriteReverse(LED_OUT, LED_OUT1_PIN);
        //Beep_Load();//蜂鸣器负载刷新
        
        //Relay_Load();//继电器负载刷新
        
        UartDriver();  //调用串口驱动
        
        IWDG_ReloadCounter();//喂狗
        
/************ 5min调试光敏时间,时间到关闭外部中断 *********/
        if( dog_time == 0 )
        {
            GPIO_Init(GPIOB, GPIO_PIN_6, GPIO_MODE_IN_PU_NO_IT);
            GPIO_WriteHigh(LED_OUT, LED_OUT1_PIN);
        }  
    }

如果不是要求时间间隔非常小的话,我建议还是尽量定时器配置的中断时间久一些。
/*******************************************************************************
* 名称: Time4_Init
* 功能: 定时器4初始化
* 形参: 无
* 返回: 无
* 说明: 定时器4用来一个1MS的时间基准
******************************************************************************/
void Time4_Init(void)
{
    TIM4_TimeBaseInit(TIM4_PRESCALER_128, 124);//理论定时中断时间8us*125=1MS
    TIM4_PrescalerConfig(TIM4_PRESCALER_128, TIM4_PSCRELOADMODE_IMMEDIATE);
    TIM4_ARRPreloadConfig(ENABLE);
    TIM4_ClearFlag(TIM4_FLAG_UPDATE);
    TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
    TIM4_Cmd(ENABLE);
}
我用的定时器4,配置的是1ms

U]}{RMQ}1X9ZJE$`){D96N3.png (10.67 KB )

U]}{RMQ}1X9ZJE$`){D96N3.png

使用特权

评论回复
13
HARRY007| | 2015-11-28 13:44 | 只看该作者
再多注释几个,主函数里反转频率有500Khz了

使用特权

评论回复
14
HARRY007| | 2015-11-28 14:11 | 只看该作者
我又做了实验,定时器4定时15us中断一次,在中断中I/O取反
void Time4_Init(void)
{
    TIM4_TimeBaseInit(TIM4_PRESCALER_16, 14);
    TIM4_PrescalerConfig(TIM4_PRESCALER_16, TIM4_PSCRELOADMODE_IMMEDIATE);
    TIM4_ARRPreloadConfig(ENABLE);
    TIM4_ClearFlag(TIM4_FLAG_UPDATE);
    TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
    TIM4_Cmd(ENABLE);
}

QQ图片20151128140955.jpg (5.3 MB )

QQ图片20151128140955.jpg

使用特权

评论回复
15
HARRY007| | 2015-11-28 14:29 | 只看该作者
还没探究STM8的极限,等下有空了用查询的方法做短延时我再试一下吧。

使用特权

评论回复
16
HARRY007| | 2015-11-28 15:28 | 只看该作者
定时个10us

10us.jpg (5.2 MB )

10us.jpg

使用特权

评论回复
17
gmm2015| | 2015-11-28 15:30 | 只看该作者
进入退出中断都要时间,系统主时钟只有这么快,估计很难得到很快的频率

使用特权

评论回复
18
HARRY007| | 2015-11-28 15:34 | 只看该作者
gmm2015 发表于 2015-11-28 15:30
进入退出中断都要时间,系统主时钟只有这么快,估计很难得到很快的频率

赞同,其实搞10us没啥意义的,就是玩玩。实际用的1ms,10Ms直接上

使用特权

评论回复
19
sting_yang| | 2015-11-28 15:48 | 只看该作者
看了几个楼主的帖子,只能说,请楼主先把基础的C、硬件,复习几次

使用特权

评论回复
20
desertsailor| | 2015-12-2 15:43 | 只看该作者
10us时间太短了,用中断根本处理不过来。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

25

主题

146

帖子

1

粉丝