




已阅读5页,还剩14页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
3.1.1 pinMode(pin, mode)3.1 数字I/O3.1.1 pinMode(pin, mode)pinMode函数在第2章中已经出现过了,用以配置引脚为输出或输出模式,它是一个无返回值函数,函数有两个参数pin和mode,pin参数表示所要配置的引脚,mode参数表示设置的模式INPUT(输入)或OUTPUT(输出)。注意:Arduino板上的模拟引脚也可以当做数字引脚使用,编号为14(对应模拟引脚0)到19(对应模拟引脚5)。由于Arduino项目是完全开源的,所以pinMode(pin, mode)函数原型可直接在Arduino开发环境目录下的hardwarearduinocoresarduino文件夹里的wiring_digital.c文件中查看。函数原型有助于我们深入了解Ardnino的基本函数的底层实现方式,但这部分的内容需要在单独深入学习AVR单片机的基础上进行,本书将这些函数原型从文件中提取出来,有兴趣的读者可以参考一下。一般只要能够熟练地使用这些Arduino基本函数就可以了,本书对函数原型没有进行过多讲解。pinMode(pin, mode)函数原型:void pinMode(uint8_t pin, uint8_t mode) uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); volatile uint8_t *reg; if (port = NOT_A_PIN) return; reg = portModeRegister(port); if (mode = INPUT) uint8_t oldSREG = SREG; cli(); *reg &= bit; SREG = oldSREG; else uint8_t oldSREG = SREG; cli(); *reg |= bit; SREG = oldSREG; 可以在开发环境中的下列实例程序中找到pinMode函数的应用:ADXL3xx.pde、AnalogInput.pde、Blink.pde、BlinkWithoutDelay.pde、Button.pde、Calibration.pde、Debounce.pde、Dimmer.pde、Knock.pde、Loop.pde、Melody.pde、Memsic2125.pde、PhysicalPixel.pde、Ping.pde3.1.2 digitalWrite(pin,value)digitalWrite函数也是在Blink程序中见到过的,它的作用是设置引脚的输出的电压为高电平或低电平。该函数也是一个无返回值的函数,函数有两个参数pin和value,pin参数表示所要设置的引脚,value参数表示输出的电压HIGH(高电平)或LOW(低电平)。注意:在使用digitalWrite(pin, value)函数设置引脚之前,需要将引脚设置为OUTPUT模式。digitalWrite(pin, value)函数原型同样也可以在wiring_digital.c文件中找到,函数原型如下:void digitalWrite(uint8_t pin, uint8_t val) uint8_t timer = digitalPinToTimer(pin); uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); volatile uint8_t *out; if (port = NOT_A_PIN) return; / If the pin that support PWM output, we need to turn it off / before doing a digital write. if (timer != NOT_ON_TIMER) turnOffPWM(timer); out = portOutputRegister(port); if (val = LOW) uint8_t oldSREG = SREG; cli(); *out &= bit; SREG = oldSREG; else uint8_t oldSREG = SREG; cli(); *out |= bit; SREG = oldSREG; 可以在开发环境的下列实例程序中找到digitalWrite函数的应用:ADXL3xx.pde、AnalogInput.pde、Blink.pde、BlinkWithoutDelay.pde、Button.pde、Calibration.pde、Debounce.pde、Knock.pde、Loop.pde、Melody.pde、PhysicalPixel.pde、Ping.pde3.1.3 digitalRead(pin)digitalRead函数用在引脚为输入的情况下,可以获取引脚的电压情况HIGH(高电平)或LOW(低电平),参数pin表示所要获取电压值的引脚,该函数返回值为int型,表示引脚的电压情况。函数原型如下:int digitalRead(uint8_t pin) uint8_t timer = digitalPinToTimer(pin); uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); if (port = NOT_A_PIN) return LOW; / If the pin that support PWM output, we need to turn it off / before getting a digital reading. if (timer != NOT_ON_TIMER) turnOffPWM(timer); if (*portInputRegister(port) & bit) return HIGH; return LOW;注意:如果引脚没有链接到任何地方,那么将随机返回HIGH或LOW。可以在开发环境的下列实例程序中找到digitalRead函数的应用:Button.pde、Debounce.pde3.2.1 analogReference(type)3.2 模拟I/O3.2.1 analogReference(type)analogReference函数的作用是配置模拟引脚的参考电压。在嵌入式应用中引脚获取模拟电压值之后,将根据参考电压将模拟值转换到01023。该函数为无返回值函数,参数为type类型,有3种类型(DEFAULT/INTERNAL/EXTERNAL),具体含义如下:DEFAULT:默认值,参考电压为5V。INTERNAL:低电压模式,使用片内基准电压源。EXTERNAL:扩展模式,通过AREF引脚获取参考电压,AREF引脚位置见图3.2。注意:如果在AREF引脚加载外部参考电压,需要使用一个5KW的上拉电阻,这会避免由于设置不当造成控制芯片的损坏。3.2.2 analogRead(pin)analogRead函数用于读取引脚的模拟量电压值,每读一次需要花100ms的时间。参数pin表示所要获取模拟量电压值的引脚,该函数返回值为int型,表示引脚的模拟量电压值,范围在01023。函数原型可在wiring_analog.c文件中查看,如下:int analogRead(uint8_t pin) uint8_t low, high; / set the analog reference (high two bits of ADMUX) and select / the channel (low 4 bits). this also sets ADLAR (left-adjust / result) to 0 (the default). ADMUX = (analog_reference 6) | (pin & 0x07); / start the conversion sbi(ADCSRA, ADSC); / ADSC is cleared when the conversion finishes while (bit_is_set(ADCSRA, ADSC); / we have to read ADCL first; doing so locks both ADCL / and ADCH until ADCH is read. reading ADCL second would / cause the results of each conversion to be discarded, / as ADCL and ADCH would be locked when it completed. low = ADCL; high = ADCH; / combine the two bytes return (high 8) | low;注意:函数的参数pin范围是05,表示6个模拟量I/O口中的一个。可以在开发环境中的下列实例程序中找到analogRead函数的应用:ADXL3xx.pde、AnalogInput.pde、Calibration.pde、Graph.pde、Knock.pde、Smoothing.pde、VirtualColorMixer.pde3.2.3 analogWrite(pin, value)analogWrite函数通过PWM的方式在引脚上输出一个模拟量,较多的应用在LED亮度控制、电机转速控制等方面。PWM(Pulse Width Modulation,脉冲宽度调制)方式是通过对一系列脉冲的宽度进行调制,来等效地获得所需要的波形或电压。脉冲宽度调制是一种模拟控制方式,其根据相应载荷的变化调制晶体管栅极或基极的偏置,来实现开关稳压电源输出晶体管或晶体管导通时间的改变,这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。图3.3是一个简单的PWM波示意图。其中,VCC是高电平值,T是PWM波的周期,D是高电平的宽度,D/T是PWM波的占空比,当上述PWM波通过一个低通滤波器后,波形中高频的部分被滤掉得到所需的波形,其平均电压为VCCD/T。因此,可通过调节D的大小来改变占空比,产生不同的平均电压;同样,调节PWM波的周期T也可以改变占空比,从而得到不同的平均电压值。在Arduino中执行该操作后,应该等待一定时间后才能对该引脚进行下一次操作。Arduino中的PWM的频率大约为490Hz。该函数支持以下引脚:3、5、6、9、10、11。在Arduino控制板上引脚号旁边标注的就是可用作PWM的引脚,如图3.4所示。analogWrite函数为无返回值函数,有两个参数pin和value,参数pin表示所要设置的引脚,只能选择函数支持的引脚;参数value表示PWM输出的占空比,范围在0255的区间,对应的占空比为0%100%,函数原型如下:void analogWrite(uint8_t pin, int val) if (digitalPinToTimer(pin) = TIMER1A) / connect pwm to pin on timer 1, channel A sbi(TCCR1A, COM1A1); / set pwm duty OCR1A = val; else if (digitalPinToTimer(pin) = TIMER1B) / connect pwm to pin on timer 1, channel B sbi(TCCR1A, COM1B1); / set pwm duty OCR1B = val; else if (digitalPinToTimer(pin) = TIMER0A) if (val = 0) digitalWrite(pin, LOW); else / connect pwm to pin on timer 0, channel A sbi(TCCR0A, COM0A1); / set pwm duty OCR0A = val; else if (digitalPinToTimer(pin) = TIMER0B) if (val = 0) digitalWrite(pin, LOW); else / connect pwm to pin on timer 0, channel B sbi(TCCR0A, COM0B1); / set pwm duty OCR0B = val; else if (digitalPinToTimer(pin) = TIMER2A) / connect pwm to pin on timer 2, channel A sbi(TCCR2A, COM2A1); / set pwm duty OCR2A = val; else if (digitalPinToTimer(pin) = TIMER2B) / connect pwm to pin on timer 2, channel B sbi(TCCR2A, COM2B1); / set pwm duty OCR2B = val; else if (val 128) digitalWrite(pin, LOW); else digitalWrite(pin, HIGH);可以在开发环境的下列实例程序中找到analogWrite函数的应用:Calibration.pde、Dimmer.pde、Fading.pde3.3.1 shiftOut(dataPin,clockPin,bitOrder,val)3.3 高级I/O3.3.1 shiftOut(dataPin,clockPin,bitOrder,val)shiftOut函数能够将数据通过串行的方式在引脚上输出,相当于一般意义上的同步串行通信,这是控制器与控制器、控制器与传感器之间常用的一种通信方式。shiftOut函数无返回值,有4个参数:dataPin、clockPin、bitOrder、val,具体说明如下:dataPin:数据输出引脚,数据的每一位将逐次输出。引脚模式需要设置成输出。clockPin:时钟输出引脚,为数据输出提供时钟,引脚模式需要设置成输出。bitOrder:数据位移顺序选择位,该参数为byte类型,有两种类型可选择,分别是高位先入MSBFIRST和低位先入LSBFIRST。val:所要输出的数据值。函数原型在wiring_shift.c文件中,如下: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 i); else digitalWrite(dataPin, !(val & (1 (7 - i); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); 另外还有shiftIn函数用于通过串行的方式从引脚上读入数据,其函数定义如下: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) 0) if (uint16_t)micros() - start) = 1000) ms-; start += 1000; 可以在开发环境的下列实例程序中找到delay函数的应用:ADXL3xx.pde、AnalogInput.pde、Blink.pde、Fading.pde、Graph.pde、Knock.pde、Loop.pde、Melody.pde、Memsic2125.pde、Ping.pde3.4.3 delayMicroseconds(us)delayMicroseconds函数同样是延时函数,所不同的是其参数单位是ms(1ms=1000ms)。函数原型如下:void delayMicroseconds(unsigned int us) / for a one-microsecond delay, simply return. /the overhead of the function call yields a delay of /approximately 1 1/8 us. if (-us = 0) return; / the following loop takes a quarter of a microsecond (4 cycles) / per iteration, so execute it four times for each /microsecond of delay requested. us = 2; / account for the time taken in the preceeding commands. us -= 2; / busy wait _asm_ _volatile_ ( 1: sbiw %0,1 nt / 2 cycles brne 1b : =w (us) : 0 (us) / 2 cycles );可以在开发环境中的下列实例程序中找到delayMicroseconds函数的应用:Melody.pde、Ping.pde3.8.2 attachInterrupt(interrupt,function,mode)attachInterrupt函数用于设置外部中断,函数有3个参数:interrupt、function和mode,分别表示中断源、中断处理函数、触发模式。参数中断源可选值0或1,在Arduino中一般对应2号和3号数字引脚;参数中断处理函数用来指定中断的处理函数,参数值为函数的指针,触发模式有4种类型:LOW(低电平触发)、CHANGE(变化时触发)、RISING(低电平变为高电平触发)、FALLING(高电平变为低电平触发)。下面的例子是通过外部引脚触发中断函数。然后控制13号引脚的LED的闪烁。int pin = 13;volatile int state = LOW;void setup() pinMode(pin, OUTPUT); attachInterrupt(0, blink, CHANGE); /中断源:1 /中断处理函数:blink() /触发模式:CHANGE(变化时触发)void loop() digitalWrite(pin, state);/中断处理函数void blink() state = !state;在使用attachInterrupt函数时要注意以下几点:在中断函数中delay函数不能使用。使用millis函数始终返回进入中断前的值。读取串口数据的话,可能会丢失。中断函数中使用的变量需要定义为volatile型。attachInterrupt函数的函数原型可在文件WInterrupts.c中找到,如下所示:void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) if(interruptNum EXTERNAL_NUM_INTERRUPTS) intFuncinterruptNum = userFunc; switch (interruptNum) case 0: EICRA = (EICRA & (1 ISC00) |(1 ISC01)|(mode ISC00); EIMSK |= (1 INT0); break; case 1: EICRA = (EICRA & (1 ISC10) |(1 ISC11)|(mode ISC10); EIMSK |= (1 INT1); break; 另外,还有detachInterrupt函数用于取消中断,参数interrupt表示所要取消的中断源,函数的定义如下:void detachInterrupt(uint8_t interruptNum) if(interruptNum EXTERNAL_NUM_INTERRUPTS) switch (interruptNum) case 0: EIMSK &= (1 INT0); break; case 1: EIMSK &= (1 F_CPU / 16) use_u2x = true; else / figure out if U2X mode would allow for a better connection / calculate the percent difference between the baud-rate specified and / the real baud rate for both U2X and non-U2X mode uint8_t nonu2x_baud_error = abs(int)(255- (F_CPU/(16*(F_CPU/8/baud-1)/2)+1)*255)/baud); uint8_t u2x_baud_error = abs(int)(255- (F_CPU/(8*(F_CPU/4/baud-1)/2)+1)*255)/baud); / prefer non-U2X mode because it handles clock skew better use_u2x = (nonu2x_baud_error u2x_baud_error); if (use_u2x) *_ucsra = 1 8; *_ubrrl = baud_setting; sbi(*_ucsrb, _rxen); sbi(*_ucsrb, _txen); sbi(*_ucsrb, _rxcie);2. if (Serial.available()该语句用来判断Arduino串口是否收到数据,函数Serial.available( )返回值为int型,不带参数。函数原型如下:int HardwareSerial:available(void) return (RX_BUFFER_SIZE + _rx_buffer-head - _rx_buffer-tail) % RX_BUFFER_SIZE;3. brightness = Serial.read();该语句的功能是将串口数据读入到变量brightness中,函数Serial.read( )也不带参数,返回值为串口数据,int型。函数原型如下:int HardwareSerial:read(void) / if the head isnt ahead of the tail, we dont have any characters if (_rx_buffer-head = _rx_buffer-tail) return -1; else unsigned char c = _rx_buffer-buffer_rx_buffer-tail; _rx_buffer-tail=(_rx_buffer-tail + 1) % RX_BUFFER_SIZE; return c; 3.10.1 SPI接口概述3.10 SPI接口3.10.1 SPI接口概述SPI(Serial Peripheral Interface)是由摩托罗拉公司提出的一种同步串行外设接口总线,它可以使MCU与各种外围设备以串行方式进行通信以及交换信息,总线采用3根或4根数据线进行数据传输,常用的是4根线,即两条控制线(芯片选择CS和时钟SCLK)以及两条数据信号线SDI和SDO。SPI是一种高速、全双工、同步的通信总线。在摩托罗拉公司的SPI技术规范中,数据信号线SDI称为MISO(Master-In-Slave-Out,主入从出),数据信号线SDO称为MOSI(Master-Out-Slave-In,主出从入),控制信号线CS称为SS(Slave-Select,从属选择),将SCLK称为SCK(Serial-Clock,串行时钟)。在SPI通信中,数据是同步进行发送和接收的。数据传输的时钟基于来自主处理器产生的时钟脉冲,摩托罗拉公司没有定义任何通用的SPI时钟规范。3.10.2 SPI接口数据传输SPI是以主从方式工作的,其允许一个主设备和多个从设备进行通信,主设备通过不同的SS信号线选择不同的从设备进行通信。其典型应用示意图如图3.5所示。当主设备选中某一个从设备后,MISO和MOSI用于串行数据的接收和发送,SCK提供串行通信时钟,上升沿发送,下降沿接收。在实际应用中,未选中的从设备的MOSI信号线需处于高阻状态,否则会影响主设备与选中从设备间的正常通信。3.10.3 SPI类及其成员函数Arduino中的SPI通信是通过SPIClass类来实现的,使用SPIClass类能够方便地将Arduino作为主设备与其他从设备通信。SPIClass类提供了6个成员函数供使用者调用,如下:q begin()q setBitOrder ()q setClockDivider ()q setDataMode ()q transfer ()q end ()begin函数用于初始化SPI总线,函数原型如下:void SPIClass:begin() / Set direction register for SCK and MOSI pin. / MISO pin automatically overrides to INPU
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论