郭 辛
(綿陽師范學院機電工程學院,四川綿陽 621000)
單片機自誕生之日起已走過近半個世紀的歷程.隨著電子技術和計算機技術的飛速發展,進入21世紀以來以嵌入式系統為代表的新興技術正在逐漸占據工業控制領域主導地位,并逐步取代以8位處理器為核心的傳統測控系統[1].近年來由于數字信息技術和網絡技術的廣泛應用,單片機作為主流核心處理器的地位逐步下降,現代電子技術的發展正朝著智能化、網絡化和低功耗的方向邁進.新技術的不斷更新,需要新的設計思想的注入才能滿足技術發展需求.那么,如何將新興技術融合到傳統知識架構體系,將基礎理論與工程應用實際相結合,就成為設計人員急需破解的難題.
ARM作為一種32位的高性能、低成本的嵌入式RISC微處理器,得到了廣泛的應用,STM32系列是意法半導體 (STMicroelectronics) 集團專為要求高性能、低成本和低功耗的嵌入式應用設計的ARM Cortex-M系列產品的代表作.基于STM32的嵌入式技術已經滲透在工業控制系統、數據采集系統、智能化儀器儀表和辦公自動化等諸多領域的應用,甚至在很大程度上正在改變我們現有的商業模式和工作生活方式,如智能手機、導航系統、無人機和平板電腦等,并呈現出明顯的系統化、人工智能化和物聯網的趨勢.
目前, Cortex系列處理器已經占據了大部分嵌入式處理器的中高端產品市場,而嵌入式系統的應用開發對從業者要求很高,初學者若要快速掌握其原理并在實際工程中加以應用,必須改變傳統的思維方式并構建新的設計理念.本文以STM32F103RC處理器(Cortex-M普通型號之一)為平臺,通過對定時器、中斷系統和LCD顯示模塊的組合設計為例,針對基于固件庫設計思想的方法進行探討與總結,以開啟嵌入式系統的應用設計學習之門[2].
固件庫是指“STM32 標準函數庫”,它是由 ST 公司針對 STM32 提供的函數接口,即 API(Application Program Interface),是一個固件函數包,它由程序、數據結構和宏組成,包括了微控制器所有外設的性能特征.它是架設在構成部件的寄存器與用戶驅動層之間的代碼,向下處理與寄存器直接相關的配置,向上為用戶提供配置寄存器的接口[3].部件的調用和基本操作寫成了通用的子函數,對復雜的硬件操作實現了函數封裝.
在以51單片機為代表的8位機由于硬件系統相對簡單,通常采用直接配置寄存器的方式來進行應用開發;而32位處理器核內系統復雜,外設資源豐富.應用系統若仍舊采用傳統的設計方式,不但效率低、可移植性差,而且技術難度大,已不能適應較復雜的工程應用.
基于固件庫的技術思想為解決這一問題提供了新思路:開發者根據具體任務需求按照CMSIS標準構建工程,利用固件庫提供的資源,設計和改造相關函數以實現對部件的操作.本文結合綜合實驗項目的開發——電子時鐘的設計為例,首先介紹庫函數中主要涉及的定時器和LCD顯示驅動的基本結構和工作原理,在此基礎上利用現有庫資源進行功能設計與系統構建.
STM32F1 系列中,共有 8 個定時器TIM1—TIM8,分為基本定時器,通用定時器和高級定時器.基本定時器 TIM6 和 TIM7 是一個 16 位的只能向上計數的定時器,它只能定時,沒有外部 I/O;通用定時器 TIM2/3/4/5 是一個 16 位的可以向上/下計數的定時器,可以定時、輸出比較和輸入捕捉,每個定時器有四個外部I/O;高級定時器 TIM1/8是一個 16 位的可以向上/下計數的定時器,可以定時、輸出比較,輸入捕捉,以及實現三相電機互補輸出信號,每個定時器有 8 個外部 I/O[4].此例以TIM6作定時器,設計一款LCD屏顯電子時鐘,計時60 min,最小顯示值1s.
根據STM32參考手冊基本定時器的功能結構如圖1所示[3].

圖1 基本定時器功能框圖Fig.1 Block Diagram of Basic Timer Function
定時器若要向外提供基本時鐘信號,需對相關寄存器進行參數設置:
1)時鐘源TIM*CLK:根據STM32時鐘系統設置,通常掛載APB1時鐘總線,默認取值為72MHz[5];
2)16位分頻器PSC:用于存放預分頻值,分頻范圍1~65536,則時鐘周期
CK_CLK= (PSC+1)/ TIM*CLK
(1)
即每計1個數的時間間隔
3)自動重裝載寄存器ARR:用于存放16位計數值,用于設定定時長度
Td= CK_CLK*ARR
(2)
綜上所述,首先對定時器初始化,將所預設參數寫入到對應的結構體中,賦值包含以下內容:
……
#define BASIC_TIM TIM6
#define BASIC_TIM_CLK RCC_APB1Periph_TIM6
#define BASIC_TIM_ARR 1000-1
#define BASIC_TIM_PSC 71
……
按照以上參數設置,基本定時時長為:
Td= 〔(PSC+1)/ TIM*CLK〕 *ARR =(72/72M)*1 000=1ms
(3)
如圖2所示,內部定時器提供基準時長Td=1ms,引入定時中斷,每計時1ms中斷一次;中斷次數time= 1 000產生1s定時,即LCD 顯示屏每隔1 s更新一次秒位(sec)計數值;每計滿60 s更新一次分位(min)計數值,并將其分別顯示到LCD屏上.

圖2 定時原理示意圖Fig.2 Schematic Diagram of Timing Principle
內部時基信號產生后,還需將結果顯示出來,STM32F103實驗板配2.8吋16位數據接口液晶屏,控制芯片采用了ILI0341.ILI0341是一個用于TFT液晶顯示的單芯片控制驅動器,具有262,144色的240RGB×320像素顯示方案;ILI0341支持8/9/16/18位數據總線的MCU接口,6/16/18位數據總線的RGB接口以及3/4線的SPI 接口[4],本示例中液晶屏控制器采用了預先配置的8080 接口通訊,使用 16 根數據線的 RGB565格式.其相關驅動程序按照ILI9341標準編制,主要由如下幾步完成:
1)初始化LCD數據/控制管腳ILI9341_GPIO_Config ().
2)點亮背光 ILI9341_BackLed_Control ( ENABLE ).
3)初始化控制寄存器ILI9341_REG_Config ().
4)設置顯示模式ILI9341_GramScan(LCD_SCAN_MODE).
初始化液晶屏完成后,調用顯示驅動函數.
5)清屏ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH).
6)設置顯示字符字體(8x16)、顏色(紅字)及背景(黑底)LCD_SetFont(&Font8x16);LCD_SetColors(RED,BLACK).
7)使用c標準庫把時間變量轉化成字符串并顯示 sprintf(dispBuff,"time : %d: %d ",y,x);[6]LCD_ClearLine(LINE(6));ILI9341_DispStringLine_EN(LINE(6),dispBuff).將數據轉換成字符串,存放于數組dispBuff并寫入指定行.
在以51單片機為主控單元的系統中,我們往往采用直接配置寄存器控制字的方法來操控硬件,因為MCS-51內部寄存器只有21個,而且功能簡單,程序設計直觀簡便;而STM32作為系統主控制器,其內部設備多達幾十個,而控制這些設備的寄存器有幾百個,若要使系統維持基本運轉,操作這些寄存器所需的驅動程序代碼成千上萬行,這對于應用開發者來說逐條寫程序是不現實的.芯片廠商將這些外設的驅動源碼封裝成固件函數包提供給用戶,由用戶在此基礎上進行應用開發,因此以STM32為主控制器的應用系統開發就包括項目搭建和程序設計兩部分.
1)啟動文件startup_stm32f10x_hd.s:設置堆棧、PC指針和配置系統時鐘等.
2)時鐘配置文件system_stm32f10x.c:將外部時鐘倍頻并為各子模塊提供配套的時鐘源.
3)內核相關的驅動文件core_cm3.h:內核的外設寄存器映射;core_cm3.c:內核的外設驅動固件庫.
NVIC(嵌套向量中斷控制器)描述文件:misc.h和misc.c.
4)外設相關的庫文件stm32f10x.h:實現了內核之外的寄存器映射;stm32f10x_xx.c:外設的驅動函數庫文件;
核外設備:GPIO、USRAT、I2C、SPI、FSMC等驅動文件.
5)頭文件的配置文件stm32f10x_conf.h 頭文件的配置文件,將多個外設的頭文件進行統一調配管理,如:
stm32f10x_usart.h,stm32f10x_i2c.h,stm32f10x_spi.h,stm32f10x_adc.h,stm32f10x_fsmc.h...
對外設描述的結構體,映射地址的頭文件都放在stm32f10x_conf.h中進行聲明,使用時只需包含該配置頭文件即可,并可通過“宏斷言”函數進行選配.
6)專門注冊中斷服務函數的C文件:stm32f10x_it.c和stm32f10x_it.h.這些文件按照相應的規則分布在不同的路徑下,這個規則就是ST集團與各芯片開發商共同制訂的CMSIS標準[3].
參照CMSIS標準創建項目文件以及組文件夾:CMSIS、FWlib、inc、src、Project、Output和User,并將固件庫提供的基本源代碼拷貝到對應目錄下,如:項目文件創建并保存在Project路徑下;核外外設的驅動程序復制到src源碼目錄下;對描述部件的寄存器結構體統一定義在inc頭文件目錄下;而直接針對任務而設計的程序文件通常放置在用戶目錄User中,如main()程序,中斷服務程序等等.
在本例的電子時鐘設計中,根據前面所介紹的定時器和LCD的工作原理,配置相關驅動程序或函數集,并寫入預設的定時參數,重新組合、設計功能程序:1)計算并確定定時初值以及分頻器參數;2)LCD 初始化機模式配置,設計變量顯示程序;3)中斷服務程序的數據處理部分程序設計.
首先對定時器、中斷寄存器、AFIO引腳以及液晶屏進行初始化設置,并將設計的參數值寫入對應寄存器中;開啟定時時鐘和中斷系統,主程序實時不間斷顯示時間——分位(min)和秒位(sec);中斷服務程序完成定時器計數值的更新和處理,并將其轉換成時間變量傳回主程序顯示,程序流程圖見圖3.

圖3 程序流程圖Fig.3 Program Flow Chart
由于內部時鐘源能提供1K~72MHz時鐘信號,誤差為±1%,則時鐘誤差最小可以控制在0. 01 us范圍內.通過上述實驗教學項目的開發,總結出32位微處理平臺在工程實踐中的設計流程:(1)任務分析:根據設計要求明確項目所需實現功能,提出設計方案主體框架、功能模塊構成、技術實現路線;(2)搭建工程項目:根據STM32平臺所提供資源,確定主控系統模塊并搭建項目主體框架;對照現有資源匹配現有的子模塊,制作與主系統的接口函數并確定底層部件參數;(3)主系統集成:完成主要業務的程序編制并進行系統整和調試.基于STM32平臺的嵌入式系統開發,應采用立足于對系統資源的整合和集成的思維方式,將各部件的驅動程序看作一種供開發者使用的函數集合,開發者需要做的是將這些離散、抽象的“程序塊”有機地進行組合,以搭積木的方式進行模塊化設計,這才是嵌入式系統應用的本質所在.