Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ADC в PIC16F887 (HiTech C)
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > PIC
dccharacter
Пытаюсь портировать простенький урок из набора "44-pin demoboard" на С, ничегошеньки не получается. Пытаюсь отлаживать - и Proteus и MPLab SIM после возникновения первого прерывания по таймеру0 уходят в обработчик прерывания и там и сидят (в тело main не возвращаются). Байты результатов преобразования - пустые. Сломал голову, научите, пожалуйста. Листинг:

Код
#include <pic.h>
#define _XTAL_FREQ 20000000

__CONFIG (INTIO & WDTDIS & PWRTEN & MCLRDIS & BOREN & LVPDIS & UNPROTECT);

struct adc_result
    {
    int value;         // ADC built-in functions default to 8 bit result.
    int new_flag;      // 1-bit falg to indicate a new (fresh) value
    } adc_conversion;

void init_io()
{
    // set up PORTA so RA0 is an input for the ADC, RA1-RA7 are outputs
    TRISA = 0xFF;   // bit 0 = output, 1 = input
    
    // set up PORTB so RB0 is an input for the switch SW1, RB1-RB7 are outputs
    TRISB = 0x00;   // bit 0 = output, 1 = input

    // set up remaining ports to be all outputs
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;
    ANSEL = 0xFF;

    T0CS = 0;
    PSA = 0;
    PS0 = PS1 = PS2 = 1;
    T0IE = 1;    //enable timer0 int
    GIE  = 1;    //enable ints (global)
}

void init_adc()
{

//ADC setup
ADCON1 = 0b10000000; // bit7 = ADFM, set to 0 - left justified;
//bit 4-5 - reference voltage select, 00s are VDD and VSS

ADCON0 = 0b01000001; //ADCS1:0 = 01, Fosc/8; CHS5:2 = 0000, select AN0; GO = 1; ADON = 1;


GODONE = 1;    
}


// This function will be called on a Timer0 interrupt
void interrupt int_rtcc ()
{
    // channel is always set to AN0.  Otherwise we might change
    // it here
    
    // Get last conversion result.
    adc_conversion.value = ADRESH;
    adc_conversion.new_flag = 1;    // new value
    
    // start next conversion
    GODONE= 1;
/*PORTD = ~PORTD;
__delay_ms(150);*/
}

void main (void)
{
    int led_bar_right = 0; // default is led bar graph starting on the left (DS0)  
    int switch_count = 0;   // used for debouncing the switch
    int bars = 0;           // used to compute the number of LED "bars" to display
    int temp1 = 0;          // temporary working variable
    int led_display = 0;    // led display value

    // initialize global variables
    adc_conversion.value = 0;
    adc_conversion.new_flag = 0;


    // Set up MCU
    init_io();
    init_adc();
        // Timer 0 runs off internal clock with 1:256 prescaler
        // This means it should run over every ((256*256)/(4MHz/4)) = 65.5ms
        // It will be used to start an ADC conversion.
    
while(1)
    {
        // look for a new conversion result
        __delay_us(5);
        if (1)
        {
            bars = adc_conversion.value;
            adc_conversion.new_flag = 0;        // reset flag
            // We'll use the 3 most significant bits of the conversion result
            // to determine whether to display 1 to 8 "bars" on the LED display
            bars = (bars >> 5) + 1; // add one to make it 1 to 8 (vs 0 to 7)
            led_display = 0; // clear display variable
            for (temp1 = 0; temp1 < bars; temp1++)
            {
                // shift in a '1' for each bar
                led_display = (led_display << 1) + 1;
            }
        }

        // check for a switch press & debounce
        if (RB0 == 0)
        { // switch is low when pressed
            if (switch_count < 8)
            { // increment the count on all consecutive checks where switch is pressed
              // to a max of 8
                switch_count ++;
                // if we've seen 8 consecutive checks where the switch is pressed
                // it's considered a valid switch press.  Reverse the bar graph
                if (switch_count == 8)
                {
                    led_bar_right = ~led_bar_right;
                }
            }
        }
        else
        { // anytime switch is detected as not pressed, reset the count
            switch_count = 0;
        }


        // update display
        if (led_bar_right == 0)
        {  // from left
           PORTD = led_display;
        }
        else
        { // from right
            // we have to shift it so it displays 1-8 bars.  Just complementing
            // would display 0-7.
            PORTD =  ~(led_display >> 1);
        }

    }

/*

while (1)
    {
    if (GODONE == 0)
        {
        PORTD = 0;
        for ( int i=0; i= (ADRESH >> 5); i++)
            {
            PORTD = ( PORTD << 1 ) + 1;
            }
        GODONE = 1;
        }
    } */

}


И "заодно" вопросик - какой смысл в этом примере использовать прерывание? Почему не запускать новое преобразование по окончанию предыдущего (ну понятно, со всеми задержками необходимыми)?
asp
У Вас не получается в эмуляторах или железе?
В железе все прекрасно работает, дорабатывал вывод через usart, проблем небыло.
dccharacter
Цитата(asp @ Jul 3 2009, 19:58) *
У Вас не получается в эмуляторах или железе?
В железе все прекрасно работает, дорабатывал вывод через usart, проблем небыло.

Хм, ни там ни там не выходит. Причем прерывание срабатывает ОК, а вот такое чувство что я неправильно включаю АЦП. Еще смущает то, что в русском даташите на 887 нет такой вещи как ANSEL совсем - но я на всякий случай добавил, все равно не помогло. Сейчас попробую тоже через УАРТ посмотреть что там.

Цитата(dccharacter @ Jul 3 2009, 20:52) *
Хм, ни там ни там не выходит. Причем прерывание срабатывает ОК, а вот такое чувство что я неправильно включаю АЦП. Еще смущает то, что в русском даташите на 887 нет такой вещи как ANSEL совсем - но я на всякий случай добавил, все равно не помогло. Сейчас попробую тоже через УАРТ посмотреть что там.

Хм, похоже у меня вотчдог стреляет. Странно, он отключен. Пошел опять даташит курить.

Цитата(dccharacter @ Jul 3 2009, 21:00) *
Хм, ни там ни там не выходит. Причем прерывание срабатывает ОК, а вот такое чувство что я неправильно включаю АЦП. Еще смущает то, что в русском даташите на 887 нет такой вещи как ANSEL совсем - но я на всякий случай добавил, все равно не помогло. Сейчас попробую тоже через УАРТ посмотреть что там.


Хм, похоже у меня вотчдог стреляет. Странно, он отключен. Пошел опять даташит курить.

Не понимаю В симуляции МК ресеттится вотчдогом. Вотчдого отключен в конфиге. SWDTEN нигде не установлен. Бред.
Herz
Тихо сам с собою...
testerplus
Цитата(dccharacter @ Jul 3 2009, 15:38) *
Пытаюсь портировать простенький урок из набора "44-pin demoboard" на С, ничегошеньки не получается. Пытаюсь отлаживать - и Proteus и MPLab SIM после возникновения первого прерывания по таймеру0 уходят в обработчик прерывания и там и сидят (в тело main не возвращаются).


Добавь в прерывание:
Код
   T0IF = 0;
dccharacter
Цитата(testerplus @ Jul 4 2009, 00:38) *
Добавь в прерывание:
Код
   T0IF = 0;

Нет, не помогло. Причем в какой-то момент у меня железный сетап перестал в прерывание входить.

йолки, тот же алгоритм на CCS - работает. А на хи-тек не допру как сделать.
xemul
Цитата(dccharacter @ Jul 4 2009, 00:53) *
йолки, тот же алгоритм на CCS - работает. А на хи-тек не допру как сделать.

Видимо, пользуете ломаную ПРО версию. Попробуйте СТД или займитесь проверкой ассемблерного листинга на соответствие сишному коду.
dccharacter
Цитата(xemul @ Jul 4 2009, 01:27) *
Видимо, пользуете ломаную ПРО версию. Попробуйте СТД или займитесь проверкой ассемблерного листинга на соответствие сишному коду.

Переписал с нуля по-своему, заработало. Так и не понял, что это было.
Всем спасибо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.