【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(&g_adc_handle); /* 初始化ADC */
}
/**
* @brief ADC底层驱动,引脚配置,时钟使能
此函数会被HAL_ADC_Init()调用
* @param hadc:ADC句柄
* @retval 无
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
if(hadc->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, &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, &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(&g_adc_handle , ch, 1, ADC_SAMPLETIME_640CYCLES_5); /* 设置通道,序列和采样时间 */
HAL_ADC_Start(&g_adc_handle); /* 开启ADC */
HAL_ADC_PollForConversion(&g_adc_handle, 10); /* 轮询转换 */
return (uint16_t)HAL_ADC_GetValue(&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 < 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(&g_atimx_handle);/* 启动高级定时器1 */
HAL_ADC_MspInit(&g_adc_handle);
adc_init();
while (1)
{
HAL_Delay(500);
Data=adc_get_result_average(ADC_ADCX_CHY, 10);
if(Data<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]