На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
    > АЦП на ATmega8. , ПОМГИТЕ
      Здравствуйте уважаемые форумчане, начал осваивать програмирование МК, добрался до АЦП.

      Попытался сделать индикатор напряжения 0-16В на светодиодах, вроде все работает
      схема в архиве - LEDs_scale
      ExpandedWrap disabled
        #include <avr/io.h>
        #include <util/delay.h>
         
        int main (void)
        {
        DDRD = 0xFF;
        PORTD = 0x00;
        ADCSRA|=(1<<ADEN) //Включение АЦП
         |(1<<ADPS1)|(1<<ADPS0); // Предделитель преобразователя на 8
         
         ADMUX|=(0<<MUX0)|(0<<MUX1)|(0<<MUX2)|(0<<MUX3)//Вход PC0
         |(1<<REFS0)|(0<<REFS1); //AVcc является опорным напряжением
         
        while(1)
        {
        unsigned int u;
        ADCSRA |= (1 << ADSC);    //Начинаем преобразование
        while ((ADCSRA&(1 << ADIF))== 0); //Ждем флага окончания преобразования    
         
        u = (ADCL|ADCH << 8);  // Считываем  ADC
        if (u > 128)                   //2V
        {PORTD = (1 << PD0);}          
        else {PORTD &= ~(1 << PD0);}
         
        if (u > 256)                   //4V
        PORTD = (1 << PD0)|(1 << PD1);    
         
        if (u > 384)                  //6V  
        PORTD = (1 << PD0)|(1 << PD1)
        |(1 << PD2);
         
        if (u > 512)                   //8V
        PORTD = (1 << PD0)|(1 << PD1)
        |(1 << PD2)|(1 << PD3);
         
        if (u > 639)                   //10V
        PORTD = (1 << PD0)|(1 << PD1)
        |(1 << PD2)|(1 << PD3)
        |(1 << PD4);
         
        if (u > 767)                   //12V
        PORTD = (1 << PD0)|(1 << PD1)
        |(1 << PD2)|(1 << PD3)
        |(1 << PD4)|(1 << PD5);
         
        if (u > 895)                   //14V
        PORTD = (1 << PD0)|(1 << PD1)
        |(1 << PD2)|(1 << PD3)
        |(1 << PD4)|(1 << PD5)
        |(1 << PD6);
         
        if (u > 1020)                  //16V
        PORTD = (1 << PD0)|(1 << PD1)
        |(1 << PD2)|(1 << PD3)
        |(1 << PD4)|(1 << PD5)
        |(1 << PD6)|(1 << PD7);
        _delay_ms(30);
        }
        }


      Затем решил попробовать сделать 2е шкалы (на PORTB и PORTD) на 1ом микроконтроллере, тут возникает проблема АЦП не хочет переключаться с РС0 на РС1.
      вот код
      ExpandedWrap disabled
        #include <avr/io.h>
         #include <util/delay.h>
         
         
         int main (void)
         {
         
         DDRD = 0xFF;
         PORTD = 0x00;
         
         DDRB = 0xFF;
         PORTB = 0x00;
         
         while(1)
         
         {
         unsigned int u, u_VCC;
         
         ADCSRA|=(1<<ADEN) //Включение АЦП
         |(1<<ADPS1)|(1<<ADPS0); // Предделитель преобразователя на 8
         
         ADMUX|=(0<<MUX0)|(0<<MUX1)|(0<<MUX2)|(0<<MUX3)//Вход PC0
         |(1<<REFS0)|(0<<REFS1); //AVcc является опорным напряжением
         
         ADCSRA |= (1 << ADSC); //Начинаем преобразование
         
         while ((ADCSRA&(1 << ADIF))== 0); //Ждем флага окончания преобразования
         
         u = (ADCL|ADCH << 8); // Считываем ADC
         
         if (u > 128) //2V
         {PORTD = (1 << PD0);}
         else {PORTD &= ~(1 << PD0);}
         
         if (u > 256) //4V
         PORTD = (1 << PD0)|(1 << PD1);
         
         if (u > 384) //6V
         PORTD = (1 << PD0)|(1 << PD1)
         |(1 << PD2);
         
         if (u > 512) //8V
         PORTD = (1 << PD0)|(1 << PD1)
         |(1 << PD2)|(1 << PD3);
         
         if (u > 639) //10V
         PORTD = (1 << PD0)|(1 << PD1)
         |(1 << PD2)|(1 << PD3)
         |(1 << PD4);
         
         if (u > 767) //12V
         PORTD = (1 << PD0)|(1 << PD1)
         |(1 << PD2)|(1 << PD3)
         |(1 << PD4)|(1 << PD5);
         
         if (u > 895) //14V
         PORTD = (1 << PD0)|(1 << PD1)
         |(1 << PD2)|(1 << PD3)
         |(1 << PD4)|(1 << PD5)
         |(1 << PD6);
         
         if (u > 1020) //16V
         PORTD = (1 << PD0)|(1 << PD1)
         |(1 << PD2)|(1 << PD3)
         |(1 << PD4)|(1 << PD5)
         |(1 << PD6)|(1 << PD7);
         
         
         _delay_ms(100);
         
         ADMUX|=(0<<MUX0)|(0<<MUX1)|(0<<MUX2)|(1<<MUX3)//Вход PC1
         |(1<<REFS0)|(1<<REFS1); //2,56В является опорным напряжением
         
         ADCSRA |= (1 << ADSC); //Начинаем преобразование
         
         while ((ADCSRA&(1 << ADIF))== 0); //Ждем флага окончания преобразования
         
         u_VCC = (ADCL|ADCH << 8); // Считываем ADC
         
         if (u_VCC < 837)
         {PORTB = (1 << PB0);}
         else {PORTB &= ~(1 << PB0);}
         
         if (u_VCC > 912)
         PORTB = (1 << PB0)|(1 << PB1);
         
         if (u_VCC > 1020)
         PORTB = (1 << PB0)|(1 << PB1)|(1 << PB2);
         
         _delay_ms(100);
         }
         }

      схема лежит в архиве - LED_SCALE
      Подскажите пожалуйста в чем у меня ошибка???
      Прикреплённый файлПрикреплённый файлLEDs_scale.rar (52,94 Кбайт, скачиваний: 339)
      Прикреплённый файлПрикреплённый файлLED_SCALE.rar (57,99 Кбайт, скачиваний: 275)

      Добавлено
      Прошу прощения за опечатку в слове ПОМОГИТЕ, просьба модераторам если не сложно исправьте пожалуйста
      Сообщение отредактировано: 1988Олег1988 -
        ADMUX=(1<<MUX1)|(1<<REFS0)|(1<<REFS1);
        ?
        Сообщение отредактировано: Prince -
          Цитата Prince @
          ADMUX=(1<<MUX1)|(1<<REFS0)|(1<<REFS1);
          ?

          не получается протеус все равно гоаорит Wrong MUX value=8 и ничего не работает :no-sad:

          или вы просто увидели там ошибку??
          Сообщение отредактировано: 1988Олег1988 -
            Ну только то что бросилось в глаза:
            установленный бит MUX3 подключает к входу ADC пин PC4, а не PC1;
            MUX3 по идее должен быть равен 3. А MUX, соотвественно = 8.
            Возможно, вы уже используете PC4 в качестве выхода, но в любом случае вы подключаете к АЦП не РС1.
            (0<<...)|(0<<...)|(0<<...) - что оно должно, по вашему, делать?
            в операции присваивания ADMUX|= - зачем логическое ИЛИ?
              Цитата Prince @
              Ну только то что бросилось в глаза:
              установленный бит MUX3 подключает к входу ADC пин PC4, а не PC1;
              MUX3 по идее должен быть равен 3. А MUX, соотвественно = 8.
              Возможно, вы уже используете PC4 в качестве выхода, но в любом случае вы подключаете к АЦП не РС1.
              (0<<...)|(0<<...)|(0<<...) - что оно должно, по вашему, делать?
              в операции присваивания ADMUX|= - зачем логическое ИЛИ?

              если честно я слабо понял что вы написали :'(
              в коде записал
              ExpandedWrap disabled
                ADMUX=0b000111; // вроде на РС1 задал АЦП вход?


              ошибки исчезли но шкала с РС1, все равно не реагирует.

              Извиняюсь за тупизм
                Цитата
                ADMUX=0b000111;
                ошибки исчезли но шкала с РС1, все равно не реагирует.

                Вы обнулили биты источника опорного напряжения REFS0, REFS1 и подключили ADC7 вместо ADC1.
                ADMUX=(1<<MUX1)|(1<<REFS0)|(1<<REFS1);
                ADMUX=b11000001;
                  Цитата Prince @
                  Цитата
                  ADMUX=0b000111;
                  ошибки исчезли но шкала с РС1, все равно не реагирует.

                  Вы обнулили биты источника опорного напряжения REFS0, REFS1 и подключили ADC7 вместо ADC1.
                  ADMUX=(1<<MUX1)|(1<<REFS0)|(1<<REFS1);
                  ADMUX=b11000001;

                  Спасибо огромное, все заработало!!!


                  Получается:

                  ADMUX=0b000111;

                  первые 2 бита это REFS0, REFS1 соответственно

                  вторые 4 бита это уже MUX
                    Цитата
                    первые 2 бита это REFS0, REFS1 соответственно

                    вторые 4 бита это уже MUX

                    Да. Только не первые 2, а последние, и не вторые 4, а первые. Двоичные числа записываются, от старшего разряда к младшему, слева направо.
                    Сообщение отредактировано: Prince -
                      Цитата Prince @
                      Да. Только не первые 2, а последние, и не вторые 4, а первые. Двоичные числа записываются, от старшего разряда к младшему, слева направо.

                      ADMUX=(1<<MUX0)|(0<<MUX1)|(0<<MUX2)|(0<<MUX3)|(1<<REFS0)|(1<<REFS1);
                      вот то что надо было РС1, теперь работает))), еще раз спасибо
                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                      0 пользователей:


                      Рейтинг@Mail.ru
                      [ Script execution time: 0,0696 ]   [ 17 queries used ]   [ Generated: 28.04.24, 11:54 GMT ]