靈動微-呼吸燈功能
呼吸燈,就是指電子產(chǎn)品上的LED燈的亮度隨著時間由暗到亮逐漸增強,再由亮到暗逐漸衰減,有節(jié)奏感地一起一伏,就像是在呼吸一樣,因而被廣泛應(yīng)用于手機、電腦等電子設(shè)備的指示燈中。在使用MCU開發(fā)相關(guān)的應(yīng)用產(chǎn)品中也可以加入呼吸燈功能,增強用戶的體驗感,在本實驗中將介紹如何使用MM32L0系列產(chǎn)品芯片做呼吸燈功能。在平時應(yīng)用中可以知道,MCU的GPIO輸出高低電平變化可以實現(xiàn)LED燈的亮、滅兩個過程,如果GPIO的電平一直維持高電平或者低電平,LED燈就處于長亮或長滅的狀態(tài),呼吸燈就是通過較高頻率的電平變化來實現(xiàn)亮滅的切換,由于人的視覺暫留效應(yīng),肉眼無法迅速捕捉快速亮滅變化的過程,所以在視覺中一直出現(xiàn)一直亮或者滅的狀態(tài),通過調(diào)整占空比可以控制LED燈的亮度,給人視覺上一種燈光由暗到亮逐漸增強,然后又由亮到暗逐漸衰減。
正常的成年人的吸氣呼氣時間整個過程持續(xù)大約3秒時間,即吸氣時間(LED燈亮度逐漸變亮)時間為1.5S,吸、呼氣時間(LED燈亮度逐漸變暗)時間為1.5S。
亮度隨著時間逐漸變強再衰減,可以用兩種算數(shù)方式實現(xiàn):半周期的正弦函數(shù)曲線和指數(shù)上升曲線及對稱的下降沿曲線。
指數(shù)方式曲線圖
要控制 LED 燈達到呼吸燈的效果,實際上就是要控制 LED 燈的亮度擬合呼吸特性曲線,在本次實驗中,將采用指數(shù)上升曲線及對稱的下降沿曲線方式,用戶如果對正弦方式感興趣也可以進行嘗試。在本次實驗中,我們使用MM32L0xx輸出較高頻率的PWM信號,通過調(diào)制信號的占空比,控制LED燈的亮度。
生成指數(shù)方式的曲線圖主要因素:
TIMPeriod:定時器的計數(shù)周期,它的值必須與PWM 表中的極大值相等(應(yīng)用中賦值需要減 1),而 PWM表的極大值決定了控制的分辨率。例如極大值為 10時,PWM 占空比只有10個等級,精確到0.1,當(dāng)極大值為1000 時,PWM 占空比1000個等級,精確到0.001。在本次實驗中設(shè)置定時器的計數(shù)周期值為255+1,即PWM表中的極大值也是256。
TIM_Prescaler:定時器時鐘分頻因子,它控制定時器計數(shù)器 CNT計數(shù)加1所需要的時間,它的值太大會導(dǎo)致輸出的單個PWM波周期過長,影響控制的動態(tài)特性。如控制LED燈時,該值太大會導(dǎo)致LED燈開關(guān)時間變長,閃爍明顯。一般來說,該值越小越好。在本次實驗中設(shè)置定時器時鐘分頻因子為1757+1,即對時鐘1758分頻。
PWM 表的點數(shù):PWM表的點數(shù)即對擬合曲線的采樣點數(shù),即把LED燈的亮度分為0-255個等級,采樣點越多,能更好地還原擬合曲線,采樣點太少,可能會導(dǎo)致失真。在本次實驗中設(shè)置PWM 表的點數(shù)為40。
Period_class:周期倍數(shù),即 PWM 表中每個元素的循環(huán)次數(shù),它影響擬合曲線的周期。
在本次實驗中設(shè)置設(shè)置周期倍數(shù)為8。
本次實驗程序直接從MM32L073的定時器PWM輸出的例程的基礎(chǔ)上修改得來,TIM3配置成向上計數(shù),PWM通道輸出也被配置成當(dāng)計數(shù)器 CNT 的值小于輸出比較寄存CCR1的值時,PWM通道輸出低電平,點亮 LED 燈。在函數(shù)的最后還使能了定時器中斷,每當(dāng)定時器的一個計數(shù)周期完成時,產(chǎn)生中斷,配合中斷服務(wù)函數(shù),即可切換CCR1 比較寄存器的值。
程序配置如下:
TIM3初始化配置
//LED亮度等級列表
uint8_t PWM_Wave[] = {1,1,2,2,3,4,6,8,10,14,19,25,33,44,59,80,107,143,191,255,255
,191,143,107,80,59,44,33,25,19,14,10,8,6,4,3,2,2,1,1};
TIM3的初始化、中斷及PWM輸出配置:
void TIM3_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能TIM3時鐘
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);//使能GPIOB時鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //TIM3_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中斷源
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01; //設(shè)置中斷優(yōu)先級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_TimeBaseStructure.TIM_Period = arr;//設(shè)置自動裝載寄存器值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision=0; //設(shè)置時鐘分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//設(shè)置計數(shù)模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //初始化TIM3寄存器
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //配置PWM模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //輸出使能
TIM_OCInitStructure.TIM_Pulse = 0; //設(shè)置初始脈沖寬度為0
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;//小于CCR1值為低電平
TIM_OC1Init(TIM3, &TIM_OCInitStructure); //初始化TIM3_OC1寄存器
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //預(yù)裝載使能
TIM_ARRPreloadConfig(TIM3, ENABLE); //使能 TIM 重載寄存器 ARR
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //使能TIM3的更新中斷
TIM_Cmd(TIM3, ENABLE);//使能TIM3
}
中斷服務(wù)函數(shù):
void TIM3_IRQHandler(void)
{
static uint8_t a = 0;//PWM表的成員數(shù),用于PWM查表
static uint8_t b = 0;//計算周期數(shù)
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)//判斷更新中斷標(biāo)志位
{
b++;
if(b >= 8) //周期倍數(shù)
{
TIM3->CCR1 = PWM_Wave [a]; //修改定時器比較寄存器值
a++;//查表指向下一個成員變量
if( a >= 40) //查表查到最后一位,重新指向表頭
{
a=0;
}
b=0; //重置周期計數(shù)標(biāo)志
}
TIM_ClearITPendingBit (TIM3, TIM_IT_Update);
}
}
主程序:
int main(void)
{
TIM3_PWM_Init(255,1757);
while(1)
{
}
}
本次實驗配置擬合曲線周期計算:
TIMPeriod=255+1;
TIM_Prescaler=1757+1;
PWM 表的點數(shù)(a)=40;
Fpwm = 48M / ((arr+1)*(psc+1))(單位:Hz)
定時器 update 事件周期,即定時器中斷周期:t1= 1/ Fpwm = 9376us
每個 PWM 點的時間:t2= t1*8= 75008us
遍歷PWM表的周期時間為:t3=t2*40= 3000320us
通過公式的計算可知本工程的配置可使得輸出的擬合曲線周期約等于3秒,符合成年人的吸氣呼氣時間整個過程持續(xù)大約3秒時間。
利用GPIO模擬PWM波形設(shè)計呼吸燈功能:
void LedOnOff(uint16_t t,uint16_t i)
{
LED1_ON();
delay_us(i);
LED1_OFF();
delay_us(t-i);
}
int main(void)
{
int i,j;
LED_Init();
TIM3_PWM_Init(255,1757);
while(1)
{
for(i=0;i<100;i+=1){
for(j=0;j<47;j+=1)
{
LedOnOff(100,i);
}
}
for(i=100;i>0;i--) {
for(j=0;j<46;j+=1)
{
LedOnOff(100,i);
}
}
}
}
使用MM32L0系列MCU上述兩種方式都可以實現(xiàn)呼吸燈功能,兩種方法GPIO分別是PB4和PB5,download到MiniBoard中,可以對比測試兩種實現(xiàn)方法的差異性,選擇合適的呼吸燈實現(xiàn)方式。
如需要了解更多靈動微MCU產(chǎn)品,請聯(lián)系靈動微核心代理商-穎特新科技
編輯:ls 最后修改時間:2022-06-08