STM32——SYStyck(使用SYStick实现延时+中断,通过LED显示)

关于LED的寄存器配置,比较简单,在此就不在简述。实现systick的定时或者定时中断,首先要配置时钟源,systick是挂在AHB总线上的

寄存器配置主要用到STK_CTRL和STK_VAL,如图

 配置时钟来源代码:

uint8_t SYSTEM_SetClock(uint8_t freq)
{
    uint32_t rccCrHserdy = 0;
    uint32_t faultTime = 0, RCC_CFGR_PLL;

    /* 选择倍频系数 */
    switch(freq)
    {
        case(32):
            RCC_CFGR_PLL = RCC_CFGR_PLLMULL4;
            break;
        case(40):
            RCC_CFGR_PLL = RCC_CFGR_PLLMULL5;
            break;
        case(48):
            RCC_CFGR_PLL = RCC_CFGR_PLLMULL6;
            break;
        case(56):
            RCC_CFGR_PLL = RCC_CFGR_PLLMULL7;
            break;
        case(64):
            RCC_CFGR_PLL = RCC_CFGR_PLLMULL8;
            break;
        case(72):
            RCC_CFGR_PLL = RCC_CFGR_PLLMULL9;
            break;
        default:
            return 0xFF;
    }

    /*复位RCC_CR寄存器*/
    RCC_Reset();

    /*开启外部时钟*/
    RCC->CR &= (~RCC_CR_HSEON);
    RCC->CR |= RCC_CR_HSEON;//设置第16位

    /*检测外部时钟开启成功*/
    do
    {
        rccCrHserdy = RCC->CR & RCC_CR_HSERDY;//检测第17位是否为1
        faultTime++;//检测时间
    }
    while ((faultTime<0x0FFFFFFF) && (rccCrHserdy==0));
    /* 如果外部时钟开启成功*/
    if ((RCC->CR & RCC_CR_HSERDY) != 0)
    {
        /* Enable Prefetch Buffer */
        FLASH->ACR |= FLASH_ACR_PRFTBE;

        /* Flash 2 wait state */
        FLASH->ACR &= (~(uint32_t)FLASH_ACR_LATENCY);
        FLASH->ACR |= (uint32_t) FLASH_ACR_LATENCY_2;  

        /*AHB(0000)、APB2(000)不分频(即PLL输出时钟)*/
        /*APB1(100)要2分频(因最大只能36MHZ)*/
        RCC->CFGR &= (~(RCC_CFGR_HPRE | RCC_CFGR_PPRE1 | RCC_CFGR_PPRE2));
        RCC->CFGR |= (RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE1_DIV2
                      | RCC_CFGR_PPRE2_DIV1);

        /*设置HSE为输入时钟,同事HSE不分频*/
        RCC->CFGR &= (~(uint32_t)(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE ));
        RCC->CFGR |= (RCC_CFGR_PLLSRC);

        /*设置PLL倍频系数为9倍*/
        RCC->CFGR &= (~RCC_CFGR_PLLMULL);//先清除原来的设置
        RCC->CFGR |= (RCC_CFGR_PLL);//设置倍频系数

        /*打开PLL使能*/
        RCC->CR |= RCC_CR_PLLON;

        /*等待开启PLL开启成功*/
        while ((RCC->CR & RCC_CR_PLLRDY) == 0)
        {
        }

        /*将PLL作为SYSCLK的时候来源*/
        RCC->CFGR &= (~RCC_CFGR_SW);//先清除先前的设置
        RCC->CFGR |= RCC_CFGR_SW_PLL;

        /*等待PLL作为SYSCLK时钟启动成功*/
        while ((RCC->CFGR & RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
        {
        }
    }/*end of if((RCC->CR & RCC_CR_HSERDY) != 0)*/
    /*如果外部时钟开启失败*/
    else
    {
        RCC_Reset();
        return 0xFF;
    }

    return 0;    
}

这段代码,跟配置系统时钟基本一样,可以移植。

配置systick代码:

void SYSTICK_Config(void)
{
    /* 时钟是72MHZ时,所以计数72次(最大为16777215),就是1us */
    /* 主要是为了设置时钟 */
    if(SysTick_Config(72) == 0)//开启成功返回0
    {
        /* 调用这个设置函数的时候默认是直接打开计数器的,现在把它关掉。 */
        /* 关闭中断 */    
         SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);             
    }    
}

重要的是SysTick_Config(72)

而SysTick_Config():

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                   /* Reload value impossible */
  }

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  return (0UL);                                                     /* Function successful */
}

 实现的功能:判断载入值是否大于2的24次方,如果满足条件,就装载,之后给systick中断分组,设置优先级,这里设置的是最低优先级,这个优先级设置挺有意思,可以深入研究下。

最后使能定时器。
延时函数:

void SYSTICK_Delay1s(uint16_t s)
{
    uint32_t countValue;

    s *= 5; 
    SysTick->LOAD  = 72000 * 200 - 1;           //设置重装数值, 72MHZ时延时200ms
    SysTick->VAL   = 0;                            //清零计数器
    SysTick->CTRL |=  ((uint32_t)0x01 << 1);    //    使能中断
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;    //打开计时器

    do
    {
        countValue = SysTick->CTRL;
        if(countValue & (1 << 16))              //当到200ms是计数减1
        {
            s--;
        }     
    }
    while(s);                                    //等待时间到来

    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;    //关闭计数器    
}
看注释就可以。

主函数:

#include <stm32f10x.h>
#include "system.h"
#include "led.h"
int F=1;
/****************************************************************************
* Function Name  : main
* Description    : Main program.
* Input          : None
* Output         : None
* Return         : None
****************************************************************************/
void SysTick_Handler(void)
{
uint8_t ledState=0x10;
static uint16_t Time_Count = 0;
    
if(++Time_Count>=5)
{
    if(F==1)
    {
   ledState = 0x10;
    }
    else if(F==-1)
    {
    ledState=0x8;
    }
  LED_SetState(ledState);
    if(F==-1)
    {
    F=1;
    }
    else if(F==1)
    {
        F=-1;
    }
    Time_Count=0;
    
}
}
int main(void)
{
    uint8_t ledState = 0xE0;
    
    /* 初始化 */
    SYSTEM_SetClock(72);   //设置时钟,给AHB赋值时钟来源    
    LED_Config();
    SYSTICK_Config();
 
    while(1)
    {
        /* 选择 */
                ledState =0xF8;
        LED_SetState(ledState);
                SYSTICK_Delay1s(3);      //利用系统滴答定时器
        
                ledState =0x1F;
        
            LED_SetState(ledState);
        SYSTICK_Delay1s(3);      //利用系统滴答定时器延时
                
    }                            
}

SysTick_Handler是Systick中断服务函数,定义在启动文件中,我的是在STM32F10x.s中

 中断内容自己编写。

实现效果:

STM32

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉城美金

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值