PIC16F18855 ADC 寄存器的行为方式不符合我的预期(C、CCS 编译器)



我正在使用以CCS为编译器的PIC16F18855微型,我正在尝试使ADC工作。从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

这表现得很奇怪,读数完全独立于PIN上的实际电压(随机在9到18介于10位读数之间)。

一位同事通过C汇编的组件浏览,并告诉我,当使用read_adc() In In In In In In In In In In In In In In In In In In In In In In In In In In In In读取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
}

我的代码有两个主要问题:

如果我在拨打adc_setup();后立即致电fprintf(HOST, "0x%x", ADC_CON_0);,则当我期望0x84时会获得0x80。这意味着将10位ADC值保持在2 8位寄存器中,而不是右对齐。我不知道为什么它不正确写。我检查过的所有其他寄存器(ADCON1-3和ADCLK)都是正确的。

当我致电read_adc_custom_implementation();时,它会永远在段循环中等待,表明adgo位永远不会重置,因为数据表明应该是。

有人知道为什么我对adc_setupread_adc_custom_implementation的实现不起作用吗?另外,如果有人知道为什么CCS的提供的功能不起作用,如果可以使用这些功能,我会很高兴。

pic16f18855数据表,ADCON0在第357页。

我在CCS论坛的用户的帮助下找到了解决该问题的解决方案。

我遇到的错误是一个硅错误 - 如果设置ADGO位,然后在下一个时钟周期中读取它,则ADC永远不会重置ADGO位。这意味着我的时循环将永远等待。在勘误表中,此错误有更多详细信息。我实际上是在移交之前读过的,但误解了它不适用于我,因为我的项目的发生与文档中所述的内容并不相同。

解决方法是在设置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
}

此解决方法包含在read_adc()函数中,该函数在CCS中内置在版本5.069及以后的CCS中,但我使用的是5.065,这是编译器的第一个支持18855的编译器。我首先尝试了解决方法,它解决了我的一个。问题,但是我仍然遇到许多其他错误。我没有尝试围绕它们工作,而是更新为5.075并使用了内置的read_adc()功能。一切都开始完美地工作。

很长的故事,如果您有相同的问题,请更新编译器。

相关内容

  • 没有找到相关文章

最新更新