Arduino初学——基本函数与操作

序言

玩起arduino其实一直没有好好的把arduino的基本操作过一遍,今天本小白就忙里偷闲干了这件事情,当然,首先还是要把之前的bug解决一下。

上一篇OLED的bug

尝试oled分屏显示的时候,本来是因为每屏的内容不同,所以进行了分几屏显示的操作。
后来做单屏滚动的时候,是想在一屏里解决的,但是总会出现显示提前结束的bug。
于是我想起来我改过一个变量的类型。

unsigned long draw_state = 0;

为了增长显示时间,我把类型改成了unsigned long
但是在函数调用的时候我没有改。。。
错误如下:

void u8g_print1(uint8_t a) {
case 0 : u8g_print1 (draw_state&(uint8_t)(pow(2,Con_interval)-1)); 

这两行代码里数据类型都用的是unsigned char…
于是把这两行修改之后,程序就正常运行了。【揭棺而起.jpg】
代码如下:

#include "U8glib.h"
U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE);  // I2C / TWI 
# define Con_interval 11   
# define Con_pages 1
void u8g_prepare(void) {
  u8g.setFont(u8g_font_6x10);
  u8g.setFontRefHeightExtendedText();
  u8g.setDefaultForegroundColor();
  u8g.setFontPosTop(); 
}
void u8g_print1(unsigned long a) {
  u8g.drawStr( 0, 0-a/8, "Schools apart,");
  u8g.drawStr( 0, 11-a/8, "day after day,");
  u8g.drawStr( 0 ,22-a/8, "And I slowly ");
  u8g.drawStr( 0 ,33-a/8, "go insane.");
  u8g.drawStr( 0 ,44-a/8, "But you left");
  u8g.drawStr( 0, 55-a/8, "which was");
  u8g.drawStr( 0, 66-a/8, "my deep pain.");
  u8g.drawStr( 0, 77-a/8, "Since you've");
  u8g.drawStr( 0, 88-a/8, "broken my heart,");
  u8g.drawStr( 0, 99-a/8, "you need not");
  u8g.drawStr( 0, 110-a/8, "be with me.");
  u8g.drawStr( 0, 121-a/8, "Let's say goodbye");
  u8g.drawStr( 0, 132-a/8, "and depart,");
  u8g.drawStr( 0, 143-a/8, "And I'm what");
  u8g.drawStr( 0, 154-a/8, "I used to be.");
  u8g.drawStr( 0, 165-a/8, "Do not say forever;");
  u8g.drawStr( 0, 176-a/8, "Do not");
  u8g.drawStr( 0, 187-a/8, "meet tomorrow.");
  u8g.drawStr( 0, 198-a/8, "And I see you never,");
  u8g.drawStr( 0, 209-a/8, "I am virtue as snow.");
}
unsigned long draw_state = 0;

void draw(void) {
  u8g_prepare();
  switch(draw_state >> Con_interval) {
    case 0 : u8g_print1 (draw_state); break;
}
}
void setup(void) {
  u8g.setRot180();
}
void loop(void) {
  u8g.firstPage();  
  do {
    draw();
      } 
  while( u8g.nextPage() );
  draw_state++;
  if ( draw_state >= Con_pages * pow(2,Con_interval))
  draw_state = 0;
}

这就实现前一篇的功能了hhh

进入正题——arduino

arduino的编程跟c语言差别不大,所以并不会很难上手。我个人感觉差异主要在于:需要声名端口输入或输出,用函数而非赋值进行输入输出,可以直接使用analog输入和pwm输出,拥有串口监视器简便的进行串口通讯。以下详述。

基本框架

arduino有很明确的编程框架:
1.在开头引用头文件,做宏定义,声名全局变量,给管脚命名。
2.紧接着编写自己的函数
3.之后在setup()里进行管脚的初始化,以及串口的初始化
管脚初始化有以下的形式:

pinMode(pin1,INPUT);      //初始化管脚为输入
pinMode(pin2,OUTPUT);     //初始化管脚为输出
pinMode(pin3,INPUT_PULLUP)//初始化管脚为输入且启用上拉电阻

4.最后就是loop()循环执行主函数

数字输入输出

arduino的数字输出是通过函数。

digitalWrite(pin1,HIGH);
digitalWrite(pin2,LOW);

分别是输出高,低电平。
输入也是通过函数,函数返回值即为输入值(感觉说读取值好一点??)

key=digitalRead(pin);
analog输入

通俗的说就是能读取端口的电压值,之后表示为0-1023之间的数。
具体表示方法:返回值/1023=实际电压/标准电压(默认5v)
标准电压是可以设置的,在setup里调用函数analogReference(参数)

analogReference(DEFAULT);      //默认电压值
analogReference(INTERNAL1V1);  //1.1v
analogReference(INTERNAL2V56); //2.56v
analogReference(EXTERNAL);     //AREF口外加电压

需要注意的是:当端口处于悬空状态(意思明白就好)时,读取到的电压可能为任意值
其实其他口也是这样,但这个特性对analog输入的影响更大。具体下文会提到。这里先把函数放出来

Value=analogRead(A0);             //读取A0口的电压并赋值给Value
PWM输出

与analog相应的输出,实际上是通过调整高、低电平在一个周期里的所占总时间比例,实现将数字信号转换为模拟信号。(可以理解为输出0与5v之间的电压值??)
直接上代码了,这是一个9脚输出控制呼吸灯的程序。

int ledpin=9;
int brightness=0;
int fadeAmount=5;
void setup() {
  pinMode(ledpin,OUTPUT);
}
void loop() {
  analogWrite(ledpin,brightness);
  brightness+=fadeAmount;
  if(brightness==0||brightness>=255)
  {
    fadeAmount=-fadeAmount;
    delay(100);
    if(brightness==0)digitalWrite(ledpin,LOW);
    delay(600);
  }
  delay(100);
  }

其中analogWrite完成了PWM输出,其第二个参数应介于0-255之间,在这个程序中第二个参数brightness反映了亮度。

串口监视器

感觉arduino特别人性化的一点,就是功能整合的好,用起来方便。串口监视器就是其一。
要用的话需要在setup()里进行一个初始化。

Serial.begin(9600);

参数是波特率,波特率需要与电脑上所选择的波特率匹配
在这里插入图片描述
之后会用到的几个函数

Serial.print("xxxx");             //输出字符串
Serial.println(Value);            //输出某个变量值并换行
Serial.available();               //判读有无输入,有则返回1,没有返回0
data=Serial.read();               //返回读到的一个字节数据

一个有bug的程序

看到书上有写到一个多按键的程序,不同的按键按下会导致A0口输入不同的电压值,从而用一个端口完成了多个按键的扫描。
于是小白有了如下的实践:
需要说明的是我在0-5v之间串联5个相同电阻,按键接在了两两电阻之间。按键的另一端共同接到A0

int Value;
void setup() {
pinMode(A0,INPUT);
Serial.begin(9600);
}
void loop() {
Value=analogRead(A0);
if(Value>202&&Value<205) Serial.println(Value);
    else if(Value>408&&Value<412) Serial.println(Value);
        else if(Value>613&&Value<616) Serial.println(Value);
            else if(Value>817&&Value<821) Serial.println(Value);
delay(200);
}

当分别按下4个按键,在监视器里分别会看到4种值。
不过bug在于按键不按的时候A0口相当于悬空,可能返回任意值,就有可能凭空触发按键的程序,而A0口接在vcc或者gnd都会影响按键的扫描,导致按下没有效果。。
不知道这个bug有什么办法解决。我统计了5分钟内“凭空触发”的次数,如下:在这里插入图片描述
5分钟这么多次还是不少的……所以看来这个暂且还不能作为一个操作按键的方法,还希望有大佬来指点迷津一些。

今天内容就这些了,鄙人不才,告辞。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值