ARM技术论坛
登录
直播中
Warden
12年用户
13经验值
擅长:模拟技术
私信
关注
[问答]
关于STM32F030K6T6用DMA传输ADC采样值问题,请大神指导。
开启该帖子的消息推送
STM32
adc
最近在学
STM32
F0芯片,在网上看到一个网友用DMA传输ADC采样值,并用
ti
M15间隔触发ADC的思路,觉得不错想把他的代码移植一下,由于我用的是STM32F030K6T6,与网友的芯片不一样,网友做的是三路连续采样,而我的硬件
电路
采样点只有一个,就是采样外部锂电池电压,锂电池电压约4.1v,用两个10K电阻串联分压,PA3采样分压电压(,图片上是两个100K,由于ADC采样电流的问题后将100K调整成10K),于是准备将通道17(
Vref)
加进来,也就是用DMA传输2路,后串口打印
仿真
发现采样值不正确,看规格书发现这句代码配置
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward 的解释是:
向前扫描 ( 从 CHSEL0 到 CHSEL16) ,那这样可能采样不到通道17上面,将采样2路的想法放弃,于是又只单采样一路再打印值为97,为简单验证是否正确,用芯片供电电压3.3V加到采样通道PA3上,打印值为255,这样肯定采样不对,因我配置的是12位采样(
DC_InitStructure.ADC_Resolution = ADC_Resolution_12b),理论值应该在4095左右,反复查询代码找不到问题,后来发现255这个参数好是配置8位采样的理论值,于是又将采样配置成8位,串口打印150,在PA3上加3.3v也是255,这样3.3V*150/255的结果是1.92V,至此排除误差,感觉ADC采样正确。
做这个实验我已经花了很多时间和精力,我不知道是不是
因为只有一个ADC通道还配置DMA传输的问题,如果多几个通道(0-16)可能不会这样,能成功配置成12位采样,能力有限,请大神们帮忙指导一下,谢谢!
代码如下:
//
u16 ADC_Array[SAMPLE_NUM];
//u16 sample0[10],sample1[10];
u16 adc1,adc2;
u8 ADC_Updata=0;//DMA传输完成标志
void Adc_Battery_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStruct;
/*配置DMA中断*/
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);//12M
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; //用PA3采样一个电压
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1);
DMA_DeInit(DMA1_Channel1);//channel1
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC ;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable ;//
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&adc1;
DMA_InitStructure.DMA_MemoryDataSize =
DMA_MemoryDataSize_HalfWord;
DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc= DMA_MemoryInc_Disable ;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular ;
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)(ADC1_BASE+0x40);//(uint32_t)(&ADC1->DR);//网友配置 的 是(uint32_t)ADC1_DR_Address,因为MDK没有这个定义,我修改了下,不知道是否正确,看有数据出来,猜想应该没问题。
DMA_InitStructure.DMA_PeripheralDataSize= DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable ;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
ADC_DeInit(ADC1);
ADC_StructInit(&ADC_InitStructure);
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;// 关闭连续模式,用定时器触发采样
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_Rising;//上升沿触发 ;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_8b ;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConv_T3_TRGO; //网友配置的是TIM15,我的芯片没有TIM15,用TIM3替代
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward ; //
向前扫描 ( 从 CHSEL0 到 CHSEL16)
ADC_JitterCmd(ADC1, ADC_JitterOff_PCLKDiv4, ENABLE);//12M滤波采样
ADC_OverrunModeCmd(ADC1, ENABLE);
ADC_ChannelConfig(ADC1, ADC_Channel_3, ADC_SampleTime_55_5Cycles);
ADC_Init(ADC1,&ADC_InitStructure);
// ADC_VrefintCmd(ENABLE);
ADC_GetCalibrationFactor(ADC1);
// ADC_ContinuousModeCmd(ADC1, ENABLE);
ADC_Cmd(ADC1,ENABLE);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY ) == RESET);
DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);
DMA_ClearFlag(DMA1_FLAG_TC1);
ADC_DMACmd(ADC1, ENABLE);
ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);
DMA_Cmd(DMA1_Channel1,ENABLE);
ADC_StartOfConversion(ADC1);
// while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)==RESET);
}
void Adc_TimerInit(void)
{
TIM_TimeBaseInitTypeDef timer_init_structure;
NVIC_InitTypeDef nvic_init_structure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 , ENABLE); //打开TIM3时钟
nvic_init_structure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
nvic_init_structure.NVIC_IRQChannelCmd = ENABLE; //
nvic_init_structure.NVIC_IRQChannelPriority = 2; //
NVIC_Init(&nvic_init_structure);
TIM_DeInit(TIM3); //
TIM_TimeBaseStructInit(&timer_init_structure); //
timer_init_structure.TIM_ClockDivision = TIM_CKD_DIV1; //TIM3时钟48M
timer_init_structure.TIM_CounterMode = TIM_CounterMode_Up; //
timer_init_structure.TIM_Period = 999; //怕时间不够ADC采样,配置1S采样1次
timer_init_structure.TIM_Prescaler = 48000-1;
timer_init_structure.TIM_RepetitionCounter = 0x00;
TIM_TimeBaseInit(TIM3,&timer_init_structure);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //??TIM15??
TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update); //配置TIM3更新触发中断
TIM_Cmd(TIM3, ENABLE); //??TIM15
}
void TIM3_IRQHandler()
{
if(TIM_GetITStatus(TIM3, TIM_IT_Update)) //????update????
{
//加一LED指示TIM3是否有工作
if(GPIO_ReadOutputDataBit(LED_PORT, LED3_PIN)==RESET)
GPIO_SetBits(LED_PORT, LED3_PIN);
else
GPIO_ResetBits(LED_PORT, LED3_PIN);
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //
}
}
void DMA1_Channel1_IRQHandler()
{
/* u8 SampleIndex=0;
if(DMA_GetITStatus(DMA1_IT_TC1))
{
while(SampleIndex !=10)
{
sample0[SampleIndex] = ADC_Array[0+SampleIndex*2]&0x00000fff;
sample1[SampleIndex] =ADC_Array[1+SampleIndex*2]&0x00000fff;
SampleIndex++;
}
ADC_Updata=1;
}
DMA_ClearFlag(DMA1_FLAG_TC1);*/
if(DMA_GetITStatus(DMA1_IT_TC1))
{
ADC_Updata=1;
}
DMA_ClearFlag(DMA1_FLAG_TC1);
}
主程序
int main(void)
{
u16 Adc_Value;
RCC_ClocksTypeDef RCC_CLOCK;
SystemInit();//用的内部时钟,配置最大时钟48MHZ
Delay_Init(); //systicK时钟配置
ALL_Config();
RCC_MCOConfig(RCC_MCOSource_HSI);
RCC_GetClocksFreq(&RCC_CLOCK);
while(1)
{
if(ADC_Updata==1)
{
ADC_Updata=0;
// Adc_Value = ADC_Get_Average(sample0);
printf("ADC_Valeue:%dn",adc1);
printf("ADC_Voltage:%fn",3.3*adc1/255);
// printf("ADC_Valeue:%fn",3.3*Adc_Value/4095);
}
delay_ms(1000);
delay_ms(1000);
}
已退回
10
积分
回帖
(2)
hih
2021-11-19 14:26:05
dma多通道 采集的数据存储 一般是 建立个 二维数组 存储方式 是按顺序存储 类似{1, 2} {1, 2} {1, 2} 每个数组 第一个数据 才是 第一通道的数据
dma多通道 采集的数据存储 一般是 建立个 二维数组 存储方式 是按顺序存储 类似{1, 2} {1, 2} {1, 2} 每个数组 第一个数据 才是 第一通道的数据
举报
jinyi7016
2021-11-26 08:50:14
最好是用cubemx进行配置一下再试
最好是用cubemx进行配置一下再试
举报
更多回帖
rotate(-90deg);
回复
相关问答
STM32
adc
为什么要用XM1008
K6T6
芯片去替代
STM32F030K6T6
呢
2021-12-10
1587
MM32
F031K6T6
产品特性介绍
2021-01-01
1990
采用
STM32F030K6T6
作互补PWM输出时,互补通道没有波形输出是为什么?
2024-04-22
89
STM32G030C6T6
多
ADC
通道不工作是何原因呢
2022-12-23
319
如何在
stm32f030k6t6
运行时获得所有低脉冲宽度呢
2022-12-08
151
STM32F030K6T6
作互补PWM输出时互补通道没有波形输出
2019-04-18
3469
stm32f030k6t6
串口1配置
2018-12-06
7372
请问
STM32F030R8T6
内部校准过的
值
Embedded internal reference voltage可用来做校准吗?
2018-10-17
3777
如何在MCSDK 5中选择特定的微控制器?
2018-10-09
1545
stm32f030c6t6
和
f031c6t6
有什么区别?
2023-09-25
316
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
首页
论坛版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分