DA14580 embodies ADC function in two places. First, in terms of power management, 10 bit ADC can measure battery voltage; Second, in terms of analog interface, there is 4-channel 10bit AD conversion.
The 10bit ADC can be differential at one end, and the one-time conversion takes 65ns. The maximum conversion rate is 3.3M/s. The power consumption is only 5uA at 100K conversion rate. And there are two full-scale configurations of 1.2V and 3.6V.
The ADC is fixed with four pins P0-0 to P0-3.
Let's look at the register of ADC.
ADC control register 1
Register bit12 GP_ ADC_ When mute is set to 1, it is used for ADC calibration. Bit10 GP_ ADC_ Set sign to 1 and 0, turn on ADC sampling to obtain positive and negative offset values respectively, which are written into the following two registers: GP_ADC_OFFP_REG and GP_ADC_OFFN_REG.
ADC positive and negative offset value register
The calibration procedures provided by the official SDK are as follows:
/** **************************************************************************************** * @brief ADC calibration sequence. * @return void **************************************************************************************** */ void adc_calibrate(void) { uint32_t adc_res1, adc_res2; int32_t adc_off_p, adc_off_n; int32_t new_adc_off_p, new_adc_off_n;; SetWord16(GP_ADC_CTRL_REG, GP_ADC_LDO_EN|GP_ADC_SE|GP_ADC_EN); adc_usDelay(20); SetWord16(GP_ADC_OFFP_REG, 0x200); SetWord16(GP_ADC_OFFN_REG, 0x200); SetBits16(GP_ADC_CTRL_REG, GP_ADC_MUTE, 1);//During calibration, this position is 1 SetBits16(GP_ADC_CTRL_REG, GP_ADC_SIGN, 0);//Collect forward offset value adc_res1 = adc_get_sample(); adc_off_p = adc_res1 - 0x200; SetBits16(GP_ADC_CTRL_REG, GP_ADC_SIGN, 1);//Collect negative offset value adc_res2 = adc_get_sample(); adc_off_n = adc_res2 - 0x200; new_adc_off_p = 0x200 - 2 * adc_off_p; new_adc_off_n = 0x200 - 2 * adc_off_n; SetWord16(GP_ADC_OFFP_REG, new_adc_off_p); SetWord16(GP_ADC_OFFN_REG, new_adc_off_n); }
ADC control register 2
bit3 of the register is set to 1 to realize three times the attenuation of the signal, that is, the signal with the maximum amplitude of 1.2*3=3.6V can be sampled.
ADC interrupt reset register can clear ADC interrupt by writing any value.
ADC result value register after each AD conversion result, the result value of 10bit exists in this register
ADC result value register after each AD conversion result, the result value of 10bit exists in this register
ADC delay register
/** **************************************************************************************** * @brief Gets ADC sample from VBAT1V or VBAT3V power supplies using the 20 usec delay. * @param[in] sample_vbat1v :true = sample VBAT1V, false = sample VBAT3V * @return ADC VBAT1V or VBAT3V sample **************************************************************************************** */ uint32_t adc_get_vbat_sample(bool sample_vbat1v) { uint32_t adc_sample, adc_sample2; adc_init(GP_ADC_SE, GP_ADC_SIGN, GP_ADC_ATTN3X);// adc_usDelay(20); if (sample_vbat1v) adc_enable_channel(ADC_CHANNEL_VBAT1V); else adc_enable_channel(ADC_CHANNEL_VBAT3V); adc_sample = adc_get_sample(); adc_usDelay(1); adc_init(GP_ADC_SE, 0, GP_ADC_ATTN3X ); if (sample_vbat1v) adc_enable_channel(ADC_CHANNEL_VBAT1V); else adc_enable_channel(ADC_CHANNEL_VBAT3V); adc_sample2 = adc_get_sample(); //We have to divide the following result by 2 if //the 10 bit accuracy is enough adc_sample = (adc_sample2 + adc_sample); adc_disable(); return adc_sample; } /** **************************************************************************************** * @brief ADC module initialization. * @param[in] mode :0 = Differential mode, GP_ADC_SE(0x800) = Single ended mode * @param[in] sign :0 = Default, GP_ADC_SIGN(0x0400) = Conversion with opposite sign at input and output to cancel out the internal offset of the ADC and low-frequency * @param[in] attn :0 = attenuation x1, GP_ADC_ATTN3X(0x0002) = attenuation x3 * @return void **************************************************************************************** */ void adc_init(uint16_t mode, uint16_t sign, uint16_t attn) { SetWord16(GP_ADC_CTRL_REG, GP_ADC_LDO_EN | mode | sign); SetWord16(GP_ADC_CTRL_REG, GP_ADC_LDO_EN | mode | GP_ADC_EN | sign); SetWord16(GP_ADC_CTRL2_REG, GP_ADC_DELAY_EN | GP_ADC_I20U | attn ); // Enable 3x attenuation } /** /** **************************************************************************************** * @brief Enable selected channel. * @param[in] input_selection Input channel * @return void **************************************************************************************** */ void adc_enable_channel(uint16_t input_selection) { SetBits16(GP_ADC_CTRL_REG,GP_ADC_SEL,input_selection & 0xF); }
Finally, there is a function to convert the AD conversion value into the percentage of electricity:
/** **************************************************************************************** * @brief Calculates battery level percentage for CR2032 batteries * @param[in] adc_sample adc sample * @return Battery level. 0 - 100% **************************************************************************************** */ uint8_t batt_cal_cr2032(uint16_t adc_sample) { uint8_t batt_lvl; if (adc_sample > 1705) batt_lvl = 100; else if (adc_sample <= 1705 && adc_sample > 1584) batt_lvl = 28 + (uint8_t)(( ( ((adc_sample - 1584) << 16) / (1705 - 1584) ) * 72 ) >> 16) ; else if (adc_sample <= 1584 && adc_sample > 1360) batt_lvl = 4 + (uint8_t)(( ( ((adc_sample - 1360) << 16) / (1584 - 1360) ) * 24 ) >> 16) ; else if (adc_sample <= 1360 && adc_sample > 1136) batt_lvl = (uint8_t)(( ( ((adc_sample - 1136) << 16) / (1360 - 1136) ) * 4 ) >> 16) ; else batt_lvl = 0; return batt_lvl; }
Note that if (adc_sample > 1705) in the above function, the power is equal to 100%. Some people may not understand, because the maximum conversion value of 10bit AD sampling is only 1024. How can 1705 be obtained?
In fact, take a closer look at the previous sampling function adc_get_vbat_sample(bool sample_vbat1v). The last sentence of this function is ADC_ Sample = (adc\u sample2 + adc\u sample); It is to add the results of forward acquisition and reverse acquisition, so the full scale is 10242 = 2048. 1705/20483.6V=2.997V, that is, when the battery voltage of CR2032 is 3V, it is considered to be 100% power. The nominal voltage of CR2032 is 3V.
Attached below is a picture we measured:
000003A4 is hexadecimal and 932 is converted to decimal. It can be seen that the forward and reverse conversion results are 932.
932+932=1864,1864/2048*3.6V=3.2765625V; Error rate: 1-3.2765625 / 3.3 = 1-99.3% = 0.7%
This is the result measured under 3.3V power supply, which is still very accurate. After all, the LDO output of power supply is also error.