文章目錄
- 一、SysTick實驗
- 二、定時器實驗
- 三、LED呼吸燈實驗
- 四、蜂鳴器實驗
一、SysTick實驗
- 利用 LPC1114 DevKit 開發板或者 LPC1114 MASB 最小系統板,設定 LPC1114 微控制器時鐘頻率 48 MHz,利用 SysTick 定時器定時 1 秒(如何才能定時1秒?提示:在中斷子程式中進行計數),控制(PIO1_9)引腳LED燈的閃爍功能,撰寫C語言代碼進行實作,寫出配置子程式、中斷服務子程式和主程式,在中斷子程式中設定斷點,觀察是否能產生中斷,
- LPC1114系列 ARM Cortex-M0 微控制器內核外設 SysTick 定時器為 24 位遞減計時器,當計數值達到 0 時產生中斷,并將從STRELOAD暫存器中自動重裝載定時初值,只要不把它在 SysTick 控制及狀態暫存器 STCTRL 中的使能位清除,就永不停止,要想在規定的時間點上產生中斷(回圈產生),就必須先將指定的時間間隔值裝入STRELOAD,SysTick定時器可以為作業系統或其它系統管理軟體提供固定 10ms 的中斷,
在 PIO1_9 引腳上接一個LED燈,設定 PIO1_9 引腳為GPIO,引腳方向為輸出,高電平燈滅,低電平燈亮,電路如下圖所示:


C語言程式
#include <LPC11xx.h>
/*----------------------------------------------------------------------------
Function that initializes LED
*----------------------------------------------------------------------------*/
void LED_init(void) {
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6); /* enable clock for GPIO */
/* configure GPIO1.9 as output */
LPC_GPIO1->DIR |= (1UL << 9);
LPC_GPIO1->DATA &= ~(1UL << 9);
}
/*----------------------------------------------------------------------------
Function that turns on requested LED
*----------------------------------------------------------------------------*/
void LED_On ( void ) {
LPC_GPIO1->DATA |= (1UL << 9);
}
/*----------------------------------------------------------------------------
Function that turns off requested LED
*----------------------------------------------------------------------------*/
void LED_Off ( void ) {
LPC_GPIO1->DATA &= ~(1UL << 9);
}
/*----------------------------------------------------------------------------
Function that invert the LED state
*----------------------------------------------------------------------------*/
void LED_Invert(void) {
int ledstate;
// Read current state of GPIO P1_0..31, which includes LED
ledstate = LPC_GPIO1->DATA;
if(ledstate&= (1 << 9)) { // Turn on LED if it is off
LPC_GPIO1->DATA &= ~ (1 <<9);
}
else{ // Turn off LED if it is on
LPC_GPIO1->DATA |= (1 << 9);
}
}
volatile uint32_t msTicks=0; /* counts 1ms timeTicks */
/*----------------------------------------------------------------------------
SysTick_Handler
*----------------------------------------------------------------------------*/
void SysTick_Handler(void) {
msTicks++; /* increment counter necessary in Delay() */
}
int main (void)
{
/* Initialize GPIO (sets up clock) */
LED_init();
LED_Off ( );
if (SysTick_Config(SystemCoreClock / 100)) { /* Setup SysTick Timer for 10 msec interrupts */
while (1); /* Capture error */
}
while (1) /* Loop forever */
{
if(msTicks==50){
LED_Invert();
msTicks=0;
}
// Turn LED on, then wait
}
return 0;
}
觀察開發板LED燈,可以實作控制(PIO1_9)引腳 LED 燈每隔 1s 閃爍
二、定時器實驗
利用 LPC1114 DevKit 開發板,設定 LPC1114 微控制器時鐘頻率48MHz,利用 16 位通用定時器 1 實作定時匹配輸出控制MAT0(PIO1_9)引腳狀態反轉,16位定時器 1 每 1 秒產生一次匹配中斷,設定 MAT0.0 引腳電平進行反轉,實作 LED 燈的控制,
- 選用 LPC1114 的 16 為定時計數器 1 來定時 1s 并產生中斷,在中斷中完成燈的電平翻轉,實作燈 1s 中翻轉一次的閃爍狀態,
- 首先得初始化 16 位時器1,打開時鐘,清零中斷標志暫存器、配置預分配值、設定匹配后操作、設定定時時間、打開定時器、使能 16 位定時器1中斷,配置好上述操作后便完成了定時器的初始化配置,
- 然后寫中斷程式,直接在中斷里面呼叫燈翻轉函式,使用的是中斷,沒有用匹配輸出,因此需要呼叫翻轉函式,最后在主函式里面呼叫led初始化函式、16位定時計數器1初始化函式,然后用 while(1) 陳述句一直等待進入中斷即可,
C語言程式如下:
#include <LPC11xx.h>
void LED_init(void) //LED初始化函式
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6); /* enable clock for GPIO */
/* configure GPIO1.9 as output */
LPC_GPIO1->DIR |= (1UL << 9);
LPC_GPIO1->DATA &= ~(1UL << 9);
}
void LED_Invert(void) //LED翻轉函式
{
int ledstate;
// Read current state of GPIO P1_0..31, which includes LED
ledstate = LPC_GPIO1->DATA;
if(ledstate&= (1 << 9))
{// Turn on LED if it is off
LPC_GPIO1->DATA &= ~ (1 <<9);
}
else
{// Turn off LED if it is on
LPC_GPIO1->DATA |= (1 << 9);}}
void TMR16B1_COUNT_Init(void) //16位定時器1初始化函式
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 8);
LPC_TMR16B1->IR =0x1F; //中斷標暫存器寫1清零
LPC_TMR16B1->PR = 999; //設定分頻系數
LPC_TMR16B1->MCR = 3; //匹配后TC復位且中斷
LPC_TMR16B1->MR0 = SystemCoreClock/1000; //設定定時時間
LPC_TMR16B1->TCR = 0x01; //使能定時器
NVIC_EnableIRQ(TIMER_16_1_IRQn); //設定中斷并使能
}
void TIMER16_1_IRQHandler(void) //中斷處理子程式
{
if((LPC_TMR16B1->IR |= 0x01)==1)
LED_Invert();
}
int main() //主函式
{
LED_init();
TMR16B1_COUNT_Init();
while(1);
return 0;
}
通過此次實驗明白定時器運行的流程和熟悉各種暫存器的配置,定時器打開(通過配置定時器控制暫存器TCR)后,定時/計數器 TC 會開始每隔一個時鐘周期增加1,當 TC 增加到設定的匹配值 MR 的時候,會發生一些操作例如進入中斷、TC復位等(通過匹配控制暫存器 MCR 來配置),然后在發生中斷的時候,中斷標志暫存器 IE 里面對應的位會被置1,還有注意定時器有 4 個匹配通道,配置各個暫存器的時候要配置對應的通道位,
三、LED呼吸燈實驗
- 利用 LPC1114 的 16 位定時器 1 的 PWM 輸出不同占空比的 PWM 波驅動 LED 燈,來實作呼吸燈漸變的效果,
- 首先進行定時器 PWM 模式的初始化,打開 16 位定時器時鐘和IO口 1_9 的時鐘,然后配置 PIO1_9 復用模式為MAT0(直接是定時器輸出PWM方波的埠),然后配置通道 3 為計時,設定預分頻 PR=0,MCR為0x20<<9(匹配后 TC 復位不中斷),MR3=SystemCoreClock/1000,即 MR3 的定時時間為1s,然后配置 PWMC 為 0x01 (即MAT0輸出PWM),最后打開定時器,完成定時器初始化,
- 在主函式里面,呼叫定時器 PWM 初始化函式,然后開始主回圈,我設定了一個標志變數 flag 來判斷是遞增還是遞減,也設定了一個比例變數 x(0到1)來輸出不同的占空比PWM,將 x*MR3 的值給MR0,然后遞增或者遞減(根據 flag 來判斷),即完成了不同的PWM輸出給LED實作呼吸的效果,經過實際調整和簡單計算,發現 x 每次增減值取 0.00001 時能夠達到 LED 很好的漸變的效果,
#include <LPC11xx.h>
int flag=0; //占空比x,標志變數flag
float x=0;
void TMR16B1_PWM_Init(void)
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 8);
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 16);
LPC_IOCON->PIO1_9 |= 0x01; //設定P1_9復用位mat0
LPC_TMR16B1->PR = 0; //設定分頻系數
LPC_TMR16B1->PWMC= 0x01; //MAT0為PWM輸出
LPC_TMR16B1->MCR = 0x02 <<9; //匹配后TC復位且不中斷
LPC_TMR16B1->MR3 = SystemCoreClock/1000; //設定定時時間為1ms
LPC_TMR16B1->MR0 = LPC_TMR16B1->MR3;
LPC_TMR16B1->TCR = 0x01; //使能定時器
}
int main()
{
TMR16B1_PWM_Init();
while(1)
{
if (x>=1 | x<=0)
{
flag = ~flag;
}
if(flag==0)
{
LPC_TMR16B1->MR0 = x*LPC_TMR16B1->MR3;
x=x+0.00001;
}
else
{
LPC_TMR16B1->MR0 = x*LPC_TMR16B1->MR3;
x=x-0.00001;
}
}
return 0;
}
本次實驗程序中,就遇到了程式在硬體上運行速度非常快這樣的問題,剛開始沒有察覺到,以為是按我們正常以為時間運行,卻不知道兩次增減間隔可能就只有幾十微秒,增量 x 取得太大就會出問題,后來找到原因所在,除錯設定合理的 x 值后便得到了較好的呼吸燈效果,
四、蜂鳴器實驗
-
音樂由不同音調和不同的節拍相互組合而成,音調體現在頻率,節拍體現在此音調存在的時間上,故而我們可以控制蜂鳴器以不同頻率的不同存在時間的有規律組合即可產生動聽的音樂,
-
利用定時器輸出相同占空比,不同周期的 PWM 方波驅動蜂鳴器可以實作不同頻率的聲音,此時不需要用到中斷里面去控制蜂鳴器,而是輸出的 PWM 波直接送到蜂鳴器,代碼優化了一些,實作節拍通過系統節拍器定時間來作延時功能,主要有三個陣列:頻率陣列FREQ[]、節拍陣列beat[]、歌曲陣列song[],Song[]里面的數依次為頻率和對應的節拍,
-
然后我們配置 16 位定時器 1 的 MR3 通道來作為定時,MR1通道作為 PWM 波,通過 PIO1_10 來輸出 PWM 波送給蜂鳴器,根據陣列FREQ[]里面的值來改變 MR3 定時時間,然后 MR1 根據 MR3 依次改變,實作不同頻率聲音,
-
主函式程式邏輯為:首先呼叫 16 位定時器 PWM 初始化函式,然后配置系統滴答定時器為1s,然后進行主回圈,主回圈里面取出 song[] 陣列里面的頻率和其節拍位置,然后從 FREQ[]、beat[] 取出頻率和節拍的具體值,再呼叫 sound() 函式,根據新的頻率、節拍值,調節 PWM 波周期,和存在的時間,根據 song[] 陣列重復上述取值,改變 PWM 周期,延時等操作,即可實作蜂鳴器播放音樂,
#include <LPC11xx.h>
uint16_t fre,time;
volatile uint32_t msTicks=0;
uint16_t FREQ[] = {
0x106, 0x126, 0x14A, 0x15D, 0x188, 0x1B8, 0x1EE, //低音1-0,2-1,3-2,4-3,5-4,6-5,7-6,
0x20B, 0x24B, 0x293, 0x2BA, 0x310, 0x370, 0x3DC, //1-7,2-8,3-9,4-10,5-11,6-12,7-13,
0x416, 0x497, 0x526, 0x575, 0x620, 0x6E0, 0x7B8,0x00 //高音1-14,2-15,3-16,4-17,5-18,6-19,7-20,
};
uint16_t beat[] = {
0x96,0x12C,0x1C2,0x258,0x384,0x4B0,0x00 //1/4_0,2/4_1,3/4_2,4/4_3,6/4_4,8/4_5
}; //節拍
uint16_t song1[]={
4,1, 4,1, 5,3, 4,3, 7,3, 6,5, 4,1, 4,1, 5,3, 4,3, 8,3,
7,5, 4,1, 4,1, 11,3, 9,3, 7,3, 6,3, 19,3, 10,1, 10,1, 9,3, 8,3, 7,3,
9,5, 4,1, 4,1, 5,5, 21,6
}; //音樂:頻率 節拍
void TMR16B1_PWM_Init(void)
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 8);
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 16);
LPC_IOCON->PIO1_10 |= 0x02; //設定P1_10復用位mat1
LPC_TMR16B1->PR = 999; //設定分頻系數
LPC_TMR16B1->PWMC= 0x02; //MAT1為PWM輸出
LPC_TMR16B1->MCR = 0x02 <<9; //匹配后TC復位
LPC_TMR16B1->MR3 = SystemCoreClock/1000; //設定定時時間
LPC_TMR16B1->MR1 = LPC_TMR16B1->MR3*0.5;
}
void SysTick_Handler(void) //系統滴答定時器中斷,用于延時
{
msTicks++; /* increment counter necessary in Delay() */
}
void delay(uint32_t t) //延時1ms
{
msTicks=0;
while(t!=msTicks);
}
void sound() //產生頻率和節拍
{
LPC_TMR16B1->TCR=0x01;
LPC_TMR16B1->MR3 = SystemCoreClock/(1000*fre);
LPC_TMR16B1->MR1 = LPC_TMR16B1->MR3*0.5; //頻率
delay(time); //節拍
LPC_TMR16B1->TCR=0x00;
}
int main()
{
unsigned char k,m, i;
TMR16B1_PWM_Init();
i=0;
if (SysTick_Config(SystemCoreClock / 1000)) //配置系統滴答定時器
{
while (1);
}
while(1)
{
k = song1[i] ; //取頻率位置
fre=FREQ[k]; //取頻率值
m=song2[i+1]; //取節拍位置
time =beat[m]; //取節拍值
i=i+2; //下一組頻率和節拍位置
sound();
if(fre==0) i=0;
}
}

代碼編譯執行后沒有錯誤,程式成功下載到板子上后,可以播放生日快樂歌,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/259312.html
標籤:其他
上一篇:[STM32] Stm32f103c8t6+ESP8266-01s+DHT11 實作向服務器上傳溫濕度資料(超詳細,零基礎,初學者,小白直接上手,我都怎么標題黨了還是沒人看嗎)
下一篇:N皇后問題
