完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
下面是配置代码 #if ADC_CONFIG_ENABLE #define ADC_CHANNEL_COUN 1 #define ADC_ADD_COUN 1 #define ADC_DATA_COUNTER 1 #define CHANNEL 4 #define ADC_DELAY_CALIB_ENABLE_CPU_CYCLES (LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES * 32) struct { vu32 DataTemp[ADC_CHANNEL_COUN]; vu16 DataCouter[ADC_CHANNEL_COUN]; vu16 Buffer[ADC_CHANNEL_COUN * ADC_ADD_COUN]; vu16 OutputData[ADC_CHANNEL_COUN]; vu32 Max[ADC_CHANNEL_COUN];//最大值 vu16 OUtputMax[ADC_CHANNEL_COUN];//最大值输出 vs16 TemperatureBuffer[CHANNEL]; vu16 VolumeBuffer[CHANNEL]; vu16 Flag; vu32 SwitchCounter; vu16 OutputTemperature[CHANNEL]; vu16 OutputVolume[CHANNEL]; vu16 OutputAcVoltage; } AdcData; void ADC_Config(void) { uint32_t wait_loop_index; LL_ADC_InitTypeDef ADC_InitStruct = {0}; LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0}; LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; /* Peripheral clock enable */ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC); LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB); /* DMA controller clock enable */ LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1); /* DMA interrupt init */ /* DMA1_Channel1_IRQn interrupt configuration */ /**ADC1 GPIO Configuration PA0 ------> ADC1_IN0 PA1 ------> ADC1_IN1 PA2 ------> ADC1_IN2 PA3 ------> ADC1_IN3 PA4 ------> ADC1_IN4 PA5 ------> ADC1_IN5 PA6 ------> ADC1_IN6 PA7 ------> ADC1_IN7 PB0 ------> ADC1_IN8 PB1 ------> ADC1_IN9 PB2 ------> ADC1_IN10 */ GPIO_InitStruct.Pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1 |LL_GPIO_PIN_2 | LL_GPIO_PIN_3 | LL_GPIO_PIN_4 | LL_GPIO_PIN_5| LL_GPIO_PIN_6 | LL_GPIO_PIN_7; GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1 |LL_GPIO_PIN_2 ; GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* ADC1 DMA Init */ /* ADC1 Init */ //LL_DMA_DeInit(DMA1,LL_DMA_CHANNEL_1); // DMA传输方向 外设->内存 LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY); // 通道优先级 低 LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_LOW); // DMA模式 循环 LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_NORMAL); // 外设地址递增模式 失能 LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT); // 内存地址递增模式 使能 LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT); // 外设半字 LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_HALFWORD); // 内存半字 LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_HALFWORD); //外设地址 LL_DMA_SetPeriphAddress(DMA1,LL_DMA_CHANNEL_1,(uint32_t)&ADC1->DR); // 内存地址 LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)&AdcData.Buffer[0]); // DMA传输数据长度 LL_DMA_SetDataLength(DMA1,LL_DMA_CHANNEL_1,ADC_ADD_COUN*ADC_CHANNEL_COUN); LL_ADC_EnableInternalRegulator(ADC1); LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_0 #if 0 |LL_ADC_CHANNEL_1 |LL_ADC_CHANNEL_2|LL_ADC_CHANNEL_3 |LL_ADC_CHANNEL_4|LL_ADC_CHANNEL_5 |LL_ADC_CHANNEL_6|LL_ADC_CHANNEL_7 |LL_ADC_CHANNEL_8|LL_ADC_CHANNEL_9 |LL_ADC_CHANNEL_10 #endif ); NVIC_SetPriority(DMA1_Channel1_IRQn, 0); NVIC_EnableIRQ(DMA1_Channel1_IRQn); LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);//使能DMA通道一完成中断 /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ ADC_InitStruct.Clock = LL_ADC_CLOCK_SYNC_PCLK_DIV4; //ADC时钟分频 ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B; // 采样分辨率 ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT; // 对齐方式 ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE; // 低功耗模式,使用DMA的话无法使用,这里关闭 LL_ADC_Init(ADC1, &ADC_InitStruct); #define ADC_CHANNEL_CONF_RDY_TIMEOUT_MS ( 1U) #define USE_TIMEOUT 1 #if (USE_TIMEOUT == 1) uint32_t Timeout ; /* Variable used for Timeout management */ #endif /* USE_TIMEOUT */ ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE; // 软件触发方式 //ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE; ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE; ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS; // 规则通道连续转换 // 使能DMA,并使用无限传输,如果DMA保存方式为循环覆盖的话才可以使用无限传输 ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_LIMITED; ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED; // 采集的数据循环覆盖模式 LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct); LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_DISABLE); // 失能过采样 LL_ADC_SetTriggerFrequencyMode(ADC1, LL_ADC_CLOCK_FREQ_MODE_HIGH); // 采样时钟使用高频模式 //adc通道和硬件adc in是否强制对应,因为adc的io使用时是连续的,所以这里使用非完全配置 LL_ADC_REG_SetSequencerConfigurable(ADC1, LL_ADC_REG_SEQ_FIXED); // 设置通道共用取样时间,根据需要自行选择 LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_1, LL_ADC_SAMPLINGTIME_160CYCLES_5); LL_ADC_DisableIT_EOC(ADC1); // 禁用通道采样结束中断 LL_ADC_DisableIT_EOS(ADC1); // 禁用序列采样结束中断 LL_ADC_REG_SetSequencerScanDirection(ADC1, LL_ADC_REG_SEQ_SCAN_DIR_FORWARD); //扫描方向为通道数字从小到大 /* Poll for ADC channel configuration ready */ #if (USE_TIMEOUT == 1) Timeout = ADC_CHANNEL_CONF_RDY_TIMEOUT_MS; #endif /* USE_TIMEOUT */ while (LL_ADC_IsActiveFlag_CCRDY(ADC1) == 0) { #if (USE_TIMEOUT == 1) /* Check Systick counter flag to decrement the time-out value */ if(Timeout-- == 0) { //Error_Handler(); break; } #endif /* USE_TIMEOUT */ } /* Clear flag ADC channel configuration ready */ LL_ADC_ClearFlag_CCRDY(ADC1); wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10); while(wait_loop_index != 0) { wait_loop_index--; } //DMA通道请求 LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_1, LL_DMAMUX_REQ_ADC1); LL_ADC_StartCalibration(ADC1); while(LL_ADC_IsCalibrationOnGoing(ADC1)); wait_loop_index = (ADC_DELAY_CALIB_ENABLE_CPU_CYCLES >> 1); while(wait_loop_index != 0) { wait_loop_index--; }//等待校准 //启动ADC LL_ADC_Enable(ADC1); LL_ADC_REG_StartConversion(ADC1); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); //使能 } void ADC_GetValue(void) { u32 temp = 0; u16 tempMax = 0; u8 i = 0; u8 ChannelTemp=0; for(ChannelTemp=0;ChannelTemp { temp = 0; tempMax = 0; for(i = 0; i { temp += AdcData.Buffer[i*ADC_CHANNEL_COUN+ChannelTemp]; if(tempMax < AdcData.Buffer[i*ADC_CHANNEL_COUN+ChannelTemp]) {tempMax = AdcData.Buffer[i*ADC_CHANNEL_COUN+ChannelTemp];} } temp = temp/ADC_ADD_COUN; if(temp>60000){temp=60000;} AdcData.DataTemp[ChannelTemp]+=temp; AdcData.Max[ChannelTemp] += tempMax; AdcData.DataCouter[ChannelTemp]++; if(AdcData.DataCouter[ChannelTemp]>=ADC_DATA_COUNTER) { AdcData.OutputData[ChannelTemp]=(u16)(AdcData.DataTemp[ChannelTemp]/ADC_DATA_COUNTER); AdcData.OUtputMax[ChannelTemp] = (u16)(AdcData.Max[ChannelTemp] / ADC_DATA_COUNTER); AdcData.Max[ChannelTemp] = 0; AdcData.DataTemp[ChannelTemp]=0; AdcData.DataCouter[ChannelTemp]=0; } } } void DMA1_Channel1_IRQHandler(void) { if(LL_DMA_IsActiveFlag_TC1(DMA1)) { LL_DMA_ClearFlag_TC1(DMA1); LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1); LL_ADC_Disable(ADC1); ADC_GetValue(); // DMA传输数据长度 LL_DMA_SetDataLength(DMA1,LL_DMA_CHANNEL_1,ADC_ADD_COUN*ADC_CHANNEL_COUN); //启动ADC LL_ADC_Enable(ADC1); LL_ADC_REG_StartConversion(ADC1); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);// } } #endif 主程序输出串口查看数据 USART1_SendData((u8*)&ADC1->DR,2);USART1_SendData((u8*)AdcData.Buffer[0],2); 数据情况 两个1k电阻分压3.3v输入,ad结果截图,DMA 一直不正确 [10:21:57.059]收←◆0B 08 68 EB [10:21:58.058]收←◆0B 08 68 EB [10:21:59.058]收←◆0A 08 A9 68 [10:22:00.058]收←◆0B 08 68 EB [10:22:01.058]收←◆0B 08 68 EB 前两个为寄存器DR输出 的值,0x080b转为电压大概1.66v是正确数值,DMA一直不正确,求大佬帮忙看看 |
|
相关推荐
1个回答
|
|
看看有没有大神来解答一下
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
自定义系统时钟频率后,用库函数和微带两种方式点亮LED灯,为什么灯的闪烁频率不一致?
703 浏览 2 评论
886 浏览 1 评论
1628 浏览 0 评论
【嵌入式SD NAND】基于FATFS/Littlefs文件系统的日志框架实现
649 浏览 0 评论
求助!STM32F4单片机编程与设计sEMG信号采集电路问题
866 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-3-28 16:43 , Processed in 0.586495 second(s), Total 69, Slave 52 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 深圳华秋电子有限公司
电子发烧友 (电路图) 粤公网安备 44030402000349 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号