申小林 发表于 2024-8-26 09:11

【B-G431B-ESC1-电机开发板试用】-05-如何使用ADC旋钮实现调速

<div class='showpostmsg'><p>前段时间有机会试用G431的电机开发板,但是一直有一个问题在心里搁着,那就是如何实现ADC来调速,开始的时候还是想的比较简单的,但是实现起来真的是比较恼火,为啥这么说呢?</p>

<p>因为这个里面ADC采集的数据一直都是0 ,这就让人很恼火,我查看了很多原厂的例程,基本都是使用DMA的模式,拿到查询模式不行么?我尝试了许久,查询模式得到的数据始终是0, 这就让我我从下手了,而且所有的寄存器和返回值都是正确的。</p>

<p>下面先上传一下代码,大家好一起看看。</p>

<pre>
<code>#include "ADC.h"





ADC_HandleTypeDef g_adc_handle;   /* ADC句柄 */

/**
* @brief ADC初始化函数
* @param       无
* @retval      无
*/


void adc_init(void)
{
    g_adc_handle.Instance = ADC_ADCX;
    g_adc_handle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;            /* 4分频,21Mhz */
    g_adc_handle.Init.Resolution = ADC_RESOLUTION_12B;                        /* 12位模式 */
    g_adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;                        /* 右对齐 */
    g_adc_handle.Init.ScanConvMode = DISABLE;                                 /* 非扫描模式 */
    g_adc_handle.Init.ContinuousConvMode = DISABLE;                           /* 关闭连续转换 */
    g_adc_handle.Init.NbrOfConversion = 1;                                    /* 本实验只使用到一个规则序列 */
    g_adc_handle.Init.DiscontinuousConvMode = DISABLE;                        /* 禁止不连续采样模式 */
    g_adc_handle.Init.NbrOfDiscConversion = 0;                                  /* 不连续采样通道数为0 */
    g_adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;                  /* 软件触发 */
    g_adc_handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;   /* 使用软件触发 */
    g_adc_handle.Init.DMAContinuousRequests = DISABLE;                        /* 关闭DMA请求 */
    HAL_ADC_Init(&amp;g_adc_handle);                                                /* 初始化ADC */
}

/**
* @brief       ADC底层驱动,引脚配置,时钟使能
                此函数会被HAL_ADC_Init()调用
* @param       hadc:ADC句柄
* @retval      无
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
    if(hadc-&gt;Instance == ADC_ADCX)
    {
      GPIO_InitTypeDef gpio_init_struct;
      
      ADC_ADCX_CHY_CLK_ENABLE();                                                /* 使能ADCx时钟 */
      ADC_ADCX_CHY_GPIO_CLK_ENABLE();                                             /* 开启GPIO时钟 */

      gpio_init_struct.Pin = ADC_ADCX_CHY_GPIO_PIN;                               /* ADC采集对应IO */
      gpio_init_struct.Mode = GPIO_MODE_ANALOG;                                 /* 模拟输入 */
      gpio_init_struct.Pull = GPIO_PULLUP;                                        /* 上拉 */
      HAL_GPIO_Init(ADC_ADCX_CHY_GPIO_PORT, &amp;gpio_init_struct);                   /* 初始化IO */
    }
}

/**
* @brief       ADC通道设置
* @param       adcx : adc句柄指针,ADC_HandleTypeDef
* @param       ch   : 通道号, ADC_CHANNEL_0~ADC_CHANNEL_18
* @param       stime: 采样时间0~7, 对应关系为:
*   @arg ADC_SAMPLETIME_3CYCLES,3个ADC时钟周期      ADC_SAMPLETIME_15CYCLES, 15个ADC时钟周期
*   @arg       ADC_SAMPLETIME_28CYCLES, 28个ADC时钟周期       ADC_SAMPLETIME_56CYCLES, 56个ADC时钟周期
*   @arg       ADC_SAMPLETIME_84CYCLES, 84个ADC时钟周期       ADC_SAMPLETIME_112CYCLES,112个ADC时钟周期
*   @arg       ADC_SAMPLETIME_144CYCLES,144个ADC时钟周期      ADC_SAMPLETIME_480CYCLES,480个ADC时钟周期
* @param       rank: 多通道采集时需要设置的采集编号,
                假设你定义channle1的rank=1,channle2 的rank=2,
                那么对应你在DMA缓存空间的变量数组AdcDMA 就i是channle1的转换结果,AdcDMA就是通道2的转换结果。
                单通道DMA设置为 ADC_REGULAR_RANK_1
*   @arg       编号1~16:ADC_REGULAR_RANK_1~ADC_REGULAR_RANK_16
* @retval      无
*/
void adc_channel_set(ADC_HandleTypeDef *adc_handle, uint32_t ch, uint32_t rank, uint32_t stime)
{
    ADC_ChannelConfTypeDef adc_channel;                                 /* 配置对应ADC通道 */

    adc_channel.Channel = ch;                                           /* ADC通道 */
    adc_channel.Rank = rank;                                          /* 设置采样序列 */
    adc_channel.SamplingTime = stime;                                 /* 设置采样时间 */
    HAL_ADC_ConfigChannel( adc_handle, &amp;adc_channel);   
}

/**
* @brief       获取ADC值
* @param       ch: 通道值 0~18,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_18
* @retval      无
*/
uint32_t adc_get_result(uint32_t ch)
{
    adc_channel_set(&amp;g_adc_handle , ch, 1, ADC_SAMPLETIME_640CYCLES_5);   /* 设置通道,序列和采样时间 */

    HAL_ADC_Start(&amp;g_adc_handle);                                       /* 开启ADC */

    HAL_ADC_PollForConversion(&amp;g_adc_handle, 10);                     /* 轮询转换 */

    return (uint16_t)HAL_ADC_GetValue(&amp;g_adc_handle);                   /* 返回最近一次ADC1规则组的转换结果 */
}

/**
* @brief       计算ADC的平均值(滤波)
* @param       ch      : 通道号, 0~18
* @param       times   : 累计次数
* @retval      通道ch转换结果累加times次的平均值
*/
uint32_t adc_get_result_average(uint32_t ch, uint8_t times)
{
    uint32_t temp_val = 0;
    uint8_t t;

    for (t = 0; t &lt; times; t++)               /* 获取times次数据 */
    {
      temp_val += adc_get_result(ch);         /* 累加 */
       HAL_Delay(5);
    }
    return temp_val / times;                  /* 返回平均值 */
}

</code></pre>

<p>我们可以通过原理图看到,我们的ADC的旋钮的位置是在PB12上的,对应的数据手册是ADC1_ch11的,</p>

<pre>
<code class="language-cpp">#include "stm32g4xx_hal.h"
#include "DRV_LED.h"
#include "DRV_TIM.h"
#include "DRV_UART.h"

//
#include "ADC.h"
#include "bldc.h"
#include "bldc_tim.h"

unsigned int Data=0,        Resoult=0;
int main(void)
{

        HAL_Init();
        SystemClock_Config();
        LED_Init();
        TIM_Init();
        UART_Init();
        bldc_init(10000-1,0);
        bldc_ctrl(MOTOR_1,CCW,0);
        HAL_TIM_Base_Start_IT(&amp;g_atimx_handle);/* 启动高级定时器1 */
        HAL_ADC_MspInit(&amp;g_adc_handle);
        adc_init();


while (1)
{
   
                HAL_Delay(500);
                Data=adc_get_result_average(ADC_ADCX_CHY, 10);
                if(Data&lt;500)
                {
                  stop_motor1();
      g_bldc_motor1.run_flag = STOP;
                }
                else
                {
                  start_motor1();
                          Resoult=                Data * (3.3 / 4096);   
      g_bldc_motor1.run_flag = RUN;
                                g_bldc_motor1.pwm_duty = Resoult;
              g_bldc_motor1.dir = CW;
                }
}
/* USER CODE END 3 */
}

</code></pre>

<p>我们通过Main函数实现了ADC的初始化的调用,在每次采集之前,实现了通道的配置,但是数据读取仍然是0 ,不知道哪位大侠用过查询模式读取ADC成功过么?很希望大家能给一些指导意见。</p>
</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                                                                                (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>
页: [1]
查看完整版本: 【B-G431B-ESC1-电机开发板试用】-05-如何使用ADC旋钮实现调速