一板网
发表于: 2015-6-2 16:22:17 | 显示全部楼层

一、准备工作:

将上一节搭建的LED工程复制一份,命名为“2.systick”。这一节主要讲如何使用系统的SysTick节拍定时器来进行精准延时程序。


二、程序编写:


SysTick是CM3/CM4内核芯片提供的一个定时器,我们的板子使用的SAM4N芯片是CM4内核的,自然少不了这个定时器。


首先在Drivers文件夹中建立delay.c和delay.h文件并添加到工程中,在delay.c中写入如下代码:



  1. #include "delay.h"

  2. uint32_t timeout=0;

  3. /**************************************************************************

  4. * 函数名:SysTick_Handler()

  5. * 参数  :void

  6. * 返回值:void

  7. * 描述  :系统节拍中断服务函数

  8. **************************************************************************/

  9. void SysTick_Handler(void)

  10. {

  11. /*定时计数自减1*/

  12.     timeout--;

  13. }

  14. /**************************************************************************

  15. * 函数名:systick_hw_init()

  16. * 参数  :void

  17. * 返回值:void

  18. * 描述  :系统节拍初始化函数

  19. **************************************************************************/

  20. void systick_hw_init(void)

  21. {

  22. //选择系统节拍定时器的时钟源为系统内核时钟

  23. SysTick->CTRL|=0x01<<2;

  24. //设置重装值,配置系统节拍定时器为1ms中断一次

  25. /*1ms <-->SystemCoreClock/1000

  26. * 100us <-->SystemCoreClock/10000

  27. * 10us <-->SystemCoreClock/100000

  28. */

  29. SysTick->LOAD = SystemCoreClock/1000 - 1;

  30. //使能系统节拍时钟中断

  31. SysTick->CTRL|=0x02;

  32. //使能系统节拍时钟

  33. SysTick->CTRL|=0x01;

  34. }

  35. /**************************************************************************

  36. * 函数名:delay_ms()

  37. * 参数  :uint32_t n  延时的毫秒数

  38. * 返回值:void

  39. * 描述  :使用系统节拍进行精准延时函数

  40. **************************************************************************/

  41. void delay_ms(uint32_t n)

  42. {

  43.    timeout = n;        //设置系统节拍延时

  44.    while(timeout!=0);      //等待延时时间到

  45. }

  46. /**************************************************************************

  47. * 函数名:delay()

  48. * 参数  :uint32_t n  延时的循环个数

  49. * 返回值:void

  50. * 描述  :简单的循环延时函数

  51. **************************************************************************/

  52. void delay(uint32_t n)

  53. {

  54. while(n--);

  55. }
复制代码


虽然注释已经写得很清楚了,但还是讲一下吧,主要是systick_hw_init函数,这是初始化配置SysTick的代码,第一步先选择SysTick的时钟源,这里我选择使用系统内核时钟作为时钟源;第二步是设置SysTick的Load值,这里设置为ystemCoreClock/1000 - 1;,这样SysTick就会每毫秒中断一次,最后是开启中断和使能SysTick。


延时主要是通过设定timeout的值,然后等待timeout为0,在Systick中断中,timeout会自减1,直到为0。这样就实现了ms级的精准延时函数delay_ms()。


在delay.h中主要写写函数声明,如下:


  1. #ifndef __DELAY_H

  2. #define __DELAY_H

  3. #include "sam4n16c.h"

  4. /**************************************************************************

  5. * 函数名:SysTick_Handler()

  6. * 参数  :void

  7. * 返回值:void

  8. * 描述  :系统节拍中断服务函数

  9. **************************************************************************/

  10. void SysTick_Handler(void);

  11. /**************************************************************************

  12. * 函数名:systick_hw_init()

  13. * 参数  :void

  14. * 返回值:void

  15. * 描述  :系统节拍初始化函数

  16. **************************************************************************/

  17. void systick_hw_init(void);

  18. /*************************************************************************

  19. * 函数名:delay_ms()

  20. * 参数  :uint32_t n  延时的毫秒数

  21. * 返回值:void

  22. * 描述  :使用系统节拍进行精准延时函数

  23. **************************************************************************/

  24. void delay_ms(uint32_t n);

  25. /**************************************************************************

  26. * 函数名:delay()

  27. * 参数  :uint32_t n  延时的循环个数

  28. * 返回值:void

  29. * 描述  :简单的循环延时函数

  30. **************************************************************************/

  31. void delay(uint32_t n);

  32. #endif
复制代码

接下来把main.c中的delay改掉,如下:



  1. int main(void)

  2. {

  3. systick_hw_init();

  4. led_hw_init();

  5. while(1){

  6. led_hw_on();

  7. delay_ms(500);

  8. led_hw_off();

  9. delay_ms(500);

  10. }

  11. }
复制代码

好了,下载程序到板子,这下是不是延时很准?



跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 28 | 回复: 31



手机版|

GMT+8, 2024-12-21 21:02 , Processed in 0.064941 second(s), 7 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表