完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、前言
首先说明一下,我所指的“爬坑”并不是说STM32L151的时钟有问题哈,STM32L151的时钟肯定是没问题的,只是跟STM32F1或F4的时钟配置有些差别,我正是因为没有注意这些差别,以为L1跟F1的时钟应该是一样的,才有了这篇爬坑记, 自己挖坑自己跳自己填,相当的刺激!还是太年轻啊! 二、挖坑过程 我们在一个项目中使用了L151这个芯片,我是用CubeMAX配置生成的工程,其中有用到L151的ADC用来采集多通道的模拟量,采用的DMA方式。由于为了要低功耗嘛(用这个芯片就是为了低功耗),在时钟初始化中有一个内部的高速时钟(HSI)的配置,由于之前F1系列的单片机用得多一些,F1项目工程中HSI都没有用到过,我以为时钟应该都是一样的嘛,所以自己手动把HSI初始化给屏蔽了。贴上被我屏蔽的HSI配置,SystemClock_Config 是CUberMAX自动生成的 void SystemClock_Config(void) { .... LL_RCC_HSI_Enable(); /* Wait till HSI is ready */ while(LL_RCC_HSI_IsReady() != 1) { } LL_RCC_HSI_SetCalibTrimming(16); .... } 三、填坑记录 用CubeMAX配置了ADC_IN18用于循环采集该通道的模拟量,重点配置了: 1、DMA:外设地址和内存地址、模式为循环模式(ADC多通道必须)、数据长度。 2、ADC:数据对齐方式为12bit右对齐、开启低功耗模式、开始多通道扫描、开启通道转换为连续模式、失能间断模式、开始DMA传输、设置规则组的通道序列、采样时间。初始化内容如下(没有问题的): /* ADC init function */ void MX_ADC1_Init(void) { LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0}; LL_ADC_InitTypeDef ADC_InitStruct = {0}; LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; /* Peripheral clock enable */ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC1); LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB); /**ADC GPIO Configuration PB12 ------> ADC_IN18 */ GPIO_InitStruct.Pin = LL_GPIO_PIN_12; GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* ADC DMA Init */ /* ADC Init */ LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY); LL_DMA_SetPeriphAddress (DMA1, LL_DMA_CHANNEL_1,(uint32_t)(&ADC1->DR)); LL_DMA_SetMemoryAddress (DMA1, LL_DMA_CHANNEL_1,(uint32_t)(&stADCData.DMA[0])); LL_DMA_SetChannelPriorityLevel (DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_LOW); LL_DMA_SetMode (DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_CIRCULAR); 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_DisableChannel (DMA1, LL_DMA_CHANNEL_1); //这里的长度为 MemorySize类型的长度,比如MemorySize=Byte则为字节长度,MemorySize=HALFWORD则为半字长度 LL_DMA_SetDataLength (DMA1, LL_DMA_CHANNEL_1, ADC_CH_MAX); LL_DMA_EnableChannel (DMA1, LL_DMA_CHANNEL_1); /* ADC interrupt Init */ NVIC_SetPriority(ADC1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0)); NVIC_EnableIRQ(ADC1_IRQn); /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_ASYNC_DIV1; LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct); ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B; ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT; ADC_InitStruct.LowPowerMode = LL_ADC_LP_AUTOWAIT|LL_ADC_LP_AUTOPOWEROFF_IDLE_PHASE; ADC_InitStruct.SequencersScanMode = LL_ADC_SEQ_SCAN_ENABLE; LL_ADC_Init(ADC1, &ADC_InitStruct); 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; //LL_ADC_REG_CONV_SINGLE LL_ADC_REG_CONV_CONTINUOUS ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_UNLIMITED;//LL_ADC_REG_DMA_TRANSFER_UNLIMITED LL_ADC_REG_DMA_TRANSFER_NONE LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct); LL_ADC_REG_SetFlagEndOfConversion(ADC1, LL_ADC_REG_FLAG_EOC_SEQUENCE_CONV); LL_ADC_SetChannelsBank(ADC1, LL_ADC_CHANNELS_BANK_A); /** Configure Regular Channel */ LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_18); LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_18, LL_ADC_SAMPLINGTIME_384CYCLES); LL_ADC_Enable(ADC1); // LL_ADC_EnableIT_EOS(ADC1);//使能转换结束后产生中断 LL_ADC_REG_StartConversionSWStart(ADC1); } 按理在这一切配置完成后,ADC应该能采集了才对。but 不好使,我的第一反应就是纳尼??? what???这刚在F1的工程中配置过能使的啊?一脸懵逼。然后开始查硬件,发现引脚是有电压的;还是不行然后开始检查配置,各种对比啊把寄存器跟F103的都对了一遍,发现L151的ADC寄存器跟F103的ADC寄存器有的为是不一样的,但还是没有解决问题;正在开始怀疑人生的时候,突然想起了时钟(因为前两天刚被L151的GPIO时钟配置坑过一把,点灯点了一天,最后发现是时钟配置有问题),然后开始对比F103和L151的时钟树,果然问题就出现时钟上,先附上时钟对比图 问题原因: F103中ADC时钟来源:HSE ---> PLLCLK ---> HCLK ---> APB2 ---> ADC时钟 L151中ADC时钟来源:HSI ---> ADC时钟 F103中GPIO时钟来源:HSE ---> PLLCLK ---> HCLK ---> PCLK2 ---> APB2外设时钟 L151中GPIO时钟来源:HSE ---> PLLCLK ---> HCLK ---> PCLK1 ---> APB1外设时钟 所以在STM32L151中,必须使能初始化HSI时钟,不然ADC没法用!!! |
|
|
|
只有小组成员才能发言,加入小组>>
3309 浏览 9 评论
2988 浏览 16 评论
3490 浏览 1 评论
9050 浏览 16 评论
4084 浏览 18 评论
1169浏览 3评论
602浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
593浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2331浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1894浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-19 18:50 , Processed in 1.188224 second(s), Total 80, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号