前言
本文讲述的是有关LED指尖陀螺的制作,也是笔者闲暇之余做的小玩具来打发时间。
一、原理介绍
思维导图:
原理:
我们知道人眼具有视觉暂留的现象,当一束光射到人的眼睛里时它会停留一段时间,而停留时间的长短取决于光的频率以及强度,所以我们便可利用这个特性来实现LED指尖陀螺的旋转成像功能。
首先通过取模软件来得到自己需要的图形或数字的数组,然后在主程序里面不断扫描特定的数组,同时结合适当的延时来实现LED按照一定的频率闪烁。而只烁还是不够的还得结合指尖陀螺本身的旋转过程,因为我做的指尖陀螺上面的LED灯组是16个,所以当我旋转陀螺的时候就会呈现一个16*16的点整,此时再结合LED灯本身的闪烁就能实现在指尖陀螺上面成像了。
这是取模软件的链接:
https://pan.baidu.com/s/1gsYNWw-hieK7GCjVSzV2kQ
提取码:prjv
二、制作过程:
硬件部分:
原理图:
1.这里我采用的是STM32F030F4P6作为主控芯片:
该芯片体积小巧且资源丰富,符合指尖陀螺所需要的功能配置。当然有些STC51的芯片也符合要求,也可以灵活选择,不过原理图部分要做些许改变。
2.LED灯组
可以看到我这里做了一个简单的PNP三极管放大电路,除去限流电阻以外,在其基极和发射极分别连接着芯片的GPIO口,(eg:当PA7和PA3同时输出低电平时LED1就能被点亮。)且一共有4组灯,每组灯有4个LED,所以通过扫描的方式来控制具体第几组第几个灯的亮灭,而且前面所提到的取模软件的数组,便是用于存储LED亮灭及其位置信息的,具体后面程序会再进行解释
3.霍尔传感器:
这是一个霍尔传感电路,其工作原理是当有磁场经过传感器时,其OUT端会输出低电平供单片机识别。之所以需要用这个传感器,是为了让图案或者字符能稳定的显示,不然就会出现文字连在一起的情况。即指尖陀螺在旋转的时候在放手指的垫盘处有一块小磁体,在旋转的过程中每当霍尔传感器进入磁体的磁场内就触发传感器给芯片输入一次低电平信号,芯片检测到之后就显示扫描数组并控制LED进行显示。
4.其余:
剩下的部分就分别是一个电源模块,以及下载口,和切换图案用的按键。
PCB图:
程序部分:
这里程序的基础部分我直接是使用的STM32CubeMX生成的HAL库版本,然后再在其上对程序进行进行编辑。
下面是我的资源配置图:
主程序:(这里只做基础原理介绍)
#include "main.h" #include "gpio.h" uint8_t i,j,k; uint8_t Mode=0; //图像一 uint16_t Pic1[][16]={ {0xFF,0xFF,0xFB,0xFD,0xFB,0xFE,0x3B,0xFF,0xC5,0xFF,0xEB,0xFF,0xEB,0xFC,0x0B,0xFF}, // {0xFB,0xFF,0xFF,0xFF},/*"?",0*/ {0xFF,0xFD,0xFF,0xFE,0x03,0xFF,0xFB,0xFF,0x03,0xFE,0xFD,0xFE,0x61,0xFF,0x1D,0xFF}, // {0xFF,0xFE,0xFF,0xFF},/*"?",1*/ {0xFF,0xFF,0xFF,0xFD,0x7F,0xFE,0x81,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xFC,0xFF,0xFD}, // {0xFF,0xFC,0xFF,0xFD},/*"?",2*/ }; //图像二 uint16_t Pic2[][16]={ {0xBF,0xDF,0xBB,0xED,0xAB,0xB5,0x9A,0x7D,0x39,0x80,0x9B,0xFD,0xAB,0xF5,0xBB,0x6D}, {0xFF,0x9F,0x03,0xE0,0xBB,0xFF,0xBB,0xFF,0x3B,0x00,0xBD,0xFF,0xBF,0xFF,0xFF,0xFF},/*"?",0*/ {0xFF,0xFB,0xDF,0xFB,0xE7,0xFB,0x38,0xF8,0xBB,0xFB,0xBB,0xFB,0xBB,0xFB,0xBB,0xFB}, {0x03,0x00,0xBB,0xFB,0xBB,0xFB,0xBB,0xFB,0xBB,0xFB,0xFB,0xFB,0xFF,0xFB,0xFF,0xFF},/*"?",1*/ {0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0x00,0x00,0xEF,0xFF,0xDF,0x7E,0xF7,0xBE,0xF7,0xCE}, {0xF7,0xF2,0x00,0xFC,0xF7,0xF2,0xF7,0xCE,0x07,0xBE,0xFF,0x7E,0xFF,0x7E,0xFF,0xFF},/*"?",2*/ {0xFF,0xFF,0xFF,0xDF,0x1F,0xEF,0x63,0xF7,0x7B,0xF9,0x7B,0xBF,0x7B,0x7F,0x0B,0x80}, {0x7D,0xFF,0x7D,0xFF,0x7C,0xFD,0x7D,0xFB,0x7F,0xF7,0x7F,0xCF,0xFF,0xFF,0xFF,0xFF},/*"?",3*/ }; //图像三 uint16_t Pic3[][16]={ {0xFF,0xFF,0xE3,0xFF,0xC1,0xFF,0x80,0xFF,0x00,0xFF,0x00,0xFE,0x01,0xFC,0x03,0xF8}, {0x03,0xF8,0x01,0xFC,0x00,0xFE,0x00,0xFF,0x80,0xFF,0xC1,0xFF,0xE3,0xFF,0xFF,0xFF},/*"?????",0*/ }; void Delay(uint16_t t)//延时 { while(t--); } void Mode_Choose(void) //按键判断 { if(HAL_GPIO_ReadPin(Hour_GPIO_Port,Hour_Pin)==0) { HAL_Delay(20); while(HAL_GPIO_ReadPin(Hour_GPIO_Port,Hour_Pin)==0); HAL_Delay(20); for(i=0;i<2;i++) { GPIOA->ODR=0x00; HAL_Delay(200); GPIOA->ODR=0XFF; HAL_Delay(100); } Mode++; if(Mode==4) { Mode=0; } } } //下面的循环中, //k表示每组二维数组中里面一共有多少行。 //i表示每行数组里面的个数,因为下面2*i和2*i+1分别取了每行数组的前两个数,所以这里i只循环8次 //j为了加强视觉暂留效果,故而加长每行显示的时间。 //GPIOA->ODR是STM32里面的一个16位寄存器,通过直接给它赋值可以控制PA0~PA15端口。其中高八位控制PA8~PA15,低八位控制PA0~PA7,这里我们只需要控制其低8位就行了。eg:数组中每一个16进制数的含义 0x11 --> 0001 0001 表示亮3组灯每组亮3个灯,高4位表示第几组亮灯,低4位表示每组亮几个灯。 void Display(void) //显示函数 { if(Mode==1) { if(HAL_GPIO_ReadPin(Hour_GPIO_Port,Hour_Pin)==0)//判断传感器是否被触发 { for(k=0;k<3;k++) { for(i=0;i<8;i++) { for(j=0;j<20;j++) { GPIOA->ODR=0XE0|(Pic1[k][2*i]&0X0F); Delay(120); GPIOA->ODR=0XFF; Delay(10); GPIOA->ODR=0XD0|(Pic1[k][2*i]>>4); Delay(120); GPIOA->ODR=0XFF; Delay(10); GPIOA->ODR=0XB0|(Pic1[k][2*i+1]&0X0F); Delay(120); GPIOA->ODR=0XFF; Delay(10); GPIOA->ODR=0X70|(Pic1[k][2*i+1]>>4); Delay(120); GPIOA->ODR=0XFF; Delay(10); } } } } }else if(Mode==2) { if(HAL_GPIO_ReadPin(Hour_GPIO_Port,Hour_Pin)==0) { for(k=0;k<8;k++) { for(i=0;i<8;i++) { for(j=0;j<20;j++) { GPIOA->ODR=0XE0|(Pic2[k][2*i]&0X0F); Delay(50); GPIOA->ODR=0XFF; Delay(10); GPIOA->ODR=0XD0|(Pic2[k][2*i]>>4); Delay(50); GPIOA->ODR=0XFF; Delay(10); GPIOA->ODR=0XB0|(Pic2[k][2*i+1]&0X0F); Delay(50); GPIOA->ODR=0XFF; Delay(10); GPIOA->ODR=0X70|(Pic2[k][2*i+1]>>4); Delay(50); GPIOA->ODR=0XFF; Delay(10); } } } } }else if(Mode==3) { if(HAL_GPIO_ReadPin(Hour_GPIO_Port,Hour_Pin)==0) { for(k=0;k<2;k++) { for(i=0;i<8;i++) { for(j=0;j<20;j++) { GPIOA->ODR=0XE0|(Pic3[k][2*i]&0X0F); Delay(100); GPIOA->ODR=0XFF; Delay(10); GPIOA->ODR=0XD0|(Pic3[k][2*i]>>4); Delay(100); GPIOA->ODR=0XFF; Delay(10); GPIOA->ODR=0XB0|(Pic3[k][2*i+1]&0X0F); Delay(100); GPIOA->ODR=0XFF; Delay(10); GPIOA->ODR=0X70|(Pic3[k][2*i+1]>>4); Delay(100); GPIOA->ODR=0XFF; Delay(10); } } } } } } void SystemClock_Config(void); int main(void) { HAL_Init(); SystemClock_Config();//软件自动生成的系统时钟程序 MX_GPIO_Init(); while (1) { Mode_Choose(); Display(); } }
三、实物展示:
因为手机的刷新频率快于人眼,所以看起来图像是不完整的。
总结
以上就是我要讲的内容啦,本文仅仅简单介绍了LED指尖陀螺的实现方法,快过年了还不快快做几个给你家的熊孩子,说不定今年过年又“逃过一劫呢!”哈哈 ^&^