Проблемы с аналого-цифровым преобразованием PIC

Я пытаюсь прочитать аналоговый сигнал для своего рода мыши с контроллером pic18f14k50. Вот простая схема: http://dl.dropbox.com/u/14663091/schematiconew.pdf . Мне нужно прочитать аналоговый сигнал с порта схемы AN9. Основная функция читает из порта и мигает 30 раз, если достигнут порог:

 void main(void) {
      InitializeSystem();

      #if defined(USB_INTERRUPT)
         USBDeviceAttach();
     #endif

     while(1) {

             if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) continue;

      if(!HIDTxHandleBusy(lastTransmission))
      {
       int readed = myReadADC2(); //Here i tried both myReadADC2() or myReadADC1()
       if(readed>40) { //If read threshold > 40, blink led 30 times
        int i;
        for(i=0; i<30; i++) {
         Delay1KTCYx(0);
         mLED_1_On();
         Delay1KTCYx(0);
         mLED_1_Off();
        }
              }
              lastTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x03);


     }//end while
 }//end main

Я использовал два метода для чтения из порта AN9, myReadADC(), который использует метод API OpenADC():

int myReadADC(void) {
   #define ADC_REF_VDD_VDD_X 0b11110011                      
   OpenADC(ADC_FOSC_RC & ADC_RIGHT_JUST & ADC_12_TAD, ADC_CH9 & ADC_INT_OFF, ADC_REF_VDD_VDD_X & ADC_REF_VDD_VSS, 0b00000010); // channel 9
   SetChanADC(ADC_CH9);
   ConvertADC();                 // Start conversion
   while(BusyADC());             // Wait for completion
   return ReadADC();           // Read result
}

и myReadADC2(), реализующий ручное чтение из порта.

int myReadADC2() {

  int iRet;
  OSCCON=0x70;         // Select 16 MHz internal clock
  ANSEL = 0b00000010;  // Set PORT AN9 to analog input
  ANSELH = 0;          // Set other PORTS as Digital I/O
  /* Init ADC */
  ADCON0=0b00100101;   // ADC port channel 9 (AN9), Enable ADC
  ADCON1=0b00000000;   // Use Internal Voltage Reference (Vdd and Vss)
  ADCON2=0b10101011;   // Right justify result, 12 TAD, Select the FRC for 16 MHz
  iRet=100;


  ADCON0bits.GO=1;
  while (ADCON0bits.GO);   // Wait conversion done
  iRet=ADRESL;           // Get the 8 bit LSB result
  iRet += (ADRESH << 8); // Get the 2 bit MSB result
  return iDelay; 

}

Оба случая не работают, я касаюсь (отправляю аналоговый сигнал) порта AN9, но когда я устанавливаю высокий порог (~ 50), светодиод не мигает, с низким порогом (~ 0) он мигает сразу, когда я подаю питание на PIC. Может быть, я использую неправильный порт? Я на самом деле передаю AN9 как порт для чтения? Или, может быть, порог неправильный? Как я могу найти правильное значение? Спасибо

Здесь MPLAB C18 Apis http://dl.dropbox.com/u/14663091/API%20microchip%20C18.pdf .


person Emilio    schedule 13.12.2010    source источник
comment
разве этот вопрос не принадлежит electronics.stackexchange.com?   -  person YudhiWidyatama    schedule 13.12.2010
comment
Хм, может быть, да. Я должен переместить его или это задача администратора?   -  person Emilio    schedule 13.12.2010
comment
К сожалению, мы не можем переместить его для вас автоматически. Поскольку PIC программируемый, я думаю, что вопросы по PIC можно задавать либо здесь, либо на Electronics SE (или и там, и там).   -  person Bill the Lizard    schedule 13.12.2010
comment
Хорошо, я отправлю в электронике тоже. Спасибо.   -  person Emilio    schedule 13.12.2010


Ответы (1)


Относительно функции myReadADC2(): вам необходимо переключить конфигурации ANSEL и ANSELH, поскольку RC7/AN9 настраивается в бите 1 ANSELH. Также называйте меня параноиком, но для линии

iRet += (ADRESH << 8);

Я всегда предпочитаю сначала сохранить его как временную переменную или явно указать значение ADRESH, прежде чем сдвигать его вверх:

iRet += (((UINT) ADRESH) << 8);

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

Относительно функции myReadADC(): OpenADC() принимает только два параметра. Я предполагаю, что битовое поле в третьем поле параметра предназначено для аналогового включения (АДРЕС/АДРЕС). Я предполагаю, что это обрабатывается SetChanADC(), но вам, возможно, придется установить ADRESH/ADRES вручную. Это может помочь установить точку останова в отладчике и остановиться после завершения настройки, чтобы убедиться, что ваши регистры установлены правильно.

person spade78    schedule 14.12.2010
comment
Что-то не так с result = ADRESL + (unsigned int)(ADRESH << 8);, где результатом является беззнаковое короткое длинное целое? Мой компилятор XC8. - person abdullah kahraman; 18.04.2012