首页 文章

PIC16F18855 ADC寄存器的行为与我期望的不同(C,CCS编译器)

提问于
浏览
2

我正在使用PIC16F18855 micro和CCS作为编译器,我正在努力使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

这表现得很奇怪,读数与引脚上的实际电压完全无关(对于10位读数,随机介于9和18之间) .

同事看了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
}

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

如果我在调用 adc_setup(); 之后立即调用 fprintf(HOST, "0x%x", ADC_CON_0); ,当我预期 0x84 时,我得到 0x80 . 这意味着10位adc值在2 8位寄存器内保持对齐,而不是右对齐 . 我不知道它为什么没有检查(ADCON1-3和ADCLK)是否正确 .

当我调用 read_adc_custom_implementation(); 时,它会在while循环中永远等待,表明ADGO位永远不会被重置,因为数据表显示它应该是 .

有谁知道为什么我的 adc_setupread_adc_custom_implementation 的实现没有工作我会很高兴,如果我可以使用它们 .

PIC16F18855 datasheet,ADCON0在第357页 .

1 回答

  • 1

    user from the CCS forums的帮助下,我找到了问题的解决方案 .

    我遇到的错误是硅片错误 - 如果你设置ADGO位然后在下一个时钟周期读取它,ADC就不会复位ADGO位 . 这意味着我的while循环将永远等待 . errata中有关于此错误的更多详细信息 . 我事先已经阅读了这篇文章,但误解为它并不适用于我,因为我的项目所发生的事情与文档中描述的内容不同 .

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

    此解决方法包含在版本5.069及更高版本的CCS中内置的 read_adc() 函数中,但我使用的是5.065,这是支持18855的第一个编译器版本 . 我首先尝试了解决方法,它解决了我的一个问题,但是我还在遇到其他一些错误 . 我没有尝试解决它们,而是更新到5.075并使用了内置的 read_adc() 函数 . 一切都开始完美 .

    长话短说,如果你有同样的问题,那么更新编译器 .

相关问题