0


Digispark USB开发板的应用_写给刚学完C的你

文章目录


学前小故事

大一上学期,学校完成了半本《C++黑皮书》的教学。我学会了打HelloWorld!!!

#include<stdio.h>intmain(){printf("Hello World!\n");return0;}

寒假,乘着对计算机的热情,我在家花了三天的时间,啃完了后半册《类和对象》。我学会了!!!
用结构体打HelloWorld…

#include<stdio.h>struct{char*str ="Hello World!";} test;intmain(){printf(test.str);return0;}

这个黑不拉几的命令行是用来解小学奥数题的吗?这和炫酷好像差了亿点点啊?
在这里插入图片描述

后来,我就去学HTML画网页去了…
我在一堂讲座上听到了BadUSB。由于Bad这一单词太帅。
出于对计算机的强烈热爱。我在淘宝上斥20元巨资,买了两个最便宜的USB开发板。
最终,完成了一次C语言的实际应用,并对次项目的完成过程和出现的问题进行记录和完善。


一、Hello Digispark

1.硬件介绍

硬件:

Attiny85 Digispark

开发板,某宝

10元

上下浮动。
在这里插入图片描述

2.实现原理

Attiny85 Digispark

开发板可以模拟成日常使用的USB键盘进行模拟输入。
利用Win系统,按下WIN+R打开并锁定到CMD的特性,能够用cmd命令行代码做到诸如

在命令行打HELLO WORLD

、打开一个网页、关闭电脑等事情。
所有操作只要事先编写好代码,在插入USB后会自动执行。

3.配置环境

软件下载

百度网盘链接(失效请联系我补链):https://pan.baidu.com/s/1_dSDderH-UtY0XozLq3WhQ?pwd=nbut

操作系统:Win7、10、11
驱动安装:DigisparkWindowsDriver
编译器:Arduino在这里插入图片描述

软件安装

(1)

解压

DigisparkWindowsDriver,根据操作系统位数

双击某个exe

,安装相应的安装包。

在这里插入图片描述
(2)

解压

Arduino,进入目录

运行arduino.exe

在这里插入图片描述

(3)此步骤已在我的ZIP中封装好,可能可以省略,建议检查一遍。

打开左上方

文件->首选项

,在附加开发板管理网址中输入

http://digistump.com/package_digistump_index.json

在这里插入图片描述

科学上网

后,打开

工具->开发板->开发板管理

,下载相应开发包。

在这里插入图片描述

4.第一个USB开发板程序

工具->开发板

中选择

Digispark(Defult - 16.5mhz)

在页面中输入以下代码。

#include"DigiKeyboard.h"voidsetup(){//第一步操作,打开cmd命令
  DigiKeyboard.delay(2000);
  DigiKeyboard.sendKeyStroke(0);
  DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT);//按R和win键,打开运行//*****第二步操作,输入代码,多次实验得出的解决方案//***此步骤适配系统为WIN10标准输入法,在中英文下皆可成功输入正确代码//*输入字符请用print,切勿使用println,因为println会在输入完字符后在后面追加回车,括号中内容最好全用大写
  DigiKeyboard.delay(200);
  DigiKeyboard.sendKeyPress(MOD_SHIFT_LEFT);//按住shift
  DigiKeyboard.print("HELLO");
  DigiKeyboard.sendKeyPress(0);//松开shift
  DigiKeyboard.sendKeyStroke(KEY_SPACE);
  DigiKeyboard.sendKeyStroke(KEY_SPACE);//按两次空格,确保正确输入并有空行 

  DigiKeyboard.delay(200);
  DigiKeyboard.sendKeyPress(MOD_SHIFT_LEFT);//按住shift
  DigiKeyboard.print("DIGISPART");
  DigiKeyboard.sendKeyPress(0);//松开shift
  DigiKeyboard.sendKeyStroke(KEY_SPACE);
  DigiKeyboard.sendKeyStroke(KEY_SPACE);//按两次空格,确保正确输入并有空行 //第三步操作,按下回车,此次作为测试盘不建议使用(也可以增加等待时间来测试)//  DigiKeyboard.delay(200);//  DigiKeyboard.sendKeyStroke(KEY_ENTER);//按回车}voidloop(){}

代码输入完成后,点击左上方的

勾勾

,会出现下方信息。

在这里插入图片描述

再点击勾勾旁边的箭头,并

关闭奇怪的框框

,会在下方出现黄色的,请在60s内插入开发板的提示。

在这里插入图片描述

立刻插入开发板,就会进行烧录并稍后执行相应命令。在电脑左下角出现下面情况即为完成第一个项目。

在这里插入图片描述


二、结构介绍以及C语言美化

相信学过C的都会想到,上面的

HELLO WORLD

程序虽然在格式上

完全正确

,但是好像差了点什么?
没错,就是重复代码太多了。要修改起来过于麻烦,下面1,2两步处理后也许会好看很多。

1.#difine定义常量

对于常用的重复变量,我们可以给它改个名字,让它变得好看又方便修改。

  DigiKeyboard.delay(2000);
  DigiKeyboard.sendKeyStroke(0);
  DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT);//按R和win键,打开运行

  DigiKeyboard.delay(200);
  DigiKeyboard.sendKeyPress(MOD_SHIFT_LEFT);//按住shift
  DigiKeyboard.print("HELLO");
  DigiKeyboard.sendKeyPress(0);//松开shift
  DigiKeyboard.sendKeyStroke(KEY_SPACE);
  DigiKeyboard.sendKeyStroke(KEY_SPACE);//按两次空格,确保正确输入并有空行 

  DigiKeyboard.delay(200);
  DigiKeyboard.sendKeyPress(MOD_SHIFT_LEFT);//按住shift
  DigiKeyboard.print("DIGISPART");
  DigiKeyboard.sendKeyPress(0);//松开shift
  DigiKeyboard.sendKeyStroke(KEY_SPACE);
  DigiKeyboard.sendKeyStroke(KEY_SPACE);//按两次空格,确保正确输入并有空行 

HELLO WORLD

代码中,我们不难发现,2000,200这两个变量时常出现,那么就可以用#define重新定义一下。在引用头文件下打上如下两行代码,将2000命名为

LONG_TIME

,代表长停顿时间,短停顿时间则命名为

SHORT_TIME

,这里我将

SHORT_TIME

改为100,代表0.1s。

#include"DigiKeyboard.h"#define LONG_TIME 2000#define SHORT_TIME 100

2.函数封装调用

再次观察

HELLO WORLD

代码,还可以发现,在输入单词阶段,有大量重复代码,那我们就可以创建一个新的函数,将它封装起来。下面是我封装完后的

HELLO WORLD

代码。

#include"DigiKeyboard.h"#define LONG_TIME 2000#define SHORT_TIME 100voidrun_begin(){
  DigiKeyboard.delay(LONG_TIME);//开机延迟两秒钟,用于系统识别Digispark
  DigiKeyboard.sendKeyStroke(0);//适应老旧系统
  DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT);//按R和win键,打开运行}voidstr_print(char* str){
  DigiKeyboard.delay(SHORT_TIME);//停滞一段时间
  DigiKeyboard.sendKeyPress(MOD_SHIFT_LEFT);//按住shift
  DigiKeyboard.print(str);//*输出字符,内容大写
  DigiKeyboard.sendKeyPress(0);//松开shift
  DigiKeyboard.sendKeyStroke(KEY_SPACE);
  DigiKeyboard.sendKeyStroke(KEY_SPACE);//按两次空格,确保正确输入并有空行}voidrun_end(){
  DigiKeyboard.delay(SHORT_TIME);//停滞一段时间
  DigiKeyboard.sendKeyStroke(KEY_ENTER);//按回车}voidsetup(){run_begin();str_print("HELLO");str_print("-WORLD");//  run_end();}voidloop(){}

三、强化学习

1.源码阅读

读懂别人写的代码也是团队协作和成神的必要技能点。
已经被官方开发承认的头文件理所应当是阅读的首要材料。
欢迎来到<走进源码>栏目。一起剖析

<DigiKeyboard.h>


此文件我复制了一个,放在了

example文件夹

中。
下面是部分源码:
这部分源码定义了常用键盘按键。

#define MOD_CONTROL_LEFT    (1<<0)#define MOD_SHIFT_LEFT      (1<<1)#define MOD_ALT_LEFT        (1<<2)#define MOD_GUI_LEFT        (1<<3)#define MOD_CONTROL_RIGHT   (1<<4)#define MOD_SHIFT_RIGHT     (1<<5)#define MOD_ALT_RIGHT       (1<<6)#define MOD_GUI_RIGHT       (1<<7)#define KEY_A       4#define KEY_B       5#define KEY_C       6#define KEY_D       7#define KEY_E       8#define KEY_F       9#define KEY_G       10#define KEY_H       11#define KEY_I       12#define KEY_J       13#define KEY_K       14#define KEY_L       15#define KEY_M       16#define KEY_N       17#define KEY_O       18#define KEY_P       19#define KEY_Q       20#define KEY_R       21#define KEY_S       22#define KEY_T       23#define KEY_U       24#define KEY_V       25#define KEY_W       26#define KEY_X       27#define KEY_Y       28#define KEY_Z       29#define KEY_1       30#define KEY_2       31#define KEY_3       32#define KEY_4       33#define KEY_5       34#define KEY_6       35#define KEY_7       36#define KEY_8       37#define KEY_9       38#define KEY_0       39#define KEY_ENTER   40#define KEY_SPACE   44

这部分源码定义了可以调用的函数。

class DigiKeyboardDevice : public Print {
 public:
  DigiKeyboardDevice (){cli();usbDeviceDisconnect();_delay_ms(250);usbDeviceConnect();usbInit();sei();// TODO: Remove the next two lines once we fix//       missing first keystroke bug properly.memset(reportBuffer,0,sizeof(reportBuffer));usbSetInterrupt(reportBuffer,sizeof(reportBuffer));}voidupdate(){usbPoll();}// delay while updating until we are finished delayingvoiddelay(long milli){unsignedlong last =millis();while(milli >0){unsignedlong now =millis();
        milli -= now - last;
        last = now;update();}}//sendKeyStroke: sends a key press AND releasevoidsendKeyStroke(byte keyStroke){sendKeyStroke(keyStroke,0);}//sendKeyStroke: sends a key press AND release with modifiersvoidsendKeyStroke(byte keyStroke, byte modifiers){sendKeyPress(keyStroke, modifiers);// This stops endlessly repeating keystrokes:sendKeyPress(0,0);}//sendKeyPress: sends a key press only - no release//to release the key, send again with keyPress=0voidsendKeyPress(byte keyPress){sendKeyPress(keyPress,0);}//sendKeyPress: sends a key press only, with modifiers - no release//to release the key, send again with keyPress=0voidsendKeyPress(byte keyPress, byte modifiers){while(!usbInterruptIsReady()){// Note: We wait until we can send keyPress//       so we know the previous keyPress was//       sent.usbPoll();_delay_ms(5);}memset(reportBuffer,0,sizeof(reportBuffer));
         
    reportBuffer[0]= modifiers;
    reportBuffer[1]= keyPress;usbSetInterrupt(reportBuffer,sizeof(reportBuffer));}
   
  size_t write(uint8_t chr){
    uint8_t data =pgm_read_byte_near(ascii_to_scan_code_table +(chr -8));sendKeyStroke(data &0b01111111, data >>7? MOD_SHIFT_RIGHT :0);return1;}//private: TODO: Make friend?
  uchar    reportBuffer[2];// buffer for HID reports [ 1 modifier byte + (len-1) key strokes]
  using Print::write;};

2.源码总结

看懂了源码,可以对此进行归纳总结。下面是我的

总结


在这里插入图片描述


四、效果展示

这是example文件夹中Shutdown-H代码的运行效果

Shutdown-H代码运行效果


C语言其实很厉害

C语言从出生开始基本没遇到过什么挑战。
对于C的具体语法。人们实在想不出整数类型除了用按字节数归类为char、short、int、long,还能怎么分类。
结构体好似恰到好处,往struct加什么都像是画蛇添足。
它的指针更为精妙,能完美地和数组配合起来。
基本的malloc和free似乎是内存管理的唯一方式。
函数调用和递归还是用调用栈实现。

虽然它没有现在的Python,Java,C#那么简单易学,但它依旧是游戏内核,硬件领域的龙头语言。
应为他的

效率

比它们都高!!!

认真学C的你真的很帅/美

黑乎乎的命令行有时真的很让人感到疲倦,但是它有时就像黑夜中的刺客,让人摸不着脑袋,又让人浮想联翩。不管你学C的目的是什么。
做游戏内核?成为算法大牛?做硬件工程师?写驱动程序进行多端适配?当一名坏坏的黑客?
祝你不忘初心,一路成神,这真的很帅,很美…

加油,陌生人。

本文转载自: https://blog.csdn.net/weixin_46500938/article/details/123559772
版权归原作者 快穿上小裤裤 所有, 如有侵权,请联系我们删除。

“Digispark USB开发板的应用_写给刚学完C的你”的评论:

还没有评论