我正在使用以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_setup
和read_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()
功能。一切都开始完美地工作。
很长的故事,如果您有相同的问题,请更新编译器。