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