STM32F10X--->Systick(BSP)

大纲

前沿:系统滴答 首先选择哪个时钟,作为计数一次的时间,第二选择计数的次数,配置完基本配置后。

编写相应的中断服务函数,然后配置应用层的延时函数,或者一直计时也可以。

1.BSP_SYSTICK(编程要点)

       编写自己的BSP,将固件库函数uint32_t SysTick_Config(uint32_t ticks),主要用来配置

每次滴答的时间(通过选择相应的时钟源决定)。

       编写全局函数,因为系统滴答一次需要进入中断,可以在中断中搞事情。对某个变量进行递减的

操作等等。编写相关延迟函数,而其参数与该全局变量有关。

        延迟函数编写要点就是不断检测该全局变量是否为某个值或者是否为0,而在中断中也是,按照

来变化该全局变量。

2.调用函数

(1)中断延时函数

        void delay_s(uint32_t nTime)

        void delay_ms(uint32_t nTime)

        void delay_us(uint32_t nTime)

(2)标志位判断延时函数

void SysTick_Delay_Ms( __IO uint32_t ms)
void SysTick_Delay_Us( __IO uint32_t us)
(3)systick是内核外设
 设置重载值:计数的次数,至于计数一次需要多少时间需要根据该外设挂载在那个总线上时钟

 =================================================================================================

=================================================================================================



1.定时器初始化配置函数,这个 固件库函数 在 core_cm3/4.h中

static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
    // reload 寄存器为24bit,最大值为2^24
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
  // 配置 reload 寄存器的初始值                                                                  
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
  // 配置中断优先级为 1<<4-1 = 15,优先级为最低
    NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
  // 配置 counter 计数器的值
    SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
     // 配置systick 的时钟为 72M
    // 使能中断
    // 使能systick
    SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
  return (0);                                                  /* Function successful */
}

2.启动系统滴答定时器

其中systemcoreClock是宏定义72MHZ时钟

/**
  * @brief  启动系统滴答定时器 SysTick
  * @param  无
  * @retval 无
  */     //link:   system_stm32f10x.c     ---STM32F10x_System_Private_Variables
    void SysTicks_Init_(void)
    {
        if(SysTick_Config(SystemCoreClock/100000))     //这里的systemcoreClock=72MHZ,然后重装载值=  SystemCoreClock/100000,表示计数的数量,在后面乘上每一次计数需要的时间(计数一次的时间),
24bit计数器,总共可以计数的范围是2^24次
核心:次数*每次计数需要的时间=总的计数时间
          
{
 /* Capture error */ while (1); 
} 
}

3.获取节拍程序

/**
  * @brief  获取节拍程序
  * @param  无
  * @retval 无
  * @attention  在 SysTick 中断函数 SysTick_Handler()调用
  */
void TimeDelay_Decrement(void)
{
    if(TimingDelay !=0x00 )
    {
        TimingDelay--;
    }
}

//将上线的函数放入中断函数中

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
    TimeDelay_Decrement();
}

4. 采用中断的方式定时

      10us延时函数

/**
  * @brief   us延时程序,10us为一个单位
  * @param  
  *        @arg nTime: Delay_us( 1 ) 则实现的延时为 1 * 10us = 10us
  * @retval  无
  */    
void delay_us(uint32_t nTime)
{
    TimingDelay = nTime;
    
    // 使能滴答定时器  
    SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;
    
    while(TimingDelay != 0);
}    

     ms延时函数

/**
  * @brief   ms延时程序,1ms为一个单位
  * @param  
  *        @arg nTime: Delay_ms( 1 ) 则实现的延时为 1 * 1ms = 1ms
  * @retval  无
  */    
void delay_ms(uint32_t nTime)
{
    TimingDelay = 100*nTime;
    
    // 使能滴答定时器  
    SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;
    
    while(TimingDelay != 0);
}    

     s延时函数

/**
  * @brief   s延时程序,1s为一个单位
  * @param  
  *        @arg nTime: Delay_s( 1 ) 则实现的延时为 1 * 1s = 1s
  * @retval  无
  */    
void delay_s(uint32_t nTime)
{
    TimingDelay = 100000*nTime;
    
    // 使能滴答定时器  
    SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;
    
    while(TimingDelay != 0);
}    

不采用中断的方式延时,通过检查寄存器固定位的方式

1us

void SysTick_Delay_Us( __IO uint32_t us)
{
    uint32_t i;
    SysTick_Config(SystemCoreClock/1000000);
    
    for(i=0;i<us;i++)
    {
        // 当计数器的值减小到0的时候,CRTL寄存器的位16会置1    
        while( !((SysTick->CTRL)&(1<<16)) );
    }
    // 关闭SysTick定时器
    SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}

1ms

void SysTick_Delay_Ms( __IO uint32_t ms)
{
    uint32_t i;    
    SysTick_Config(SystemCoreClock/1000);
    
    for(i=0;i<ms;i++)
    {
        // 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
        // 当置1时,读取该位会清0
        while( !((SysTick->CTRL)&(1<<16)) );
    }
    // 关闭SysTick定时器
    SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}

 

最后:设计一个每次计1ms的系统时钟,应用于CANopen通信中Heartbeat_timestamp以及TPDO_inhibitstamp

和TPDO_Eventstamp


extern uint8_t increasement;              //系统时间
extern uint16_t count;                        //由于10us进入中断一次,要想计时1ms一次,就要计数10000次
uint16_t count= 0;   //initialize count to zero
//1s=1000ms=1000 000us = 1000 000 000ns
//10us = 1x10-4s

//1.中断服务函数

systick_hander()
{
   count++;
   if(count==4000)
  {
     count=0;
     increasement++;            //我自己知道她增加1就代表增加1ms(其他人看不懂)
  }
  
}

//2.main

//主函数中调用increasement,这个全局函数在背后一直增加时间,每次增加1ms

应用:CANopen通讯协议中的时间戳,用于记录这一次发报文的时间,由于总线上不能一直接受报文,

然后判断这一次时间发报文与上一次时间发报文有没有超出,超出就发送报文。

 

Date:2021-11-14  10:33:26

posted @ 2021-11-07 19:43  InitForever  阅读(230)  评论(0)    收藏  举报