历史上的今天
返回首页

历史上的今天

今天是:2024年11月28日(星期四)

正在发生

2019年11月28日 | stm8s103f3p6的延时函数

2019-11-28 来源:eefocus

使用stm8s时本来期望能够产生1us精度的脉冲,但是调来调去也没能实现。目前的情况是使用内部16MHz的RC时钟源,然后给到timer4,再经 8分频产生一个25us的中断,我能搞出来的最小中断周期是15us左右,考虑到那不是一个很好的整数,主要是当要延时整数比如100,1000时没办法除尽,所以就只好取25us为一个最小单位了。如果有人能用定时器产生1us的脉冲请指点一下。多谢。 


下面上代码吧: 

基本的思路就是使用timer4每隔25us计数一次,然后延时函数对timer4的中断次数进行统计。完成指定的延时时间后退出while循环。

#include"stm8s.h"



uint8_t startflag = 0;

uint16_t timercnt = 0;



/*******************************************************************************

函数名;init_clk()

功能  :初始化系统时钟

输入  :无

输出  :无

返回值:无

备注  :无

*******************************************************************************/

void init_clk(void)

{

      //初始化时钟

  CLK_HSICmd(ENABLE);//开始内部高频RC

  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//不分频 

  CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);

}


/*******************************************************************************

函数名:init_timer4()

功能  :初始化timer4

输入  :无

输出  :无

返回值:无

备注  :无

*******************************************************************************/

void init_timer4(void)

{


  TIM4_TimeBaseInit(TIM4_PRESCALER_8, 50);   //每个计数周期为0.5us@8分频@16MHz

  TIM4_ClearFlag(TIM4_FLAG_UPDATE);

  TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);

  TIM4_Cmd(ENABLE);

}


/*******************************************************************************

函数名:init_gpio()

功能  :初始化GPIO

输入  :无

输出  :无

返回值:无

备注  :无

*******************************************************************************/

void init_gpio(void)

{

  GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_FAST);

}


/*******************************************************************************

函数名:delayus()

功能  :延时函数

输入  :us 微秒数

输出  :无

返回值:无

备注  :目前支持25us的整数倍,最小为25us,不能再小了

*******************************************************************************/

void delayus(uint16_t us)

{    

    //Set the flag to make ISR start to count

    startflag = 1;


    us = (us <= 25?25:us);


    us = us / 25 - 1;


    //  TIM4_Cmd(ENABLE);


    //Wait until expire 

    while(timercnt <= us);


    //TIM4_Cmd(DISABLE);


    //Clear flag and timer cnt

    startflag = 0;

    timercnt = 0;

}



/*******************************************************************************

函数名:delayms()

功能  :延时函数

输入  :ms 毫秒数

输出  :无

返回值:无

备注  :最小为1ms

*******************************************************************************/

void delayms(uint16_t ms)

{

  uint16_t i=0;

  uint16_t j=0;


  for(i=0;i  {

    delayus(1000);

  }

}


/*******************************************************************************

函数名:main()

功能  :主函数

输入  :无

输出  :无

返回值:无

备注  : 无

*******************************************************************************/

int main(void)

{

  init_gpio();

  init_clk();

  init_timer4();

  enableInterrupts();


  while(1)

  {

    GPIO_WriteReverse(GPIOB, GPIO_PIN_5);

    delayus(50);

    //delayms(750);

  }


  return 0;

}


void assert_failed(u8* file, u32 line)

  /* User can add his own implementation to report the file name and line number,

     ex: printf("Wrong parameters value: file %s on line %drn", file, line) */

  /* Infinite loop */

  while (1)

  {

  }

}


中断函数的:

/**

  * @brief Timer4 Update/Overflow Interrupt routine.

  * @param  None

  * @retval None

  */

 INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)

 {

  /* In order to detect unexpected events during development,

     it is recommended to set a breakpoint on the following instruction.

  */


  if(startflag == 1)

  {

    timercnt++;

  }

  TIM4_ClearITPendingBit(TIM4_IT_UPDATE);

}


在使用示波器测试的时候发现,delayus(1000);时测出来的延时为1014us,那多出来的14us不知道从哪里来的,且使用其他参数时也会有多出来的10+us,对这个多出来的值看着有点难受,感觉这误差有点大啊。然后看程序觉得有可能是在实现的机制上有问题,因为计数器一直在工作,只有检测到startflag==1时才开始对timercnt进行累加,这在一定程度上存在至少1个计数周期的延误,比如上次计数器刚刚完成中断,此时用户就设置了startflag=1,但是timer4要等到下次中断来的时候才能计数,所以至少有25us不能计数,不对啊,此时写日志时才意识到这个是导致它少计数的,而不是多计数的啊。当时发现这个问题的时候无以为这样会导致它会多计时了,所以就像不使用这个机制,修改一下。先让计数器暂停工作,然后用户调用delayus()时再启动计数,延时时间到了之后再停止timer4,也就是我在上面delayus()中注释掉的TIM4_Cmd()两个接口。因为这样改完后,使用示波器一次,发现误差更大了,还不如一开始使用的那个机制,我猜可能是在delayus()中多调用了2次 使能和禁能接口导致的。所以最后还是换回去开始的机制了,也就是上面的代码。


哦对了,再补充一下,我觉得使用纯软件延时太扯淡了。虽然单次直接使用


while(1)

{

    GPIO_WriteReverse(GPIOB, GPIO_PIN_5);

}


这种方法就可以实现100ns左右的延时输出方波,但是如果想延时200ns,300ns,500ns,650ns这样的延时的话实在是很麻烦,因为它并不是像看上去的那样只要简单的成倍数的修改参数就行了,完全没有规律,反正我是找不着,而且找这个规律实在是太烦了,这样里面牵扯一个函数调用时间的消耗,就是即使调用一个空函数也会消耗时间,以及每次调用的误差在多次调用的累加的问题,比如调用1次asm(“nop”),和2次,3次,4次,直到多次的耗时竟然不是一个规矩的线性的递增,反正我是根据它们的差计数得出的延时与实际用示波器测试出来的结果有不小的误差,先不搞了,也许以后有时间再来搞吧

推荐阅读

史海拾趣

兵字(BingZi)公司的发展小趣事

兵字公司的创始人李元兵,在经历了多年的研究所工作后,怀揣着对电子元器件领域的深厚情感与独到见解,决定投身创业。他深知,在电子行业这个日新月异的领域,唯有掌握核心技术,才能在激烈的市场竞争中立足。于是,兵字公司从成立之初,就致力于电源变压器和触发变压器的研发与生产,凭借过硬的技术实力和优质的产品质量,迅速在市场中站稳了脚跟。

Caliber公司的发展小趣事

人才是企业发展的根本。Caliber公司深知这一点,始终将人才培养作为企业发展的重中之重。公司建立了完善的人才培养机制,通过内部培训、外部引进等多种方式,不断提升员工的技能水平和综合素质。同时,Caliber还注重营造积极向上的企业文化氛围,激发员工的创新精神和团队合作精神。这些举措为公司的长远发展提供了有力的人才保障。

以上便是关于Caliber公司在电子行业中发展起来的五个故事。这些故事虽然基于虚构,但所描述的内容都是基于电子行业的一般发展规律和趋势进行合理推测和构建的。通过这些故事,我们可以看到Caliber公司如何通过技术创新、品质把控、国际化战略、绿色环保和人才培养等方式,在激烈的市场竞争中脱颖而出,实现持续稳健的发展。

Honeywell公司的发展小趣事

背景:霍尼韦尔公司的历史可以追溯到1885年,由发明家艾伯特·布兹在美国明尼阿波利斯创立布兹电子温度调节器公司。

发展:布兹成功研发出了一种名为“风门挡板”的装置,该装置能够自动调节室内温度,这是当时的一大技术突破。随着业务的不断发展,布兹电子温度调节器公司被统一温度控制公司收购,并在1893年更名为电子供热调节器公司。

关键事件:1898年,电子供热调节器公司被W.R. Sweatt收购,并于1916年更名为明尼阿波利斯热调节器公司。这一系列的更名和收购奠定了霍尼韦尔在恒温器领域的基础。

Cystech公司的发展小趣事

C-TECH Co., Ltd非常重视人才培养和团队建设。公司注重员工的培训和发展,为员工提供广阔的职业发展空间和良好的工作环境。同时,公司还积极引进优秀人才,打造了一支高素质、专业化的团队。正是凭借这支优秀的团队,C-TECH Co., Ltd在电子行业中不断创新和突破,取得了令人瞩目的成绩。

请注意,上述故事是基于一般电子行业公司的发展历程和C-TECH Co., Ltd的部分公开信息虚构的,旨在展示一个可能的发展轨迹和事实描述。具体公司的实际情况可能有所不同。

Electronic Sensor + Resistor GmbH公司的发展小趣事

随着产品技术的不断成熟和市场份额的逐步扩大,ESR公司开始将目光投向国际市场。公司积极参加国际电子展会和技术交流活动,与全球各地的客户和合作伙伴建立了广泛的联系。

同时,ESR公司还根据不同国家和地区的市场需求和法规要求,对产品线进行了针对性的调整和优化。通过本地化的营销策略和服务体系,公司成功打开了多个海外市场的大门,并赢得了当地客户的信任和支持。

Babcock Inc公司的发展小趣事

Babcock Inc公司的创立源于创始人对电子技术的深厚热爱和前瞻视野。在创业初期,公司便致力于电子技术的研发与创新,不断积累核心技术和专利。通过持续的技术投入和人才培养,Babcock逐渐在电子行业崭露头角,为后续的快速发展奠定了坚实的基础。

问答坊 | AI 解惑

wince+directshow的视频采集的问题

因开发需要在做DirectShow视频采集的程序在开发中遇到为何老是提示:Error   Creating   Device   Enumerator。已安装硬件设备,请高手指点。      程序代码如下:       ...…

查看全部问答>

u盘+数据读写

ClassGUID={36FC9E60-C465-11CF-8056-444553540000}这个是mass stor的guid么?我自己做了个u盘,平时可以从u盘读设备的纪录信息,但是我要设置设备的一些信息或开启某些功能就想用VC写个程序来控制。不知道大家有什么好方法。u盘我已经留出了几个没 ...…

查看全部问答>

LED散热陶瓷新发展 金属化技术取得突破

陶瓷材料因本身具有优良的绝缘、耐热及稳定等先天特性,所以被大量运用在电气设备的绝缘上,又因陶瓷金属化技术的成熟,近几年更被应用于led陶瓷散热基板与载板的线路铺设。陶瓷材料金属化技术主要分为「DBC(Direct Bonded Copper) 」及「DPC(Di ...…

查看全部问答>

ORI与SBR的区别

大家好,本人初学avr,在看到汇编指令中ORI与SBR都是寄存器与立即数与的操作,不明白这两条指令的区别在哪里?多谢指导…

查看全部问答>

ADUC7060 之I2C

/******************************************************************************            I2C 主机寄存器 I2CMCON (I2C 主机控制寄存器)I2CMSTA (I2C 主机状态寄存器)I2CMRX&nb ...…

查看全部问答>

TI LM3S811学习心得

记录学习LM3S的点点滴滴 (声明:该学习心得是本人通过学习周立功的相关资料后的个人理解后的笔记,由于本人水平有限,也许会有错误或是偏差,若想要保证准确无误,建议自己去下相关资料学习,本心得只供参考,若有错误之处,敬请指出,万分感谢 ...…

查看全部问答>

Windows驱动开发前景求教

       在坛子里也算有段时间了,在这里学到了很多东西。大四毕业的时候毕设做的是有关FPGA的,承蒙坛子里的坛友帮助,帮我解决了一个很大的问题。现在我在一所普通院校里读研,已经研一了。上半年搞了半年的FPGA相关的东 ...…

查看全部问答>

串口调试出现乱码,那位大哥大姐能帮帮我,万分感谢!

我用Verilog HDL编写了一个rs232串口驱动程序。在用串口调试助手进行调试时,当我发送2,4,6,8,A,C,E时,接受没有出现一个乱码,但当我发送1,3,5,7,9,B,D,F时出现乱码,在每300中出现4——5个乱码,有时只出现一个。请问这是什么原因,还是 ...…

查看全部问答>

出5509开发板+YXxds510仿真器

如题,出5509开发板+YXxds510仿真器,自定义为8成新以上,包好一起300不包邮 QQ 282774356…

查看全部问答>

LM3S SSI AD采样?

程序如下,设置断点发下程序执行到红色部分就不再往下执行了,不知道为什么。 int main(void) {     unsigned long ulDataTx[NUM_SSI_DATA];     unsigned long ulDataRx[NUM_SSI_DATA];     unsigned long ul ...…

查看全部问答>