ADC1多通道_DMA_内部温度传感器+内部VREFINT
实现目标:
使用ADC1的16和17通道(对应内部温度传感器和内部VREFINT),DMA通道1(Only)管理,存储到内存并串口输出。
Ready
- 时钟:
- ADC:RCC_APB2Periph_ADC1,RCC_ADCCLKConfig(RCC_PCLK2_Div6);
- DMA:RCC_AHBPeriph_DMA1
- NVIC:DMA1_Channel1_IRQn //传输完成中断DMA_IT_TC
- DMA:
- 起点/终点地址
- 数据数量/单位
- 传输方向
- 地址是否自动加
- 单次/连续模式
- 是否M2M
- 中断:DMA_IT_TC
- ADC:
- ADC间合作方式:ADC_Mode = ADC_Mode_Independent
- 单次/连续
- 是否开启扫描模式
- 触发方式:ADC_ExternalTrigConv_None;//软件触发
- 数据对齐
- 通道数
逐个配置通道:ADC_RegularChannelConfig(ADC1, 16, 1, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, 17, 2, ADC_SampleTime_239Cycles5 );- 打开DMA信号:ADC_DMACmd(ADC1,ENABLE);
- Sensor:ADC_TempSensorVrefintCmd(ENABLE);//打开内部温度和电压传感器的DMA连接
Go
#include "delay.h"#include "sys.h" #include "usart.h" #include "timer.h" u16 data[2]; void NVIC_ADC1_DMA1_Init() { DMA_InitTypeDef DMA_InitStructure; ADC_InitTypeDef ADC_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel=DMA1_Channel1_IRQn ; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStructure); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//DMA时钟 RCC_ADCCLKConfig(RCC_PCLK2_Div6); ADC_DeInit(ADC1); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//规则组和注入组独立 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_InitStructure.ADC_NbrOfChannel = 2; ADC_Init(ADC1, &ADC_InitStructure); ADC_TempSensorVrefintCmd(ENABLE);//打开内部温度和电压传感器的DMA连接 ADC_RegularChannelConfig(ADC1, 16, 1, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig(ADC1, 17, 2, ADC_SampleTime_239Cycles5 ); ADC_DMACmd(ADC1,ENABLE); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); //重置指定的ADC1的复位寄存器 while(ADC_GetResetCalibrationStatus(ADC1)); //获取ADC1重置校准寄存器的状态,设置状态则等待 ADC_StartCalibration(ADC1); // while(ADC_GetCalibrationStatus(ADC1)); //获取指定ADC1的校准程序,设置状态则等待 DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & (ADC1->DR); //外设寄存器基地址 DMA_InitStructure.DMA_MemoryBaseAddr =(u32)data; //RAM基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //传输方向 DMA_InitStructure.DMA_BufferSize = 2;//Size DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设的地址是否自动增加 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //RAM的地址是否自动增加 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize =DMA_MemoryDataSize_HalfWord; //传输单位 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA_Mode_Normal; //是否不断传输 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //优先组 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //是不是RAM2RAM DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE ); //DMA中断(别忘了NVIC) DMA_Cmd(DMA1_Channel1,ENABLE);//开启DMA } int main(void) { NVIC_ADC1_DMA1_Init(); uart_init(9600); delay_init(); printf("START\n"); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(1); } void DMA1_Channel1_IRQHandler() { if(DMA_GetITStatus(DMA_IT_TC)==SET) { double tp=(1.43-data[0]*(3.3/4096))/0.0043+25; printf("TEMORI:%x\tTEM:%f\tVOT:%x\n",data[0],tp,data[1]); DMA_ClearITPendingBit(DMA_IT_TC); } }
坑
- DMA数据单位:
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize =DMA_MemoryDataSize_HalfWord;