Arduino 代码机制

     新建一个Arduino程序。可是建完就郁闷了,因为只看到了setup和loop函数,却没有基本的c函数。
void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}
       于是好奇心就来了,当然对于开源代码来说这个没有什么秘密。查一下源代码就知道了。
       从配置文件来看,核心代码在cores\arduino下。进入代码目录可以看到这里各个文件都是按照功能来命名的,所以很好辨认。很容易就能找到main.cpp,我们打开来看看具体内容:
int main(void)
{
        init();

#if defined(USBCON)
        USBDevice.attach();
#endif
       
        setup();
   
        for (;;) {
                loop();
                if (serialEventRun) serialEventRun();
        }
        
        return 0;
}

       看到我们熟悉的main函数了吧,同时看到main函数里在初始化时调用了setup函数,在for循环里调用了loop函数,所以这下大家明白了为什么在arduino中写代码的时候只看到setup和loop函数了吧,setup函数和loop函数已经预调用了。

       接下来再打开一个最简单的例子Blink。
int led = 13;

// the setup routine runs once when you press reset:
void setup() {               
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

       这个代码原理很简单,把引脚13设置成输出,然后使用for循环,在13脚交替输出高低电平;这个逻辑很好理解。但是这其中又有疑问了;写过avr c代码的同学肯定都知道,一般对某个端口或者引脚操作都是使用DDRX,PORTX,PINX来操作的,为什么这里可以直接用数字来操作呢?
       接下来继续分析一下pinMode这个函数,这个函数在cores\arduino\Wiring_digital.c文件里。
void pinMode(uint8_t pin, uint8_t mode)
{
        uint8_t bit = digitalPinToBitMask(pin);
        uint8_t port = digitalPinToPort(pin);
        volatile uint8_t *reg, *out;

        if (port == NOT_A_PIN) return;

        // JWS: can I let the optimizer do this?
        reg = portModeRegister(port);
        out = portOutputRegister(port);
        ……
        ……
}

       我只贴出了主要功能函数,其它部分代码感兴趣的可以自己去研究。这里可以看出主要函数是digitalPinToBitMask,digitalPinToPort,portModeRegister,portOutputRegister这几个。本着打破砂锅问到底的精神,我们继续搜索这几个函数的实现,这下可以看到是4个宏。
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )

       对于pgm_read_byte这个函数说明如下:

       读取指令pgm_read_xxx宏定义其实就是一段包括了flash读取指令的内联汇编代码。函数原型为:

pgm_read_byte(address_short);

pgm_read_word(address_short);

pgm_read_dword(address_short);

pgm_read_float(address_short);//括号中是地址值。

       本文的关键,不是pgm_read_byte这个函数,而是pgm_read_byte这个函数里面的参数:digital_pin_to_port_PGM,digital_pin_to_bit_mask_PGM,pgm_read_word( port_to_input_PGM,pgm_read_word( port_to_mode_PGM。看看这四个参数的定义在哪里。

          经过搜索发现在   hardware\arduino\variants\leonardo\ Pins_arduino.h里,是不是很眼熟呀,是的,就是讲配置文件的时候讲过这个文件作用。

       所以不难发现,arduino是是先把各个芯片的端口和引脚的映射关系都定义成几个表格,这几个表格把引脚所在的位置作为索引,在使用的时候通过引脚位置,通过查表得到对应的功能寄存器。然后就可以设置输出输入模式,设置输入输出电平,对于arduino来说只需要告诉它需要操作哪个引脚,以及要怎么操作。而不需要去关心这个引脚在哪个port上,是在PORTA还是在PORTB,更不用关心这个芯片是什么型号。
       对于芯片的定时器,pwm等基础功能arduino都是按照这种方式实现的。就不再多说了。有了这些相信各位同学对arduino的使用会更加得心应手。
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值