• 笔记:stm32f030 要点总结(时钟、中断、GPIO、定时器、串口、看门狗)



    不支持位带操作
    只有一条AHB-lite总线接口连到存储器、总线矩阵等
    1条外设总线,APB速度高达48MHz
    4个中断优先级
    GPIO连载AHB总线,最高翻转速度为12MHz

    一、时钟系统

    M0芯片的时钟源有4个,

    一个高速内部RC时钟源,频率为8M,精度1%

    一个高速外部时钟源,频率为8到32MHz

    一个低速外部时钟源,频率一般为32.768kHz,驱动RTC

    一个低速内部时钟源,频率为40kHz,驱动IWDG

    芯片上电的时候默认启用内部RC震荡,即8MHz的内部时钟源

    倍频最高48MHz

    启用HSI

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    /*
    *********************************************************************************************************
    *   函 数 名: HSI_setSysClk
    *   功能说明: 设置HSI为系统时钟,
    *   形    参:
    *   返 回 值: 无
    *********************************************************************************************************
    */
    void HSI_setSysClk(void)
    {
      __IO uint32_t StartUpCounter = 0, HSIStatus = 0;
       
        /* SYSCLK, HCLK, PCLK configuration ----------------------------------------*/
        /* Enable HSI*/ //使能内部时钟  
        RCC->CR |= ((uint32_t)RCC_CR_HSION);//使用内部8M时钟
      
        /* Wait till HSI is ready and if Time out is reached exit */ //等待内部时钟起振
        do
        {
            HSIStatus = RCC->CR & RCC_CR_HSIRDY;
            StartUpCounter++;  
        }while((HSIStatus== 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));
     
        if ((RCC->CR & RCC_CR_HSIRDY) != RESET)//使用内部8M时钟
        {
            HSIStatus = (uint32_t)0x01;
        }
        else
        {
            HSIStatus = (uint32_t)0x00;
        }  
      
        if (HSIStatus == (uint32_t)0x01)
        {
            /* Enable Prefetch Buffer and set Flash Latency */ //flash总线时钟使能
            FLASH->ACR |= FLASH_ACR_PRFTBE;
            FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY;
     
            /* HCLK = SYSCLK *///外设AHB总线时钟等于系统时钟
            RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
     
            /* PCLK = HCLK *///外设APB总线时钟等于系统时钟
            RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;
     
            /* PLL configuration = HSI/2 * 12= 48 MHz */
            RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL));
            RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_Div2 | RCC_CFGR_PLLMULL12); //RC时钟2分频后 进行12倍频
             
            /* Enable PLL *///使能锁相环倍频开关 
            RCC->CR |= RCC_CR_PLLON;
     
            /* Wait till PLL is ready *///等待锁相环就绪 
            while((RCC->CR & RCC_CR_PLLRDY) == 0)
            {
            }
     
            /* Select PLL as system clock source *///选择锁相环输出时钟作为系统时钟 
            RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
            RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    
     
            /* Wait till PLL is used as system clock source *///等待锁相环输出时钟已经成为系统时钟 
            while((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
            {
            }
        }
        else
        /* If HSE fails to start-up, the application will have wrong clock 
             configuration. User can add here some code to deal with this error */
        }  
    }



    二、NVIC
    4个中断优先级
    1
    2
    3
    /* 开关全局中断的宏 */
    #define ENABLE_INT()    __enable_irq()     /* 使能全局中断 */
    #define DISABLE_INT()   __disable_irq()    /* 禁止全局中断 */
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void NVIC_Configuration(void)
    {
      NVIC_InitTypeDef NVIC_InitStructure;
     
      /* 外设中断 */
      NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;                  //IRQ通道:串口1
      NVIC_InitStructure.NVIC_IRQChannelPriority = 1;                    //优先级 :1级
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                    //使能IRQ通道
      NVIC_Init(&NVIC_InitStructure);
    }


    三、GPIO

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #define PORT_LED                  GPIOC                    //端口
    #define PIN_LED                   GPIO_Pin_13              //引脚
     
    #define LED_ON                    (PORT_LED->BSRR = PIN_LED)
    #define LED_OFF                   (PORT_LED->BRR  = PIN_LED)
    #define LED_TOGGLE                (PORT_LED->ODR ^= PIN_LED)
     
    /*
    **********************************************************************
    * @fun     :bsp_led_init  
    * @brief   :板上LED初始化
    * @param   :None
    * @return  :None 
    * @remark  :
    **********************************************************************
    */
    void bsp_led_init(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
     
        GPIO_InitStructure.GPIO_Pin = PIN_LED;                             //LED引脚
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                      //输出模式
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                  //高速输出
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                     //推完输出
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;                   //无上下拉(浮空)
        GPIO_Init(PORT_LED, &GPIO_InitStructure);
    }

    四、定时器

    滴答定时器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    /*
    **********************************************************************
    * @fun     :SysTick_Init  
    * @brief   :滴答定时器初始化,提供1ms时基
    * @param   :None
    * @return  :=0,初始化成功;=1,初始化失败 
    * @remark  :None
    **********************************************************************
    */
    unsigned char SysTick_Init(void)
    {
        unsigned char sysFlag = 1;
         
        /* SystemFrequency / 1000    1ms中断一次
         * SystemFrequency / 100000  10us中断一次
         * SystemFrequency / 1000000 1us中断一次
         */ 
         
        sysFlag = SysTick_Config(SystemCoreClock / 1000);
     
        return sysFlag;
    }
     
    /*
    **********************************************************************
    * @fun     :bsp_DelayUS  
    * @brief   :us级延迟。 必须在systick定时器启动后才能调用此函数
    * @param   :None
    * @return  :n-延迟长度,单位1 us
    * @remark  :None
    **********************************************************************
    */
    void bsp_DelayUS(uint32_t n)
    {
        uint32_t ticks;
        uint32_t told;
        uint32_t tnow;
        uint32_t tcnt = 0;
        uint32_t reload;
            
        reload = SysTick->LOAD;                
        ticks = n * (SystemCoreClock / 1000000); /* 需要的节拍数 */  
         
        tcnt = 0;
        told = SysTick->VAL;             /* 刚进入时的计数器值 */
     
        while (1)
        {
            tnow = SysTick->VAL;    
            if (tnow != told)
            {    
                /* SYSTICK是一个递减的计数器 */    
                if (tnow < told)
                {
                    tcnt += told - tnow;    
                }
                /* 重新装载递减 */
                else
                {
                    tcnt += reload - tnow + told;    
                }        
                told = tnow;
     
                /* 时间超过/等于要延迟的时间,则退出 */
                if (tcnt >= ticks)
                {
                    break;
                }
            }  
        }
     
    /*
    **********************************************************************
    * @fun     :SysTick_Handler  
    * @brief   :滴答定时器中断服务函数
    * @param   :None
    * @return  :=0,初始化成功;=1,初始化失败 
    * @remark  :None
    **********************************************************************
    */
    void SysTick_Handler(void)
    {
     
    }

    五、串口

    重定向prinf函数

    1、需要在Options for Target -> Code Generation 中勾选Use MicroLIB;

    2、需要加入下面这个函数:

    int fputc(int ch, FILE *f)

    {

      USART_SendData(USART1,(uint8_t)ch);

      while (USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);

      return (ch);

    }

    3、需要加入如下一个头文件:

    #include "stdio.h"

    (在网上看到多数人加了两个头文件:

    #include "stdio.h"

    #include "stdarg.h"

    但在实际中只需加入一个头文件即可

    )。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #ifdef __GNUC__
        #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    #else
        #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    #endif
      
    /** 
      * @brief  Retargets the C library printf function to the USART. 
      * @param  None 
      * @retval None 
      */  
    PUTCHAR_PROTOTYPE  
    {  
      /* Place your implementation of fputc here */  
      /* e.g. write a character to the USART */  
      USART_SendData(USART1, (uint8_t) ch);  
       
      /* Loop until the end of transmission */  
      while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)  
      {  
      }  
       
      return ch;  
    }



    六、看门狗

    驱动独立看门狗的晶振为40KHz

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    /*
    **********************************************************************
    * @fun     :bsp_iwdg_init  
    * @brief   :独立看门狗初始化,超时时间2048ms
    * @param   :None
    * @return  :None 
    * @remark  :
    **********************************************************************
    */
    void bsp_iwdg_init(void)
    {
        if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET)
            RCC_ClearFlag();                             //清除标志
         
        IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);   //使能寄存器 写功能
        IWDG_SetPrescaler(IWDG_Prescaler_64);           //设置预分频 40K/64=0.625k 一个周期是 1.6ms
        IWDG_SetReload(1280);                          //1280*1.6ms=2048ms //设置初值
        IWDG_ReloadCounter();                           //喂狗
        IWDG_Enable();                                  //使能独立看门狗
    }
     
    /*
    **********************************************************************
    * @fun     :bsp_iwdg_feed  
    * @brief   :独立看门狗喂狗,必须在超时时间内调用
    * @param   :None
    * @return  :None 
    * @remark  :
    **********************************************************************
    */
    void bsp_iwdg_feed(void)
    {
        IWDG_ReloadCounter();
    }













  • 相关阅读:
    二维树状数组的区间加减及查询 tyvj 1716 上帝造题的七分钟
    hdu5399
    WebLogicSSL解决苹果IOS itms下载问题
    怎样封装RESTful Web Service
    ie8下面版本号(包含ie8)的浏览器不支持html5标签属性解决方式(Modernizr 2.6.2插件的使用)
    在Linux平台使用VNC连接树莓派
    合作开发——设计阶段
    HDU-1165-Eddy&#39;s research II
    Iocomp控件教程之LinearGauge--线性刻度尺控件
    VB中的排序问题 15个
  • 原文地址:https://www.cnblogs.com/bog-box/p/11782230.html
Copyright © 2020-2023  润新知