首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AVR /O: DIgital与模拟输入编程

AVR /O: DIgital与模拟输入编程
EN

Stack Overflow用户
提问于 2021-09-28 19:32:55
回答 1查看 108关注 0票数 0

我正在尝试使用一些以前开发的从Github中开发的sw,并且遇到了一些有趣的sw编码。

他使用的是带有数字I/O的Atmel ATtiny45,大部分的PortB引脚上都有数字I/O,但是PB3被用作外部电位器的模拟(AtoD)输入。在他的代码中,他有以下代码片段:

代码语言:javascript
复制
  if(PINB & MANCLK){
       PORTB |= CLKOUT;
       } else {
       PORTB &= ~CLKOUT;
       }
    }

(注:“CLKOUT”是数字输出引脚。)

"MANCLK“是PB3的模拟输入引脚--所以,行:"if(PINB &MANCLK).”做?它是否真的考虑到了所有输入到该引脚上的模拟值,那么,小于2.5V的任何东西都被认为是逻辑低的,任何超过2.5V的都是高的,或者,这甚至是一个有效的语句吗?“MANCLK”是简单地被认为是"0“还是"1"?不知道在哪里能找到关于这一特殊情况的好信息。

谢谢你提供的帮助。

你好,格兰特

更新这是密码..。

`

代码语言:javascript
复制
 #include <stdio.h>
 #include <stdlib.h>
 #include <avr/io.h>
 #include <avr/interrupt.h>
 #include <avr/sleep.h>
 #if !defined(TIMSK)
 #define TIMSK               TIMSK0
 #endif
 #if !defined(TIMER0_COMPA_vect)
 #define TIMER0_COMPA_vect   TIM0_COMPA_vect
 #endif

// 100 us per tick
#define COUNT   199
#define TPSC    (1<<CS01)

#define AUTO    (1<<PB0)    //Pin5, MOSI and EN (via RN33 Pins 4&5).
 High = Enable
#define RUN     (1<<PB1)    //Pin6, MISO and ~HLT (via RN33 Pins 3&6).
 Low = Halt
#define MANCLK  (1<<PB3)    //Pin2, Analog input, Manual Clock Speed
 Setting (via potentiometer RV1)
#define CLKOUT  (1<<PB4)    //Pin3, CLK output
#define AUTOINT (1<<PCINT0)
#define RUNINT  (1<<PCINT1)
#define CLKINT  (1<<PCINT2)

#define MANDLY  500

volatile uint16_t count;
volatile uint8_t trigger;
volatile uint8_t manual;

uint16_t maxcnt;

void stopTimer(void) {
    PORTB &= ~CLKOUT;       // Clock output low
    TCCR0B &= ~TPSC;
    TCNT0;
    count = 0;
    trigger = 0;
}

void startTimer(void) {
    PCMSK = 0;
    TCCR0B |= TPSC;
}

void halt(void) {
    cli();
    stopTimer();
    PCMSK = RUNINT|AUTOINT;
    sei();

    sleep_enable();
    while(!(PINB & RUN)) sleep_cpu();
    sleep_disable();

    cli();
    startTimer();
    sei();
}

void manclk(void) {
    cli();
    stopTimer();
    PCMSK = CLKINT|RUNINT|AUTOINT;
    sei();

    while(!(PINB & AUTO)) {
        if(PINB & RUN) {
            if(PINB & MANCLK) {
                PORTB |= CLKOUT;
                } else {
                PORTB &= ~CLKOUT;
                }
        }
        sleep_enable();
        sleep_cpu();
        sleep_disable();
    }

    cli();
    startTimer();
    sei();
}

int main(void)
{
   DDRB = CLKOUT;
   PORTB &= ~CLKOUT;

   cli();
   TCCR0A = 0;
   TCCR0B = 0;
   TCNT0 = 0;
   TCCR0A |= (1 << WGM01);
   OCR0A = COUNT;          // Interrupts every 100us when Timer running
   TCCR0B |= (1 << CS01);  // Timer Start /8 pre-scaler
   TIMSK |= (1 << OCIE0A);
   GIMSK |= (1 << PCIE);
   sei();

   // Setup the ADC
   //ADMUX |= (1 << MUX1); // Only using ADC2 (original)
   ADMUX |= (1 << MUX0) | (1 << MUX1);   //new code - MUX Select ADC3 @
    PB3
   ADCSRA |= (1 << ADEN);
   ADCSRA |= (1 << ADPS2) | (1 << ADPS1); // 125 kHz ADC clock

   //Enable Sleeping
   set_sleep_mode(SLEEP_MODE_IDLE);

   while (1) {

//if RUN = HLT = Low ==> HALT
       if (!(PINB & RUN)) {
           halt();
           continue;
       }

//if AUTO = ENABLE = Low ==> manclk...if AUTO (ENABLE) == LOW ==>
 MANCLK
       if (!(PINB & AUTO)) {
           manclk();
           continue;
       }

       ADCSRA |= (1 << ADSC);
       while (ADCSRA & (1 << ADSC));
       maxcnt = 5000 / (64 - ADC/16);

       if (trigger) {#
           PORTB ^= CLKOUT;
           trigger = 0;
       }

       sleep_enable();
       sleep_cpu();
       sleep_disable();
   }

   return 0; // never reached
   }

   ISR(TIMER0_COMPA_vect) {
       count++;
       if (count >= maxcnt) {
           count = 0;
           trigger = 1;
       }

}

EMPTY_INTERRUPT(PCINT0_vect);`
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-29 14:30:44

如果我们扩展了一些预处理宏,您的代码就会变得更容易解释:

代码语言:javascript
复制
if (PINB & (1 << 3))
{
  PORTB |= (1 << 4);
}
else
{
  PORTB &= ~(1 << 4);
}

现在只看上面的代码,我们就可以知道它做了以下工作:它读取PINB寄存器的第3位,如果它是1,它将PORTB寄存器的第4位设置为1,否则,它会清除PORTB寄存器的(设置为0)位4位。

如果您不明白为什么是这样,我建议您在C书或C教程中查找以下C位逻辑运算符的定义:& |<<|=&=

描述代码的一种更简单的方法是将PINB的第3位的值复制到PORTB的第4位。

现在,为了更好地理解代码的功能,您需要找到ATtiny45数据表,并读取PINB和PORTB寄存器的定义。然后,您将发现以下内容:

  1. 读取PINB的第3位是如何实现数字阅读 of PB3的。它不使用ADC,也不像你想的那样有一个超精确的阈值。阈值定义在数据表的“电气规范”部分或类似的地方。

  1. ,因为DDRB的第4位在您的程序中是1,所以PB4被配置为数字输出。因此,将值写入PORTB的第4位是如何设置PB4的输出值的。给它写0会使它驱动低(0 V),而给它写1会使它驱动高。

总之,这是一些非常基本的AVR代码,可以进行数字读取并将该值写入数字输出。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69367546

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档