本帖最后由 jarry315 于 2021-1-28 12:47 编辑
LED最为一个常用的电子元件,控制方式也很简单,以下是本人亲测的一款状态机方式的无阻塞式LED频闪控制。
特点是,闪烁次数可调,闪烁周期可调,闪烁时长可调。常用作故障指示,也可以用于蜂鸣器鸣叫等等,比如,故障1=闪烁1下,故障2=闪烁2下。。。
在此,非常感谢21IC论坛和东软载波电子提供的ES32F369x开发板。
以下是申请到的开发套件的全家福
来一张开发板的特写
还提供了东软载波电子的产品线选型指南一份,里面包含了多个系列,包含8位、32位、带LCD、带Touch Key、Cortex-M0、Cortex-M3、RF等等
还有开发工具
最后,还有一份精美的日历
废话不多说,接下来进入正题,准备工作:
SDK下载:http://www.essemi.com/article/c141.html
原理图:http://www.essemi.com/file-download-1561-left.html
MDK5:https://www.keil.com/demo/eval/arm.htm
Keil 5 芯片支持包:http://www.essemi.com/data/source/Eastsoft.ES32_DFP.1.0.9.zip
此外,东软官网也有他们自己提供的开发软件:http://www.essemi.com/article/c52.html
安装开发环境
iDesigner运行环境安装顺序:
1.dotNetFx40_Full_x86_x64.exe
2.dotNetFx40LP_Full_x86_x64中文补丁包.exe
3.VSIsoShell_cn.exe
注:请严格按照以上顺序安装!!
本人使用的是KEIL 5开发的,安装过程就略过了,论坛中有大神贴出来,想了解的小伙伴可以自行搜索一下即可。
接下来,还是大家最关心的代码了
此程序主要是在官方的范例代码的基础上整合起来的,主要用到的范例为:
ES32_SDK_V1.09\Projects\ES32F36xx\Examples_ALD\KEY_LED_ADC
ES32_SDK_V1.09\Projects\ES32F36xx\Examples_ALD\TIMER\01_base
首先,在app目录下,新建代码文件:alarm.c
/******************************************************************************* * 蜂鸣器鸣叫参数 */ unsigned char isMute,NextMute;
struct AlarmFormat{ unsigned int cnt; // 鸣叫计数器 unsigned int time; // 次数 unsigned int period; // 周期 unsigned int pulse; // 时长 } AlarmData;
/******************************************************************************* * 函数声明 */
void setAlarm( unsigned int count, unsigned int pulse, unsigned int period ); void alarm( void ); void Hal_Led_on(void); void Hal_Led_off(void);
/****************************************************************************** * 蜂鸣器鸣叫 */ void Di(void){ //短鸣叫 setAlarm( 1, 5,10); // 测试异步蜂鸣器方式鸣叫 } void Dii(void){ //长鸣叫 setAlarm( 1, 50,55); // 测试异步蜂鸣器方式鸣叫 } void Didi(void){ //长鸣叫 setAlarm( 2, 5,10); // 测试异步蜂鸣器方式鸣叫 }
void setMute(unsigned char cmd){ if(cmd) NextMute = 1; else{ NextMute = 0; isMute = 0; }
} /******************************************************************************* *函数:alarm() *说明:蜂鸣器鸣叫方式 * TimerA1周期执行。 */
void alarm( void ) { //====================================================================== // 不鸣叫时,直接退出 if( AlarmData.time == 0 ){ isMute = NextMute; return; } //====================================================================== // 鸣叫的脉宽>周期时,全程鸣叫 if(isMute == 0){ if( AlarmData.period <= AlarmData.pulse ) { Hal_Led_on(); } else{ // 计数器 < 脉宽时,一直鸣叫 if( AlarmData.cnt <= AlarmData.pulse ) { Hal_Led_on(); } // 脉宽 < 计数器 < 周期时,不鸣叫 else{ // if( AlarmData.cnt <= AlarmData.period ) { Hal_Led_off(); } } } //====================================================================== // 报警次数递减 if( AlarmData.cnt >= AlarmData.period ) { AlarmData.cnt = 0; AlarmData.time --; if( AlarmData.time == 0) { Hal_Led_off(); } }
AlarmData.cnt++; }
/******************************************************************************* *函数:setAlarm() *说明:设置报警方式 *参数:count 鸣叫的次数 * pulse 鸣叫时长,<周期时,间歇鸣叫。>周期时,一直鸣叫 * period 鸣叫的周期 */ void setAlarm( unsigned int count, unsigned int pulse, unsigned int period ) { AlarmData.time = count; // 报警鸣叫次数 AlarmData.period = period; // 报警周期 AlarmData.pulse = pulse; // 报警时长 }
其次,打开KEY_LED_ADC范例,改写main()函数 int main(){ int diff;
/* Initialize ALD */ ald_cmu_init(); /* Configure system clock */ ald_cmu_pll1_config(CMU_PLL1_INPUT_HOSC_3, CMU_PLL1_OUTPUT_48M); ald_cmu_clock_config(CMU_CLOCK_PLL1, 48000000); /* Enable peripheral */ ald_cmu_perh_clock_config(CMU_PERH_GPIO, ENABLE); ald_cmu_perh_clock_config(CMU_PERH_ADC0, ENABLE); ald_cmu_perh_clock_config(CMU_PERH_ALL, ENABLE);
/* Initialize peripheral */ timer_config();
bsp_light_init(); bsp_adc_init();
bsp_key_init(); bsp_key_bond_func(BSP_KEY_ALL, key_handle);
while (1) { if(timerFlag){ timerFlag=0; if(FlashType==0) setAlarm(0,0,1000); else if(FlashType==1) setAlarm(1,200,1000); else if(FlashType==2) setAlarm(2,200,1000); else if(FlashType==3) setAlarm(3,200,1000); else setAlarm(4,500,1000); } } } 注意:需要新建控制LED的函数,如下: void Hal_Led_on(void){ bsp_light_ctrl(BSP_LIGHT_1, BSP_LIGHT_ON); }
void Hal_Led_off(void){ bsp_light_ctrl(BSP_LIGHT_1, BSP_LIGHT_OFF); }
然后,在按键事件代码中,添加以下代码:
unsigned char FlashType; void key_handle(bsp_key_event_t event){ switch ((uint32_t)event) { //--------------------------------------------------------------------- case BSP_KEY1_PRESS: FlashType=1; break; case BSP_KEY1_RELEASE: break; //--------------------------------------------------------------------- case BSP_KEY2_PRESS: FlashType=2; break; case BSP_KEY2_RELEASE: break; //--------------------------------------------------------------------- case BSP_KEY3_PRESS: FlashType=0; break; case BSP_KEY3_RELEASE: break;
//--------------------------------------------------------------------- case BSP_KEY4_PRESS: FlashType=3; break; case BSP_KEY4_RELEASE: break;
//--------------------------------------------------------------------- case BSP_KEY5_PRESS: FlashType=4; break; case BSP_KEY5_RELEASE: break; //--------------------------------------------------------------------- default: break; } return; } 在定时器中断中,添加void alarm(void),如下:
unsigned int timerCnt; unsigned char timerFlag; void ald_timer_period_elapsed_callback(struct timer_handle_s *arg){ alarm(); timerCnt++; if(timerCnt>=10000){ timerFlag = 1; timerCnt = 0; } } 此代码的关机函数为:alarm(),和setAlarm( unsigned int count, unsigned int pulse, unsigned int period ),setAlarm()是设置闪烁方式的,alarm()是实现自动闪烁的,一般放在定时器中断中。这样就能实现指示灯的自动闪烁了,同样,这些代码也可以用在蜂鸣器鸣叫程序中。
代码编写完成,进行编译,烧写代码 值得注意的是,使用ES-LINK II烧写软件时,Debug器件应选择“CMSIS-DAP Debugger”
运行代码后,按开发板上的方向按键,指示灯LED1就会周期闪烁了。 最后,上传代码。由于论坛上传的附件有大小限制,因此只上传了“main.c”和“alarm.c”,小伙伴们只需将这两个文件放入代码目录下的“src”文件夹下即可,如“...\ES32_SDK_V1.09\Projects\ES32F36xx\Examples_ALD\KEY_LED_ADC\01_base\Src”。 [url=]Src.zip[/url] 初次接触东软载波电子,编程习惯与之前有很大的不同,慢慢熟悉之后,发现也不是很难上手。再次感谢21IC论坛以及东软载波电子,祝那些收到开发板的小伙伴们开箱快乐,学习进步。
|