试用项目:电子教鞭(PPT翻页器)
借助板卡试用的机会,制作这么一个小玩意(女朋友现在是老师,做个这玩意哄哄她)
系统框图如下:
功能简介: 就是按键控制PPT翻页的一个小玩意,最主要的就是按键检测以及串口发送,无线模块用的是一款串口透传模块,转USB信号用的是沁恒的CH9328,能把串口信号转为USB信号
试用进程:
2 开箱
3 点灯+编译+烧录
5 添加串口点灯
7 召唤神龙
开发环境搭建
废话不多说,趁板子没回来先环境搭建直接上官网找到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)
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
【笔记】生成报错synthdesignERROR被打赏50分 | |
【STM32H7S78-DK评测】LTDC+DMA2D驱动RGBLCD屏幕被打赏50分 | |
【STM32H7S78-DK评测】Coremark基准测试被打赏50分 | |
【STM32H7S78-DK评测】浮点数计算性能测试被打赏50分 | |
【STM32H7S78-DK评测】Execute in place(XIP)模式学习笔记被打赏50分 | |
每周了解几个硬件知识+buckboost电路(五)被打赏10分 | |
【换取逻辑分析仪】RA8 PMU 模块功能寄存器功能说明被打赏20分 | |
野火启明6M5适配SPI被打赏20分 | |
NUCLEO-U083RC学习历程2-串口输出测试被打赏20分 | |
【笔记】STM32CUBEIDE的Noruletomaketarget编译问题被打赏50分 |