专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
STM32
请问STM32L053怎么设置ADC实现多通道采集?
2019-07-14 14:14
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
STM32/STM8
18143
6
1305
请问哪位高手用过
STM32
L053 ,怎样设置ADC实现多通道采集
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
6条回答
60user124
1楼-- · 2019-07-14 17:31
要用dma读
加载中...
60user124
2楼-- · 2019-07-14 20:20
/**
* @file ADC_Configuration
* @brief 完成ADC和DMA的初始化
* @param 无
* @retval 无
*/
void ADC_Configuration(uint32_t _ulFreq)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
TIM_TimeBaseInitTypeDef timer_init_structure;
NVIC_InitTypeDef NVIC_InitStructure;
uint16_t usPeriod;
uint16_t usPrescaler;
uint32_t uiTIMxCLK;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/*设置ADC分频因子为4 ,ADC最大时间不能超过14M*/
RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);
/* ADC1 Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* 使能DMA时钟 */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_6 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*-----------------------------------------------------------------------
system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:
HCLK = SYSCLK / 1 (AHB1Periph)
PCLK2 = HCLK / 2 (APB2Periph)
PCLK1 = HCLK / 4 (APB1Periph)
因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;
因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;
APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM6, TIM12, TIM13,TIM14
APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11
----------------------------------------------------------------------- */
uiTIMxCLK = SystemCoreClock;
if (_ulFreq < 100)
{
usPrescaler = 10000 - 1; /* 分频比 = 10000 */
usPeriod = (uiTIMxCLK / 10000) / _ulFreq - 1; /* 自动重装的值 */
}
else if (_ulFreq < 3000)
{
usPrescaler = 100 - 1; /* 分频比 = 100 */
usPeriod = (uiTIMxCLK / 100) / _ulFreq - 1; /* 自动重装的值 */
}
else /* 大于4K的频率,无需分频 */
{
usPrescaler = 0; /* 分频比 = 1 */
usPeriod = uiTIMxCLK / _ulFreq - 1; /* 自动重装的值 */
}
/*复位TIM2*/
TIM_DeInit(TIM2);
/*初始化TIMBASE结构体*/
TIM_TimeBaseStructInit(&timer_init_structure);
/*系统时钟,不分频,48M*/
timer_init_structure.TIM_ClockDivision = TIM_CKD_DIV1;
/*向上计数模式*/
timer_init_structure.TIM_CounterMode = TIM_CounterMode_Up;
/*每312 uS触发一次中断,开启ADC*/
timer_init_structure.TIM_Period = usPeriod;
/*计数时钟预分频,f=1M,systick=1 uS */
timer_init_structure.TIM_Prescaler = usPrescaler;
/*发生0+1次update事件产生中断 */
timer_init_structure.TIM_RepetitionCounter = 0x00;
TIM_TimeBaseInit(TIM2, &timer_init_structure);
/*使能TIM2中断 */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
/*选择TIM2的update事件更新为触发源*/
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
/*使能TIM2*/
TIM_Cmd(TIM2, ENABLE);
/* ADC1 DeInit */
ADC_DeInit(ADC1);
/*初始化ADC结构体,此句必须加,不加的话多路ADC数据会交换*/
ADC_StructInit(&ADC_InitStructure);
/*配置ADC分辨率为12位*/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
/*开启连续转换*/
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
/*禁止触发检测,使用软件触发*/
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConv_T2_TRGO;
/*ADC采集数据右对齐*/
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
/*向上扫描*/
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
/*ADC初始化*/
ADC_Init(ADC1, &ADC_InitStructure);
/*配置采样通道及时间*/
ADC_ChannelConfig(ADC1, GPIO_Pin_2 | ADC_Channel_3 | ADC_Channel_5 | GPIO_Pin_6 , ADC_SampleTime_28_5Cycles);
/* ADC 校准 */
ADC_GetCalibrationFactor(ADC1);
/* 循环模式下的 ADC DMA 请求 */
ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);
/* 使能 ADC_DMA */
ADC_DMACmd(ADC1, ENABLE);
/* 使能 ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* 等待 ADCEN 标志 */
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));
/* ADC1 常规软件启动转换 */
ADC_StartOfConversion(ADC1);
/* 复位DMA1_Channel1 */
DMA_DeInit(DMA1_Channel1);
/*DMA外设ADC基地址*/
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
/*DMA内存基地址*/
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue;
/*外设作为数据传输源*/
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
/*DMA通道的DMA缓存的大小*/
DMA_InitStructure.DMA_BufferSize = 4 * AD_Count;
/*外设地址寄存器不变*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
/*内存地址寄存器递增*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/*外设取值大小设置为半字*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
/*数据大小设置为半字*/
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
/*DMA循环模式,即完成后重新开始覆盖*/
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
/*DMA优先级设置为高*/
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
/*DMA通道x禁用内存到内存传输*/
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
/*DMA初始化*/
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/*清除一次DMA中断标志*/
DMA_ClearITPendingBit(DMA1_IT_TC1);
/*使能DMA传输完成中断*/
DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE);
/*选择DMA1通道中断*/
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
/*中断使能*/
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/*优先级设为0 */
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
/*使能 DMA 中断*/
NVIC_Init(&NVIC_InitStructure);
/* DMA1 Channel1 enable */
DMA_Cmd(DMA1_Channel1, ENABLE);
}
/**
* @brief ADC滤波
* @param 无
* @retval 无
*/
void ADC_Filter(void)
{
uint8_t i, j;
/*从DMA缓存中取出AD数据*/
for(i=0; i<4; i++)
{
for(j=0; j<AD_Count; j++)
{
ADCresults
[j] = ADC_ConvertedValue[j]
;
}
}
/*取值求和取平均*/
for(i=0; i<4; i++)
{
AD_Data
= 0;
for(j=0; j<AD_Count; j++)
{
AD_Data
+= ADCresults
[j];
}
AD_Data
=(AD_Temp
*75 + ((AD_Data
)/ (AD_Count))*25)/100;
AD_Temp
= AD_Data
;
}
// printf(" AD_value1=%d AD_value2=%d ",AD_Data[0], AD_Data[1]);
}
/**
* @brief DMA1_Channel1中断服务函数
* @param 无
* @retval 无
*/
void DMA1_Channel1_IRQHandler()
{
/*判断DMA传输完成中断*/
if(DMA_GetITStatus(DMA1_IT_TC1) != RESET)
{
// AD_Count_flag++;
// if(AD_Count_flag==64)
flag_ADC = 1;
}
/*清除DMA中断标志位*/
DMA_ClearITPendingBit(DMA1_IT_TC1);
}
加载中...
billbian
3楼-- · 2019-07-14 21:45
精彩回答 2 元偷偷看……
加载中...
吔屎蛋拉雷
4楼-- · 2019-07-15 02:27
billbian 发表于 2019-2-13 10:15
假如不用DMA,可以获得多通道的数据?
不用 DMA 可以使用 ADC 断续模式 例如选用 内部软件触发,一个序列 每触发一次 转换一个通道,检测EOC标志 就好了,读取出数据。手册上有的
加载中...
吔屎蛋拉雷
5楼-- · 2019-07-15 03:34
billbian 发表于 2019-2-13 10:15
假如不用DMA,可以获得多通道的数据?
使用 DMA很简单的 不复杂 使用 cube
加载中...
billbian
6楼-- · 2019-07-15 09:21
但是CUBE生成代码中只有配置,没有启动,没有多通道读取部分,如何处理呢?加1个qq,咨询下,24039851
加载中...
一周热门
更多
>
相关问题
STM32F4上I2C(在PROTEUS中模拟)调试不通的问题
6 个回答
芯片供应紧张,准备换个MCU,MM32L系列替换STM32L系列的怎么样?
7 个回答
STM32同时使用两个串口进行数据收发时数据丢包的问题
5 个回答
STM32F103串口通信死机问题
4 个回答
STM32WLE5CC连接SX1268在LoRa模式下能与 SX1278互通吗?
2 个回答
STM32开发板免费用活动
7 个回答
stm32 处理 DHT11占用太多时间,大家程序是怎么设计的
8 个回答
分享一个STM32单片机做的离线编程器代码
9 个回答
相关文章
ST公司第一款无线低功耗单片机模块有效提高物联网设计生产效率
0个评论
如何实现对单片机寄存器的访问
0个评论
通过USB用STM32片内自带Bootloader下载程序及注意事项
0个评论
欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行
0个评论
×
关闭
采纳回答
向帮助了您的网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
STM32
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
关闭
您已邀请
15
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
* @file ADC_Configuration
* @brief 完成ADC和DMA的初始化
* @param 无
* @retval 无
*/
void ADC_Configuration(uint32_t _ulFreq)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
TIM_TimeBaseInitTypeDef timer_init_structure;
NVIC_InitTypeDef NVIC_InitStructure;
uint16_t usPeriod;
uint16_t usPrescaler;
uint32_t uiTIMxCLK;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/*设置ADC分频因子为4 ,ADC最大时间不能超过14M*/
RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);
/* ADC1 Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* 使能DMA时钟 */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_6 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*-----------------------------------------------------------------------
system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:
HCLK = SYSCLK / 1 (AHB1Periph)
PCLK2 = HCLK / 2 (APB2Periph)
PCLK1 = HCLK / 4 (APB1Periph)
因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;
因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;
APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM6, TIM12, TIM13,TIM14
APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11
----------------------------------------------------------------------- */
uiTIMxCLK = SystemCoreClock;
if (_ulFreq < 100)
{
usPrescaler = 10000 - 1; /* 分频比 = 10000 */
usPeriod = (uiTIMxCLK / 10000) / _ulFreq - 1; /* 自动重装的值 */
}
else if (_ulFreq < 3000)
{
usPrescaler = 100 - 1; /* 分频比 = 100 */
usPeriod = (uiTIMxCLK / 100) / _ulFreq - 1; /* 自动重装的值 */
}
else /* 大于4K的频率,无需分频 */
{
usPrescaler = 0; /* 分频比 = 1 */
usPeriod = uiTIMxCLK / _ulFreq - 1; /* 自动重装的值 */
}
/*复位TIM2*/
TIM_DeInit(TIM2);
/*初始化TIMBASE结构体*/
TIM_TimeBaseStructInit(&timer_init_structure);
/*系统时钟,不分频,48M*/
timer_init_structure.TIM_ClockDivision = TIM_CKD_DIV1;
/*向上计数模式*/
timer_init_structure.TIM_CounterMode = TIM_CounterMode_Up;
/*每312 uS触发一次中断,开启ADC*/
timer_init_structure.TIM_Period = usPeriod;
/*计数时钟预分频,f=1M,systick=1 uS */
timer_init_structure.TIM_Prescaler = usPrescaler;
/*发生0+1次update事件产生中断 */
timer_init_structure.TIM_RepetitionCounter = 0x00;
TIM_TimeBaseInit(TIM2, &timer_init_structure);
/*使能TIM2中断 */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
/*选择TIM2的update事件更新为触发源*/
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
/*使能TIM2*/
TIM_Cmd(TIM2, ENABLE);
/* ADC1 DeInit */
ADC_DeInit(ADC1);
/*初始化ADC结构体,此句必须加,不加的话多路ADC数据会交换*/
ADC_StructInit(&ADC_InitStructure);
/*配置ADC分辨率为12位*/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
/*开启连续转换*/
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
/*禁止触发检测,使用软件触发*/
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConv_T2_TRGO;
/*ADC采集数据右对齐*/
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
/*向上扫描*/
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
/*ADC初始化*/
ADC_Init(ADC1, &ADC_InitStructure);
/*配置采样通道及时间*/
ADC_ChannelConfig(ADC1, GPIO_Pin_2 | ADC_Channel_3 | ADC_Channel_5 | GPIO_Pin_6 , ADC_SampleTime_28_5Cycles);
/* ADC 校准 */
ADC_GetCalibrationFactor(ADC1);
/* 循环模式下的 ADC DMA 请求 */
ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);
/* 使能 ADC_DMA */
ADC_DMACmd(ADC1, ENABLE);
/* 使能 ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* 等待 ADCEN 标志 */
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));
/* ADC1 常规软件启动转换 */
ADC_StartOfConversion(ADC1);
/* 复位DMA1_Channel1 */
DMA_DeInit(DMA1_Channel1);
/*DMA外设ADC基地址*/
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
/*DMA内存基地址*/
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue;
/*外设作为数据传输源*/
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
/*DMA通道的DMA缓存的大小*/
DMA_InitStructure.DMA_BufferSize = 4 * AD_Count;
/*外设地址寄存器不变*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
/*内存地址寄存器递增*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/*外设取值大小设置为半字*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
/*数据大小设置为半字*/
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
/*DMA循环模式,即完成后重新开始覆盖*/
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
/*DMA优先级设置为高*/
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
/*DMA通道x禁用内存到内存传输*/
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
/*DMA初始化*/
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/*清除一次DMA中断标志*/
DMA_ClearITPendingBit(DMA1_IT_TC1);
/*使能DMA传输完成中断*/
DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE);
/*选择DMA1通道中断*/
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
/*中断使能*/
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/*优先级设为0 */
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
/*使能 DMA 中断*/
NVIC_Init(&NVIC_InitStructure);
/* DMA1 Channel1 enable */
DMA_Cmd(DMA1_Channel1, ENABLE);
}
/**
* @brief ADC滤波
* @param 无
* @retval 无
*/
void ADC_Filter(void)
{
uint8_t i, j;
/*从DMA缓存中取出AD数据*/
for(i=0; i<4; i++)
{
for(j=0; j<AD_Count; j++)
{
ADCresults[j] = ADC_ConvertedValue[j];
}
}
/*取值求和取平均*/
for(i=0; i<4; i++)
{
AD_Data = 0;
for(j=0; j<AD_Count; j++)
{
AD_Data += ADCresults[j];
}
AD_Data =(AD_Temp*75 + ((AD_Data)/ (AD_Count))*25)/100;
AD_Temp = AD_Data;
}
// printf(" AD_value1=%d AD_value2=%d ",AD_Data[0], AD_Data[1]);
}
/**
* @brief DMA1_Channel1中断服务函数
* @param 无
* @retval 无
*/
void DMA1_Channel1_IRQHandler()
{
/*判断DMA传输完成中断*/
if(DMA_GetITStatus(DMA1_IT_TC1) != RESET)
{
// AD_Count_flag++;
// if(AD_Count_flag==64)
flag_ADC = 1;
}
/*清除DMA中断标志位*/
DMA_ClearITPendingBit(DMA1_IT_TC1);
}
不用 DMA 可以使用 ADC 断续模式 例如选用 内部软件触发,一个序列 每触发一次 转换一个通道,检测EOC标志 就好了,读取出数据。手册上有的
使用 DMA很简单的 不复杂 使用 cube
一周热门 更多>