05.03 ARM 嵌入式編程與實戰應用(STM32F1 系列)第4章RGB 舞臺燈光

上一章主要介紹了基本定時器中斷的用法,本章將首先介紹在線仿真調試程序的方法,然後講解STM32的位帶操作,最後學習通用定時器的輸出比較功能產生PWM,並且通過實用例程進一步強化實際產品開發能力。

4.1Keil在線仿真調試

51單片機程序相對簡單,調試程序時依靠程序員根據實驗現象做分析,改動程序進行邏輯驗證的方式查找程序邏輯錯誤。隨著要實現的功能越來越複雜,所選用的單片機從51單片機換到了STM32,所要編寫的代碼量也成倍增加,因此調試工具也要鳥槍換炮,採用ST-Link在線調試程序。

在線仿真調試就是將程序下載到系統中運行後,可以對程序進行逐步跟蹤並且察看數據的變化。有了在線仿真調試功能,程序員可以測試每一行源代碼,從而找出程序錯誤。在這個過程中,程序員可以通過設置斷點,顯示和監控內存內容、寄存器內容、控制輸入輸出等多種方式,從而找出錯誤根源。

在線仿真調試可以實現Keil軟件和目標板的聯調,更加直觀瞭解單片機運行的過程,高效快速排查問題,從而提高產品和項目開發的效率。

4.1.1 軟件配置

在所構建的工程模板中的system_stm32f10x.c文件中,有兩段針對系統時鐘的宏定義,如圖4-1所示,用戶選擇哪個時鐘就在圖4-1左側一段取消註釋哪個時鐘,其他時鐘全部註釋掉,這裡系統默認用的是72MHz。

圖4-1 系統時鐘宏定義

在線調試仿真,Keil軟件的配置信息必須要和實際目標板的運行時鐘一致,因此在Debug選項卡中選擇ST-Link仿真器,然後點擊Settings按鈕,如圖4-2所示。

圖4-2 debug窗口

打開Trace選項卡,在Core Clock處填寫系統時鐘72.000000MHz,如圖4-3所示。

圖4-3 設置硬件仿真時鐘頻率

當程序編譯通過,顯示0錯誤0警告的時候,選擇菜單項Debug-->Start/Stop Debug Session,或者點擊圖4-4中紅色方框內的按鈕,進入在線仿真調試頁面。

圖4-4啟動/結束仿真調試按鈕

在程序窗口中顯示代碼行號的左側灰色區域點擊鼠標左鍵,設置斷點(紅色標記)。如圖4-5所示:


1、Reset:為程序復位;

2、Run:為全速運行;

3、Step:為單步執行,一次執行一條語句。當遇到函數時就進入並且繼續單步執行;

4、Step Over:也是單步執行,但它遇到函數時不會進入函數內部,而是直接執行整個函數;

5、Step Out:單步執行到函數內時,用step out就可以執行完函數餘下部分,並返回到上一層函數。

點擊全速運行,程序就會循環執行,如果設置了斷點,每次運行到斷點處就會停止。此時,可以通過點擊view菜單,打開watch窗口,然後設定所要觀察的變量和寄存器,當運行到斷點處或者單步運行時,就可以觀察出寄存器狀態。

圖4-5 Keil仿真界面

在實際項目和產品開發的過程中,調試程序功能往往是程序員的最重要的工作,而在線仿真調試這個功能非常重要,體現在可以幫助程序員快速查找定位問題和解決問題。這個重要的功能主要是針對邏輯錯誤查找的,因此難以舉例演示,這個功能的重要性需要慢慢在開發中體會。

4.2位帶操作

4.2.1 位帶、位帶識別區

前邊操作STM32的GPIO時都是採用操作寄存器的方式,也就是一次性操作16位,這種方式編程比較複雜,單片機的執行效率也低。編寫程序代碼時,更多時候是操作一組GPIO中的某一位,而其它位不需要操作,這種情況下希望用更加簡易的方式,不需要對16個口全部操作,就可以使用STM32的位帶操作。

如果之前學過51單片機,對位帶並不陌生。在51單片機中有一部分寄存器,可以直接對寄存器中的某一位進行讀寫;比如sbit LED = P1^0; LED = 0;再比如TR0 = 1;這些都是位帶操作。除此之外,51單片機的內存地址20H到2FH這16個字節共128位的內存,是可以位操作的,其他內存地址只能字節操作。用C語言編程時,內存的位操作一般不直接使用,但可以直觀的感受到寄存器的位操作。

STM32的位帶在《Cortex-M3權威指南》資料中有詳細介紹,可以進行位帶操作的有兩部分,分別是SRAM區的最低1MB範圍和片內外設區的最低1MB範圍。SRAM區1MB的內存一般編程的時候不常用,用的比較多的是片內外設區的最低1MB,也就是外設寄存器所在地址空間。

編程操作時,不方便對外設寄存器的某一位直接訪問,因此在片內外設區另外開闢了一個32MB大小的尋址空間,取名為位帶別名區。在這個地址空間中,每4個字節對應了位帶區的一個位。有了這層關係,對位帶別名區的某4個字節的操作,就等價於對這個地址對應的位帶區的某一位的操作。

Cortex-M3的地址空間是4GB,片內外設的地址從0x40000000到0x5FFFFFFF共512MB。其中從0x40000000到0x40100000的地址空間是片內外設的1MB的位帶區,從0x42000000到0x43FFFFFF是對應的32MB的位帶別名區,如圖4-6所示。

圖4-6 片內外設地址

一般情況下,要改寫某一個寄存器某一位的值,如果不採用位帶操作,要分三步,第一步讀出寄存器的值,第二步改變需要改變的那一位,第三步將改變後的值寫進寄存器;而如果採用位帶操作程序代碼會更簡單,代碼執行效率也更高。

4.2.2 位帶和位帶別名區

編寫代碼時我們要操作某個寄存器的某一位,比如是GPIO的某一個IO口,那在程序中直接操作的就是相對應的位帶別名區的一個32位的地址。首先確定要操作的寄存器的地址,也就是他的位帶地址,然後確定要操作的是哪一位,最終根據映射關係計算出要操作的這一位所映射的位帶別名區的地址。

統一用一個片上外設區和SRAM區的位帶與位帶別名區的映射公式:

1、其中addr表示的是外設寄存器的地址,bitnum表示的是要操作的這一位在這個寄存器的第幾位。

2、(addr & 0xF0000000)+0x2000000區分的是片上外設區還是SRAM區的位帶,片上外設區的位帶地址是從0x40000000到0x40100000,SRAM區的位帶地址是從0x20000000到0x20100000,大多數情況下只操作外設。

3、(addr &0x00FFFFFF)<<5)表示這一位所在的寄存器的第0位對應的位帶別名區地址。由於位帶區的一個寄存器是32位,因此映射到位帶別名區就是32個字節,左移5相當於乘以32。

4、bitnum<<2是確定這一位相對於寄存器第0位對應的位帶別名區地址的偏移地址。由於相對於寄存器的第0位,每偏移1個位,位帶別名區就偏移4個字節,因此需要左移2位,相當於乘以4。

0x4001080C~0x4001080F表示的是GPIO端口A上"端口輸出數據寄存器(ODR)" 4字節的地址空間。該寄存器的0~15位,對應端口A上的16個引腳。以0x4001080C地址空間中的第0位(0 bit)為例,它表示PA0引腳,通過膨脹關係,在位帶別名區有一個4字節(32bit)大小的區域也表示PA0引腳,該區域的起始地址為0x42210180,如圖4-7所示。之前我們是通過對ODR寄存器的第0位"置1",控制PA0引腳輸出高電平,現在我們可以直接對PA0對應的位帶別名區的地址空間置1,實現同樣的功能,並且操作更簡單,效率更高。

圖4-7位帶區與位帶別名區的膨脹對應關係圖

實際開發中,位帶主要是應用在GPIO端口操作。將GPIO端口輸入/輸出數據寄存器的數據位通過公式找到對應的位帶別名區地址,將代碼保存在config.h文件中,若想使用位帶操作,必須添加以下代碼,之後的例程中默認在config.h中添加代碼。具體代碼如下:

通過上面位帶設置程序,對IO口賦值時不必再使用"位設置"或"位清除"函數,而是可以像操作51單片機的IO口一樣操作STM32的GPIO引腳。比如以PA1引腳為例,設置其為輸出模式:

首先使用宏定義PA1對應的位帶區地址,即: define PA1 PAout(1) 。其中PA1為宏定義的引腳名稱,這個可以隨意設置,PAout(1)才是關鍵,其中PA表示GPIO端口A,out表示輸出模式,in表示輸入模式;(1)表示引腳號。

通過這種操作,可以用PA1 = 1; 替代GPIO_SetBits(GPIOA, GPIO_Pin_1);

4.2.3 練習

將2.6,3.6.3,3.9小節中的程序,改為位帶方式,重新編寫一編,在此不再粘貼代碼,具體代碼可以到"Kingst-32F1開發板配套光盤\\《ARM嵌入式編程與實戰應用--STM32F1系列》例程\\Lesson4"文件夾下查看。

4.3 RGB調色

在音樂廣場、KTV、酒吧等場所,往往都有激情四射的舞臺燈光,效果絢爛奪目,本小節通過開發一套簡易舞臺燈控制系統來提高讀者的實際產品開發能力。

4.3.1 RGB調色原理

前邊介紹過RGB小燈的發光原理,理論上三原色相互搭配,可以產生七色,如圖4-8所示。有了七種顏色,就可以編程實現單色顯示、單色漸變、漸變切換、單色閃爍、閃爍切換等複雜的功能,讓簡單的RGB小燈通過程序發揮出強大的功能。

圖4-8 RGB調色

4.3.2

PWM脈寬調製

PWM是Pulse Width Modulation的縮寫,它的中文名字是脈衝寬度調製,一種說法是它利用微處理器的數字輸出來對模擬電路進行控制的一種有效的技術,其實就是使用數字信號達到一個模擬信號的效果。

首先從它的名字來看,脈衝寬度調製,就是改變脈衝寬度來實現不同的效果。我們先來看三組不同的脈衝信號,如圖4-9所示。

圖4-9 PWM波形

這是一個週期是10ms,即頻率是100Hz的波形,但是每個週期內,高低電平脈衝寬度各不相同,這就是PWM的本質。在這裡大家要記住一個概念,叫做"佔空比"。佔空比是指高電平的時間佔整個週期的比例。比如第一個週期的佔空比是40%,第二週期的佔空比是60%,第三週期的佔空比是80%,這就是PWM的解釋。

如果我們用100Hz的信號,如4-9所示,假如高電平熄滅小燈,低電平點亮小燈的話,第一部分波形熄滅4ms,點亮6ms,亮度最高,第二部分熄滅6ms,點亮4ms,亮度次之,第三部分熄滅8ms,點亮2ms,亮度最低。通過定時器的輸出比較功能,就可以實現PWM的脈衝寬度調製,來調整小燈的亮暗程度。

4.4 通用定時器調製PWM

4.4.1 通用定時器輸出比較功能

STM32F103ZE擁有TIM2、TIM3、TIM4和TIM5共4個通用定時器。這4個定時器除了具備基本定時器的向上計數器功能外,還可以向下、向上/向下計數。此外還具備獨立通道,能夠實現輸入捕獲、輸出比較、PWM輸出、單脈衝輸出等功能,其中輸出比較模式用來控制輸出一個波形,或者指示一段給定的的時間已經計到,這裡所說的計到指的是設定一個比較值與計數器中的計數值進行對比,當計數值等於設定的比較值時表示設定的時間計到。比如設置定時器預分頻值為7199,預裝載值為99,向上計數,當啟動定時器後,計數器開始從0計數到99共計10ms,然後溢出,重新計數。通過輸出比較功能設定一個比較值為49,當計數器計數到49時會產生一個捕獲/比較事件,告訴單片機已經計到比較值,此時可以控制IO口輸出低電平,然後計數器繼續計數到99,當計數器溢出時再設置IO口輸出高電平。計數器從0計到49期間輸出高電平,從50計到99之間輸出低電平,每隔10ms循環一次,這就相當於輸出了一個週期為10ms,佔空比為50%的PWM信號。通過改變比較值的大小,就可以設定PWM的佔空比。

STM32自帶的PWM輸出功能就是通過輸出比較模式設定佔空比信號,進而通過硬件控制通道引腳的電平狀態。由於RGB小燈引腳沒有連接到定時器的外部通道上,因為無法使用硬件PWM輸出功能,但是依舊可以利用定時器的輸出比較功能生成PWM,這比使用定時器控制IO口模擬產生PWM要精確很多。

已知每個通用定時器擁有4路捕獲/比較通道,每路通道都擁有一個捕獲/比較寄存器(TIMx_CCRx)用於裝載比較值,該寄存器同樣包含兩個寄存器,一個是用戶可以操作的,用於寫入比較值,另一個用於和計數器進行比較的當前捕獲/比較寄存器。如果設置了捕獲/比較模式寄存器x(TIMx_CCMRx)中的輸出比較預裝載使能位(OCxPE),寫入到TIMx_CCRx寄存器的比較值將在更新事件到來時才會傳入到當前捕獲/比較寄存器,否則比較值將立即寫入當前捕獲/比較寄存器,即寫入的比較值立即生效,通常情況下默認使能輸出比較預裝載位,捕獲/輸入寄存器結構如圖4-10所示。

圖4-10 通用定時器捕獲/比較通道結構圖

當計數器與捕獲/比較寄存器(TIMx_CCRx)中的內容相同時,如果設置了事件產生寄存器(TIMx_EGR)中的CCxG位,將會在通道上產生一個捕獲/比較事件,若設置了相應的中斷使能位(TIMx_DIER寄存器中的CCxIE位),則會產生一個捕獲/比較中斷。

配置通用定時器的輸出比較功能步驟如下:

1、配置通用定時器的基本定時功能(參考3.6節基本定時器配製方法)

2、設置 TIMx 捕獲/比較寄存器(CCRx)的預裝載使能(x表示1、2、3、4)

3、設置 TIMx 捕獲比較寄存器(CCRx)的值

4、設置NVIC中斷優先級

5、清除TIMx更新中斷及捕獲/比較x中斷標誌位

6、使能TIMx更新中斷和捕獲/比較x的中斷源

7、使能TIMx定時器

其中設置 TIMx 捕獲/比較寄存器的預裝載使能所用庫函數如下:

上面四個庫函數分別對應設置捕獲/比較寄存器1、2、3、4的預裝載使能,其中TIMx: x 可以是 2、3、4、5來選擇 TIM 外設;TIM_OCPreload:輸出比較預裝載狀態,參數如表4-1所示;

設置捕獲比較寄存器(CCRx)的值所用到的庫函數如下:

其中TIMx:x可以是 2、3、4、5,來選擇 TIM 外設,CompareX(X表示1、2、3、4)設定的捕獲/比較X寄存器新值。

關於設置捕獲/比較中斷源可以參考教程3.6.3小結表3-5,在此不再重複介紹。

4.4.2 RGB七色漸變實驗

由於人眼視覺暫留效應,當小燈的閃爍頻率為100Hz以上時,人眼基本分辨不出小燈在閃爍,因此PWM的頻率要達到100Hz以上,假定PWM的頻率為100Hz,其週期為1/100Hz=10ms,假設調節級別設定為256級,則每一級的時間約為39us,因此需要設定定時器的最小計數週期為39us。本節通過定時器TIM5的捕獲/比較通道1、2、3分別控制R、G、B三個引腳的輸出電平狀態,產生三路PWM信號控制RGB刷新。上一章介紹了配置定時器TIM6定時1s進入中斷,本節在上一章的基礎上,設置定時器TIM5自動重裝載值為255,預分頻值為72*39-1,即計數週期為39us;設置TIM5捕獲/比較通道1、2、3預裝載使能,並使能對應中斷。捕獲/比較1、2、3寄存器的取值範圍為0~255,對應256級調節亮度,當定時器TIM5計數到設定的捕獲/比較x寄存器的數值時,觸發捕獲/比較x中斷,在中斷中設置RGB相應引腳輸出高電平,熄滅小燈;當計數到255後產生定時器更新中斷,設置RGB引腳輸出低電平,點亮小燈。同時使用TIM6定時50ms刷新捕獲/比較1、2、3寄存器中設定的比較值,控制RGB的亮度,實現七色漸變效果。

具體代碼如下:

4.5 簡易舞臺燈控制系統

生活中經常能在熒幕或者舞臺現場看到絢麗的舞臺燈光,本節對實際舞臺燈光效果進行了拆分,通過Kingst-32F1開發板自帶的一個RGB小燈實現舞臺燈光的各類顯示效果。

4.5.1 舞臺燈光控制程序

一、首先設計舞臺燈光控制器的功能需求,如下所示:

1、單色閃爍顯示模式——實現紅、綠、藍、黃、紫、青、白七種顏色單獨閃爍顯示類型;

3、多色閃爍顯示模式——實現紅綠、綠藍、紅藍、紅綠藍間隔閃爍類型;

4、多色漸變顯示模式——實現紅綠藍三色漸變、紅黃綠紫藍青白七色漸變顯示類型;

5、按鍵實現顯示模式可調;

6、按鍵實現閃爍和漸變速度可調;

7、數碼管顯示當前RGB顯示模式。

二、設置舞臺燈光控制器的整體程序框架

1、功能劃分

按鍵1: RGB模式選擇按鍵;

範圍1~13: 1-紅光閃爍,2-綠光閃爍,3-藍光閃爍,4-黃光閃爍,5-紫光閃爍,

6- 青光閃爍,7-白光閃爍,8-紅綠交替閃爍,9-綠藍交替閃爍,

10- 紅藍交替閃爍,11-紅綠藍交替閃爍,12-紅綠藍三色漸變,

13-紅黃綠紫藍青白七色漸變

按鍵2:調節閃爍或漸變速度逐漸變快

按鍵3:調節閃爍或漸變速度逐漸變慢

數碼管:顯示當前RGB燈光模式,使用數字1~13表示

三、編程程序代碼

本節需要新建兩個文本文件,保存在lighting.h和lighting.c,用於存放舞臺燈光控制程序。

具體代碼如下:

長按識別關注

知識共享|助力夢想