加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權(quán)保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 1. delay文件
    • 2. sys文件
    • 重要函數(shù)
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

STM32固件庫system文件介紹

02/06 16:49
3646
閱讀需 24 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

1. delay文件

delay 文件夾內(nèi)包含了 delay.c 和 delay.h 兩個文件,這兩個文件用來實現(xiàn)系統(tǒng)的延時功能,其中包含 7 個函數(shù):

void delay_osschedlock(void); 
void delay_osschedunlock(void); 
void delay_ostimedly(u32 ticks); 
void SysTick_Handler(void); 

前面 4 個函數(shù),僅在支持操作系統(tǒng)(OS)的時候,需要用到,而后面三個函數(shù),則不論是否支持 OS 都需要用到。

void delay_init(void); 
void delay_ms(u16 nms); 
void delay_us(u32 nus); 
void      delay_init(void); 
//初始化延遲函數(shù) 
//當(dāng)使用 OS 的時候,此函數(shù)會初始化 OS 的時鐘節(jié)拍 
//SYSTICK 的時鐘固定為 HCLK 時鐘的 1/8 
//SYSCLK:系統(tǒng)時鐘 
void delay_init(u8 SYSCLK) 
{ 
#if SYSTEM_SUPPORT_OS //如果需要支持 OS. 
 u32 reload; 
#endif 
 SysTick->CTRL&=~(1<<2); //SYSTICK 使用外部時鐘源 
 fac_us=SYSCLK/8; //不論是否使用 OS,fac_us 都需要使用 
#if SYSTEM_SUPPORT_OS //如果需要支持 OS. 
 reload=SYSCLK/8; //每秒鐘的計數(shù)次數(shù) 單位為 K ,所以對于晶振是9MHZ時 syclk=72000
 reload*=1000000/delay_ostickspersec; //根據(jù) delay_ostickspersec 設(shè)定溢出時間 
 //reload 為 24 位寄存器,最大值:16777216,在 72M 下,約合 1.86s 左右 
 fac_ms=1000/delay_ostickspersec; //代表 OS 可以延時的最少單位 
 SysTick->CTRL|=1<<1; //開啟 SYSTICK 中斷 
 SysTick->LOAD=reload; //每 1/delay_ostickspersec 秒中斷一次 
 SysTick->CTRL|=1<<0; //開啟 SYSTICK 
#else 
 fac_ms=(u16)fac_us*1000; //非 OS 下,代表每個 ms 需要的 systick 時鐘數(shù) 
#endif 
} 

2. sys文件

    1. 共有五個文件,其中sys.c和sys.h是由ALIENTEK提供,是重點介紹的部分。在 sys.h 里面定義了 STM32F1 的 IO 口輸入讀取宏定義和輸出宏定義。sys.c 里面定義了很多STM32F1 底層硬件很相關(guān)的設(shè)置函數(shù),包括系統(tǒng)時鐘的配置、IO 配置、中斷的配置等。下面我們將分別向大家介紹這兩個文件。
      1. IO口的位操作

例如

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5) 
+(bitnum<<2)) 
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) 
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) 
//IO 口地址映射 
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C 
對應(yīng):
//IO 口操作,只對單一的 IO 口! 
//確保 n 的值小于 16! 
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //輸出 
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //輸入 
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //輸出 
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //輸入 
//這使得調(diào)取IO口非常方便

重要函數(shù)

    1. Stm32_Clock_Init 函數(shù)
//系統(tǒng)時鐘初始化函數(shù) 
//pll:選擇的倍頻數(shù),從 2 開始,最大值為 16 
void Stm32_Clock_Init(u8 PLL) 
{ 
 unsigned char temp=0; 
 MYRCC_DeInit(); //復(fù)位并配置向量表 
 RCC->CR|=0x00010000; //外部高速時鐘使能 HSEON 
 while(!(RCC->CR>>17)); //等待外部時鐘就緒 
 RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1; 
 PLL-=2; //抵消 2 個單位 
 RCC->CFGR|=PLL<<18; //設(shè)置 PLL 值 2~16 
 RCC->CFGR|=1<<16; //PLLSRC ON 
 FLASH->ACR|=0x32; //FLASH 2 個延時周期 
 RCC->CR|=0x01000000; //PLLON 
 while(!(RCC->CR>>25)); //等待 PLL 鎖定 
 RCC->CFGR|=0x00000002; //PLL 作為系統(tǒng)時鐘 
 while(temp!=0x02) //等待 PLL 作為系統(tǒng)時鐘設(shè)置成功 
 { 
  temp=RCC->CFGR>>2; 
 temp&=0x03; 
 } 
} 
//Stm32_Clock_Init 函數(shù)中,我們設(shè)置了 APB1 為 2 分頻,APB2 為 1 分頻,AHB 為 1 分頻,

同時選擇 PLLCLK 作為系統(tǒng)時鐘。該函數(shù)只有一個參數(shù) PLL,就是用來配置時鐘的倍頻數(shù)的,比如當(dāng)前所用的晶振為 8Mhz,PLL 的值設(shè)為 9,那么 STM32 將運行在 72M 的速度下。

  1. MYRCC_DeInit 函數(shù)

MYRCC_DeInit 函數(shù)實現(xiàn)外設(shè)的復(fù)位,并關(guān)斷所有中斷,同時調(diào)用向量表配置函數(shù)MY_NVIC_SetVectorTable,配置中斷向量表。MYRCC_DeInit 函數(shù)如下:

//把所有時鐘寄存器復(fù)位 
void MYRCC_DeInit(void) 
{ 
 RCC->APB1RSTR = 0x00000000;//復(fù)位結(jié)束 
 RCC->APB2RSTR = 0x00000000; 
 RCC->AHBENR = 0x00000014; //睡眠模式閃存和 SRAM 時鐘使能.其他關(guān)閉. 
 RCC->APB2ENR = 0x00000000; //外設(shè)時鐘關(guān)閉. 
 RCC->APB1ENR = 0x00000000; 
 RCC->CR |= 0x00000001; //使能內(nèi)部高速時鐘 HSION 
 RCC->CFGR &= 0xF8FF0000; 
//復(fù)位 SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0] 
 RCC->CR &= 0xFEF6FFFF; //復(fù)位 HSEON,CSSON,PLLON 
 RCC->CR &= 0xFFFBFFFF; //復(fù)位 HSEBYP 
 RCC->CFGR &= 0xFF80FFFF;//復(fù)位 PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE 
 RCC->CIR = 0x00000000; //關(guān)閉所有中斷 
 //配置向量表 
#ifdef VECT_TAB_RAM 
 MY_NVIC_SetVectorTable(0x20000000, 0x0); 
#else 
 MY_NVIC_SetVectorTable(0x08000000,0x0); 
#endif 
} 
  1. Sys_Soft_Reset 函數(shù)

該函數(shù)用來實現(xiàn) STM32 的軟復(fù)位,代碼如下:

//系統(tǒng)軟復(fù)位 
void Sys_Soft_Reset(void) 
{ 
 SCB->AIRCR =0X05FA0000|(u32)0x04; 
} 
SCB  MDK 定義的一個寄存器組,里面包含了很多與內(nèi)核相關(guān)的控制器,該結(jié)構(gòu)體
core_m3.h 里面,可以找到,具體的定義如下所示: 
typedef struct 
{ 
 __I uint32_t CPUID; //CM3 內(nèi)核版本號寄存器 
 __IO uint32_t ICSR; //中斷控制及狀態(tài)控制寄存器 
 __IO uint32_t VTOR; //向量表偏移量寄存器 
 __IO uint32_t AIRCR; //應(yīng)用程序中斷及復(fù)位控制寄存器 
 __IO uint32_t SCR; //系統(tǒng)控制寄存器 
 __IO uint32_t CCR; //配置與控制寄存器 
 __IO uint8_t SHP[12]; //系統(tǒng)異常優(yōu)先級寄存器組 
 __IO uint32_t SHCSR; //系統(tǒng) Handler 控制及狀態(tài)寄存器 
 __IO uint32_t CFSR; //MFSR+BFSR+UFSR 
 __IO uint32_t HFSR; //硬件 fault 狀態(tài)寄存器 
 __IO uint32_t DFSR; //調(diào)試 fault 狀態(tài)寄存器 
 __IO uint32_t MMFAR; //存儲管理地址寄存器 
 __IO uint32_t BFAR; //硬件 fault 地址寄存器 
 __IO uint32_t AFSR; //輔助 fault 地址寄存器 
 __I uint32_t PFR[2]; //處理器功能寄存器 
 __I uint32_t DFR; //調(diào)試功能寄存器 
__I uint32_t ADR; //輔助功能寄存器 
 __I uint32_t MMFR[4]; //存儲器模型功能寄存器 
 __I uint32_t ISAR[5]; //ISA 功能寄存器 
} SCB_TypeDef; 

在 Sys_Soft_Reset 函數(shù)里面,我們只是對 SCB-> AIRCR 進行了一次操作,即實現(xiàn)了 STM32的軟復(fù)位。AIRCR 寄存器的各位定義如圖 5.2.3.1 所示:

  1. usart 文件夾介
    1. usart.c 里面包含了 2 個函數(shù)
      1. 一個是 void USART1_IRQHandler(void);
      2. 另外一個是 void uart_init(u32 bound);
      3. 還有一段對串口 printf 的支持代碼,如果去掉,則會導(dǎo)致 printf 無法使用,雖然軟件編譯不會報錯,但是硬件上 STM32 是無法啟動的,這段代碼不要去修改。
    2. printf 函數(shù)向串口發(fā)送我們需要的內(nèi)容,方便開發(fā)過程中查看代碼執(zhí)行情況以及一些變量值這段代碼不需要修改,引入到 usart.h 即可。
    3. uart_init 函數(shù) ,這個很常見,也很重要,筆記中的串口通信和通信專欄都有詳細的講解。以下是 uart_init(u32 bound)的配置范例:
void uart_init(u32 bound){ 
 //GPIO 端口設(shè)置 
 GPIO_InitTypeDef GPIO_InitStructure; 
 USART_InitTypeDef USART_InitStructure; 
 NVIC_InitTypeDef NVIC_InitStructure; 
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA , ENABLE);  //使能 USART1,GPIOA 時鐘 
 //USART1_TX PA.9 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 復(fù)用推挽輸出 
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出 
 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.0 發(fā)送端 
 
 //USART1_RX PA.10 浮空輸入 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入 
 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.10 接收端 
 
 //Usart1 NVIC 中斷配置 配置 
 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //對應(yīng)中斷通道 
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//搶占優(yōu)先級 3 
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優(yōu)先級 3 
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能 
  NVIC_Init(&NVIC_InitStructure); //中斷優(yōu)先級配置 
 
 //USART 初始化設(shè)置 
  USART_InitStructure.USART_BaudRate = bound;//波特率設(shè)置; 
   USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為 8 位 
  USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位 
  USART_InitStructure.USART_Parity = USART_Parity_No; //無奇偶校驗位 
   USART_InitStructure.USART_HardwareFlowControl= 
 USART_HardwareFlowControl_None;//無硬件數(shù)據(jù)流控制 
   USART_InitStructure.USART_Mode = USART_Mode_Rx |USART_Mode_Tx;//收發(fā)模式 
  USART_Init(USART1, &USART_InitStructure); //初始化串口 
 
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟中斷 
  USART_Cmd(USART1, ENABLE); //使能串口 
} 
USART1_IRQHandler 函數(shù) 一共三個:
 DCD USART1_IRQHandler ; USART1
 DCD USART2_IRQHandler ; USART2
 DCD USART3_IRQHandler ; USART3

void USART1_IRQHandler(void)函數(shù)是串口 1 的中斷響應(yīng)函數(shù),當(dāng)串口 1 發(fā)生了相應(yīng)的中斷后,就會跳到該函數(shù)執(zhí)行。中斷相應(yīng)函數(shù)的名字是不能隨便定義的,一般我們都遵循 MDK定義的函名。這些函數(shù)名字在啟動文件 startup_stm32f10x_hd.s 文件中可以找到。

函數(shù)體里面通過函數(shù):

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) 

判斷是否接受中斷,如果是串口接受中斷,則讀取串口接受到的數(shù)據(jù):

Res =USART_ReceiveData(USART1);//(USART1->DR); //讀取接收到的數(shù)據(jù) 

讀到數(shù)據(jù)后接下來就對數(shù)據(jù)進行分析。

1、 PLLMUL

PLLMUL 用于設(shè)置 STM32 的 PLLCLK,STM32 支持 2~16 倍頻設(shè)置。我們常用的是 8M 外部晶振+9 倍頻設(shè)置,剛好得到 72Mhz 的 PLLCLK。從上圖可以看出,PLLMUL 的時鐘源,可以來自內(nèi)部 8M RC 振蕩/2 或者外部高速晶振(4~16Mhz)。這里切記 PLLMUL 設(shè)置后的頻率不要超過72Mhz(想超也是可以,最大 128M 也可以跑,不過一旦出問題 ST 是不負(fù)責(zé)的!)。

2、 SW

SW 是 STM32 的 SYSCLK(系統(tǒng)時鐘)切換開關(guān),從上圖可以看出,SYSCLK 的來源可以是3個:HSI、PLLCLK 和HSE。我們一般選擇PLLCLK作為SYSCLK。SYSCLK最大為 72M。這里提示一下大家:STM32 剛上電的時候,用的是系統(tǒng)內(nèi)部 8M RC 時鐘,之后運行程序才會把時鐘源設(shè)置為其他。

3、 系統(tǒng)滴答時鐘(SYSTICK)

SYSTICK 就是 CortexM3 的系統(tǒng)滴答時鐘,上圖清楚的表明 SYSTICK 的來源是AHB 分頻后再 8 分頻,因為我們一般設(shè)置 AHB 不分頻,所以 SYSTICK 的頻率就等于SYSCLK/8,如果 SYSCLK 為 72M,那么 SYSTICK 的頻率就是 9Mhz。前面介紹的延時函數(shù),就是基于 SYSTICK 來實現(xiàn)的。

4、 PCLK1

PCLK1 是 APB1 總線上外設(shè)的時鐘,最大為 36Mhz,所有掛載在 APB1 上的外設(shè),最大時鐘都是 36Mhz(定時器除外,原因見上圖),比如串口 2~5、SPI2 和 SPI3 等,在使用的時候,要特別留意。PCLK1 的時鐘可以通過 APB1 預(yù)分頻器設(shè)置,我們默認(rèn)一般設(shè)置為 2 分頻。

5、 PCLK2

PCLK2 是 APB2 總線上外設(shè)的時鐘,最大為 72Mhz,所有掛載在 APB2 上的外設(shè),最大時鐘都是 72Mhz,比如 GPIOA~G、串口 1、SPI1、ADC1~3 等。 PCLK2 的時鐘可以通過 APB2 預(yù)分頻器設(shè)置,我們默認(rèn)一般設(shè)置為 1,也就是不分頻。

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風(fēng)險等級 參考價格 更多信息
ATS08ASM-1 1 CTS Corporation Parallel - Fundamental Quartz Crystal, 8MHz Nom, GREEN, RESISTANCE WELD, METAL PACKAGE-2

ECAD模型

下載ECAD模型
$0.59 查看
510ABA156M250AAG 1 Silicon Laboratories Inc LVPECL Output Clock Oscillator,

ECAD模型

下載ECAD模型
$3.67 查看
CNY65B 1 Telefunken Semiconductor GmbH & Co Kg Transistor Output Optocoupler, 1-Element, 12000V Isolation,
$1.17 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜