Analysis and improvement of ADC driven by RT-Thread 4.0 device

Keywords: PHP

OS version: RT thread 4.0.0

Chip: STM32F407

The following is the reference provider provided by the official ADC

Access ADC device

The application program accesses the ADC hardware through the ADC device management interface provided by RT thread, and the relevant interfaces are as follows:

function describe
rt_device_find() Find device and get device handle according to ADC device name
rt_adc_enable() Enable ADC device
rt_adc_read() Read ADC device data
rt_adc_disable() Turn off ADC device

Here is a brief analysis of the main implementation methods of the driver source code:

In DRV? ADC. C, there is no support for RT? Using? Device? OPS item. Add the following code

#Ifdef RT? Using? Device? OPS / / added support for RT? Using? Device? Ops
const static struct rt_device_ops adc_ops = 
{
    RT_NULL,
    RT_NULL,
    RT_NULL,
    _adc_read,
    RT_NULL,
    _adc_control
};
#endif

rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const struct rt_adc_ops *ops, const void *user_data)
{
    rt_err_t result = RT_EOK;
    RT_ASSERT(ops != RT_NULL && ops->convert != RT_NULL);
    
    device->parent.type = RT_Device_Class_Miscellaneous;
    
#ifdef RT_USING_DEVICE_OPS
    device->parent.ops          = &adc_ops;
#else
    device->parent.init = RT_NULL;
    device->parent.open = RT_NULL;
    device->parent.close = RT_NULL;
    device->parent.read = _adc_read;
    device->parent.write = RT_NULL;
    device->parent.control = _adc_control;
#endif

    device->ops = ops;
    device->parent.user_data = (void *)user_data;

    result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR);

    return result;
}

Among them, the device ops interface needs to realize ADC ﹣ ops

const static struct rt_device_ops adc_ops = 
{
    RT_NULL,
    RT_NULL,
    RT_NULL,
    _adc_read,
    RT_NULL,
    _adc_control
};

The subclass of device, RT ﹣ ADC ﹣ device, needs to implement the OPS of RT ﹣ ADC ﹣ ops

static const struct rt_adc_ops stm_adc_ops =
{
    .enabled = stm32_adc_enabled,
    .convert = stm32_get_adc_value,
};

Where, call STM32 ADC enabled, call STM32 get ADC value;

In the official example, in order to simplify the ADC driver operation, directly export the relevant ADC operation functions for the user to use, as follows:

    rt_adc_device_t adc_dev;
    rt_uint32_t value, vol;
    rt_err_t ret = RT_EOK;

    /* Search device */
    adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
    if (adc_dev == RT_NULL)
    {
        rt_kprintf("adc sample run failed! can't find %s device!\n", ADC_DEV_NAME);
        return RT_ERROR;
    }
    
    /* Enabling equipment */
    ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);

    /* Read sample value */
    value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
    rt_kprintf("the value is :%d \n", value);

    /* Convert to corresponding voltage value */
    vol = value * REFER_VOLTAGE / CONVERT_BITS;
    rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);

    /* Close channel */
    ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);

Since there is an I/O device model, the driver interface is too scattered by using this method. Here is an example of adc collection using the I/O device interface:

When using RT? Device? Read, pay attention to the meaning of pos and size

    rt_device_t adc_dev = rt_device_find(ADC_DEV_NAME);    
    rt_device_open(adc_dev, RT_DEVICE_FLAG_RDWR);    //Remember to open the device, otherwise the rt_device_read unavailable
    
    ret = rt_device_control(adc_dev, RT_ADC_CMD_ENABLE, (void*)ADC_DEV_CHANNEL);    //Enable ADC
    
    ret = rt_device_read(adc_dev, ADC_DEV_CHANNEL, &value, 4);    //When the program is not modified,_adc_read Functional pos Item representation adc Passageway size Is a multiple of 4. If it is greater than 4, the subsequent channels will be read in order
//    value = rt_adc_read((rt_adc_device_t)adc_dev, ADC_DEV_CHANNEL);
    rt_kprintf("the value is :%d  %d  %d\n", value, ret, *_rt_errno());
    vol = value * REFER_VOLTAGE / CONVERT_BITS;
    rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
    
    ret = rt_device_control(adc_dev, RT_ADC_CMD_DISABLE, (void*)ADC_DEV_CHANNEL);    //prohibit ADC

Posted by SEVIZ on Mon, 04 Nov 2019 07:09:14 -0800