2017-12-18 30 views
2

저는 CCS와 함께 PIC16F18855 마이크로를 컴파일러로 사용하고 있으며 ADC가 작동하도록하려고합니다. CCS가 제공하는 기능부터 I 쓴 : 이것은 (10 비트 읽기 임의로 9와 18 사이) 핀상의 실제 전압 완전히 독립적이었다 판독하여, 이상하게 작동시켰다PIC16F18855 ADC 레지스터가 예상대로 작동하지 않습니다 (C, CCS 컴파일러)

#device ADC=10 
... 
setup_adc_ports(sAN21); 
setup_adc(ADC_CLOCK_DIV_8); 
set_adc_channel(21); 
... 
fprintf(HOST, "%ld", read_adc()); //I have RS232 implemented elsewhere 

.

C가 컴파일 한 어셈블리를 동료가 살펴본 결과 컴파일러가 read_adc() 함수를 사용하여 ADC를 읽으려고 시도 할 때 컴파일러가 잘못된 레지스터에 쓰고 있다고 알려줍니다. 특히, 변환을 시작하기 위해 ADGO 비트를 기록해야 할 때 존재하지 않는 ADCON0 이전의 레지스터에 기록합니다.

는이 문제를 해결하려면

, 나는 ADC를 설정하고 읽는 내 자신의 기능을 구현하기 위해 노력 :

#byte ADC_CON_0 = getenv("SFR:ADCON0") 
#byte ADC_CON_1 = getenv("SFR:ADCON1") 
#byte ADC_CON_2 = getenv("SFR:ADCON2") 
#byte ADC_CON_3 = getenv("SFR:ADCON3") 
#byte ADC_CLK = getenv("SFR:ADCLK") 
#byte ADC_RES_H = getenv("SFR:ADRESH") 
#byte ADC_RES_L = getenv("SFR:ADRESL") 
#byte AN_SEL_C = getenv("SFR:ANSELC") 
#byte ADC_PCH = getenv("SFR:ADPCH") 

void adc_setup(void){ 
    //setting the mode and clock 
    ADC_CON_0 = 0x84; //turn on ADC and right justify it 
    ADC_CON_1 = 0x00; 
    ADC_CON_2 = 0x00; 
    ADC_CON_3 = 0x00; 
    ADC_CLK = 0x03; //gives Fosc/8, for 1us T_AD with 8MHz clock 

    //setting the input channel and telling the pin to be analogue 
    AN_SEL_C = 0x20; //set pin C5 to analogue input 
    ADC_PCH = 0x15; //0x15 = 21, analogue channel 21 is pin C5 
} 

int16 read_adc_custom_implementation(void){ 
    ADC_CON_0 |= 0x01;      //set ADGO bit to start conversion 
    while(ADC_CON_0 & 0x01){}    //wait till conversion is finished (indicated by hardware reset of ADGO bit) 
    return make16(ADC_RES_H, ADC_RES_L); //read the result registers and return them combined into a 16bit integer 
} 

내 코드에 두 가지 문제가 있습니다 : 나는 즉시 fprintf(HOST, "0x%x", ADC_CON_0);를 호출 할 경우

가 전화 adc_setup(); 내가 0x84 일 때 0x80이 나옵니다. 즉, 10 비트 ADC 값은 오른쪽 정렬보다 2 8 비트 레지스터 내에 정렬됩니다. 왜 제대로 쓰지 않는지 나는 모른다. 확인한 다른 모든 레지스터 (ADCON1-3 및 ADCLK)는 정확합니다.

read_adc_custom_implementation();을 호출하면 while 루프에서 영원히 기다립니다. 데이터 시트에 반드시 ADGO 비트가 재설정되지 않는다고 표시됩니다.

내 구현이 adc_setupread_adc_custom_implementation인데 왜 작동하지 않는지 알고 있습니까? 또는 CCS의 제공된 기능이 작동하지 않는 이유를 아는 사람이라면 대신 그 기능을 사용할 수 있다면 행복 할 것입니다.

PIC16F18855 datasheet는 ADCON0 내가 user from the CCS forums의 도움으로, 문제에 대한 해결책을 찾을 페이지 357

+0

'read_adc()'는 어떤 타입을 반환합니까? 'read_adc()'의 정의를 게시하십시오. CCS 매뉴얼의 – chux

+0

: #DEVICE ADC = 지시문에 따라 8 비트 또는 16 비트 int. #device adc = 10의 int16을 사용하고 있기 때문입니다. – Escape

+0

'long'에'l' 대신에'fprintf (HOST, "% d", (int) read_adc());를 사용하십시오 ' – chux

답변

0

에 있습니다.

내가 만난 버그는 실리콘 버그입니다. ADGO 비트를 설정 한 후 다음 클럭 사이클에서 ADC를 읽으면 ADC가 ADGO 비트를 재설정하지 않습니다. 즉, while 루프는 영원히 기다릴 것입니다. 이 버그에 대한 자세한 내용은 errata입니다. 필자는 실제로 이것을 먼저 읽었지 만 프로젝트에 어떤 일이 일어나는지는 문서에 설명 된 내용과 동일하지 않기 때문에 나에게 적용되지 않는 것으로 잘못 해석했습니다.

해결은을 ADGO 비트를 설정하고 확인하는 사이에 단일 클록 사이클의 지연, 예를 포함하는 것이다

int16 read_adc_custom_implementation(void){ 
    ADC_CON_0 |= 0x01;      //set ADGO bit to start conversion 
    delay_cycles(1);      //workaround 
    while(ADC_CON_0 & 0x01){}    //wait till conversion is finished (indicated by hardware reset of ADGO bit) 
    return make16(ADC_RES_H, ADC_RES_L); //read the result registers and return them combined into a 16bit integer 
} 

이 해결은 버전 5.069 이상에서 CCS에 내장 read_adc() 함수에 포함 그러나 나는 18855를 지원하는 컴파일러의 첫 번째 버전 인 5.065를 사용하고있었습니다. 먼저 해결 방법을 시도하고 문제 중 하나를 해결했지만 다른 버그가 계속 발생했습니다. 대신에 5.075로 업데이트하고 read_adc() 내장 함수를 사용했습니다. 모든 것이 완벽하게 작동하기 시작했습니다.

짧은 이야기로, 동일한 문제가 발생하면 컴파일러를 업데이트하십시오.