眾所周知,微控制器從模擬傳感器獲取模擬輸入,并使用ADC(模數(shù)轉(zhuǎn)換器)來處理這些信號。但是,如果微控制器想要產(chǎn)生模擬信號來控制伺服電機(jī)、直流電機(jī)等模擬操作設(shè)備怎么辦?微控制器不會產(chǎn)生像 1V、5V 這樣的輸出電壓,而是使用一種稱為 PWM 的技術(shù)來操作模擬設(shè)備。PWM的一個(gè)例子是我們筆記本電腦的冷卻風(fēng)扇(直流電機(jī))需要根據(jù)溫度進(jìn)行速度控制,這也是通過在主板中使用脈寬調(diào)制(PWM)技術(shù)來實(shí)現(xiàn)的。
在本教程中,我們將使用 ARM7-LPC2148 微控制器中的 PWM 控制 LED 的亮度。
PWM(脈沖寬度調(diào)制)
PWM 是一種使用數(shù)字值控制模擬設(shè)備的好方法,例如控制電機(jī)的速度、LED 的亮度等。雖然 PWM 不提供純模擬輸出,但它會產(chǎn)生不錯(cuò)的模擬脈沖來控制 Analog Devices。PWM 實(shí)際上調(diào)制矩形脈沖波的寬度,以便得到結(jié)果波平均值的變化。
PWM 的占空比
PWM 信號保持高電平(開啟時(shí)間)的時(shí)間百分比稱為占空比。如果信號始終打開,則占空比為 100%,如果始終關(guān)閉,則占空比為 0%。
占空比=開啟時(shí)間/(開啟時(shí)間+關(guān)閉時(shí)間)
ARM7-LPC2148 中的 PWM
ARM7-LPC2148 有 6 個(gè) PWM 引腳和 14 個(gè) ADC 引腳。它具有 8 位 PWM 分辨率(2 8),即計(jì)數(shù)器和變量可以高達(dá) 255,因此:
255 的數(shù)字值可提供 LED 的全亮度(100% 占空比)
同樣,數(shù)字值 127 可提供 50% 的 LED 亮度(占空比為 50%)
數(shù)字值 64 提供 25% 的 LED 亮度(25% 占空比)
ARM7-LPC2148 中的 PWM 引腳
下圖顯示了ARM7-LPC2148 的 PWM 輸出引腳。PWM共有 6 個(gè)引腳。
ARM7-LPC2148 中的 PWM 寄存器
在進(jìn)入我們的項(xiàng)目之前,我們需要了解 LPC2148 中的 PWM 寄存器。
這是 LPC2148 中用于 PWM 的寄存器列表
1. PWMPR : PWM 預(yù)分頻寄存器
用途:它是一個(gè) 32 位寄存器。它包含在遞增 PWM 定時(shí)器計(jì)數(shù)器之前 PCLK 必須循環(huán)的次數(shù)(減 1)(它實(shí)際上保存了預(yù)分頻計(jì)數(shù)器的最大值)。
2. PWMPC: PWM 預(yù)分頻計(jì)數(shù)器
用途:它是一個(gè) 32 位寄存器。它包含遞增的計(jì)數(shù)器值。當(dāng)該值等于 PR 值加 1 時(shí),PWM 定時(shí)器計(jì)數(shù)器 (TC) 遞增。
3. PWMTCR : PWM 定時(shí)器控制寄存器
用途:它包含計(jì)數(shù)器使能、計(jì)數(shù)器復(fù)位和 PWM 使能控制位。它是一個(gè) 8 位寄存器。
4. PWMTC : PWM 定時(shí)器計(jì)數(shù)器
用途:它是一個(gè) 32 位寄存器。它包含遞增 PWM 定時(shí)器的當(dāng)前值。當(dāng)預(yù)分頻器計(jì)數(shù)器 (PC) 達(dá)到預(yù)分頻器寄存器 (PR) 的值加 1 時(shí),該計(jì)數(shù)器遞增。
5. PWMIR: PWM中斷寄存器
用途:它是一個(gè) 16 位寄存器。它包含 PWM 匹配通道 0-6 的中斷標(biāo)志。當(dāng)該通道(MRx 中斷)發(fā)生中斷時(shí),將設(shè)置一個(gè)中斷標(biāo)志,其中 X 是通道號(0 到 6)。
6. PWMMR0-PWMMR6: PWM匹配寄存器
用途:它是一個(gè) 32 位寄存器。 實(shí)際上,匹配通道組允許設(shè)置 6 個(gè)單邊沿控制或 3 個(gè)雙邊沿控制 PWM 輸出。您可以修改七個(gè)匹配通道來配置這些 PWM 輸出以滿足您在 PWMPCR 中的要求。
7. PWMMCR : PWM 匹配控制寄存器
用途:它是一個(gè) 32 位寄存器。它包含控制所選匹配通道的中斷、復(fù)位和停止位。PWM 匹配寄存器和 PWM 定時(shí)器計(jì)數(shù)器之間發(fā)生匹配。
8. PWMPCR : PWM 控制寄存器
用途:它是一個(gè) 16 位寄存器。它包含啟用 PWM 輸出 0-6 并為每個(gè)輸出選擇單邊沿或雙邊沿控制的位。
9. PWMLER: PWM 鎖存器使能寄存器
用途:它是一個(gè) 8 位寄存器。它包含每個(gè)匹配通道的匹配 x 鎖存位。
現(xiàn)在讓我們開始構(gòu)建硬件設(shè)置來演示 ARM 微控制器中的脈沖寬度調(diào)制。
所需組件
電路圖和連接
LCD和ARM7-LPC2148之間的連接
LED與ARM7-LPC2148之間的連接
LED 的 ANODE 連接到 LPC2148 的 PWM 輸出 (P0.0),而 LED 的 CATHODE 引腳連接到 LPC2148 的 GND 引腳。
ARM7-LPC2148與帶3.3V穩(wěn)壓器的電位器連接
需要注意的點(diǎn)
1. 這里使用 3.3V 的穩(wěn)壓器為 LPC2148 的 ADC 引腳 (P0.28) 提供模擬輸入值,因?yàn)槲覀兪褂玫氖?5V 電源,我們需要使用 3.3V 的穩(wěn)壓器來調(diào)節(jié)電壓。
2. 電位器用于在(0V 至 3.3V)之間改變電壓,以向 LPC2148 引腳 P0.28 提供模擬輸入(ADC)
為 PWM 和 ADC 編程 LPC2148 所涉及的步驟
第 1 步:-首先是配置 PLL以生成時(shí)鐘,因?yàn)樗鶕?jù)程序員的需要設(shè)置 LPC2148 的系統(tǒng)時(shí)鐘和外設(shè)時(shí)鐘。LPC2148 的最大時(shí)鐘頻率為 60Mhz。以下行用于配置 PLL 時(shí)鐘生成。
void initilizePLL (void) //使用 PLL 產(chǎn)生時(shí)鐘的函數(shù)
{
PLL0CON = 0x01;
PLL0CFG = 0x24;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
而(?。≒LL0STAT&0x00000400));
PLL0CON = 0x03;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
VPBDIV = 0x01;
}
第 2 步:-接下來是使用 PINSEL 寄存器選擇 LPC2148 的 PWM 引腳和 PWM 功能。我們使用 PINSEL0,因?yàn)槲覀兪褂?P0.0 作為 LPC2148 的 PWM 輸出。
PINSEL0 = 0x00000002;//設(shè)置引腳P0.0為PWM輸出
第 3 步:-接下來我們需要使用 PWMTCR(定時(shí)器控制寄存器)重置定時(shí)器。
PWMTCR = (1<<1); //設(shè)置PWM定時(shí)器控制寄存器為計(jì)數(shù)器復(fù)位
然后,設(shè)置決定 PWM 分辨率的預(yù)分頻值。我將它設(shè)置為零
PWMPR = 0X00;//設(shè)置PWM預(yù)分頻值
第 4 步:-接下來我們需要設(shè)置 PWMMCR(PWM 匹配控制寄存器),因?yàn)樗O(shè)置了復(fù)位等操作,PWMMR0 的中斷。
PWMMCR = (1<<0)|(1<<1); //設(shè)置PWM匹配控制寄存器
第 5 步:-使用 PWMMR 設(shè)置 PWM 通道的最大周期。
PWMMR0 = PWM值;//給PWM值最大值
在我們的例子中,最大值是 255(對于最大亮度)
第 6 步:-接下來我們需要使用 PWMLER 將 Latch Enable 設(shè)置為相應(yīng)的匹配寄存器
PWMLER = (1<<0); //啟用PWM鎖存器
(我們使用 PWMMR0)所以通過在 PWMLER 中設(shè)置 1 來啟用相應(yīng)的位
第 7 步:-要使 PWM 輸出到引腳,我們需要使用 PWMTCR 來啟用 PWM 定時(shí)器計(jì)數(shù)器和 PWM 模式。
PWMTCR = (1<<0) | (1<<3); //啟用PWM和PWM計(jì)數(shù)器
第 8 步:-現(xiàn)在我們需要從 ADC 引腳 P0.28 獲取用于設(shè)置 PWM 占空比的電位器值。因此,我們使用 LPC2148 中的 ADC 模塊將電位器模擬輸入(0 至 3.3V)轉(zhuǎn)換為 ADC 值(0 至 1023)。
在這里,我們通過將其除以 4 將值從 0-1023 轉(zhuǎn)換為 0-255,因?yàn)?LPC2148 的 PWM 具有 8 位分辨率 (2 8 )。
第 9 步:-為了選擇 LPC2148 中的 ADC 引腳 P0.28,我們使用
PINSEL1 = 0x01000000;//設(shè)置P0.28為ADC INPUT
AD0CR = (((14)<<8) | (1<<21)); //為A/D轉(zhuǎn)換設(shè)置時(shí)鐘和PDN
以下行捕獲模擬輸入(0 到 3.3V)并將其轉(zhuǎn)換為數(shù)字值(0 到 1023)。然后將此數(shù)字值除以 4 以將它們轉(zhuǎn)換為(0 到 255),最后作為PWM 輸出饋送到連接 LED 的 LPC2148 的 P0.0 引腳。
AD0CR |= (1<<1);
//在ADC寄存器delaytime(10)
中選擇AD0.1通道;AD0CR |= (1<<24); //開始A/D轉(zhuǎn)換
while( (AD0DR1 & (1<<31)) == 0 ); //檢查ADC數(shù)據(jù)寄存器中的DONE位
adcvalue = (AD0DR1>>6) & 0x3ff; //從 ADC 數(shù)據(jù)寄存器中獲取 RESULT
dutycycle = adcvalue/4; //從 (0 到 255) 獲取占空比值的公式
PWMMR1 = dutycycle; //設(shè)置占空比值到 PWM 匹配寄存器
PWMLER |= (1<<1); //使用占空比值啟用 PWM 輸出
第 10 步:-接下來我們在 LCD (16X2) 顯示模塊中顯示這些值。所以我們添加以下行來初始化 LCD 顯示模塊
void LCD_INITILIZE(void) //準(zhǔn)備 LCD 的函數(shù)
{
IO0DIR = 0x0000FFF0; //設(shè)置引腳P0.12,P0.13,P0.14,P0.15,P0.4,P0.6為OUTPUT
delaytime(20);
LCD_SEND(0x02); // 以 4 位操作模式初始化 lcd
LCD_SEND(0x28); // 2 行 (16X2)
LCD_SEND(0x0C); // 光標(biāo)關(guān)閉時(shí)顯示
LCD_SEND(0x06); // 自動(dòng)遞增光標(biāo)
LCD_SEND(0x01); // 顯示清除
LCD_SEND(0x80); // 第一行第一個(gè)位置
}
當(dāng)我們將4 位模式的 LCD 與 LPC2148連接時(shí),我們需要發(fā)送值以逐個(gè)半字節(jié)(上半字節(jié)和下半字節(jié))顯示。所以使用以下幾行。
void LCD_DISPLAY (char* msg) //函數(shù)將發(fā)送的字符一一打印
{
uint8_t i=0;
while(msg[i]!=0)
{
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((msg[i] & 0xF0)<<8) ); //發(fā)送高半字節(jié)
IO0SET = 0x00000050; //RS HIGH & ENABLE HIGH 打印數(shù)據(jù)
IO0CLR = 0x00000020; //RW LOW 寫模式
延遲時(shí)間(2);
IO0CLR = 0x00000040;// EN = 0,RS 和 RW 不變(即 RS = 1,RW = 0)
delaytime(5);
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((msg[i] & 0x0F)<<12) ); //發(fā)送低半字節(jié)
IO0SET = 0x00000050; //RS & EN HIGH
IO0CLR = 0x00000020;
延遲時(shí)間(2);
IO0CLR = 0x00000040;
延遲時(shí)間(5);
我++;
}
}
為了顯示這些 ADC 和 PWM 值,我們在int main()函數(shù)中使用以下行。
LCD_SEND(0x80);
sprintf(displayadc, "adcvalue=%f", adcvalue);
LCD_DISPLAY(displayadc); //顯示ADC值(0到1023)
LCD_SEND(0xC0);
sprintf(ledoutput,“PWM OP=%.2f”,亮度);
LCD_DISPLAY(LED輸出);//顯示從(0到255)的占空比值
無效初始化PLL(無效);
無效初始化PWM(無符號整數(shù)周期PWM);
無效延遲時(shí)間(uint16_t j);
void initilizePLL (void) //使用PLL產(chǎn)生時(shí)鐘的函數(shù)
{
PLL0CON = 0x01;
PLL0CFG = 0x24;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
而(!(PLL0STAT&0x00000400));
PLL0CON = 0x03;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
VPBDIV = 0x01;
}
void delaytime(uint16_t j) // 產(chǎn)生 1 毫秒延遲的函數(shù)
{
uint16_t x,i;
for(i=0;i
{
對于(x=0;x<6000;x++);
}
}
無效初始化PWM(無符號整數(shù)PWM值)
{
PINSEL0 = 0x00000002;//設(shè)置引腳P0.0為PWM輸出
PWMTCR = (1<<1); //設(shè)置PWM定時(shí)器控制寄存器為計(jì)數(shù)器復(fù)位
PWMPR = 0X00;//設(shè)置PWM預(yù)分頻值
PWMMCR = (1<<0)|(1<<1); //設(shè)置PWM匹配控制寄存器
PWMMR0 = PWM值;//給PWM值最大值
PWMLER = (1<<0); //啟用PWM鎖存器
PWMTCR = (1<<0) | (1<<3); //啟用PWM和PWM計(jì)數(shù)器
}
void LCD_SEND(char command) //發(fā)送十六進(jìn)制命令的函數(shù)
{
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((命令 & 0xF0)<<8) ); //發(fā)送命令的上半字節(jié)
IO0SET = 0x00000040;//使啟用高
IO0CLR = 0x00000030;//使 RS & RW 低
延遲時(shí)間(5);
IO0CLR = 0x00000040;//使啟用低
延遲時(shí)間(5);
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((命令 & 0x0F)<<12) ); //發(fā)送命令的低半字節(jié)
IO0SET = 0x00000040;//啟用高
IO0CLR = 0x00000030;//RS & RW 低
延遲時(shí)間(5);
IO0CLR = 0x00000040;//啟用低
延遲時(shí)間(5);
}
void LCD_INITILIZE(void) //準(zhǔn)備LCD的函數(shù)
{
IO0DIR = 0x0000FFF0;//設(shè)置引腳P0.12,P0.13,P0.14,P0.15,P0.4,P0.6為OUTPUT
延遲時(shí)間(20);
LCD_SEND(0x02); // 以 4 位操作模式初始化 lcd
LCD_SEND(0x28); // 2 行 (16X2)
LCD_SEND(0x0C); // 光標(biāo)關(guān)閉時(shí)顯示
LCD_SEND(0x06); // 自動(dòng)遞增光標(biāo)
LCD_SEND(0x01); // 顯示清晰
LCD_SEND(0x80); // 第一行第一個(gè)位置
}
void LCD_DISPLAY (char* msg) //函數(shù)將發(fā)送的字符一一打印
{
uint8_t i=0;
而(味精[i]!=0)
{
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((msg[i] & 0xF0)<<8) ); //發(fā)送上半字節(jié)
IO0SET = 0x00000050;//RS HIGH & ENABLE HIGH 打印數(shù)據(jù)
IO0CLR = 0x00000020;//RW LOW 寫模式
延遲時(shí)間(2);
IO0CLR = 0x00000040;// EN = 0,RS 和 RW 不變(即 RS = 1,RW = 0)
延遲時(shí)間(5);
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((msg[i] & 0x0F)<<12) ); //發(fā)送低半字節(jié)
IO0SET = 0x00000050;//RS & EN 高
IO0CLR = 0x00000020;
延遲時(shí)間(2);
IO0CLR = 0x00000040;
延遲時(shí)間(5);
我++;
}
}
主函數(shù)()
{
LCD_INITILIZE(); //調(diào)用函數(shù)準(zhǔn)備LCD顯示
字符顯示ADC[18];
浮動(dòng)亮度;
字符 LED 輸出[18];
LCD_DISPLAY("電路摘要");
延遲時(shí)間(900);
LCD_SEND(0xC0);
LCD_DISPLAY("LPC2148 中的 PWM");
延遲時(shí)間(900);
占空比;
浮動(dòng) adc 值;
初始化PLL();//調(diào)用函數(shù)initilizePLL
PINSEL1 = 0x01000000;//設(shè)置P0.28為ADC INPUT
AD0CR = (((14)<<8) | (1<<21)); //為A/D轉(zhuǎn)換設(shè)置時(shí)鐘和PDN
初始化PWM(255);//調(diào)用函數(shù)initilizePWM,值為255
PWMPCR |= (1<<9); //在LPC2148的P0.0引腳啟用PWM1輸出
而(1)
{
AD0CR |= (1<<1); //選擇ADC寄存器中的AD0.1通道
延遲時(shí)間(10);
AD0CR |= (1<<24); //開始A/D轉(zhuǎn)換
而( (AD0DR1 & (1<<31)) == 0 ); //檢查ADC數(shù)據(jù)寄存器中的DONE位
adcvalue = (AD0DR1>>6) & 0x3ff; //從ADC數(shù)據(jù)寄存器中獲取RESULT
占空比 = adcvalue/4;//從 (0 到 255) 獲取占空比值的公式
PWMMR1 = 占空比;//設(shè)置占空比值到PWM匹配寄存器
PWMLER |= (1<<1); //使用占空比值啟用 PWM 輸出
亮度 = 占空比;
LCD_SEND(0x80);
sprintf(displayadc, "adcvalue=%f", adcvalue);
LCD_DISPLAY(displayadc); //顯示ADC值(0到1023)
LCD_SEND(0xC0);
sprintf(ledoutput,“PWM OP=%.2f”,亮度);
LCD_DISPLAY(LED輸出);//顯示從(0到255)的占空比值
}
}
-
微控制器
+關(guān)注
關(guān)注
48文章
7600瀏覽量
151757 -
led
+關(guān)注
關(guān)注
242文章
23323瀏覽量
661960 -
PWM
+關(guān)注
關(guān)注
114文章
5196瀏覽量
214388 -
ARM7
+關(guān)注
關(guān)注
3文章
207瀏覽量
50387
發(fā)布評論請先 登錄
相關(guān)推薦
評論