自己慢慢搭面包板电路的同时也在学Arduino
无意间从Arduino15这个路径发现些板子内置的代码 因为自己有一个SAMD的板子 所以文件夹中两种架构
AVR (Uno、Nano常规板子) SAMD (MKR低功耗点的板子)
其中wiring_shift.c里面只有两个函数 想看看主要是做什么的
AVR
/*
wiring_shift.c - shiftOut() function
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
#include "wiring_private.h"
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
uint8_t value = 0;
uint8_t i;
for (i = 0; i < 8; ++i) {
digitalWrite(clockPin, HIGH);
if (bitOrder == LSBFIRST)
value |= digitalRead(dataPin) << i;
else
value |= digitalRead(dataPin) << (7 - i);
digitalWrite(clockPin, LOW);
}
return value;
}
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
uint8_t i;
for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST) {
digitalWrite(dataPin, val & 1);
val >>= 1;
} else {
digitalWrite(dataPin, (val & 128) != 0);
val <<= 1;
}
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
}
这里两个函数基本上是利用给定的数据引脚和时钟引脚 做读取和写入操作
shiftIn() 依靠digitalWrite()给时钟引脚拉高/拉低电平之间来从数据引脚读取 根据LSBFIRST/MSBFIRST 会依次从最低位/最高位利用或运算做补位
shiftOut() 直接对val进行位移 如果是LSBFIRST只读取最低位(&1 00000001 与运算) 通过digitalWrite直接写入数据引脚 之后右移1位(/2) 再去读最低位 而MSBFIRST是只读取最高位(&128 10000000 与运算) 同样用digitalWrite写入 之后左移1位(*2) 再去读最高位 所有这8位都结束后将时钟引脚拉高后立刻拉低 形成一种脉冲来提示设备有数据写入
SAMD
/*
Copyright (c) 2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include <Arduino.h>
#include "wiring_private.h"
#ifdef __cplusplus
extern "C"{
#endif
uint8_t shiftIn( pin_size_t ulDataPin, pin_size_t ulClockPin, BitOrder ulBitOrder )
{
uint8_t value = 0 ;
uint8_t i ;
for ( i=0 ; i < 8 ; ++i )
{
digitalWrite( ulClockPin, HIGH ) ;
if ( ulBitOrder == LSBFIRST )
{
value |= digitalRead( ulDataPin ) << i ;
}
else
{
value |= digitalRead( ulDataPin ) << (7 - i) ;
}
digitalWrite( ulClockPin, LOW ) ;
}
return value ;
}
void shiftOut( pin_size_t ulDataPin, pin_size_t ulClockPin, BitOrder ulBitOrder, uint8_t ulVal )
{
uint8_t i ;
for ( i=0 ; i < 8 ; i++ )
{
if ( ulBitOrder == LSBFIRST )
{
digitalWrite( ulDataPin, !!(ulVal & (1 << i)) ) ;
}
else
{
digitalWrite( ulDataPin, !!(ulVal & (1 << (7 - i))) ) ;
}
digitalWrite( ulClockPin, HIGH ) ;
digitalWrite( ulClockPin, LOW ) ;
}
}
#ifdef __cplusplus
} // extern "C"
#endif
能发现从代码功能上和AVR板子上大体相同 用
extern C
防止编译器命名重整
可以发现 无论是shiftIn还算shiftOut 参数的类型都要更严苛
packages\arduino\hardware\samd\1.8.14\cores\arduino\api\Common.h
#ifdef EXTENDED_PIN_MODE
// Platforms who want to declare more than 256 pins need to define EXTENDED_PIN_MODE globally
typedef uint32_t pin_size_t;
#else
typedef uint8_t pin_size_t;
#endif
typedef enum {
LSBFIRST = 0,
MSBFIRST = 1,
} BitOrder;
和AVR稍显不同的地方在shiftOut() 之前在AVR板子上是直接对val进行位移 而SAMD是直接通过循环i的位移来ulVal通过与运算写入
!!
(强制转换为布尔值) 这里也是为了确保读取的结果只限定位0和1
结语
代码主要提供了一个位移操作的软件实现 是类SPI的操作
而真正的SPI通信是由硬件实现的 有固定的引脚 有片选 能够全双工通信
评论区