zoukankan      html  css  js  c++  java
  • STM32 滴答时钟 SysTick 的使用 STM32F103C8T6

          程序完成利用STM32F103C8T6 滴答时钟 SysTick进行定时,每隔1秒输出脚PC13的小灯闪烁一下。

    注意,小灯每隔1秒闪烁只是转换状态,可以理解为定时或1个脉冲时间,但并不是频率,频率要2个

    脉冲时间2秒,所以要测频率的话是0.5Hz,即频率=1/2秒= 0.5Hz 。

    1  使用中断的方法

    修改stm32f10x_it.c文件,增加下面内容:

    extern void LED_PC13 ();             //外部引入函数声明  加在文件首部

    void SysTick_Handler(void)          //中断入口
    {

    LED_PC13 ();                               //亮灯取反灭灯函数

    }

    下面是main.c

    #include "stm32f10x.h"

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

    void GPIO_CFG()                                                                   //亮灯引脚配置函数
    {
    GPIO_InitTypeDef GPIO_InitStructure;                                   //声明GPIO_InitStructure结构变量
    // 原版创作,引用请指明出处 https://www.cnblogs.com/beiyhs/p/12438787.html   北有寒山
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能AHB预分频器到端口C的开关

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;                     //指定脚13输出
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;       //设置为推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //设定端口最快输出50MHz
    GPIO_Init(GPIOC, &GPIO_InitStructure);                              //按以上参数设置C口

    GPIO_SetBits( GPIOC, GPIO_Pin_13);                                 //置高GPIO_Pin_13,关闭LED
    }

    //*********************************************************************************
    void LED_PC13(void)                                                             //亮灯取反灭灯函数
    {
    GPIO_WriteBit(GPIOC, GPIO_Pin_13,                                  //指定修改PC13脚的位
    (BitAction)((1-GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13)))); //读PC状态后取反
    }

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

    //*********************************************************************************
    int main(void)
    {
    GPIO_CFG() ;                                           //亮灯脚PC13的设置函数

    SysTick_Config(9000000);                        //重装值设9M,定时1秒
    //SysTick_Config(9000);                            //重装值设9K,定时1毫秒
    //SysTick_Config(9);                                  //重装值设9,定时1微秒
    //NVIC_SetPriority (SysTick_IRQn, 0);      //设SysTick中断优先级最高,不会在中断时被别的中断打断
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);  //配置SysTick时钟=HCLK时钟/8
                                                                                                          //即72M/8=9MHz 即记数9M次耗时1秒
                                                                                                          //注意要放在SysTick_Config函数之后

                                                                                                           //如果屏蔽此句,默认使用的时钟是72M

                                                                                                          //将上面9000000 改为72000000仍可得到

                                                                                                          //1秒定时

    while (1)
    { }
    }

     说明:
     1.1  systick定时器的内部计数器是24位递减的,最大重装值0xFFFFFF,即16777215,设置时不能超此值。

     1.2  使用systick定时器,只需调用SysTick_Config(uint32_t ticks)函数即可,该函数可以自动完成重装载

            值的装载、时钟源选择、计数寄存器复位、中断优先级的设置(默认最低)、开中断、开始计数的工作。

            一次搞定,是不是很爽。函数是在core_cm3.h头文件中进行定义的。
     1.3  要修改时钟源,比如外部时钟,可以修改SysTick_CLKSourceConfig函数内部,也可按照SysTick_Config

           中默认设置FCLK不变。

     1.4 要修改中断优先级调用 NVIC_SetPriority函数,函数在core_cm3.h

     1.5 systick是cortex_m3的标配,不是外设。故不需要在RCC寄存器组打开他的时钟。

     1.6 每次systick溢出后会置位计数标志位和中断标志位,计数标志位在计数器重装载后被清除,而中断标志位

          也会随着中断服务程序的响应被清除,所以这两个标志位都不需要手动清除。

    2  使用延时的方法

    下面是下面是main.c

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

    #include "stm32f10x.h"

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

    void delay_ms(unsigned int ms)  //把ms换成us,下面9000换成9,就改成了us定时函数

    {
    unsigned int tmp = 0;

    SysTick->LOAD = ms * 9000;    //  重装寄存器 设置 72MHz/9000=9MHz

    SysTick->VAL = 0x00;               // 当前计数寄存器 清零

    SysTick->CTRL = 0x01;            // 控制寄存器  使能systick,禁止中断,时钟频率AHB/8
    do
       {
        tmp = SysTick->CTRL;         // 读取控制寄存器的值赋给tmp
       }

     while (!(tmp & (1<<16)));         // 就是读取tmp的第16位的值,这一位如果为0就表示计数器的值不是0(即

                                                     // 还在计数),如果是1就表示计数器已经自减到0了,计数结束。

                                                      //假设该值为0,还在计数,套上外面的!取反为1,继续做do的内容。

     SysTick->VAL = 0x00;             // 当前计数寄存器 清零
     
    SysTick->CTRL = 0x00;          //失能systick
    }

    //*********************************************************************************
    int main(void)

    {

    GPIO_CFG() ;                                           //亮灯脚PC13 设置   参照上面同名函数,不再贴出

    while(1)

     {

      Delay_ms(1000);

      GPIO_SetBits(GPIOC,GPIO_Pin_13);
      Delay_ms(1000);
      GPIO_ResetBits(GPIOC,GPIO_Pin_13);

      }

    }

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

    说明: 上面的定时函数如果用到us级别时,误差还是不能忽视的,尤其是10us级别误差很大的这是因为

    程序指令的执行、跳转都是要花费时间的,也是在us级别。如果是us级精确定时输出控制的话,可以考

    虑使用PWM方式,毕竟设定一次即可,后面全是硬件自己控制。

  • 相关阅读:
    [禅悟人生]学习是一种偏执
    [家里蹲大学数学杂志]第393期中山大学2015年计算数学综合考试考博试题回忆版
    [家里蹲大学数学杂志]第392期中山大学2015年泛函分析考博试题回忆版
    [数分提高]2014-2015-2第2教学周第1次课
    [数分提高]2014-2015-2第1教学周第2次课
    [数分提高]2014-2015-2第1教学周第1次课
    所教课程
    16种床上动作的内涵图,你都看懂了吗?
    为什么美国学生学的数学比我们简单却还能做出很牛逼的东西?
    来自数学君的羊年祝福
  • 原文地址:https://www.cnblogs.com/beiyhs/p/12438787.html
Copyright © 2011-2022 走看看