这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【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 <SI_EFM8BB52_Register_Enums.h>

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 <stdio.h>
#include <string.h>

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 ›| 跳转至

回复

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