筆記: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();
}














免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM