已经写完了STM8S的系统文件(同stm32一样,包括sys.c,delay.c和uart.c三个文件)
这里先分享delay.c和delay.h.
本来想仿效STM32用一个定时器来做,无奈STM8S提供的是一个8位定时器,真是食之无味了...
算来算去,用这个8位的定时器横竖都不好做延时,用16位的定时器嘛又怕浪费.真不知道st的人怎么想的.
这个8位的基本定时器,连ucosii的滴答时钟都不好提供...(24Mhz下,最大只能1.3ms左右中断一次,16Mhz则是2ms左右)
难不成多次中断,触发一次任务切换?
所以,表示蛋疼的很,无奈只能想用汇编的方式来实现精确延时了.
研究了几天,终于小有成就.汇编写了一个us级延时函数,还算比较准.
24M和8M时,差别有点多,24M时STM8S要插入一个flash等待周期,这样st说是可以提供20MIPS的性能,但是我迷糊了...到底此时的指令周期如何算?st没有提到.
最后测试发现,大概是19Mhz的指令运行速度,也就是单周期指令,执行时间在24M时钟频率下约为1/19Mhz 秒.单根据我的计算公式,得不到19这个值,于是只能取近似了,按理说20比较准,不过实测16会准确一些.故采用了16,然后导致的结果就是延时变快了.
比如延时100ms,实际上可能是92ms左右.
而8Mhz时,差别有点多,表示不太理解,因为根据我的设计,刚好是8个周期的,应该是延时准确才对,但事实并非如此.
下面是各时钟频率下的延时准确性(测试时使用的延时至少>10us):
//92% @24Mhz
//98% @16Mhz
//98% @12Mhz
//86% @8Mhz
可以看到,12M和16M条件下有比较高的准确度,24M稍微差点(主要是偏快).
一般应用,这样的精度,应该都可以满足使用了,源码下面附上,如有改进意见,欢迎提出,开源才能集思广益,而后才能精益求精.
delay.h代码如下:
#ifndef __DELAY_H
#define __DELAY_H
#include "sys.h"
////////////////////////////////////////////////////////////////////////////////
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK
//使用汇编代码进行精确延时处理
//包括delay_us,delay_ms
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2013/6/25
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//******************************************************************************
//V1.0 20130625
//支持不同时钟频率
//提供delay_us,delay_ms两个延时函数.
////////////////////////////////////////////////////////////////////////////////
void delay_init(u8 clk); //延时函数初始化
void delay_us(u16 nus); //us级延时函数,最大65536us.
void delay_ms(u32 nms); //ms级延时函数
#endif
delay.c代码如下:
#include "delay.h"
////////////////////////////////////////////////////////////////////////////////
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK
//使用汇编代码进行精确延时处理
//包括delay_us,delay_ms
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2013/6/25
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//******************************************************************************
//V1.0 20130625
//支持不同时钟频率
//提供delay_us,delay_ms两个延时函数.
////////////////////////////////////////////////////////////////////////////////
volatile u8 fac_us=0; //us延时倍乘数
//延时函数初始化
//为确保准确度,请保证时钟频率最好为4的倍数,最低8Mhz
//clk:时钟频率(24/16/12/8等)
void delay_init(u8 clk)
{
if(clk>16)fac_us=(16-4)/4;//24Mhz时,stm8大概19个周期为1us
else if(clk>4)fac_us=(clk-4)/4;
else fac_us=1;
}
//延时nus
//延时时间=(fac_us*4+4)*nus*(T)
//其中,T为CPU运行频率(Mhz)的倒数,单位为us.
//准确度:
//92% @24Mhz
//98% @16Mhz
//98% @12Mhz
//86% @8Mhz
void delay_us(u16 nus)
{
__asm(
"PUSH A n" //1T,压栈
"DELAY_XUS: n"
"LD A,fac_us n" //1T,fac_us加载到累加器A
"DELAY_US_1: n"
"NOP n" //1T,nop延时
"DEC A n" //1T,A--
"JRNE DELAY_US_1 n" //不等于0,则跳转(2T)到DELAY_US_1继续执行,若等于0,则不跳转(1T).
"NOP n" //1T,nop延时
"DECW X n" //1T,x--
"JRNE DELAY_XUS n" //不等于0,则跳转(2T)到DELAY_XUS继续执行,若等于0,则不跳转(1T).
"POP A n" //1T,出栈
);
}
//延时nms
//为保证准确度,nms不要大于16640.
void delay_ms(u32 nms)
{
u8 t;
if(nms>65)
{
t=nms/65;
while(t--)delay_us(65000);
nms=nmse;
}
delay_us(nms*1000);
}
设计资源 培训 开发板 精华推荐
- LT3663HMS8E-3.3 5V 降压转换器的典型应用
- 技小新ESP8266开发板Type-C自动下载版
- 双路输出 LTC1149 电源以低成本提供高效率
- 使用 NXP Semiconductors 的 MAX3232CP 的参考设计
- LTC3632EMS8E 小尺寸、有限峰值电流、4mA 稳压器的典型应用电路
- 根据 EN50121-3-2(双输出)使用带有 EMC 滤波的 RP40-4812SFR DC/DC 转换器的典型应用
- TB62757FUG 升压 DC-DC 转换器用于 4 个白光 LED 驱动器的典型应用
- 基于梁山派的智能小车
- 使用 ON Semiconductor 的 KA7805E 的参考设计
- Avenger96、96Boards Avenger96 板基于 ST STM32MP157A 2x Cortex-A7 + 1x Cortex-M4 多核处理器,旨在支持物联网 (IoT) 中的安全和空间约束应用