最近正在学习STM32相关内容,了解了STM32的ADC,DAC,DMA,TIM等原理及配置后,DAC输出、ADC采集的例子。
ADC配置
ADC_GPIO配置
static void ADCx_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_GPIO_APBxClock_FUN (ADC_GPIO_CLK, ENABLE );// 打开 ADC IO端口时钟
GPIO_InitStructure.GPIO_Pin = ADC_PIN;// 配置 ADC IO 引脚模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(ADC_PORT, &GPIO_InitStructure); // 初始化 ADC IO
}
ADC_TIM配置
static void ADx_TIM_Config(uint16_t arr, uint16_t psc){
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(ADCx_TIM_CLK, ENABLE); //TIM3时钟使能
//定时器TIM3初始化,简单进行定时器初始化,设置预装载值和分频系数
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_SelectOutputTrigger(ADCx_TIM,TIM_TRGOSource_Update);//TIM做触发
TIM_ITConfig(ADCx_TIM,TIM_IT_Update,ENABLE);
TIM_Cmd(ADCx_TIM, ENABLE); //使能TIMx
}
ADC_TIM_NVIC配置
static void ADCx_TIM_NVIC_Config(void){
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = ADCx_TIM_IRQ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStructure);
}
ADC配置
static void ADCx_Mode_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_APBxClock_FUN ( ADC_CLK, ENABLE );// 打开ADC时钟
ADC_DeInit(ADCx);// ADC 模式配置
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;// 只使用一个ADC,属于独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE ; // 禁止扫描模式,多通道才要,单通道不需要
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;// 连续转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;// 使用外部触发转换
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;// 转换结果右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; // 转换通道1个
ADC_Init(ADCx, &ADC_InitStructure);// 初始化ADC
RCC_ADCCLKConfig(RCC_PCLK2_Div8); // 配置ADC时钟为PCLK2的8分频,即9MHz
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1,
ADC_SampleTime_55Cycles5);// 配置 ADC 通道转换顺序和采样时间
ADC_ExternalTrigConvCmd(ADCx, ENABLE);
ADC_DMACmd(ADCx, ENABLE);// 使能ADC_DM请求
ADC_Cmd(ADCx, ENABLE);// 开启ADC,并开始转换
ADC_ResetCalibration(ADCx);// 初始化ADC 校准寄存器
while(ADC_GetResetCalibrationStatus(ADCx));// 等待校准寄存器初始化完成
ADC_StartCalibration(ADCx);// ADC开始校准
while(ADC_GetCalibrationStatus(ADCx));// 等待校准完成
}
ADC_DMA配置
static void ADCx_DMA_Config(void){
DMA_InitTypeDef MDA_InitStruct;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
DMA_DeInit(DMA1_Channel1);
MDA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)ADC1_BASIC_DR; //外设地址-------相当于配置源地址
MDA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue; //存储器地址-----相当于配置目标地址
MDA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; //传输方向 设置数据传输方向,决定是从外设读取数据到内存还送从内存读取数据发送到外设,
//也就是外设是源地还是目的地
MDA_InitStruct.DMA_BufferSize = 1; //传输数目
MDA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址增量模式
MDA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据宽度
MDA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Disable; //存储器地址增量模式
MDA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //存储器数据宽度
MDA_InitStruct.DMA_Mode = DMA_Mode_Circular; //模式选择
MDA_InitStruct.DMA_Priority = DMA_Priority_High; //通道优先级
MDA_InitStruct.DMA_M2M = DMA_M2M_Disable; //存储器到存储器模式
DMA_Init(DMA1_Channel1,&MDA_InitStruct);
}
ADC初始化函数
void ADCx_Init(uint16_t arr, uint16_t psc)
{
ADCx_GPIO_Config();
ADCx_TIM_NVIC_Config();
ADx_TIM_Config(arr,psc);
ADCx_DMA_Config();
ADCx_Mode_Config();
DMA_Cmd(DMA1_Channel1,ENABLE);
}
ADC配置完成后在ADC_TIM的中断函数中读取采集结果
void ADCx_TIM_IRQHandler(){
if(TIM_GetITStatus(ADCx_TIM,TIM_IT_Update) != RESET){
printf("%.2f\n",(float)ADC_GetConversionValue(ADCx)/4096*3.3);
}
TIM_ClearFlag(ADCx_TIM,TIM_IT_Update);
}
ADC配置完成后,配置DAC
static void DAC_Config(void){
DAC_InitTypeDef DAC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//开启DAC总线时钟
DAC_APBxClock_FUN(DAC_CLK, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//
GPIO_InitStructure.GPIO_Pin = DAC_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DAC_PORT, &GPIO_InitStructure);
DAC_InitStructure.DAC_Trigger = DAC_TRIGGER_TIMx;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
DAC_Init(DAC_CHANNEL, &DAC_InitStructure);
DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值
DAC_Cmd(DAC_CHANNEL, ENABLE);
}
DAC_TIM配置
static void DAC_TIMx_Config(uint16_t arr, uint16_t psc){
TIM_TimeBaseInitTypeDef TIM_BASE_InitStructure;
BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK,ENABLE);
TIM_BASE_InitStructure.TIM_Period = arr;//自动重装寄存器的值,累计TIM_Period+1后产生中断或更新事件
TIM_BASE_InitStructure.TIM_Prescaler = psc;//时钟预分频数
TIM_TimeBaseInit(BASIC_TIM,&TIM_BASE_InitStructure);
TIM_ClearFlag(BASIC_TIM,TIM_FLAG_Update);
TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);
TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);/* 配置 TIM6 触发源 */
TIM_Cmd(BASIC_TIM,ENABLE);
}
DAC_TIM_NVIC配置
static void NVIC_Configuration(void){
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = BASIC_TIM_IRQ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStructure);
}
DAC初始化函数
void DAC_Mode_Init(uint16_t arr, uint16_t psc)
{
NVIC_Configuration();
DAC_TIMx_Config(arr,psc);
DAC_Config();
}
DAC_TIM中断处理函数
void BASIC_TIM_IRQHandler(void){
if(TIM_GetITStatus(BASIC_TIM,TIM_IT_Update) != RESET){
adc_temp += 0.2;
if(adc_temp >= 3.3)adc_temp = 0;
DAC_SetChannel1Data(DAC_Align_12b_R,adc_temp*4096/3.3);//12位右对齐数据格式设置DAC值
//printf("%d\n",DAC_GetDataOutputValue(DAC_Channel_1));
}
TIM_ClearFlag(BASIC_TIM,TIM_IT_Update);
}