一、實驗目的
1 了解ARM 處理器PWM接口的處理機制
2 掌握在S3C2440A 平台下進行PWM 接口應用編程
二、實驗設備
1 硬件:SinoSys-EA2440a 實驗平台,PC 機
2 軟件:ADS1.2 開發工具,DNW 工具
三、實驗任務
實現功能:
1 點擊鍵盤的“+”號提高蜂鳴器頻率,點擊“-”號則降低頻率。
2 通過ADS1.2 建立工程,編譯。程序通過ICE 仿真器調試。調試完成后通過DNW 直接下載到實驗板上運行。
實驗原理:
3.1概述
脈沖寬度調制(PWM),是英文“Pulse Width Modulation”的縮寫,簡稱脈寬調制,其廣泛應用在從測量、通信到功率控制與變換的許多領域中,是利用微處理器的數字輸出來對模擬電路進行控制的一種非常有效的技術。脈沖寬度調制是一種模擬控制方式,從物理意義上說,其根據相應載荷的變化來調制晶體管柵極或基極的偏置,來實現開關穩壓電源輸出晶體管或晶體管導通時間的改變,從實際使用上說,其通過高分辨率計數器,將方波的占空比來編碼一個具體的模擬信號。這種方式能使電源的輸出電壓在工作條件變化時保持恆定,是利用微處理器的數字輸出來對模擬電路進行控制的一種非常有效的技術。PWM 控制技術以其控制簡單,靈活和動態響應好的優點而成為電力電子技術最廣泛應用的控制方式,也是人們研究的熱點。由於當今科學技術的發展已經沒有了學科之間的界限,結合現代控制理論思想或實現無諧振軟開關技術將會成為PWM 控制技術發展的主要方向之一。
3.2 S3C2440 的PWM
由於PWM 的實際應用和相關寄存器非常之多,因此本文僅僅介紹和使用本系統所使用的相關概念和使用方法。PWM 控制器主要有4 個特征:1、由5 個16 位定時器、2 個8 位預分頻器以及2 個4 位分割器組成;2、擁有自動重載模式或者單擊脈沖模式;3、可編程控制輸出波形;4、死區發生器。其中除了定時器4 以外,其余三個均具有脈寬調制(PWM)功能,定時器4 僅僅是一個內部定時器,沒有輸出引腳。開發板定時器結構框圖如下:
3.3 PWM 相關寄存器介紹
PWM 的寄存器共有17 個,相應的寄存器分為5 組,分別為配置和模式選擇寄存器(TCFG0~TCFG1),定時器計數緩存寄存器(TCNTB0~ TCNTB4),定時器比較緩存寄存器(TCMPB0~ TCMPB3),定時器控制寄存器(TCON),定時器計數觀測寄存器(TCNTO0~TCNTO4)。
由於PWM 寄存器相對較多,不需要全部使用,只需要使用系統需要的即可。本系統中最為重要的是TCNTB0 和TCMPB0,TCNTB0 決定着PWM 的脈沖頻率,而PWM 的寬度則由TCMPB0 決定。一般來說,如果要得到一個較高的PWM 的輸出值,就需要增加TCMPB0的值,如果說輸出反轉器被時能,那么增加和減少的結果也是反轉的。基於雙緩沖器的特性,下一個PWM 周期的TCMPB0 的值可以通過中斷或者其他手段在當前PWM 周期中任何一點寫入。
3.4設置占空比和輸出頻率
報警器采用TOUT0 作為其脈沖輸入信號,通過修改TCFG0 和TCFG1 設置預分頻值和計時器分割器的選擇(可查詢表3.2),占空比(rate)由TCNTB0 和TCMPB0 決定
其值的計算公式如下:
div=PCLK/{pre value+1}/{div value}/freq
{pre value+1}=0~255 由TCFG0 決定
{div value}=2,4,6,8,16,32 由TCFG1 決定
rate={cmp value}/{tcn value}
最終的value 由div 和rate 生成,即
value=div*rate //rate<1;
實驗流程圖(簡化)分析如下,設置TCNTB0 為180(70+110),設置TCMPB0 為110,設置人工加載位、配置極性轉換位。同時設置下一次TCNTB0 為80(40+40),設置TCMPB0為40 作為下一次定時的參數。定時器延遲一定時間后定時器下降計數器開始計數,當TCNTB0 和TCMPB0 數值一致時,TOUT0 的邏輯將由低變高。當TCNTB0 計數為0 時,定時器中斷打開,同時將寄存器數據更新,從而繼續上一次操作。從而形成了下圖的波形圖,此時報警器會根據所設置的頻率發出不同大小的聲音,已基本實現所要功能。
3.5 蜂鳴器接口電路
系統的報警器電路就是由平台將S3C2440 的定時器0 的脈沖輸出端口(TOUT0)GPB0與報警器的脈沖輸入端口相連。在系統初始化時,就要進行I/O 端口初始化,設置端口控制寄存器(將再下面講到),將GPB0 設置為工作方式1,並設置為輸出狀態。控制電路如圖所示,
3.6 源代碼分析
首先是main_beep.c程序
#define GLOBAL_CLK 1 #include <stdlib.h> #include <string.h> #include "def.h" #include "option.h" #include "2440addr.h" #include "2440lib.h" void Main(void) { int i; U8 key; U32 mpll_val = 0 ; Port_Init(); //端口初始化 Isr_Init(); //中斷初始化 i = 2 ; //設置系統時鍾 400M switch ( i ) { case 0: //200 key = 12; mpll_val = (92<<12)|(4<<4)|(1); break; case 1: //300 key = 13; mpll_val = (67<<12)|(1<<4)|(1); break; case 2: //400 key = 14; mpll_val = (92<<12)|(1<<4)|(1); break; case 3: //440!!! key = 14; mpll_val = (102<<12)|(1<<4)|(1); break; default: key = 14; mpll_val = (92<<12)|(1<<4)|(1); break; } //init FCLK=400M, so change MPLL first ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3); ChangeClockDivider(key, 12); //設置分頻 1:4:8,即HCLK=100M PCLK=50M cal_cpu_bus_clk(); //計算總線頻率 Uart_Init(0,115200); //串口初始化 波特率為115200 Uart_Select(0); //選者串口0 Clk0_Disable(); Clk1_Disable(); i=0; Uart_Printf("\nBegin to start BEEP test,OK? (Y/N)\n"); get_key: key = Uart_Getch(); if(key=='y'||key=='Y') { beep_test(); } else if(key=='n'||key=='N') { Uart_Printf("\nOh! You quit the test!\n"); } else goto get_key; }
接下來是beep.c程序
#include "def.h" #include "option.h" #include "2440addr.h" #include "2440lib.h" #include "2440slib.h" /* freq 為頻率 */ void Beep( U32 freq ) { rGPBCON&=~0x3; rGPBCON|=0X2; //設置B口為TOUT0模式 rTCFG0&=~0XFF; rTCFG0|=0XF; //預分頻15+1 PCLK rTCFG1&=~0XF; rTCFG1|=0X3; //再16分頻 計數頻率等於PCLK/256 //因為定時器的選擇PCLK作為源時鍾頻率,但是定時器不可能工作在這么高的頻率下,所以我們要通過二次分頻來降低定時器的工作頻率,上面這四句就是起設置分頻值的作用。 rTCNTB0=(PCLK>>8)/freq;; //右移8位即除以256。若freq=1,則定時周期正好為1s rTCMPB0=rTCNTB0>>1; //定時器0比較緩沖器的值,PWM輸出占空比50% rTCON&=~0X1F; rTCON|=0XB; //自動重載,關閉變相,手動更新,開啟定時器0 rTCON&=~2; //清除手動更新位 } void beep_test(void) { U8 key; U16 freq=200; rGPBCON|=0xffffff&0x01; //set GPB0 as output while(1) { key=Uart_Getch(); if(key=='+') { if ( freq < 20000 ) { freq += 100 ; Uart_Printf( "Press +to increase/reduce the frequency of beep !\n" ) ; } } else if( key == '-' ) { if( freq > 100 ) { freq -= 100 ; Uart_Printf( "Press - to increase/reduce the frequency of beep !\n" ) ; } } Beep(freq) ; } }
2013-04-02 17:03:30