stm32之路:五 写好的剧本

        看了前辈通过配置寄存器来点亮LED灯,大家对stm32理解深了很多吧?在正常情况下,大家都用的固件函数库来编程,这样能缩短开发时间,减少开发中的bug,提高开发的效率。所以前辈的帖子,就当做是初学时加深对stm32的认识吧。

        都说人生如戏,那么编程也是这样。演戏,就要有剧本。固件库就是ST给我们写好的剧本,怎么样“演”好stm32中各个“角色”,就看大家发挥了。下面,就以SysTick()来熟悉下固件库(2.0.3)吧。

        上次的程序中,SysTick配置函数共有4句。我们来逐句分析,这次要“打破砂锅问到底”!

void Systick_Configuration(void)

{

       SysTick_CounterCmd(SysTick_Counter_Disable);                                        // ①

       SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);                 // ②

       SysTick_CounterCmd(SysTick_Counter_Clear);                                            // ③

       SysTick_SetReload(9000*1000);                                                                        //④

① SysTick_CounterCmd(SysTick_Counter_Disable);

③ SysTick_CounterCmd(SysTick_Counter_Clear);

        打开我们在工程里添加的systick.c文件,找到SysTick_CounterCmd();。下面是代码,我们继续分析。

voidSysTick_CounterCmd(u32 SysTick_Counter)

{

  assert_param(IS_SYSTICK_COUNTER(SysTick_Counter));

  if (SysTick_Counter ==SysTick_Counter_Enable)

  {

    SysTick->CTRL |= SysTick_Counter_Enable;

  }

  else if (SysTick_Counter ==SysTick_Counter_Disable)

  {

    SysTick->CTRL &=SysTick_Counter_Disable;

  }

  else

  {

    SysTick->VAL = SysTick_Counter_Clear;

  }   

}

        第一句,调用assert_param();函数。这个是干嘛的呢?在stm32F10xxx函数固件库手册中查找,里面有这个函数的说明:宏assert_param来实现运行时间检测,所有要求输入参数的函数都使用这个宏。它可以检查输入参数是否在允许的范围内。宏assert_param编写与文件stm32f10x_conf.h中。

        这样大家就明白它的作用了。其实这个是在debug时用的,所以就不继续解释了,有兴趣的可以去stm32f10x_conf.h中看看,代码写的很清楚。

        再往下,IS_SYSTICK_COUNTER(SysTick_Counter)是个嵌套的函数,什么作用呢?打开stm32f10x_systick.h,里面用它的宏定义,三个常量都是什么,上面也都有,很清楚的,不多说。然后就是if else结构,SysTick_Counter是传入的形参,后面还是刚才的常量,经过判断,然后是个赋值的表达式:

SysTick->CTRL|= SysTick_Counter_Enable;

SysTick->CTRL是结构体变量,定义的位置是stm32f10x_map.h,

typedef struct

{

  vu32 CTRL;

  vu32 LOAD;

  vu32 VAL;

  vuc32 CALIB;

}SysTick_TypeDef;

这里边的四个变量又是什么呢?就是systick的四个寄存器了。看下它们的地址,还是在stm32f10x_map.h中,

#defineSCS_BASE              ((u32)0xE000E000)

#defineSysTick_BASE          (SCS_BASE + 0x0010)

#ifdef _SysTick

  EXT SysTick_TypeDef         *SysTick;

#endif

        为了访问SysTick寄存器,_SysTick在stm32f10x_conf.h中定义:#define  _SysTick,再看上面的结构体,很清楚吧,四个变量的地址就是四个寄存器的地址,分别是:控制及状态寄存器(0xE000E010)、重装载数值寄存器(0xE000E014)、当前数值寄存器(0xE000E018)、校准数值寄存器(0xE000E01C)。所以SysTick->CTRL就是控制和状态寄存器,还记得上面看过的吧?

#define   SysTick_Counter_Enable  ((u32)0x00000001)

#define   SysTick_Counter_Disable ((u32)0xFFFFFFFE)

#define   SysTick_Counter_Clear   ((u32)0x00000000)

再来看下:控制及状态寄存器CTRL(0xE000E010),最后一位是ENABLE,1 是计数器工作在连拍模式,0是禁能计数器。可以这么理解,用SysTick_Counter_Enable和这个寄存器“按位或”,就把状态置1,同样,清零的时候,就用SysTick_Counter_Disable 和下面这个寄存器“按位与”,就把状态复位了。最后

SysTick->VAL= SysTick_Counter_Clear;

这句,就是把VAL(当前数值寄存器)清零,准备重新计数了。

②SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);

        上面说了这么多,下面就简单点了。还是看systick.c文件,有下面的函数:

 voidSysTick_CLKSourceConfig(u32 SysTick_CLKSource)

{

 assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));

  if (SysTick_CLKSource ==SysTick_CLKSource_HCLK)

  {

    SysTick->CTRL |=SysTick_CLKSource_HCLK;

  }

  else

  {

    SysTick->CTRL &=SysTick_CLKSource_HCLK_Div8;

  }

}

第一句和上面一样,不再解释。后面的部分,设置的还是刚才的寄存器,也很清楚。

④ SysTick_SetReload(9000*1000);

还是在systick.c文件中,

void SysTick_SetReload(u32 Reload)

{

 assert_param(IS_SYSTICK_RELOAD(Reload));

 SysTick->LOAD = Reload;

}

啰嗦的话就不说了。

再看延时函数。

void Delay_Second(void)

{

       SysTick_CounterCmd(SysTick_Counter_Enable);

       while(SysTick_GetFlagStatus(SysTick_FLAG_COUNT)== 0);

       SysTick_CounterCmd(SysTick_Counter_Disable);

       SysTick_CounterCmd(SysTick_Counter_Clear);

}

这里主要看函数中的第二句

while(SysTick_GetFlagStatus(SysTick_FLAG_COUNT)== 0);

在systick.c中,有如下代码:

FlagStatus SysTick_GetFlagStatus(u8SysTick_FLAG)

{

  u32statusreg = 0, tmp = 0 ;

 FlagStatus bitstatus = RESET;

 assert_param(IS_SYSTICK_FLAG(SysTick_FLAG));

  tmp= SysTick_FLAG >> 3;

  if(tmp == 2)

  {

   statusreg = SysTick->CTRL;

  }

 else         

  {

   statusreg = SysTick->CALIB;

  }

  if((statusreg & ((u32)1 << SysTick_FLAG)) != (u32)RESET)

  {

   bitstatus = SET;

  }

 else

  {

   bitstatus = RESET;

  }

 return bitstatus;

}

这个函数,是检查指定的SysTick 标志位设置与否,在systick.h中有定义,

#define SysTick_FLAG_COUNT             ((u32)0x00000010)

#define SysTick_FLAG_SKEW              ((u32)0x0000001E)

#define SysTick_FLAG_NOREF             ((u32)0x0000001F)

下面是说明,详细情况见固件函数库。

SysTick_FLAG_COUNT:自从上一次被读取,计数器计数至0
SysTick_FLAG_SKEW:由于时钟频率,校准值不精确等于10ms
SysTick_FLAG_NOREF:参考时钟未提供

         所以当传入的值是SysTick_FLAG_COUNT时,tmp=2成立,执行statusreg = SysTick->CTRL。再看固件函数库中,关于COUNTFLAG的描述:从上次读取定时器开始,如果定时器计数到0,则返回1。此时,if ((statusreg & ((u32)1 << SysTick_FLAG)) != (u32)RESET)条件成立,返回SET,再回到main.c,while()条件不成立,结束循环,1s延时结束!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值