这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 活动中心» 板卡试用» 【EFM8BB52单片机】PPT翻页器(已完成,妹妹很喜欢)

共56条 1/6 1 2 3 4 5 6 ›| 跳转至

【EFM8BB52单片机】PPT翻页器(已完成,妹妹很喜欢)

高工
2021-12-09 21:05:52 被打赏230分(兑奖) 打赏

试用项目:电子教鞭(PPT翻页器)

借助板卡试用的机会,制作这么一个小玩意(女朋友现在是老师,做个这玩意哄哄她)

系统框图如下:

功能简介: 就是按键控制PPT翻页的一个小玩意,最主要的就是按键检测以及串口发送,无线模块用的是一款串口透传模块,转USB信号用的是沁恒的CH9328,能把串口信号转为USB信号

试用进程:

1开发环境搭建(Simplicity StudioV5)

2开箱

3点灯+编译+烧录

4建立最小工程并点灯

5添加串口点灯

6串口1通信+按键+硬件

7召唤神龙




关键词: EFM8BB52 环境搭建

高工
2021-12-09 21:06:02 被打赏50分(兑奖) 打赏
2楼

开发环境搭建

废话不多说,趁板子没回来先环境搭建直接上官网找到Simplicity Studio

看看介绍 基于Eclipse的,还是能很快熟悉的

果断选择Simplicity Studio 5版本

下载链接:

但是需要注册,我已经下载好了,直接放在这了,直接下载即可

链接:https://pan.baidu.com/s/1LlYHl7HsV3n5Y9hvgfZVTg

提取码:rw40

WIN10用户选择iso

安装

下载的文件解压完之后直接双击,选择安装文件

一路next选择安装路径即可

安装完直接打开

类似于一个协议,直接打勾即可

说让登录,我直接X了

然后会自动下载,弹出一个窗口

用我那贫瘠的英语大概看一下似乎是安装管理,应该是安装支持包之类的,直接选择第二个

选择8位机了

我选择了第一个,应该是都安装了

看样子是安装成功了,重启一哈子

新建工程

刚重启的样子

现在没有连接设备所以选全部

可以根据芯片选择,也可以根据板子选择,新手先用板卡试试(有点STM32CUBEMX那味了 )

下边已选择直接就下载了PDF,这资料很方便啊

DEMO什么的

文档什么的

工具什么的

回来直接生成工程

先选个点灯

选择工程名字以及存放位置和添加的文件

工程全部

编译一下

好像是能免费为keil提供许可证,但是我并没有找到keil的支持包,所以直接放弃

编译成功


高工
2021-12-09 21:06:07 被打赏10分(兑奖) 打赏
3楼

开箱!多图预警!


高工
2021-12-09 21:06:12 被打赏20分(兑奖) 打赏
4楼

点个灯

看了下例程,用的是定时器点灯,太高级,还不到那一步,先梦回郭天祥,手动delay点灯撸个delay函数

void delay(uint32_t xms) { while(xms--) { NOP(); } }

51就可以愉快的位操作了,定义个位变量

查找说明

SI_SBIT(LED0, SFR_P1, 4); // P1.4 LED0

点灯

需要添加初始化函数enter_DefaultMode_from_RESET();(暂且不探究其中包含了什么,但是像STC那样不包含无法运行)

记得把总中断关了,因为例程中是在定时器中断中点灯的

void main (void) { enter_DefaultMode_from_RESET(); IE_EA = 0; while (1) { delay(0xffff); LED0 = !LED0; } }

编译烧录

点击这个小锤子,直接编译

在点击这个下载

选择编译好的文件

下载

就能看到小灯闪了


高工
2021-12-09 21:06:15 打赏
5楼

新建工程

选择板卡芯片

选择新建工程类型

选择工程名字及存储位置

成功

添加一个文件夹存储头文件

模块化编程

到了重点,回顾大Z老师的模块化编程

单片机模块化编程---第一弹(一)

单片机模块化编程---第一弹(二)

单片机模块化编程---第一弹(三)

添加头文件目录

编写初始化驱动

这里注意一下,这个单片机有一个SFRPAGE寄存器

指定读、写或修改特殊函数寄存器时使用的SFR页。

每次操作寄存器需要把SFRPAGE指向要用的寄存器页上面去

看门狗是默认打开的,先把它关了

需要在四个系统时钟内对寄存器WDTCN先写0XDE再写0XAD

操作IO口

有几个步骤

引脚设置为数字 引脚设置为推挽输出 XBR2中XBARE使能

程序如下 main.c

#include "device.h" SI_SBIT(LED0, SFR_P1, 4); // P1.4 LED0 void SiLabs_Startup (void) { // Disable the watchdog here } int main (void) { sys_init(); IE_EA = 0; while (1) { delay(0xffff); LED0 = !LED0; } }

device.c

#include "device.h" void delay(uint32_t xms) { while(xms--) { NOP(); } } void sys_init(void) { uint8_t SFRPAGE_save = SFRPAGE; //Disable Watchdog SFRPAGE = 0x00; WDTCN = 0xDE; //First key WDTCN = 0xAD; //Second key // IO Init P1MDIN = P1MDIN|P1MDIN_B4__DIGITAL; P1MDOUT = P1MDOUT|P1MDOUT_B4__PUSH_PULL; XBR2 = XBR2|XBR2_XBARE__ENABLED; SFRPAGE = SFRPAGE_save; }

device.h

#ifndef __DEVICE_H__ #define __DEVICE_H__ #include  void sys_init(void); void delay(uint32_t xms); #endif

主程序中SiLabs_Startup函数不能删去,因为启动文件里边会调用这个函数


高工
2021-12-09 21:06:20 被打赏50分(兑奖) 打赏
6楼

调通了UART0和定时器2,先把大概东西搞出来再细扣吧

现在我实现了串口点灯,把我写好的驱动分享出来 直接贴代码了

#include "device.h" uint32_t count_ms = 0; /******************************************************************************* Function: // wtg_init Description: // 关闭看门狗 Input: // 无 Return: // 无 *******************************************************************************/ void wtg_init(void) { SFRPAGE = 0x00; WDTCN = 0xDE; // First key WDTCN = 0xAD; // Second key } /******************************************************************************* Function: // io_init Description: // IO口初始化 Input: // 无 Return: // 无 *******************************************************************************/ void io_init(void) { SFRPAGE = 0x00; P0MDOUT = P0MDOUT | P0MDOUT_B4__PUSH_PULL | P0MDOUT_B5__OPEN_DRAIN; P0MDIN = P0MDIN | P0MDIN_B4__DIGITAL | P0MDIN_B5__DIGITAL; P1MDIN = P1MDIN | P1MDIN_B4__DIGITAL; P1MDOUT = P1MDOUT | P1MDOUT_B4__PUSH_PULL; XBR2 = XBR2 | XBR2_XBARE__ENABLED; XBR0 = XBR0 | XBR0_URT0E__ENABLED; } /******************************************************************************* Function: // clc_init Description: // 时钟初始化 时钟频率为24.5MHz/8 Input: // 无 Return: // 无 *******************************************************************************/ void clc_init(void) { SFRPAGE = 0x00; // set clk 24.5MHz/8 CLKSEL = CLKSEL_CLKSL__HFOSC0_clk24p5 | CLKSEL_CLKDIV__SYSCLK_DIV_8; // wait ready while ((CLKSEL & CLKSEL_DIVRDY__BMASK) == CLKSEL_DIVRDY__NOT_READY) ; } /******************************************************************************* Function: // timer1_init Description: // 定时器1初始化 用于uart0波特率生成 Input: // 无 Return: // 无 *******************************************************************************/ void timer1_init(void) { SFRPAGE = 0x00; TCON &= ~TCON_TR1__BMASK; // stop tim1 TH1 = 0XFF - (SYSCLK / UART0_BAUD / 2); // calculating baud rate CKCON0 = CKCON0_T1M__SYSCLK; TMOD = TMOD | TMOD_T1M__MODE2 | TMOD_CT1__TIMER | TMOD_GATE1__DISABLED; TCON |= TCON_TR1__RUN; TH0 = (0xC0 << TH0_TH0__SHIFT); } /******************************************************************************* Function: // timer2_init Description: // 定时器2初始化 时基1ms一次中断count_ms+1 Input: // 无 Return: // 无 *******************************************************************************/ void timer2_init(void) { SFRPAGE = 0x00; TMR2CN0 &= ~(TMR2CN0_TR2__BMASK); TMR2H = (0xFF << TMR2H_TMR2H__SHIFT); TMR2L = (0x01 << TMR2L_TMR2L__SHIFT); TMR2RLH = (0xFF << TMR2RLH_TMR2RLH__SHIFT); TMR2RLL = (0x01 << TMR2RLL_TMR2RLL__SHIFT); TMR2CN0 |= TMR2CN0_TR2__RUN; IE = IE | IE_ET2__ENABLED; } /******************************************************************************* Function: // sys_init Description: // 系统初始化 Input: // 无 Return: // 无 *******************************************************************************/ void sys_init(void) { uint8_t SFRPAGE_save = SFRPAGE; wtg_init(); io_init(); uart0_init(); clc_init(); timer1_init(); timer2_init(); uart0_init(); SFRPAGE = SFRPAGE_save; IE_EA = 1; } /******************************************************************************* Function: // led_pro Description: // led任务 1S切换一次状态 Input: // 无 Return: // 无 *******************************************************************************/ void led_pro(void) { static uint32_t timer_led = 0; if ((long)(count_ms - timer_led) > LED_BLINK_TIME) { LED0 = !LED0; timer_led += LED_BLINK_TIME; } } /******************************************************************************* Function: // TIMER2_IRQn Description: // 定时器2中断函数,1ms进入一次,count_ms+1 Input: // 无 Return: // 无 *******************************************************************************/ SI_INTERRUPT(TIMER2_ISR, TIMER2_IRQn) { count_ms++; TMR2CN0_TF2H = 0; // Clear the interrupt flag }
#include "device.h" #include  #include  URAT_RX uart0; URAT_RX rece0; uint8_t tx_flag = 0; /******************************************************************************* Function: // uart0_init Description: // 串口初始化 Input: // 无 Return: // 无 *******************************************************************************/ void uart0_init(void) { SFRPAGE = 0x00; SCON0 |= SCON0_REN__RECEIVE_ENABLED; IE = IE | IE_ES0__ENABLED; uart0.len = 0; memset((uint8_t *)&uart0.rx_buff, 0, RX_BUF_MAX_LEN); } /******************************************************************************* Function: // send_data0 Description: // 串口发送固定长度数据 Input: // buf 要发送的数据 Input: // len 要发送的数据长度 Return: // 无 *******************************************************************************/ void send_data0(char *buf, uint8_t len) { uint8_t count = 0; SCON0_TI = 0; for (count = 0; count < len; count++) { tx_flag = 0; SBUF0 = buf[count]; while (!tx_flag) ; } } /******************************************************************************* Function: // my_printf Description: // 串口发送不定长字符串 Input: // buf 要发送的字符串 Return: // 无 *******************************************************************************/ void my_printf(char *buf) { uint8_t count = 0; SCON0_TI = 0; while (buf[count] != '\0') { tx_flag = 0; SBUF0 = buf[count]; while (!tx_flag) ; count++; } } /******************************************************************************* Function: // uart0_pro Description: // 串口0主任务 Input: // 无 Return: // 无 *******************************************************************************/ void uart0_pro(void) { static uint32_t timer_uart1 = 0; static uint8_t last = 0; if (last != uart0.len) timer_uart1 = count_ms; last = uart0.len; if ((long)(count_ms - timer_uart1) > UART0_IDLE_TIME) rece0.len = uart0.len; if (rece0.len < 2) { return; } memcpy((uint8_t *)&rece0.rx_buff, (uint8_t *)&uart0.rx_buff, uart0.len); uart0.len = 0; memset((uint8_t *)&uart0.rx_buff, 0, uart0.len); my_printf("uart0 rece:"); send_data0(rece0.rx_buff, rece0.len); my_printf("\r\n"); if (rece0.rx_buff[0] == 'L' && rece0.rx_buff[1] == 'E' && rece0.rx_buff[2] == 'D') { if (rece0.rx_buff[3] == '0') { LED0 = 0; my_printf("LED OFF\r\n"); } else if (rece0.rx_buff[3] == '1') { LED0 = 1; my_printf("LED ON\r\n"); } } else { my_printf("CMD ERROR\r\n"); } memset((uint8_t *)&rece0.rx_buff, 0, rece0.len); rece0.len = 0; } /******************************************************************************* Function: // UART0_IRQn Description: // 串口0中断函数 Input: // 无 Return: // 无 *******************************************************************************/ SI_INTERRUPT(UART0_ISR, UART0_IRQn) { if (SCON0_TI == 1) // Check if transmit flag is set { tx_flag = 1; SCON0_TI = 0; // Clear interrupt flag } if (SCON0_RI == 1) { uart0.rx_buff[uart0.len++] = SBUF0; if (uart0.len == RX_BUF_MAX_LEN) uart0.len = 0; SCON0_RI = 0; } }

代码我上传至码云了

链接直接戳我

欢迎各位大神指点


高工
2021-12-09 21:06:24 打赏
7楼

由于最近时间比较忙,我们直接站在大佬的肩膀上吧,串口1部分直接使用刘滨滨大佬的代码

大佬帖子跳转处

我这里只用简单的添加驱动即可

/******************************************************************************* Function: // send_data1 Description: // 串口1发送固定长度数据 Input: // buf 要发送的数据 Input: // len 要发送的数据长度 Return: // 无 *******************************************************************************/ void send_data1(char *buf, uint8_t len) { uint8_t count = 0; for (count = 0; count < len; count++) { tx1_flag = 0; UART1_writeBuffer(buf[count], 1); while (!tx1_flag) ; } }

添加按键驱动

/******************************************************************************* Function: // key_pro Description: // 按键任务 Input: // 无 Return: // 无 *******************************************************************************/ void key_pro(void) { static uint32_t keu_up_count = 0; static uint32_t keu_down_count = 0; static uint32_t keu_bton_count = 0; static uint32_t timer_key = 0; if ((long)(count_ms - timer_key) < 9) return; timer_key = count_ms; if (UP == 0) keu_up_count++; else keu_up_count = 0; if (DOWN == 0) keu_down_count++; else keu_down_count = 0; if (BTON == 0) keu_bton_count++; else keu_bton_count = 0; if (keu_up_count > 0x5)//UP按下 { keu_up_count = 0; while (UP == 0) ; } if (keu_down_count > 0x5)//DOWN按下 { keu_down_count = 0; while (DOWN == 0) ; } if (keu_bton_count > 0xf)//BTON按下 { keu_bton_count = 0; while (BTON == 0) ; } }

思路就是10ms检测一下几个按键,连续五次检测到就判定为按下,然后等待松手

驱动基本结束,该焊接板子了

我的项目分为两部分,一部分是接收器,也就是连接电脑,另一部分是我们的板卡部分的扩展板,****

先展示一下原理图和PCB图

接收器部分(设计软件:AD21)

****部分(设计软件:立创EDA)


高工
2021-12-09 21:06:41 打赏
8楼

召唤神龙

硬件:

电池供电电路(空间原因未做充电电路)

激光+按键电路(直接电池供电+按键+激光灯头做的一个硬件电路,无单片机控制)

按键电路(IO输入)

无线通信模组(串口输出)
软件:

IO输入(检测按键)

串口发送

定时器

(时间原因未做低功耗处理)

展示硬件

系统框图

程序流程图


代码地址

上传至码云了地址戳我


硬件

扩展板上传至立创开源平台了地址戳我

接收板工程rec.zip


视频

上传至哔哩哔哩了,链接戳我


专家
2021-12-09 21:38:22 打赏
9楼

看看


专家
2021-12-10 00:02:28 打赏
10楼

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


共56条 1/6 1 2 3 4 5 6 ›| 跳转至

回复

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