0.前言
转载自我的古月居频道
Arduino程序代码是通过C/C++编辑的。
1.初步认识Arduino程序结构
我们打开Arduino IDE 创建一个新的Arduino程序。Arduino新建的程序都会以“sketch”为名称。
如上图所示,程序结构包括两个主要函数:
setup()函数
void setup() {
// put your setup code here, to run once:
// 当程序启动时首先会调用`setup()`函数。可以使用这个函数初始化变量,引脚模式,启用库等等。
// `setup()`函数只会在板子上电或复位后启动一次。
}
loop()函数
void loop() {
// put your main code here, to run repeatedly:
// 当程序启动后运行完`setup()`函数后,会循环运行`loop()`函数中的内容,`loop()`函数可以精确地连续循环执行,`loop()`函数时arduino程序的精髓。
}
疑问
看到这里,可能有些同学会疑问:“Arduino是基于C/C++编辑的,那为什么不是进入main函数”。现在我就给大家分析一下。
在进行Arduino开发时,没有像传统C/C++程序使用入口函数main。实际上main函数存在于Arduino核心库中,且仍然是程序的入口。在Arduino核心库中可见main.cpp文件,其内容如下:
#include <Arduino.h>
// Declared weak in Arduino.h to allow user redefinitions.
int atexit(void (* /*func*/ )()) { return 0; }
// Weak empty variant initialization function.
// May be redefined by variant files.
void initVariant() __attribute__((weak));
void initVariant() { }
void setupUSB() __attribute__((weak));
void setupUSB() { }
int main(void)
{
init();
initVariant();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}
通过以上程序可见,Arduino程序中编写的setup和loop函数,都在main函数中调用了。loop的循环执行,是通过for循环实现的,且每次loop结束后,都会进行串口事件判断,也正是因为这种设计,串口事件不能实时响应。
2.认识Arduino数据类型
在Arduino中有着和C中一样的数据类型,数据的类型决定着它在存储器中占有的空间以及解释存储的位模式。下表提供了Arduino中使用的常用类型。
数据类型 | 占用字节 | 数值范围 | 备注 |
---|---|---|---|
void | 无 | 无 | void(空的)只用作函数声明,表示没有返回值 |
bool | 1 | true/false | |
char | 1 | -128~127 | Arduino中的char是有符号(可分正负)的,等价于signed char。char常被是用于储存ASCII字符。如果想存储数据,建议使用byte类型。 |
unsigned char | 1 | 0~255 | 无符号字符(只能是+值) |
byte | 1 | 0~255 | Arduino中的byte类型和C/C++中的byte类型不同,在Arduino中是特有的,实际上就是无符号8位整形数据 |
int | 2 | -32758~32767 | ESP8266EX的CPU是Tensilica L106 32 bit 处理器,所以在ESP8266EX中是占4个字节 |
unsigned int | 2 | 0~65535 | |
word | 2 | 0~65535 | |
long | 4 | -2147483648~2147483647 | |
unsigned long | 4 | 0 ~ 4,294,967,295 | |
short | 2 | -32768~32767 | |
float | 4 | -3.4028235E+38~3.4028235E+38 | 只有6~7位小数精度 |
double | 4 | -3.4028235E+38~3.4028235E+38 | 精度比FLOAT高 |
string | - | - | 相当于char类型的数组,但是和c/c++下的String类有很大不同 |
3.认识Arduino变量和常量
- 在Arduino中,变量的声明
例:int a = 0
;
变量的声明是由类型 变量名 = 值
; 。
注意:变量名的首字母不能为数字。
变量的作用范围称作用域,变量的作用范围和该变量在哪声明有关,大致分为如下两种:
- 全局变量:在类型前加入extern即可声明为全局变量,即在整个程序中都能使用到。
- 局部变量:若在大括号中定义的变量,即为局部变量,此时的作用域只局限于大括号之内。
- 在Arduino中,常量的声明
例:const int a =0
;
常量的声明是由const类型 变量名 = 值
;。
注意:当我们声明完常量后,是不能对其再次赋值的。
在Arduino中还可以用宏定义#define
来定义常量。
我习惯用#define
来定义。
4.认识Arduino运算符
赋值运算符:
= | 赋值运算符 | 变量=表达式 | a=3,将a的值赋为3; |
---|---|---|---|
/= | 除后赋值 | 变量/=表达式 | a/=3,即a=a/3; |
*= 乘后赋值 | 变量*=表达式 | a*=3,即a=a*3; | |
%= | 取模后赋值 | 变量%=表达式 | a%=3,即a=a%3; |
+= | 加后赋值 | 变量+=表达式 | a+=3,即a=a+3; |
-= | 减后赋值 | 变量-=表达式 | a-=3,即a=a-3; |
<<= | 左移后赋值 | 变量<<=表达式 | 左移就是将《左边的数的二进制各位全部左移若干位,《右边的数指定移动位数,高位丢弃,低位补0, 移几位就相当于乘以2的几次方; |
>>= | 右移后赋值 | 变量>>=表达式 | 右移运算符是用来将一个数的各二进制位右移若干位,移动的位数由右操作数指定(右操作数必须是非负值),移到右端的低位被舍弃,对于无符号数,高位补0;*对于有符号数,某些机器将对左边空出的部分用符号位填补(即“算术移位”),而另一些机器则对左边空出的部分用0填补(即“逻辑移位”); * |
&= | 按位与后赋值 | 变量&=表达式 | 按位与是指参加运算的两个数据,按二进制位进行“与”运算。如果两个相应的二进制位都为1,则该位的结果值为1,否则为0;公式:有0为0 |
^= | 按位异或后赋值 | 变量^=表达式 | 参与运算的两个量按照对应的位进行异或运算,且00→0、01→1、 1^0→1、 11→0。此外,一个数与0异或仍保持不变,即a0=a,一个数与自己异或结果为0,即a^a=0;公式:不同为1 |
|= | 按位或后赋值 | 变量|=表达式 | 参与运算的两个量按照对应位进行或运算,且0|0→0、0|1→1、1|0→1、1|1→1。公式:有1为1 |
移位运算符图解:
例:(00001111)0x0f<<1 -> 0x1e(00011110)
算术运算符:
关系运算符:
逻辑运算符:
递增递减运算符:
reference from:https://www.cnblogs.com/liming19680104/p/10758293.html
5.认识Arduino 控制语句
if(…){} | 它采用括号中的表达式,后面跟随语句或语句块。如果表达式为真,则执行语句或语句块,否则跳过这些语句。 |
---|---|
if(…){}else{} | 一个 if 语句后面可以跟随一个可选的else语句,当表达式为false时执行。 |
if(…){}else if(…){} | if 语句后面可以跟随一个可选的 else if … else 语句,其对于测试各种条件非常有用。 |
switch(…){case:} | 类似于if语句, switch … case 通过允许程序员指定应在各种条件下执行的不同代码来控制程序的流程。 |
?: | 条件运算符? :是C语言中唯一的三元运算符。 |
6.认识Arduino 循环
while(…){} | while循环将会连续、无限循环,直到括号()内的表达式变为false。必须用一些东西改变被测试的变量,否则while循环永远不会退出。 |
---|---|
do{}while(…) | do … while循环类似于while循环。在while循环中,循环连续条件在循环开始时测试,然后再执行循环体。 |
for(int i =0;i<…;i++){} | for循环执行语句预定的次数。循环的控制表达式在for循环括号内完全的初始化,测试和操作 |
7.认识Arduino 字符串
在Arduino中的字符串是char类型的。一个字符串是一个char变量的数组。字符串是一个特殊的数组,在字符串的末尾有一个额外的元素,其值总是为’\0’(零)。这被称为“空终止字符串”。
字符串实例:
例:
void setup() {
char str[6]; //创建一个大小为6的char字符串
Serial.begin(9600); //打开串口,波特率为9600
str[0] = 'H';
str[1] = 'e';
str[2] = 'l';
str[3] = 'l';
str[4] = 'o'; //虽然我们并没有给数组赋值空终止字符串,但是字符串最后一位默认会是一个\0
Serial.println(str); //通过Serial.println()打印到串口监视中
}
输出示例:
Hello
其实为了方便,我们可以对字符串直接赋值
例:
void setup() {
char str[] = "Hello";
Serial.begin(9600);
Serial.println(str);
}
输出示例:
Hello
既然能赋值,那我们也能对相应的字符进行修改
例:
void setup() {
char str[] = "Hello"; // create a string
Serial.begin(9600);
Serial.println(str);
str[0] = 'n';
str[1] = 'i';
str[2] = 'h';
str[3] = 'a';
str[4] = '0';
Serial.println(str);
}
输出示例:
nihao
结语:
最近实在太忙了,忙着做自己定下目标的项目,但是实在是困难重重,就在8.29日今天,主控芯片搞砸了两块,自闭。。。不过,总要在失败中成长,这下,也知道了我的硬件设计是有问题的,所以我得在硬件上下更多的功夫取改进,更新换代。
接下来就是给大家通过项目来学习了。