• stm32之Systick(系统时钟)


    Systick的两大作用:

      1、可以产生精确延时;

      2、可以提供给操作系统一个单独的心跳(时钟)节拍;

    通常实现Delay(N)函数的方法为:

      for(i=0;i<x;i++)

        ;

      对于STM32系统微处理器来说,执行一条指令只有几十ns(纳秒),进入for循环,要实现N毫秒的x值非常大;而由于系统频率的宽广,很难计算出延时N毫秒的精确值;针对STM32微处理器,需要重新设计一个新的方法去实现该功能,以实现在程序中使用Delay(N);

      cortex的内核中包含一个SysTick时钟,SysTick为一个24位递减计数器;SysTick设定初值并使能后,每经过1个系统时钟周期,计数值就减1;计数到0,SysTick计数器自动装载初值并继续计数,同时内部的COUNTFLAG标志会置位;触发中断(前提是中断使能);

      如果外部晶振(即外接的晶振)位8Mhz,经过内部9分频;系统时钟则为72Mhz(cpu的时钟);SysTick的最高频率为9Mhz(cpu时钟的8分频);在这个条件下;如果设置SysTick值为9000;而SysTick是9Mhz;则能产生1ms的时间基;即SysTick产生1ms的中断;

     

      SysTick相关的寄存器:

      CTRL:  SysTick控制和状态寄存器;

      LOAD:  SysTick重装载值寄存器;

      VAL:   SysTick当前寄存器;(重新写入的时候;会把状态寄存器的FLAG清零)

      CALIB:  SysTick校准值寄存器;

    SysTick设置步骤:(使用ST的函数库使用Systick的方法)

      1、调用SysTick_CounterCmd()失能SysTick计数器;

      2、调用SysTick_ITConfig()失能SysTick中断;

      3、调用SysTick_CLKSourceConfig()设置SysTick时钟源;

      4、调用SysTick_SetReload() 设置SysTick重装载值;

      5、调用SysTick_ITConfig() 使能SysTick中断;

      6、调用SysTick_CounterCmd()  开启SysTick计数器;

    /*Include---------------------------*/
    #include"stm32f10x_lib.h"        //包含所有的头文件
    #include<stdio.h>
    
    //----------------函数声明--------------------
    void Delay_MS(u16 dly);
    void RCC_Configuration(void);
    void GPIO_Configuration(void);
    void USART3_Configuration(void);
    
    
    u8 tab[] = "hello welcome to class !";
    
    void SYSTICK_Configuration(void)
    {
        SysTick_CounterCmd(SysTick_Counter_Disable);
        SysTick_ITConfig(DISABLE);
        SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
        SysTick_SetReload(9000*1000);
           SysTick_CounterCmd(SysTick_Counter_Enable);
    
        //*************打开systick时钟,但是由于systick时钟是默认开启的;
        
    }      
    
    
    /*******************************************************************************
    * Function Name  : main
    * Description    : Main program.
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/ 
    int main(void)
    {
        u8 min, sec;
        #ifdef DEBUG
        debug();
        #endif
        //------------初始化------------
        RCC_Configuration();
        GPIO_Configuration();    
        USART3_Configuration();
        SYSTICK_Configuration();      
    
    //     id_num[0] = *((u8*)(0x1FFFF7E9));    //stm32芯片id的放置地址,96位id;12字节
         printf("hello world
    ");
        //------------将数据上传给上位机-----------
        min = 1;
        sec = 30;
    
        while(1)
        {
            FlagStatus Status;
            Status = SysTick_GetFlagStatus(SysTick_FLAG_COUNT);
            if(Status == RESET)
            {
                ;
            }
            else
            {
                sec++;
                if(sec == 60)
                {
                    sec=0;
                    min++;
                }
                printf("		%d:%d", min, sec);
            }
        }
            
    }
    
    /*******************************************************************************
    * Function Name  : Delay_Ms
    * Description    : delay 1 ms.
    * Input          : dly (ms)
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void Delay_MS(u16 dly)
    {
        u16 i,j;
        for(i=0;i<dly;i++)
            for(j=1000;j>0;j--);
    }
    
    /*******************************************************************************
    * Function Name  : RCC_Configuration
    * Description    : Configures the different system clocks.
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void RCC_Configuration(void)
    {
        //----------使用外部RC晶振-----------
        RCC_DeInit();            //初始化为缺省值
        RCC_HSEConfig(RCC_HSE_ON);    //使能外部的高速时钟 
        while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);    //等待外部高速时钟使能就绪
        
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);    //Enable Prefetch Buffer
        FLASH_SetLatency(FLASH_Latency_2);        //Flash 2 wait state
        
        RCC_HCLKConfig(RCC_SYSCLK_Div1);        //HCLK = SYSCLK
        RCC_PCLK2Config(RCC_HCLK_Div1);            //PCLK2 =  HCLK
        RCC_PCLK1Config(RCC_HCLK_Div2);            //PCLK1 = HCLK/2
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);    //PLLCLK = 8MHZ * 9 =72MHZ
        RCC_PLLCmd(ENABLE);            //Enable PLLCLK
    
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);    //Wait till PLLCLK is ready
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);    //Select PLL as system clock
        while(RCC_GetSYSCLKSource()!=0x08);        //Wait till PLL is used as system clock source
        
        //---------打开相应外设时钟--------------------
        RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);    //使能APB2外设的GPIOC的时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE); //复用功能时钟开启             
    }
    
    /*******************************************************************************
    * Function Name  : GPIO_Configuration
    * Description    : 初始化GPIO外设
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/
    //由电路图可知;配置PC10,PC11引脚
    void GPIO_Configuration(void)
    {
        //CLK:PB5  CLR:PE11 DATA:PE10
        GPIO_InitTypeDef    GPIO_InitStructure;        //声明一个结构体变量
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;     //选择PB.1-
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //管脚频率为50MHZ
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     //输出模式为 "复用推挽输出"
        GPIO_Init(GPIOC,&GPIO_InitStructure);                 //初始化GPIOB寄存器
        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 |GPIO_Pin_11 ;     //选择PE.10 PE.11
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //管脚频率为50MHZ
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;     //输出模式为    "浮空输入"
        GPIO_Init(GPIOC,&GPIO_InitStructure);                 //初始化GPIOE寄存器
        
        //开启时钟    必须在RCC_Configuration中设置    
        
        
        //端口重映射:PC10/PC11
        GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);    
    } 
    
    void USART3_Configuration(void)
    {
        USART_InitTypeDef USART_InitStructure;
        USART_InitStructure.USART_BaudRate = 9600;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl =    USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    
        USART_Init(USART3, &USART_InitStructure);
    
        USART_Cmd(USART3, ENABLE);    //开启使能
    }
    
    /***********************************************************
     name:    fputc                                               *
     Description:重定向这个c库printf函数,文件流--->串口USART  *
                                                               *
    ************************************************************/
    int fputc(int ch,FILE *f)
    {
        //ch发送给USART1
        USART_SendData(USART3, ch);
        //等待发送完毕
        while(USART_GetFlagStatus(USART3, USART_FLAG_TC)==RESET)
            ;
        return ch;
    }
  • 相关阅读:
    Linux基础网络设置
    CentOS安装
    一.Linux常用命令
    C# 的 ListView 中 多个 Items 的 批量移动方法
    用 Directory.GetFiles 过滤多种类型的文件
    Visual Studio 返回上次编辑位置的快捷键
    C# 的 DataGripView 在大数据时,如何加速?
    webapi和mvc 路由详解
    C# 实体类和DataTable相互转换
    WinForm的DataGridView 下拉滚动条消失
  • 原文地址:https://www.cnblogs.com/chris-cp/p/3916642.html
Copyright © 2020-2023  润新知