About Analog/Digital Conversion Code Optimisation
The analog to digital converter (ADC or A/D) module support is implemented by GCBASIC to provide 8-bit, 10-bit and 12-bit Single channel measurement mode and Differential Channel Measurement with support up to 34 channels. For compatibility all channels are supported.
There are two methods to optimise the code.
- To mimise the code, use the contstants to disable support for a specfic channels
- To adapt the ADC configuration by inserting specfic commands to set registers or register bits.
1. Minimise the code
The example below would disable support for ADC port 0 (AD0).
#define USE_AD0 FALSE
The following tables show the #defines that can be used to reduce the code size - these are the defines for the standard microcontrollers. For 16f1688x and similar microcontrollers please see the second table.
Channel | Optimisation Value | Default Value |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For 16f1688x devices see the table below.
Channel | Optimisation Value | Default Value |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This is a example - disables every channel except the specified channel by defining every channel except USE_AD0 as FALSE.
This will save 146 bytes of program memory.
#chip 16F1939 'USART settings #define USART_BAUD_RATE 9600 #define USART_TX_BLOCKING 'Set the input pin direction Dir PORTA.0 In 'Print 255 reading For CurrentAddress = 0 to 255 'Take a reading and show it HSerPrint str(ReadAD10(AN0)) 'Wait 10 minutes before getting another reading Wait 10 min Next #define USE_AD0 TRUE #define USE_AD1 FALSE #define USE_AD2 FALSE #define USE_AD2 FALSE #define USE_AD3 FALSE #define USE_AD4 FALSE #define USE_AD5 FALSE #define USE_AD6 FALSE #define USE_AD7 FALSE #define USE_AD8 FALSE #define USE_AD9 FALSE #define USE_AD10 FALSE #define USE_AD11 FALSE #define USE_AD12 FALSE #define USE_AD13 FALSE #define USE_AD14 FALSE #define USE_AD15 FALSE #define USE_AD16 FALSE #define USE_AD17 FALSE #define USE_AD18 FALSE #define USE_AD19 FALSE #define USE_AD20 FALSE #define USE_AD21 FALSE #define USE_AD22 FALSE #define USE_AD23 FALSE #define USE_AD24 FALSE #define USE_AD25 FALSE #define USE_AD26 FALSE #define USE_AD27 FALSE #define USE_AD28 FALSE #define USE_AD29 FALSE #define USE_AD30 FALSE #define USE_AD31 FALSE #define USE_AD32 FALSE #define USE_AD33 FALSE #define USE_AD34 FALSE
For 16f18855 family of microcontrollers this is a example. This will save 149 bytes of program memory.
''' PIC: 16F18855 ''' Compiler: GCB ''' IDE: GCode ''' ''' Board: Xpress Evaluation Board ''' Date: 13.3.2021 ''' 'Chip Settings. #CHIP 16F18855,32 #CONFIG MCLRE_ON #OPTION EXPLICIT '' -------------------LATA----------------- '' Bit#: -7---6---5---4---3---2---1---0--- '' LED: ---------------|D5 |D4 |D3 |D1 |- ''----------------------------------------- '' #define USART_BAUD_RATE 19200 #define USART_TX_BLOCKING #define LEDD2 PORTA.0 #define LEDD3 PORTA.1 #define LEDD4 PORTA.2 #define LEDD5 PORTA.3 Dir LEDD2 OUT Dir LEDD3 OUT Dir LEDD4 OUT Dir LEDD5 OUT #define SWITCH_DOWN 0 #define SWITCH_UP 1 #define SWITCH PORTA.5 'Setup an Interrupt event when porta.5 goes negative. IOCAN5 = 1 On Interrupt PORTABChange Call InterruptHandler do 'Read the value from the EEPROM from register Zero in the EEPROM EPRead ( 0, OutValue ) 'Leave the Top Bytes alone and set the lower four bits PortA = ( PortA & 0XF0 ) OR ( OutValue / 16 ) Sleep loop sub InterruptHandler if IOCAF5 = 1 then 'S2 was just pressed IOCAN5 = 0 'Prevent the event from reentering the InterruptHandler routine IOCAF5 = 0 'We must clear the flag in software wait 5 ms 'debounce by waiting and seeing if still held down if ( SWITCH = SWITCH_DOWN ) then 'Read the ADC adc_value = readad ( AN4 ) 'Write the value to register Zero in the EEPROM EPWrite ( 0, adc_value ) end if IOCAN5 = 1 'ReEnable the InterruptHandler routine end if end sub #define USE_ADA0 FALSE #define USE_ADA1 FALSE #define USE_ADA2 FALSE #define USE_ADA3 FALSE #define USE_ADA4 TRUE #define USE_ADA5 FALSE #define USE_ADA6 FALSE #define USE_ADA7 FALSE #define USE_ADB0 FALSE #define USE_ADB1 FALSE #define USE_ADB2 FALSE #define USE_ADB3 FALSE #define USE_ADB4 FALSE #define USE_ADB5 FALSE #define USE_ADB6 FALSE #define USE_ADB7 FALSE #define USE_ADC0 FALSE #define USE_ADC1 FALSE #define USE_ADC2 FALSE #define USE_ADC3 FALSE #define USE_ADC4 FALSE #define USE_ADC5 FALSE #define USE_ADC6 FALSE #define USE_ADC7 FALSE #define USE_ADD0 FALSE #define USE_ADD1 FALSE #define USE_ADD2 FALSE #define USE_ADD3 FALSE #define USE_ADD4 FALSE #define USE_ADD5 FALSE #define USE_ADD6 FALSE #define USE_ADD7 FALSE #define USE_ADE0 FALSE #define USE_ADE1 FALSE #define USE_ADE2 FALSE
2. Adapt the ADC configuration
Example 1:
The following example will set the specific register bits. The instruction will be added to the compiled code.
#define ADReadPreReadCommand ADCON.2=0:ANSELA.0=1
The constant ADReadPreReadCommand can be used to adapt the ADC methods. The constant can enable registers or register bit(s) that are required to managed for a specfic solution.
In the example above the following ASM will be added to your code. This WILL be added just before the ADC is enabled and the setting of the acquisition delay.
;ADReadPreReadCommand banksel ADCON bcf ADCON,2 banksel ANSELA bsf ANSELA,0
Example 2:
The following example can be used to change the ADMUX to support a sensor on ADC4.
This supports reading the internal temperature sensor on the ATTINY85. This method will work on other similar chips. Please refer the chip specific datasheet.
This will call a macro to change the ADMUX to read the ATTINY85 internal temperature sensor, set the reference voltage to 1v1 and then wait 100 ms.
#define ADREADPREREADCOMMAND ATTINY85ReadInternalTemperatureSensor Macro ATTINY85ReadInternalTemperatureSensor /* 17.12 of the datasheet The temperature measurement is based on an on-chip temperature sensor that is coupled to a single ended ADC4 channel. Selecting the ADC4 channel by writing the MUX[3:0] bits in ADMUX register to 1111 enables the temperature sensor. The internal 1.1V reference must also be selected for the ADC reference source in the temperature sensor measurement. When the temperature sensor is enabled, the ADC converter can be used in single conversion mode to measure the voltage over the temperature sensor. The measured voltage has a linear relationship to the temperature as described in Table 17-2 The sensitivity is approximately 1 LSB / ?C and the accuracy depends on the method of user calibration. Typically, the measurement accuracy after a single temperature calibration is ±10?C, assuming calibration at room temperature. Better accuracies are achieved by using two temperature points for calibration. */ IF ADReadPort=4 then ADMUX = ( ADMUX and 0X20 ) or 0X8F wait 100 ms End if End Macro
This will generate the following ASM.
;ADREADPREREADCOMMAND 'adds user code below lds SysCalcTempA,ADREADPORT cpi SysCalcTempA,4 brne ENDIF2 ldi SysTemp2,32 in SysTemp3,ADMUX and SysTemp3,SysTemp2 mov SysTemp1,SysTemp3 ldi SysTemp2,143 or SysTemp1,SysTemp2 out ADMUX,SysTemp1 ldi SysWaitTempMS,100 ldi SysWaitTempMS_H,0 rcall Delay_MS ENDIF2: