2015-09-21 5 views
-1

Прошу вас, я с трудом понимаю, как рассчитать частоту дискретизации PIC16F688 для АЦП. Моя тактовая частота (MCU) составляет 8 МГц. и я настроен ADCON1 на следующее:Частота дискретизации для PIC16F688

ADCON1 &= 0b01000000;  //clear bits 6 through 0 
ADCON1 |= 0b01000000;  //set bits 6 though 0. 

Я сделал, что согласно спецификации ПОС. Потому что он имеет внутренний генератор, а это значит, что он работает на Fosc/4 и соответствует таблице 8-1. Итак, я пытаюсь найти частоту дискретизации. Какой код связан с этим? Я думаю, что ADCON1 отвечает за часы. то есть частоты дискретизации.

Я не думаю, что delay_ms (1000) - это вопрос в моем бесконечном цикле. Так что это не моя частота дискретизации. Или либо UART1_Init (9600).

Не могли бы вы мне помочь, я был бы признателен. Спасибо.

char temp[5]; 

    unsigned int adc_value; 

    char uart_rd; 
    int i; 
    unsigned int d[10]={0}; 
    int average = 0; 
    int counter =0; 

    void main() 
     { 

      temp[0]='1'; 
      temp[1]='2'; 
      temp[2]='3'; 
      temp[3]='4'; 
      temp[4]=' '; 
      OSCCON  = 0x77;   
      //ANSEL = 0;    
      ANSEL = 0b00000100;  
      CMCON0 = 0X07; 
      TRISA = 0b00001100; 
      // ADCON0 =0b1011; 
     // ADCON1 &= 0b01000000;  
     //ADCON1 |= 0b01000000;  
     UART1_Init(9600);    
     Delay_ms(100);     
      while (1) 
       { 
       average=0; 
       for(i=0;i<10;i++) 
        { 
        average+= ADC_Read(2); 
       } 
     average/=10; 
     temp[0] = average/1000+48; 
     temp[1] = (average/100)%10+48; 
     temp[2] = (average/10)%10+48; 
     temp[3] = average%10+48; 
     for (i=0;i<5; i++) 
      { 
      UART1_Write(temp[i]); 
     } 
    } 
} 




//Updated the code using Interrupt.// But have problem reading from ANS2. 


enter code here 
char temp[5]; 
unsigned int adc_value; 
int i; 
unsigned int d[10]={0}; 
int average = 0; 
void interrupt(){ 
     if (INTCON.T0IF) { 
      INTCON.T0IF = 0 ;// clear T0IF (Timer interrupt flag). 
      average= ADC_Read(2); 
      temp[0] = average/1000+48; 
      temp[1] = (average/100)%10+48; 
      temp[2] = (average/10)%10+48; 
      temp[3] = average%10+48; 
      for (i=0;i<5; i++) 
       { 
       UART1_Write(temp[i]); 
       } 
     } 
    TMR0 = 178; 

    } 

void main() { 

     temp[0]='1'; 
     temp[1]='2'; 
     temp[2]='3'; 
     temp[3]='4'; 
     temp[4]=' '; 
     OSCCON= 0x77;  //8MHz 
     ANSEL = 0b00000100; //ANS2 
     CMCON0 = 0X07; // 
     TRISA = 0b00001100; 
     UART1_Init(9600);  
     TMR0 = 178 ; 
     // CMCON0 = 0X04; // turn off compartor. 
     OPTION_REG = 0x87; // 
     INTCON =0xA0; 
     while(1); 

    } 
+0

В приведенном выше коде вы устанавливаете бит 6 в «ADCON1» и очищаете биты 0-5 и 7, что не так, как говорится в комментариях, - это то, что вы намеревались сделать? –

+0

О, извините, но комментарий неправильный. поэтому не смотрите на комментарий, я не обновлял его. Но мой вопрос в том, как я могу окупить частоту дискретизации? если вы видите страницу 67 в приведенной ниже ссылке, если это техническое описание. Я пытаюсь довести частоту дискретизации до 100 Гц. Так что, как я понимаю, это: - F = 1/t. но ни один из тех, кто в таблице, не может дать мне 100 Гц. Опять же, я настраиваю свою тактовую частоту на 8 МГц. (Но я не знаю точно 8MHz). Итак, как я рассчитываю частоту дискретизации. Я ценю, если вы будете ходить со мной, хотя это. –

+0

OK - пожалуйста, нажмите на ссылку [edit] выше и исправьте свой вопрос, чтобы избежать дальнейших путаниц. –

ответ

2

Если вы читали о АЦПЕ в PIC16F688 datasheet, вы увидите, что вы можете выбрать преобразование часов f_AD установки ADCON1 < 4: 6>. С вашего вопроса кажется, что вы намерены установить это на f_OSC/4, хотя из двух строк кода вы не заметили, что это то, что на самом деле происходит. Попробуйте это вместо:

ADCON1 = 0b01000000; // set conversion clock to F_osc/4 

Но это было немного в стороне. Возвращаясь к листу данных, вы можете увидеть в разделе 8.1.4 «Часы преобразования», что время завершения преобразования одного бита - T_AD, а для преобразования полного 10-битного образца - 11 T_AD.

Одна вещь, которую я имею в листе данных Microchip, не очень хороша, заключается в явном определении отношений, таких как T_AD = 1/conversion_clock. Однако вы можете сделать это из таблицы данных, например таблицы 8-1, где вы можете увидеть, например, что если f_OSC равно 8 МГц, а тактовый сигнал преобразования f_AD равен f_OSC/4, то есть 2 МГц, T_AD составляет 500 нс , т.е. 1/f_AD. Обратите также внимание на таблицу 8-1, что это вне рекомендованного диапазона для АЦП. (См. Ниже)

Как указано выше, время преобразования T_S полного 10-битного образца равно 11 T_AD = 5,5 us. Частота дискретизации f_S равна 1/T_S или 181,818 кГц (это также можно рассчитать как f_AD/11)

Это теоретическая максимальная частота дискретизации, которую может выполнять периферия ADC, но это не обязательно частота дискретизации вашей системы. Если вы пробуете несколько каналов, вы разделите этот теоретический максимум на периферию, так что если у вас есть два канала, которые вы чередуете, теоретический максимум составляет ~ 90 кГц на канал. Тем не менее, также будут накладные расходы для настройки преобразования и чтения результата, а также для зарядки удерживающего конденсатора, что уменьшит фактическую максимальную частоту дискретизации ниже теоретической. В дополнение к этому, есть и другие вещи, которые делает ваш код, что может способствовать дальнейшему снижению фактической частоты дискретизации.

Если вы также используете рекомендованный T_AD, как определено в таблице 14-9, вы получите минимальный T_AD 1,6 us, давая теоретическую максимальную частоту выборки для периферийного устройства ADX f_S 56,8 кГц.

EDIT после просмотра некоторых дополнительных комментариев к вопросу.

Эти расчеты относятся только к минимуму преобразования времени (а также максимальной теоретической частоты выборки), что является верхней границей фактической частоты выборки.Не проблема иметь фактическую частоту дискретизации, которая намного ниже максимальной, но вы не можете контролировать это только с помощью периферийных регистров АЦП. Например, вы можете настроить таймер, который прерывается с нужной частотой дискретизации 100 Гц, и в ISR таймера вы начинаете одно преобразование.

EDIT после комментария 1 декабря 2015 года: Я думаю, что это совсем другой вопрос. Но, короче говоря, на основе кода, который вы отправили в качестве другого ответа, в вашем основном цикле нет задержки. Код в основном делает 10 образцов настолько быстрыми, насколько это возможно (если вы разрешите немного накладных расходов для вызовов цикла и функций, вы, вероятно, сделаете 10 выборок в 60 или 166 кГц). Затем образцы усредняются, преобразуются в ASCII и передаются. Передача займет около 5 мс (5 байт на 9600, при условии 8N1). Таким образом, вы получаете всплеск выборок, затем более длительную паузу и т. Д. В среднем время передачи доминирует, поэтому вы получите частоту дискретизации ~ 190 Гц. Как быстро и грязные изменения, вы можете изменить цикл выборки следующим образом:

average=ADC_Read(2); // was 0, but we're doing one less iteration of the loop 
for(i=0;i<9;i++) 
{ 
    delay_ms(10); // 10ms delay to get 100 Hz sampling 
    average+= ADC_Read(2); 
} 
delay_ms(5); // together with the UART transmission time, we get 10 ms here as well 

Теперь это не принимать во внимание время, необходимое, чтобы сделать дивизии, и по-прежнему будет разница в интервал между выборками в пределах «всплеска» и интервал между последним образцом в одном пакете и первый образец в следующем. Если вы устанавливаете высокий контакт при вызове ADC_Read() и низкий, когда он возвращается, вы можете проверить время и интервал в области.

Чтобы сделать это более подробно, я установил таймер на кристалле для прерывания 100 Гц и проверил флаг прерывания в основном цикле (не обязательно использовать ISR). Когда установлен флаг прерывания таймера, очистите его, повторно инициализируйте таймер, приобретите один образец и обработайте его. На каждом десятом образце выполняйте среднее и передачу. Когда флаг ясен, просто ничего не делайте.

+0

Это была настолько полезная информация и читаемость. Но я до сих пор пытаюсь установить частоту дискретизации до 100 Гц. Предыдущий теоретический метод, который вы объяснили, имел очень высокую частоту. Я действительно настроил этот код, но для меня это не имеет смысла в качестве выборки. это была очень высокая скорость. Не могли бы вы рассказать мне, как я могу установить таймер, чтобы он производил выборку каждые 100 Гц. это мой код для оформления. Благодарим вас за помощь. –

0
enter code here  
char temp[5]; 

unsigned int adc_value; 

char uart_rd; 
int i; 
unsigned int d[10]={0}; 
int average = 0; 
int counter =0; 

void main() 
{ 

    temp[0]='1'; 
    temp[1]='2'; 
    temp[2]='3'; 
    temp[3]='4'; 
    temp[4]=' '; 
    OSCCON  = 0x77;   
    //ANSEL = 0;    
    ANSEL = 0b00000100;  
    CMCON0 = 0X07; 
    TRISA = 0b00001100; 
    // ADCON0 =0b1011; 
    // ADCON1 &= 0b01000000;  
    //ADCON1 |= 0b01000000;  
    UART1_Init(9600);    
    Delay_ms(100);     
    while (1) 
    { 
     average=0; 
     for(i=0;i<10;i++) 
     { 
      average+= ADC_Read(2); 
     } 
     average/=10; 
     temp[0] = average/1000+48; 
     temp[1] = (average/100)%10+48; 
     temp[2] = (average/10)%10+48; 
     temp[3] = average%10+48; 
     for (i=0;i<5; i++) 
     { 
      UART1_Write(temp[i]); 
     } 
    } 
} 
+0

Было бы лучше добавить код к вопросу, а не как ответ. –

+0

ОК уверенный, извините, я только начинаю. - - так что сейчас смотрю учебник для timer0 для PIC6F688. Я сконфигурировал часы процессора на частоте 8 МГц, как и в коде. но я не понял в хорошей версии, как он сделал предустановленную (39), чтобы получить 1 секунду. задержка. Я знаю, что он настроил OPTION_REG = 0x07; получить макс. разрешение. Не могли бы вы помочь мне. Мне нужно установить частоту дискретизации до 100 Гц, т. Е. 0,01 сек. Это ссылка, которую я изучил. http://embedded-lab.com/blog/lab-7-timers-and-counters-part-1/ –

+0

Итак, тактовая частота 8 МГц F_osc => 2 МГц.С предварительным делителем 1: 256 таймер будет увеличиваться с частотой 2 МГц/256 = 7812,5 Гц или каждые 0,128 мс. Для прерывания со 100 Гц/каждые 10 мс вам нужно посчитать 7812,5 Гц/100 Гц = 78 'тиков'. Поскольку прерывание генерируется при переполнении счетчика (переход от 255 к 256, но переход к 0 из-за переполнения, вам необходимо установить регистр на 256-78 = 178. Обратите внимание, что в связанном учебнике 39 задайте интервалы в 1 с, но (256-39)/3906 = 0,055 с. Чтобы получить 1s, 'interrupt()' переключает светодиод только каждые 18 прерываний (18 * 0,055 = 1 с) –

Смежные вопросы