# Anxinke PB-02 module evaluation (4) - PHY62XX ADC user guide## This article was first published on EEWORLD. For details, please visit: [EEWORLD evaluation](https://bbs.eeworld.com.cn/elecplay/content/189#F5) - Software environment: SDK - Hardware: Anxinke PB-02kit ## PHY6212 ADC introduction PHY62XX ADC has a total of 9 ADC channels: 1 PGA, 1 Temp Sensor, 6 Normal ADCs, and 1 Voice.
The interesting thing is that **ADC_CH0** is **PGA**. What is PGA? ? Let me introduce: ### PGA: **Programmable Gain Amplifier** (PGA), the programmable gain amplifier contains a fully balanced differential amplifier module, a decoder module and a resistor switch array module. The resistance ratio of the negative feedback resistor divider in the fully balanced differential amplifier module determines the maximum gain of the amplifier. The attenuation of the input signal of the resistor switch array module is controlled by the decoding result of the decoder module, and finally the gain of the amplifier is programmable. Well, I don’t really understand the above paragraph. I will give you a brief answer and extract the key information. Generally, multi-channel data acquisition systems use many different types of sensors, including thermocouples, bridges, thermistors, strain gauges and ultrasonic systems. Although sensors are based on different physical principles, most products use voltage as output. In industrial process control systems, low-frequency signals can vary from a few millivolts to a few volts. At this time, PGA is applied to match it to a specific ADC input range. A 12-bit ADC receiving a signal less than one-tenth of the ADC full-scale input can only provide 8-bit resolution unless the signal is amplified by PGA before reaching the ADC. But the problem is that the manual is not fully introduced here, and it does not introduce how to use it. It is good for everyone to understand it. ### Working mode: In the 6 Normal ADC channels, each ADC has two working modes, namely - single-ended - differential. In the single-ended mode, each collects the single-ended voltage on its pin. If the differential mode is to be used, **ADC_CH2~ADC_CH3**, **ADC_CH4~ADC_CH5**, **ADC_CH6~ADC_CH7** should appear in pairs, and the collected voltage is the differential voltage on **ADC_CH2**, **ADC_CH4**, **ADC_CH6** relative to **ADC_CH3**, **ADC_CH5**, **ADC_CH7**. This has better and stronger anti-noise performance. (It is worth noting that only one pair can be configured in differential mode when working). ### Input range: - bypass mode: [0V, 1V]; - attenuation mode: [0V, 4V]; The actual displayed voltage does not exceed the chip **AVDD33** pin voltage. ### Acquisition accuracy: The accuracy of ADC acquisition varies greatly in different ranges and modes. The specific situation is as follows:
### Acquisition rate: Normal ADC supports sampling rates of 80K, 160K, and 320K, and the default rate is 320K. The ADC rate is not very fast, which may also be related to the internal mechanism. ## PHY6212 ADC actual analysis: There are two working modes - interrupt - polling. In most cases, interrupts are used to trigger acquisition signals. Here we mainly introduce the interrupt method. ### Interrupt method: 9 ADC channels share one interrupt entry, and the interrupt number is: **CM0 (29)**. The interrupt of each Normal ADC channel can be masked and cleared separately. The interrupt trigger condition is buffer full, that is, the data fills the entire memory to trigger the interrupt. The interrupt method software processing flow is as follows. Many processes have been encapsulated in the API and can be directly called and used. system initial 2. ADC initial 3. ADC enable 4. irq enable 5. enable ADC interrupt 6. wait interrupt 7. Collect Data 8. calculate ADC value 9. mask interrupt 10. clear interrupt Code analysis: ```c uint16 adc_ProcessEvent( uint8 task_id, uint16 events )//System ADC processing function{ VOID task_id; // Parameters required for OSAL registration, not used in this function//LOG("adc_ProcessEvent: 0x%x\n",events); if ( events & SYS_EVENT_MSG )//Confirm that the event occurred{ uint8 *pMsg; if ( (pMsg = osal_msg_receive( adcDemo_TaskID )) != NULL ) { adc_ProcessOSALMsg( (osal_event_hdr_t *)pMsg );//This function is actually empty// Event semaphore VOID osal_msg_deallocate( pMsg ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & 0x20 ) { // Configure event timer to occur LOG("20\n"); osal_start_timerEx( adcDemo_TaskID, 0x20, 2000); return (events ^ 0x2 0); } if ( events & adcMeasureTask_EVT ) { // Perform periodic heart rate task //LOG("adcMeasureTask_EVT\n"); adcMeasureTask(); return (events ^ adcMeasureTask_EVT); } // Discard unknown events return 0; } adc_Cfg_t adc_cfg = { .channel = ADC_BIT(ADC_CH3P_P20)|ADC_BIT(ADC_CH2P_P14)|ADC_BIT(ADC_CH3N_P15), //Set the enable pin .is_continue_mode = FALSE, //Discontinuous conversion mode .is_differential_mode = 0x00, //Mode 0 .is_high_resolution = 0x7F,//Precision setting}; static void adcMeasureTask( void )//Actual measurement task{ int ret; bool batt_mode = FALSE; uint8_t batt_ch = ADC_CH3P_P20; GPIO_Pin_e pin; if(FALSE == batt_mode) //Change according to mode { ret = hal_adc_config_channel(adc_cfg, adc_evt); } else {//This is not enabled if((((1 << batt_ch) & adc_cfg.channel) == 0) || (adc_cfg.is_differential_mode != 0x00)) return; pin = s_pinmap[batt_ch]; hal_gpio_cfg_analog_io(pin,Bit_DISABLE);// hal_gpio_write(pin, 1); adc_evt); hal_gpio_cfg_analog_io(pin,Bit_DISABLE); } if(ret) { LOG("ret = %d\n",ret); return; } hal_adc_start();//Turn on ADC } ``` The result of burning the code after turning it on is as shown in the figure: