stm32 ADC多通道采样例程HAL库.docx
《stm32 ADC多通道采样例程HAL库.docx》由会员分享,可在线阅读,更多相关《stm32 ADC多通道采样例程HAL库.docx(16页珍藏版)》请在冰豆网上搜索。
stm32ADC多通道采样例程HAL库
Stm32基于HAL库ADC多通道采样例程
1、用cubemx建立工程,cubemx5.3.0版本,芯片型号:
stm32f103zet6
(1)开启外部高速时钟HSE,配置系统时钟为72M
注意:
ADC1时钟配置为9MHz
(2)配置串口1,设置好波特率并开启串口中断
2、启用ADC1通道1,3,4,5,6
注意要先设置好通道数量才能配置,各自ADC通道的参数。
Rank是转换顺序,我们按1,2,3,4,5的顺序分别对应ADC1通道0,1,4,5,6。
多通道采样要开启扫描工作模式,在这里我们还有开启连续转换方式,连续转换是在ADC转换按照约定的转换顺序全部通道完成一次转换后,又自动启动下一次转换。
3、启用ADC转换DMA传输,多通道转换时要启用ADC的DMA传输,才能在相应的通道转换完成后,DMA自动去获取转换值。
中断方式没法在多通道采样时使用,因为在多通道扫描模式下,只有在最后一个通道转换结束时才会产生中断请求。
而ADC数据寄存器是共用的,这时候进入中断取值只能得到一个通道的数值。
4、到此,基础配置和ADC通道配置已经完成,接着我们设置工程名称和保存路径等就可以了,一般工程名和保存路径最好不要有中文,不然可能会出现一些意想不到的问题,在测试的过程中就遇到工程名或者保存路径中都用英文但是词组名称之间用空格隔开,在打开生成的工程文件后,向新建的分类文件夹中添加自己写的xxx.c文件,就导致keil软件卡死,不知道是keil软件还是cubemx的问题。
5、设置好工程名称和路径后就可以生成代码了,生成代码后我们选择打开工程。
接着我们开始编写代码
(1)首先我们要修改main函数的一个错误,就是在初始化时要把MX_DMA_Init()函数放在MX_ADC1_Init()函数之前执行,cubemx生成代码时MX_DMA_Init()是在ADC初始化函数之后。
如果在后面则转换时打印输出的ADC值,大多数都为0,具体原因就不知道是怎么回事了,应该是cubemx这个版本还不太稳定。
接下来我们在usart.c文件中增加一些代码
1)增加printf重定向到串口的代码,并定义一个串口接收到数据的标志变量和数据缓冲数组。
作用是在我们用串口调试助手给单片机发送数据时才打印输出ADC数据。
uint8_tRecFlag,RxBuf[512];
【代码】:
////重定向c库函数printf到USARTx
struct__FILE//标准库需要的支持函数
{
inthandle;
};
intfputc(intch,FILE*f)
{
while((huart1.Instance->SR&0X40)==0);//循环发送,直到发送完毕
huart1.Instance->DR=(uint8_t)ch;
return(ch);
}
2)编写串口数据接收函数voidMy_UsartDateRec(UART_HandleTypeDef*huart),这里就不在回调函数中编写了,然后stm32f1xx_it.c文件中的串口中断函数中调用这个函数来接收串口数据。
此外我们还需要在串口初始化函数
voidHAL_UART_MspInit(UART_HandleTypeDef*uartHandle)中,增加使能串口接收中断和空闲中断。
__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);//使能接收中断
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//使能空闲中断
记得在stm32f1xx_it.c文件开始部分包含usart.h头文件。
【代码】:
voidMy_UsartDateRec(UART_HandleTypeDef*huart)
{
//uint8_ttemp=0;
staticunsignedintnum;//接收计数
//查询是否发生了空闲中断
if(__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE)!
=RESET&&__HAL_UART_GET_IT_SOURCE(huart,UART_IT_IDLE)!
=RESET)
{
RecFlag=1;//收到数据
num=0;
__HAL_UART_CLEAR_IDLEFLAG(huart);//清除空闲中断
}
elseif(__HAL_UART_GET_IT_SOURCE(huart,UART_IT_RXNE)!
=RESET)//帧传输未完成,按字节接收
{
if(numRxBuf[num++]=(uint8_t)(huart->Instance->DR);
//else//缓冲区溢出
//temp=huart->Instance->DR;__HAL_UART_CLEAR_FLAG(huart,UART_FLAG_RXNE);
}
}
(2)在adc.c文件中增加代码
1)定义采样次数和通道数量,ADC数据保存数组
【代码】:
#include"adc.h"
/*USERCODEBEGIN0*/
#include"string.h"
#defineM20//采样次数
#defineN5//通道数
#ifN>1
volatileuint16_tADC_Value[N];//多个通道定义成数组
#else
uint16_tADC_Value;
#endif
//uint8_tGetADCtimes=20,ChannelNums;//采样次数和通道数
volatileuint16_tADC_ValBuf[100]={0};//100=20*5ADC_ValBuf
/*USERCODEEND0*/
ADC_HandleTypeDefhadc1;
DMA_HandleTypeDefhdma_adc1;
2)编写ADC计算平均值函数voidGet_ADC_AverageValue(void),并在adc.h中声明。
【代码】:
/*USERCODEBEGIN1*/
#ifN>1
/*多通道按顺序循环转换,ADC值也按顺序存放在ADC_Value数组中*/
voidGet_ADC_AverageValue(void)
{
uint32_tsum[N]={0};
uint16_ti,j;
for(i=0;ifor(j=0;jsum[j]+=ADC_ValBuf[i*N+j];//获取各个通道ADC值总和for(i=0;iADC_Value[i]=sum[i]/M;//计算平均值
}
#else
voidGet_ADC_AverageValue(void)
{
uint32_tsum;
uint16_ti;
for(i=0;isum+=ADC_ValBuf[i];
ADC_Value=sum/N;//计算平均值
}
#endif
/*USERCODEEND1*/
(3)最后我们就可以编写main函数了Length变量是数据的个数,所以直接通过sizeof(ADC_ValBuf)/2来计算得出。
首先,我们要在main函数开头的初始化部分调用ADCDMA启动函数,HAL_ADC_Start_DMA()函数中
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADC_ValBuf,sizeof(ADC_ValBuf)/2);
接着我们编写while循环中的函数。
【代码】:
while
(1)
{
/*USERCODEENDWHILE*/
/*USERCODEBEGIN3*/
if(RecFlag==1)
{
RecFlag=0;
Get_ADC_AverageValue();
for(i=0;i{
if(i>4&&i%5==0)
printf("\n");//打印出每个通道20次采样的数值
printf("%d",ADC_ValBuf[i]);
}
printf("\n\n");
printf("计算平均数后各通道的ADC值为:
\n");
for(i=0;i<5;i++)
{
switch(i)//打印出计算平均数后每个通道的ADC值
{
case0:
printf("ADC1Channel0Value:
%d\n",ADC_Value[i]);
break;
case1:
printf("ADC1Channel1Value:
%d\n",ADC_Value[i]);
break;
case2:
printf("ADC1Channel4Value:
%d\n",ADC_Value[i]);
break;
case3:
printf("ADC1Channel5Value:
%d\n",ADC_Value[i]);
break;
case4:
printf("ADC1Channel6Value:
%d\n",ADC_Value[i]);
break;
}
}
}
}
/*USERCODEEND3*/
}
到这里,我们在cubemx生成的工程文件中增加这些代码,就可以实现了ADC多通道采样。
其中比较关键的是:
ADC多通道采样需要启用扫描模式,并启用DMA接收ADC值(很重要),中断方式没法在多通道时实现ADC值接收。
(4)结果测试
首先,我们把通道0接到GND,把通道4和通道6接到3.3V,通道1和通道5不接入电压(悬空),然后用串口调试助手给单片机发送一个数据,按照设计的代码,程序将输出采样的ADC数据。
我们可以看到,通道0,20次采样结果都为0;通道1,5显示浮空时的采样数据;通道4,6数值都在4044左右。