这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【EFM8BB52单片机】智能小夜灯

共9条 1/1 1 跳转至

【EFM8BB52单片机】智能小夜灯

高工
2021-12-21 11:22:55   被打赏 50 分(兑奖)     打赏

试用项目:智能小夜灯

开箱EFM8BB52单片机。

内个。。虽然叫开箱,但是呢,由于快递海外来的,怕有疫情,因此箱子出来快递就喷了酒精然后就扔垃圾堆了。从箱子里带回来的就这小三样,一根USBmini数据线,一张带有芯科logo的小卡片,还有一个带有外包装的板卡,拆袋之前先把酒精喷壶准备好,边拆边喷

(防疫意识已经深入骨髓)

1640055892945426.jpg

带有芯科logo的小卡片翻过来背面写着“Get started!”还有芯科官网下载开发工具和资料的路径,既然如此,那就Start吧!首先从喷酒精开始!

1640055892326687.jpg

拆开包装之前,突然看到了黄色贴纸上写着ATTENTION几个大写字母,第一反应还是提醒注意病毒。哈哈,被疫情搞的有点过于魔怔了。

1640055891410960.jpg

不管三七二十一喷完开袋,再不管四七二十八对着小板卡一顿猛喷,正反面喷的它体无完肤。喷完后看着小板卡在台灯下闪烁着酒精那晶莹剔透的感觉,憋说,害挺美

喷完先晾一晾再说叭,晾干了再开始干活。

1640055892618553.jpg

-----------------------------------我是可可爱爱的分割线------------------------------------

    在郑州疫情的催化下,假期提前到来了。正好放假在家,做项目之余抽空继续撸板~

    话不多说,先把开发环境搭一搭,去官网下载软件。喏,如图,v5.2.0版本,版本号害挺吉利(祝天下有情人终成眷属)。另:下载软件的话,需要各位老板自行注册一个账号,这个账号在后面安装好开发软件打开运行之时,也是可以登录的。建议大家在官网注册一个吧,一分钟时间。可以省去后期在软件使用过程中的一些不方便的地方。

01.png

    下载完成后,双击setup.exe即可进入安装。如下图,安装的过程中,碰到该accept的就accept,该agree的agree就行了。

    不建议装在C盘,建议修改一下盘符,注意,仅仅修改一下盘符即可,我这里把默认的C盘,改成了D盘,如下图。

    其他路径的名称不用改,尽量不建议自己再创建其他名称的文件夹目录。

    然后就一路Next就OK。等待安装结束ing...

    在安装的过程当中,如果你的杀毒软件开着(本人用的是360杀毒),则有可能多次提示“关键程序DLL文件”被试图修改,不用理会,全部允许它修改就行了,毕竟金主爸爸的软件,让他改,随便改

    安装完成之后,即可打开运行该软件了。双击桌面上的image.png,即可打开软件,打开的时候会有个进度条,稍等片刻就OK。这个软件“Simplicity Studio 5”是基于Eclipse来的,虽然对于Eclipse没什么好感,但是毕竟是金主爸爸,用啥都有它的道理。

    第一次进入欢迎界面的时候,会进行一个“Preparing installation options...”准备安装选项的一个过程。去接杯水喝喝,就完成了。

    准备安装选项结束之后,会进入到这样一个界面中,还是该accept的accept,该agree的agree。

    点击Done,进入到一个登录界面,这时登录我们下载软件时在官网注册的账号就OK,登陆一次,以后就都不用再登录了,软件会自动记住并保存账号的登录状态。

    接下来,让选择即将进行什么设备的安装支持。我们手里的是一块EFM88B52的8位MCU,因此下图选择第二个长得像wifi信号的选项,点进去。

    继续选择类型为“8-bit Microcontrollers”其他的暂时用不到,先不勾选,勾选的话会白白占用硬盘空间。接下来一路下一步即可。

安装完了之后,重新打开一下软件。就可以进入到下面这个界面了。接下来就是新建工程了,那么还是依照惯例,先blink一个LED灯






关键词: EFM8BB52     单片机    

高工
2021-12-21 11:23:09     打赏
2楼

点个灯先~~~

首先,打开软件,新建工程。点击Flie,选择New,然后点击第一个选项如图。

image.png

接下来按照下图中进行选择就OK,这一步主要选择的是芯片或者测试板的型号和类别,以及使用的SDK和IDE工具链,然后点击NEXT。EFM8BB52是一个51内核的单片机,其实只要我们对51单片机熟悉的话,那么玩这个芯片还是比较容易上手的。

image.png

    点击完NEXT进入到如下界面。可选项有三个,第一个是有基础配置文件的工程,第二个是空工程,类似于我们使用Keil新建的空白工程。第三个则是官方的点灯例程,使用的是Timer定时器中断实现的,我们在做开发的时候,如果自己不想从头开始搭建工程,可以接选定该例程,在这个基础_上进一步做改动即可。为了省事儿,我们选第三个。

14.png

再次点击NEXT,进入到给工程命名的界面。我们给工程命名为LED_test如下图,然后点击右下角FINISH就搞定。

image.png

展开工程文件列表,可以看到各个文件如下图。其中包括.c以及.h文件,既然要操作LED,我们就直接打开看一看。

image.png

首先打开EFM8BB52_Blinky.c文件看看。

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <SI_EFM8BB52_Register_Enums.h>
#include <InitDevice.h>

该文件是主函数所在的文件,加载好相关的头文件。在我们初学51单片机的时候,头文件用的是reg52.h,而这里用的是

SI_EFM8BB52_Register_Enums.h

比较难记,直接复制粘贴就妥了。

第二个头文件InitDevice.h所对应的InitDevice.c函数里,完成的是设备的初始化相关的工作。简单看一下:

//==============================================================================
// enter_DefaultMode_from_RESET
//==============================================================================
extern void enter_DefaultMode_from_RESET(void) {
	// $[Config Calls]
	// Save the SFRPAGE
	uint8_t SFRPAGE_save = SFRPAGE;
	WDT_0_enter_DefaultMode_from_RESET();
	PORTS_1_enter_DefaultMode_from_RESET();
	PBCFG_0_enter_DefaultMode_from_RESET();
	TIMER16_2_enter_DefaultMode_from_RESET();
	INTERRUPT_0_enter_DefaultMode_from_RESET();
	// Restore the SFRPAGE
	SFRPAGE = SFRPAGE_save;
	// [Config Calls]$
}

主要干的事儿,就是在芯片复位后规定了一些外设的工作模式,或者叫初始化状态。从代码可以看出,其中包括WDT看门狗的,包括P1引脚的,包括WEAKUP和串口1的,包括对定时器的配置和中断的配置等。

看明白之后,我们就可以进一步修改并使用它们做自己的代码了。接下来我们看到main函数,可以看出,主函数中就开了个全局中断,然后停在while(1)死循环,那么灯在哪儿点的呢?不着急,我们看一看Interrupts.c,果不其然,在这里。

//-----------------------------------------------------------------------------
SI_INTERRUPT(TIMER2_ISR, TIMER2_IRQn)
{
	TMR2CN0_TF2H = 0;                  // Clear Timer2 interrupt flag
	LED0 = !LED0;                      // Change state of LED0
}

代码中将定时器2的高位中断溢出标志清零后,开始对LED0进行了电平反转的操作。这个LED0在哪儿被定义的呢?喏,这句代码:

// Global CONSTANTS
//-----------------------------------------------------------------------------
SI_SBIT(LED0, SFR_P1, 4);                  // P1.4 LED0

这里把P1.4这个IO口,取了个名儿叫做LED0。跟我们STC51单片机稍稍有点区别,其实也没什么,习惯就好。

较为关键的一点就是对timer2定时器的配置了,经过代码分析,我们可以看出,代码中将其设置成了使用默认内部时钟作为系统时钟(49MHz±2%进行12分频得到)的16位的计数模式,其中这两句话就是给定时计数器Timer2装初值

	// $[TMR2RLH - Timer 2 Reload High Byte]
	/*
	 // TMR2RLH (Timer 2 Reload High Byte) = 0x38
	 */
	TMR2RLH = (0x38 << TMR2RLH_TMR2RLH__SHIFT);
	// [TMR2RLH - Timer 2 Reload High Byte]$

	// $[TMR2RLL - Timer 2 Reload Low Byte]
	/*
	 // TMR2RLL (Timer 2 Reload Low Byte) = 0x9E
	 */
	TMR2RLL = (0x9E << TMR2RLL_TMR2RLL__SHIFT);
	// [TMR2RLL - Timer 2 Reload Low Byte]$

高字节为0x38,低字节为0x9e,经过推理计算(计算器代劳),得知每过将近200ms产生一次中断,也就是说,每秒钟LED灯的亮灭闪烁两次半简单在代码中改一改,让LED每过2s完成一次闪烁周期。

//-----------------------------------------------------------------------------
SI_INTERRUPT(TIMER2_ISR, TIMER2_IRQn)
{
	TMR2CN0_TF2H = 0;                  // Clear Timer2 interrupt flag
	LEDCOUNT++;
	if(LEDCOUNT == 5)
	  {
      LED0 = !LED0;                      // Change state of LED0
      LEDCOUNT = 0;
	  }
}

改完之后,点击编译,然后烧写,正常闪烁。

由于时间原因,没有用示波器去进一步验证误差,但是大体上差不太多。

这样一来,我们就搞清楚了定时器的工作方式,接下来我们在这个基础上,进一步去完成智能小夜灯的设计。


高工
2021-12-21 11:23:18     打赏
3楼

    开始外接模块,由于时间原因,我就不再打板了。这里直接用杜邦线吧~但是呢板卡插针没有焊上去,先手动开工,捡起我心爱的电烙铁干起来!

image.png

两分钟,搞定,晒个照~

image.png

得了,继续搞起来~~~

首先呢,需要一个按键,来手动控制小灯的各种状态的切换,既然板子上带的有按键,那就直接用上省得浪费。enn...暂时就先订开关两种状态吧。通过查看小半的硬件布局,如图:

image.png

LED灯和按键分别挂在P1.4和P0.2这两个IO口上,简单写一下代码,配置一下。我这里使用外部中断来捕捉该button是否被按下,于是查寄存器手册:

image.png

这里有个IT01CF是配置INT0和INT1外部中断通道的寄存器。可以看出,低四位和INT0有关,高四位和INT1有关。继续往下看:

image.png

第7位设置的是INT1的极性,应该是低电平触发还是高电平触发的选择选项。通过手册中这段英文解释可以读到,第6-4位这三位,当设置成不同的值时,则将INT1通道分配给不同的IO端口。既然我们要使用P0.2,那么将这三位赋值0x2就OK。

同理,低四位也是如此,只不过配置的是INT0,如果想把P0.2映射到INT0通道,则操作3-0这三位为0x2就OK,但是应当注意,通道只能选择一条,也就是说把P0.2和INT0勾搭到一起了,INT1就不能再跟他勾搭了。

image.png

好了,分析完毕,我们还是选择让P0.2和INT0勾搭吧,毕竟INT0的中断优先级高一些。那么我们可以将0000 0010通过或语句赋值给IT01CF寄存器。找到对应的函数,改一改。

首先,配置一下P0.2:

//================================================================================
// PORTS_0_enter_DefaultMode_from_RESET
//================================================================================
extern void PORTS_0_enter_DefaultMode_from_RESET(void) {
  // $[P0 - Port 0 Pin Latch]
  // [P0 - Port 0 Pin Latch]$

  // $[P0MDOUT - Port 0 Output Mode]
  /*
   // B0 (Port 0 Bit 0 Output Mode) = OPEN_DRAIN (P0.0 output is open-
   //     drain.)
   // B1 (Port 0 Bit 1 Output Mode) = OPEN_DRAIN (P0.1 output is open-
   //     drain.)
   // B2 (Port 0 Bit 2 Output Mode) = OPEN_DRAIN (P0.2 output is open-
   //     drain.)
   // B3 (Port 0 Bit 3 Output Mode) = OPEN_DRAIN (P0.3 output is open-
   //     drain.)
   // B4 (Port 0 Bit 4 Output Mode) = OPEN_DRAIN (P0.4 output is open-
   //     drain.)
   // B5 (Port 0 Bit 5 Output Mode) = OPEN_DRAIN (P0.5 output is open-
   //     drain.)
   // B6 (Port 0 Bit 6 Output Mode) = OPEN_DRAIN (P0.6 output is open-
   //     drain.)
   // B7 (Port 0 Bit 7 Output Mode) = OPEN_DRAIN (P0.7 output is open-
   //     drain.)
   */
  P0MDOUT = P0MDOUT_B0__OPEN_DRAIN | P0MDOUT_B1__OPEN_DRAIN
      | P0MDOUT_B2__OPEN_DRAIN | P0MDOUT_B3__OPEN_DRAIN
      | P0MDOUT_B4__OPEN_DRAIN | P0MDOUT_B5__OPEN_DRAIN
      | P0MDOUT_B6__OPEN_DRAIN | P0MDOUT_B7__OPEN_DRAIN;
  // [P0MDOUT - Port 0 Output Mode]$

  // $[P0MDIN - Port 0 Input Mode]
  /*
   // P0.0 pin is configured for digital mode
   // P0.1 pin is configured for digital mode
   // P0.2 pin is configured for digital mode
   // P0.3 pin is configured for digital mode
   // P0.4 pin is configured for digital mode
   // P0.5 pin is configured for digital mode
   // P0.6 pin is configured for digital mode
   // P0.7 pin is configured for digital mode
   */
  P0MDIN = P0MDIN_B0__DIGITAL | P0MDIN_B1__DIGITAL | P0MDIN_B2__DIGITAL
      | P0MDIN_B3__DIGITAL | P0MDIN_B4__DIGITAL | P0MDIN_B5__DIGITAL
      | P0MDIN_B6__DIGITAL | P0MDIN_B7__DIGITAL;
  // [P0MDIN - Port 0 Input Mode]$

}

其次,设置INT0中断通道与P0.2相关联,并设置中断触发方式:

//================================================================================
// EXTINT_0_enter_DefaultMode_from_RESET
//================================================================================
extern void EXTINT_0_enter_DefaultMode_from_RESET(void) {
  // $[IT01CF - INT0/INT1 Configuration]
  /*
   // IN0PL (INT0 Polarity) = ACTIVE_LOW (INT0 input is active low.)
   // IN0SL (INT0 Port Pin Selection) = P0_2 (Select P0.2.)
   */
  IT01CF = IT01CF_IN0PL__ACTIVE_LOW | IT01CF_IN0SL__P0_2;
  // [IT01CF - INT0/INT1 Configuration]$

}

然后,开一下总中断EA和INT0中断EX0,设置为使能ENANLED即可:

  IE = IE_EA__ENABLED | IE_EX0__ENABLED | IE_EX1__DISABLED
      | IE_ESPI0__DISABLED | IE_ET0__DISABLED | IE_ET1__DISABLED
      | IE_ET2__DISABLED | IE_ES0__DISABLED;

接下来,中断服务程序中,就可以通过LED灯的亮灭来看到中断触发的效果了:

//-----------------------------------------------------------------------------
// INT0_ISR
//-----------------------------------------------------------------------------
//
// INT0 ISR Content goes here. Remember to clear flag bits:
// TCON::IE0 (External Interrupt 0)
//
// Whenever a negative edge appears on P0.2, toggle LED_BLUE.
// The interrupt pending flag is automatically cleared by vectoring to the ISR
//
//-----------------------------------------------------------------------------
SI_INTERRUPT(INT0_ISR, INT0_IRQn)
{
  LED0 = !LED0;
}

接下来,另外换一个接口,接一个热释电红外传感器。就OK,这样能够实现人来灯亮人走灯灭了。

不过说实话,官方提供的案例的这种结构风格,让我编写代码的过程中,还是有很多的不习惯。



高工
2021-12-21 11:23:26     打赏
4楼

继续占


高工
2021-12-21 11:23:38     打赏
5楼

占了个占占


高工
2021-12-21 15:02:56     打赏
6楼

感谢楼主的分享,很实用了。


专家
2022-01-28 20:57:45     打赏
7楼

不错不错


工程师
2022-01-29 14:08:01     打赏
8楼
谢谢分享,学习了

专家
2022-01-29 14:29:37     打赏
9楼

谢谢分享


共9条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]