PIC18 Lab. Experiment #3. ADC.

Задумался у меня один небольшой проектик, где есть задача отлавливать нажатие определенной кнопки. Вроде как все проще некуда, только вот этих кнопок 10 штук, 10 ног заводить не хочется, расширители портов юзать тоже скучно. Я подумал, почему бы мне не сварганить подобие цапа на этих кнопках, и завести его выход на АЦП в pic18f14k50, получим одну ногу вместо 10, но с небольшим усложнением кода.

380px-ADC_Symbol.svg

Как пользоваться этим зверем – под катом.

Начинаем как обычно – читаем даташит.

Сначала нам рассказывают, что мы имеем 9 каналов для ацп, а сам АЦП имеет аж 10 бит. Значит при питании 5 вольт, шаг составляет примерно 5 мВ. Для наших нужд этого более чем достаточно, да и в случае если у вас небольшое изменение сигнала и вы знаете эти границы можно поднять минимальное и опустить максимальное опорное напряжение АЦП, а значит и улучшить разрешение.

Вот как это примерно выглядит:

adc_pic18

На картинке кстати хорошо видно, чтобы работал АЦП, не забывайте установить ADON = 1.

Первым делом нас просят сконфигурировать порты – установить TRIS соответствующего пина в 1 если он будет использоваться как аналоговый вход (при 0 включает цифровой буфер и нет возможности использовать этот пин как аналоговый). Здесь также необходимо сконфигурить регистры ANSEL и ANSELH (если не помните: 1 – аналоговый режим, 0 – цифровой).

ansel

anselh

Следующий шаг – выбор канала. Сделать это можно в регистре ADCON0:

adcon0

Про остальные биты чуть позже, а пока ниже возможные конфигурации:

chs

Про каналы особо говорить нечего, а вот нижние два интересные фичи, насколько я понял DAC здесь и есть дак (ЦАП), то есть мы можем вывести заданное аналоговое напряжение или FVR напряжение 1.024В (независимо от питания) на аналоговый пин ацп. Вот правда на какой и каким образом его выбрать я так и не понял, пока у нас стоит другая цель, будет нужно – разберемся (:.

Я решил использовать в качестве аналогового пина RC7, это канал AN9. На данном этапе все что у нас есть по коду:

 TRISC7 = 1;
 ANSEL = 0;                                                                   //here all analog buffers off
 ANSELH = 2;																  //turn on analog input for RC7(AN9)	
 ADCON0 = 0b00100100;														  //Channel AN9 select

В регистре ADCON1 вы можете настроить нужные референс уровни:

adcon1

Меня устраивает VDD и VSS так что я оставляю все по дефолту.

Дальше идет рассказ про то, что можно настроить количество прогонов, по которым ацп выведет усредненное значение, но здесь есть нюанс – прерывания и статусный бит все равно будут срабатывать каждый раз, и отдельной индикации о окончании сбора данных здесь нет, так что пока не пользуем.

Занимательный параметр Tad – время конверсии на 1 бит, для полной конверсии необходимо выждать 11Tad:

Tad

Чтобы задать необходимое время для конверсии используют биты ADCS из ADCON2:

adcon2

clockselect

У меня кварц 12МГц, красиво делится только на 4, и получим клок для АЦП с периодом в 3мкс.

В этом же регистре присутствует бит ADFM, который отвечает за выравнивание результирующего байта, я уже привык как то к правому, так что его надо в 1:

 ADCON2 = 0b10000100;														  //Right justification, clock = Fosc/4

 

Дальше нам осталось лишь включить АЦП (ADON = 1) и запустить процедуру измерения (GO = 1), дальше если мы работаем без прерываний, то можно просто подождать пока бит GO не сбросится в 0:

void main()
{

 TRISC7 = 1;
 ANSEL = 0;                                                                   //here all analog buffers off
 ANSELH = 2;																  //turn on analog input for RC7(AN9)	
 ADCON0 = 0b00100100;														  //Channel AN9 select		
 ADCON2 = 0b10000100;														  //Right justification, clock = Fosc/4	
 ADON = 1;																	  //ADC is enabled!!!
 TRISB7 = 0; //TX pin set as output
 TRISB5 = 1; //RX pin set as input
 
 Vmeas = 0;

 UARTConfig = USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_BRGH_HIGH ;    //прерывания выключены, асинхронный режим, 8 бит, высокоскоростной режим
 baud = 77;                 //Focs/(9600*16) - 1
 OpenUSART(UARTConfig,baud);


 putsUSART( (char *) "Welcome to Diymicro.ru\r\n" );
 GO = 1;																	   //go, go, go!!! (:

 while(GO){};
 Vmeas = (ADRESH << 8) | ADRESL;
 NumToUart(Vmeas);

 while(1){};

}

Ниже я подал на аналоговый вход напряжение 2.3 В и вот, что получилось:

Polling_probe

 

Итак 471*5000/1024 = 2299.80 мВ, очень даже неплохо. Попробуем ка теперь это сделать с помощью прерываний.

Принцип абсолютно такой же, только вместо ожидания в цикле, мы выходим на конверсию после прерывания:

void main()
{

 TRISC7 = 1;
 ANSEL = 0;                                                                   //here all analog buffers off
 ANSELH = 2;																  //turn on analog input for RC7(AN9)	
 ADCON0 = 0b00100100;														  //Channel AN9 select		
 ADCON2 = 0b10000100;														  //Right justification, clock = Fosc/4	
 ADON = 1;																	  //ADC is enabled!!!
 TRISB7 = 0; //TX pin set as output
 TRISB5 = 1; //RX pin set as input
 
 Vmeas = 0;

 UARTConfig = USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_BRGH_HIGH ;    //прерывания выключены, асинхронный режим, 8 бит, высокоскоростной режим
 baud = 77;                 //Focs/(9600*16) - 1
 OpenUSART(UARTConfig,baud);
 

 putsUSART( (char *) "Welcome to Diymicro.ru\r\n" );

 ADIF = 0;
 ADIE = 1;
 PEIE = 1;
 GIE = 1;


 GO = 1;																	   //go, go, go!!! (:



 while(1)
 {
 		if (ADCstatus)
 		{
 			Vmeas = (ADRESH << 8) | ADRESL;
 			NumToUart(Vmeas);
 			ADCstatus = 0;
 		}


 }

}



void interrupt isr()
{
	if (ADIF)
	{
		ADCstatus = 1;
		ADIF = 0;

	}
}

Отрабатывает точно также и естественно с таким же значением (:

Это все интересно, но хочется чего то более практичного, давайте попробуем загнать синус на вход с размахом до питания, но для начала надо посчитать какую частоту мы сможем нормально оцифровать на наших настройках.

Опытным путем я установил, что если убрать запихивание в уарт по каждой конверсии, то время между конверсиями составит ~13 мкс, я хочу взять 128 отсчетов на период – 128 * 13 = 1664 мкс, что соотвествует примерно 601 Гц, но чего уж тут баловаться с этими герцами, округляем до 600 Гц.

Дальше я завел 128 байтный массив, в который сгружал оцифрованные значения:

#include <xc.h>
#include <plib/usart.h>
#include <plib/delays.h>


#define _XTAL_FREQ 12000000 //The speed of your internal(or)external oscillator

#pragma config WDTEN = OFF, LVP = OFF, FOSC = HS  

unsigned char UARTConfig = 0;
unsigned char baud = 0;
unsigned int Vmeas[128] = 0;
volatile bit ADCstatus = 0;
volatile unsigned char i = 0;

void Delay1us();          //1us delay for 12MHz xtall
void DelayUs(unsigned char Us);
void DelayMs(unsigned int Ms);
void NumToUart(unsigned int Num);  

/*
 * 
 */
void main()
{

 TRISC7 = 1;
 ANSEL = 0;                                                                   //here all analog buffers off
 ANSELH = 2;																  //turn on analog input for RC7(AN9)	
 ADCON0 = 0b00100100;														  //Channel AN9 select		
 ADCON2 = 0b10000100;														  //Right justification, clock = Fosc/4	
 ADON = 1;																	  //ADC is enabled!!!
 TRISB7 = 0; //TX pin set as output
 TRISB5 = 1; //RX pin set as input
 

 TRISC5 = 0;

// Vmeas = 0;



 UARTConfig = USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_BRGH_HIGH ;    //прерывания выключены, асинхронный режим, 8 бит, высокоскоростной режим
 baud = 77;                 //Focs/(9600*16) - 1
 OpenUSART(UARTConfig,baud);
 

 putsUSART( (char *) "Welcome to Diymicro.ru\r\n" );

 ADIF = 0;
 ADIE = 1;
 PEIE = 1;
 GIE = 1;


 GO = 1;																	   //go, go, go!!! (:



 while(1)
 {
 		if ((ADCstatus)&&(i<128))
 		{
 			Vmeas[i] = (ADRESH << 8) | ADRESL;
 			//NumToUart(Vmeas);
 			//putsUSART( (char *) "\r\n" );
 			i++;
 			ADCstatus = 0;
 			GO = 1;
  		} else
  			{
  				if ((i == 128)&&(ADCstatus))
  				{
  					ADCstatus = 0;
  					for (i=0;i<128;i++)
  					{
  						 NumToUart(Vmeas[i]);	
  						 putsUSART( (char *) "\r\n" );
  					}
  				}
  			}


 }

}



void interrupt isr()
{
	if (ADIF)
	{
		ADCstatus = 1;
		ADIF = 0;
		

	}
}


void Delay1us()         //delay approx 1 us
{
  Delay1TCY();
  Delay1TCY();
  Delay1TCY();
}

void DelayUs(unsigned char Us)      //delay for a given number of microseconds
{
  for (unsigned char i = 0; i<Us; i++)
    Delay1us(); 
}

void DelayMs(unsigned int Ms)      //approx delay for a given number of miliseconds
{
  for (unsigned int i=0; i<Ms; i++)
    Delay1KTCYx(3);
}

void NumToUart(unsigned int Num)                                                //Число в уарт
{

  unsigned int bignum = 10000;
  unsigned char numtemp = 5;

  if (!Num)
  {
      WriteUSART('0');         //Выталкиеваем все разряды - от старшего к младшему
      while(BusyUSART());                                                       //Ждем пока освободится модуль иначе будут прострелы
  }
  else 
  {
	  while(numtemp>0)                                                             //Определяем сколько разрядов имеет наше число
	  {
	    if (Num/bignum)
	        break;
	    numtemp--;
	    bignum = bignum / 10;  
	  }  
	
	
	
	  for (unsigned char i = numtemp; i>0; i--)
	    {
	      WriteUSART( (Num - (Num/(bignum*10))*bignum*10 )/bignum + '0');         //Выталкиеваем все разряды - от старшего к младшему
	      while(BusyUSART());                                                       //Ждем пока освободится модуль иначе будут прострелы
	      bignum = bignum/10;
	    }
   } 
}

Как только счетчик досчитал 128 конверсию все данные вылетели в терминал, откуда я их и зацепил:

made with ChartBoot

Построив график в первый раз я понял, что косячнул с определением времени опытным путем и пришлось ввести поправку, чтобы частоты совпали, вышло что время конверсии одного значения занимает примерно 18,2 мкс.

Теперь неплохо было бы попрактиковаться на реальном чипе, синус к сожалению мне загнать нечем, поэтому я просто загнал линейно изменяющееся напряжение, питание здесь я использовал кстати 3.3 Вольта:

made with ChartBoot

Ну вроде как неплохо получилось.

 

Исходники как обычно.

PIC18 Lab. Experiment #3. ADC.: 74 комментария

  1. Вы понимаете принцип работы конструкции while()?

    while(GO){}; зациклено само в себе пока GO = 1, вы выходите из цикла по сбросу GO в 0.
    А вручную GO в 1 вы ставите вот здесь ADCON0=0b00000011;

    Про усреднения надо думать, сходу я не могу так, да и проверили ли вы все остальные пункты которые расписывали недавно, у вас же даже программатора нет

    Ответить

  2. Все теперь ведь правильно? Даже с усреднением. Времени нормально выждано?
    Если сделать сюда еще таймер, ну что-бы обновлялось каждые 0.5с как раз результат, то как тогда сделать, чтоб по кнопке прерывалось? Попроще примера нету у Вас на прерывания?
    Ну это все мне не нравится…. Это все для постоянного напряжения… Если надо измерять переменное, то никакие усреднения ненужны. Не понимаю почему у меня тогда так работает… Все же может быть из-за не правильно выжданной задержки?
    while(RA3!=0){
    ADCON0=0b00000001;
    __delay_ms(100);
    GO=1;
    __delay_ms(100);
    while(GO);
    i=0;
    while (i<7){
    celoe=ADRESH*4/51;
    ostatok=ADRESH*4*10/51-celoe*10;
    //ostatok=ADRESH*0.78431373-celoe*10;
    celoe2=celoe+celoe2;
    ostatok2=ostatok+ostatok2;
    }

    lcd_gotoxy(1,12);
    sprintf(otvet, "%d.%d ", celoe2, ostatok2);
    lcd_puts(otvet);
    __delay_ms(150);
    }

    Ответить

    sarge Ответил:

    Вы пробовали без усреднения ваш код в железе, с добавление вышеуказанных задержек?
    Вы пробовали ваш код для батарейки как раньше писали?

    Ответить

    Василий Ответил:

    Я хочу написать несколько версий программ и чтоб сразу 1 раз съездить и наверняка прошить.
    Подавал батарейкой 4.5В — не запустилось даже…
    Задержку в этот раз я правильно поставил?

    Ответить

    sarge Ответил:

    Второй делей можно было бы убрать.

    4.5 Вольта должно работать вплоть до частоты 20 МГц, может там пониже таки напряжение итоговое вышло, и соответственно требования к частоте в этом случае стали 10 МГц и ниже.

    и вообще еще добавил антидребезг на кнопку и организовал цикл по другому, если хотите знать как присылайте архив с проектом под мплабх и протеусовскими файлами.

    Ответить

  3. забыл поделить…

    ADCON1=0; // чтобы еще не быстро производилось Fosc
    while(RA3!=0){
    celoe2=0;
    ostet2=0;
    ADCON0=0b00000001;
    __delay_ms(100);
    GO=1;
    __delay_ms(100);
    while(GO);
    i=0;
    while (i<7){
    celoe=ADRESH*4/51;
    ostatok=ADRESH*4*10/51-celoe*10;
    //ostatok=ADRESH*0.78431373-celoe*10;
    celoe2=celoe+celoe2;
    ostatok2=ostatok+ostatok2;
    }
    celoe2=celoe2/7;
    ostatok2=ostatok2/7;
    lcd_gotoxy(1,12);
    sprintf(otvet, "%d.%d ", celoe2, ostatok2);
    lcd_puts(otvet);
    __delay_ms(150);
    }

    Ответить

    sarge Ответил:

    Смотрю я на ваш код и симуляцию и ни фига не понимаю.
    Зачем подано 3.3 на другой пин?
    Почему вы используете RA3? Зачем себе создавать дополнительные сложности используя пин для ресета? У вас что все остальные заняты?

    Ответить

    sarge Ответил:

    Я бы в общем пробовал как то так, если опять будет прыгать, тогда бы конфигурил Vref на внешний пин и ставил туда отдельный стабилизатор на сколько нужно, там зафильтровать проще чем питание.

    #include &lt;stdio.h&gt;
    #include &lt;lcd.h&gt;
    #include &lt;xc.h&gt;
    #define _XTAL_FREQ 8000000 //4MHz
    #pragma config MCLRE = OFF, FOSC = INTOSCIO, WDTE = OFF, PWRTE = ON
    
    int celoe, ostatok, i, celoe2, ostatok2;
    char otvet[10];
    
    main(){
    OSCCON=0b01110001; //????? ??????????????? 8 ???
    TRISA=0b001111;
    TRISC=0b000011;
    PORTA=0b000000;
    PORTC=0b000000;
    //ADCON1=0b00100000;
    ADCON1=0b01110000;
    ANSEL=0b00110111;
    
    lcd_init();
    lcd_clear();
    lcd_gotoxy(0,0);
    lcd_puts(&quot;test&quot;);
    
    while(1){
    
    
    
    
    
    if(!RA3)
    {
     __delay_ms(20);
     if (!RA3)
     {	
      ADCON0=0b00000001;
      __delay_ms(100);
      GO=1;
      while(GO){};
      lcd_gotoxy(0,12);
      sprintf(otvet, &quot;%d &quot;, ADRESH);
      lcd_puts(otvet);
      __delay_ms(150);
     }
    }
    
    }
    }
    
    

    И, да, нафиг все конверсии пока не убедитесь, что у вас все работает как надо.

    Ответить

  4. Здравствуйте. Забыл, не подскажите как погрешность определить? Если исполльзуется первые 8 бит у АЦП, а питания 5В.

    Ответить

    sarge Ответил:

    Добрый вечер,

    Зависит от погрешности питания, например питание может варьироваться от 4.9 до 5.1, соответственно минимальная ступенька АЦП будет варьироваться от 19.14 мВ до 19.9 мВ.
    Если я правильно понял то о чем вы спрашиваете.

    Ответить

  5. DOBRIY DEN . PROBOVAL ADC NA PIC 16F676 . POCHEMUTO NE RABOTAET V PRERIVANII . V PROTEUSE OPREDELYAET PRI PERVOM VKLUCHENII . PRI IZMENENII NAPRYAJENII NA VHODE ASP NEIZMENYAETSYA ZNACHENII ‘X’ . PRI OTKLUCHENII I POVTORNOM VKLUCHENII PROTEUSA BERET NOVUYU ZNACHENIYU ‘X’ . V PROTEUSE PROVERIL POCHEMUTA ‘ADIF’ NE STANOVITSYA ‘0’

    void main(void)
    {
    
       TMR0=0;
       OPTION_REG= 0b11010000; //таймер 1:2
    //   T0IE=1;             //разрешаем прерывания от таймера
        CMCON = 0b00000111; //Отключить компаратор
       TRISA=0b00010100;//RA2 I RA4 VHOD 
       PORTA=0;
       TRISC=0b00000001;
       PORTC=0;
        ADON=1;
        ANSEL=0b00010000;
    	ADCON0=0b10010001;
    
       /*
          правое выравнивание
          RC0 - аналог, все остальные из PORTA - цифра
       */
    
        ADCON1=0b01000000;  //bit 6-4: ADCS: A/D Conversion Clock Select bits
                     //100 =FOSC/4
               
    
    
       /*
          тактовый сигнал Fosc/32
        
          GO-/DONE = 0
          АЦП включен
       */
    
    
      ADIF = 0;
     ADIE = 1;
     PEIE = 1;
     GIE = 1;
      // GO = 1;
    
       	GO_DONE =1;
       while(1)
       {      
      if(x&gt;500)led_2=1;
    if(x&lt;500) led_2=0;
    
       }   
    }
    
    void interrupt IntFun(void)
    {
    if (ADIF)
    	{
    		ADCstatus = 1;
    		ADIF = 0;
     
    	}
     		if (ADCstatus)
     		{
              //   x = (ADRESH&lt;&lt;8) + ADRESL;
     			x = (ADRESH &lt;&lt; 8) | ADRESL;
    
     			ADCstatus = 0;
     		}
    
    }
    

    Ответить

    sarge Ответил:

    Добрый день,

    Сейчас нет возможности подробно потестить и вникнуть, напишите пожалуйста после выходных, чтобы я не забыл.

    Ответить

  6. Dobriy den . Vi prosili napomnit vam . ADC Proveryal rabotaet kod bez prerivanii . A s prerivaniem pochemuto ne rabotaet ne proishodit prerivaniya

    Ответить

    sarge Ответил:

    Добрый день

    Пока не особо вникая, попробуйте вот этот код:

           if (ADCstatus)
            {
              //   x = (ADRESH&amp;lt;&amp;lt;8) + ADRESL;
                x = (ADRESH &amp;lt;&amp;lt; 8) | ADRESL;
     
                ADCstatus = 0;
            }
    

    Убрать из прерываний в главный цикл.

    Ответить

    sarge Ответил:

    А и кстати этот код только один раз и отработать может, вы не включаете нигде повторно бит GO_DONE, который автоматически сбрасывается.

    Ответить

  7. Dobriy den . Ya proboval vstavit GO_DONE=1; v prerivanii i V glavnom sikle . Prerivaniya prerivaet odin raz v nachale i dalshwe programma krutitsya v prerivanie no ne idet na glavniy sikl . Neprerivaet

    Ответить

    sarge Ответил:

    Давайте исходники + файлы симуляции.

    Ответить

  8. Vstavil v yandexbar : ya.batir741 . V papke proba-c .fayl ” Adc.rar”

    Ответить

    sarge Ответил:

    И как мне его достать? Это ваш яндекс диск насколько я понимаю, ссылку давайте или шлите мне на мыло.

    Ответить

  9. Eto v yandex disk . Ya vas dobavil v prowliy raz dlya prosmotra . Vi mojete smotret fayl

    Ответить

    sarge Ответил:

    Я сейчас ничего не могу смотреть.
    Дайте мне пожалуйста либо прямую ссылку на скачивание, либо пришлите архив на sargein@gmail.com

    Ответить

    sarge Ответил:

    Копайте в сторону таймера TMR0 – у него по ходу слишком мелкий период срабатывания и он каким-то образом влияет на работу АЦП в прерываниях

    #include &lt;htc.h&gt;
    //#include &quot;delay.h&quot;
    //#include &quot;adc.h&quot;
    //__CONFIG(0x03F72);
    volatile bit ADCstatus = 0;
    unsigned char b=0;
    unsigned long a=0;
      unsigned int x=0;
      int   bt=0;
    #pragma config FOSC =  HS   //INTOSC        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
    
    //#pragma config FOSC =  INTOSCIO   //INTOSC        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
    #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
    #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
    #pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
    #pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
    //#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
    #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
    #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
    
    #define _XTAL_FREQ          4000000 // ÷àñòîòà ãåíåðàòîðà â Ãö
    
     #define   in_1   RA2 
     #define   in_2   RA3 
     #define   led_1  RC5 
     #define   led_2  RC4 
     #define   led_3  RC3 
     #define   led_4  RC2 
     #define   led_5  RC1 
     #define   led_6  RA0 
     #define   led_7  RA5 
     #define   led_8  RA4
    
    
    
    
    
    void main(void)
    {
        __delay_ms(200);
    
    
       CMCON = 0b00000111; //Îòêëþ÷èòü êîìïàðàòîð
       TRISA=0b00010100;//RA2 I RA4 VHOD 
       PORTA=0;
       TRISC=0b00000001;
       PORTC=0;
        ADON=1;
        ANSEL=0b00010000;
    	ADCON0=0b10010001;
    
       /*
          ïðàâîå âûðàâíèâàíèå
          RC0 - àíàëîã, âñå îñòàëüíûå èç PORTA - öèôðà
       */
    
        ADCON1=0b01000000;  //bit 6-4: ADCS&lt;2:0&gt;: A/D Conversion Clock Select bits
                           // 000 =FOSC/2
                          //001 =FOSC/8
                          //010 =FOSC/32
                        //x11 =FRC (clock derived from a dedicated internal oscillator = 500 kHz max)
                        //100 =FOSC/4
                       //101 =FOSC/16
                       //110 =FOSC/64
    
     __delay_ms(200);
     ADIF = 0;
     ADIE = 1;
     PEIE = 1;
     GIE = 1;
    
       	GO =1;
    
    
            
       while(1)
       {   
    
     		if (ADCstatus)
     		{
           
     			x = (ADRESH &lt;&lt; 8) | ADRESL;
                            __delay_ms(50); 
     			ADCstatus = 0;
                            GO = 1;
     		}
    
    
    
        
    }
    }
    
    void interrupt isr()
    {
    
    
    if (ADIF)
    	{
    		ADCstatus = 1;
    		ADIF = 0;
     	
    	}
    
    }
    

    Этот код постоянно входит в прерывание и обновляет значение переменной х.

    Ответить

  10. DA VI PRAVI , KOGDA OTKLUCHAYU TMR0 RABOTAET PRERIVANIYA OT ADC KOGDA TMR0 VKLUCHEN NESRABATIVAET . DO ETOGO NA ETO NE OBRATIL VNIMANIYA . SPASIBO ZA PODDERJKU

    Ответить

  11. Уведомление: Pic18 Lab. Experiment #5. USB | PIC микроконтроллеры

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.