【EFM8BB52单片机】PPT翻页器(已完成,妹妹很喜欢)
开发环境搭建
废话不多说,趁板子没回来先环境搭建直接上官网找到Simplicity Studio
看看介绍 基于Eclipse的,还是能很快熟悉的



果断选择Simplicity Studio 5版本
下载链接:
但是需要注册,我已经下载好了,直接放在这了,直接下载即可
链接:https://pan.baidu.com/s/1LlYHl7HsV3n5Y9hvgfZVTg
提取码:rw40
WIN10用户选择iso
安装
下载的文件解压完之后直接双击,选择安装文件

一路next选择安装路径即可

安装完直接打开
类似于一个协议,直接打勾即可

说让登录,我直接X了
然后会自动下载,弹出一个窗口

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

选择8位机了

我选择了第一个,应该是都安装了
看样子是安装成功了,重启一哈子

新建工程

刚重启的样子

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

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

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

文档什么的

工具什么的

回来直接生成工程

先选个点灯

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

工程全部

编译一下

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

编译成功

点个灯
看了下例程,用的是定时器点灯,太高级,还不到那一步,先梦回郭天祥,手动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;
}
}编译烧录
点击这个小锤子,直接编译

在点击这个下载

选择编译好的文件


下载

就能看到小灯闪了
新建工程

选择板卡芯片

选择新建工程类型

选择工程名字及存储位置

成功

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

模块化编程
到了重点,回顾大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函数不能删去,因为启动文件里边会调用这个函数

调通了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;
}
}代码我上传至码云了
欢迎各位大神指点
由于最近时间比较忙,我们直接站在大佬的肩膀上吧,串口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)




回复
| 有奖活动 | |
|---|---|
| 硬核工程师专属补给计划——填盲盒 | |
| “我踩过的那些坑”主题活动——第002期 | |
| 【EEPW电子工程师创研计划】技术变现通道已开启~ | |
| 发原创文章 【每月瓜分千元赏金 凭实力攒钱买好礼~】 | |
| 【EEPW在线】E起听工程师的声音! | |
| 高校联络员开始招募啦!有惊喜!! | |
| 【工程师专属福利】每天30秒,积分轻松拿!EEPW宠粉打卡计划启动! | |
| 送您一块开发板,2025年“我要开发板活动”又开始了! | |










我要赚赏金
