完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
STM32F103RCT6内部含有3个ADC,其中ADC1具有DMA通道,通过DMA可以实现多个通道同时高速模拟信号采集,并快递存储,可应用于多传感器同时快速采集场景。
ADC初始化实现代码如下: void Adc_Init(void) { ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); //使能ADC1通道时钟 RCC_ADCCLKConfig(RCC_PCLK2_Div6); //72M/6=12M GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚 GPIO_Init(GPIOA, &GPIO_InitStructure); ADC_DeInit(ADC1); //将外设 ADC1 的全部寄存器重设为缺省值 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式 ADC_InitStructure.ADC_ScanConvMode = ENABLE; //模数转换工作在规则模式 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //模数转换工作在连续转换模式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐 ADC_InitStructure.ADC_NbrOfChannel = 9; //顺序进行规则转换的ADC通道的数目 ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADC1的寄存器 ADC_TempSensorVrefintCmd(ENABLE); //开启内部温度传感器 ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 6, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 7, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 8, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 9, ADC_SampleTime_239Cycles5 ); ADC_DMACmd(ADC1 , ENABLE); ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1 ADC_ResetCalibration(ADC1); //重置指定的ADC1的校准寄存器 while(ADC_GetResetCalibrationStatus(ADC1)); //获取ADC1重置校准寄存器的状态,设置状态则等待 ADC_StartCalibration(ADC1); //开始指定ADC1的校准状态 while(ADC_GetCalibrationStatus(ADC1)); //获取指定ADC1的校准程序,设置状态则等待 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 ADC_SoftwareStartConvCmd(ADC1, ENABLE); } DMA使用通道1,由ADC1传送到内存区,初始化代码及中断代码如下: void DMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr) { NVIC_InitTypeDef NVIC_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_InitStructure.NVIC_IRQChannel=DMA1_Channel1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStructure); DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值 DMA1_MEM_LEN=cndtr; DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外设基地址 DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA内存基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,从外设读取发送到内存 DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA缓存的大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //数据宽度为16位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环模式 DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //DMA通道 x拥有最高优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x禁用设置为内存到内存传输 DMA_Init(DMA_CHx, &DMA_InitStructure); DMA_Cmd(DMA_CHx , ENABLE); DMA_ITConfig(DMA_CHx, DMA_IT_TC, ENABLE); } void DMA1_Channel1_IRQHandler(void) { if(DMA_GetFlagStatus(DMA1_FLAG_TC1)==SET) { DMA_ClearFlag(DMA1_FLAG_TC1); flag_dma=1; } } 调用时需要在main函数中定义: int main(){ u16 adc_buf[1000]; extern u8 flag_dma; double temperate; u16 my_cnt; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); uart_init(115200); DMA_Config(DMA1_Channel1,(u32)&(ADC1->DR),(u32)adc_buf,9); Adc_Init(); while(1) { printf("rnDMA DATA:%dtt",i); if(flag_dma==1) { for(my_cnt=0;my_cnt<9;my_cnt++) { if(my_cnt==0) { temperate=((float)adc_buf[my_cnt])*(3.3/4096); //电压值 temperate=(1.43-temperate)/0.0043+25; //转换为温度值 printf("%.3ft",temperate); } else printf("%dt",adc_buf[my_cnt]); } flag_dma=0; } } } 最后,就可以将片上温度传感器和PA1-8的9个模拟量顺序显示出来,效果如下: |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1817 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1631 浏览 1 评论
1103 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
739 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1692 浏览 2 评论
1951浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
755浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
586浏览 3评论
605浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
568浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-30 16:51 , Processed in 0.878451 second(s), Total 76, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号