临沂网站建设公司全国,中国化学工程第三建设有限公司,网站备案名可以更改吗,优秀专题网站航芯ACM32G103开发板评测 08 ADC Timer外设测试
1. 软硬件平台
ACM32G103 Board开发板MDK-ARM Keil
2. 定时器Timer
在一般的MCU芯片中#xff0c;定时器这个外设资源是非常重要的#xff0c;一般可以分为SysTick定时器#xff08;系统滴答定时器#xff09;、常规定时…航芯ACM32G103开发板评测 08 ADC Timer外设测试
1. 软硬件平台
ACM32G103 Board开发板MDK-ARM Keil
2. 定时器Timer
在一般的MCU芯片中定时器这个外设资源是非常重要的一般可以分为SysTick定时器系统滴答定时器、常规定时器基本定时器通用定时器高级定时器、专用定时器看门狗定时器RTC
在ACM32G103中有着丰富的定时器资源还包括低功耗定时器lptimer,具体资源如下
基础定时器最简单就只是普通的计数、定时功能。通用定时器在基础定时器的功能上增加了输入捕获和输出比较等功能。高级定时器在通用定时器的功能上造假了包含测量输入信号的脉冲宽度(输入捕获)或者产生输出波形(输出比较、PWM、嵌入死区时间的互补PWM的功能。 接下来进行基本的定时器定时功能测试。在官方给的SPL库里面只有两个例程感觉有点少与stm32相比较许多的库函数没有完善。原本打算使用HC-SR04超声波模块进行定时器测试但是发现有不少问题而且定时精度比较高就放弃了以后有时间再看看吧或者看看其他人的东西。
基本定时器包含一个16 位自动装载计数器由各自的可编程预分频器驱动。
//嵌套向量中断控制器配置
void NVIC_Configuration(void)
{NVIC_ClearPendingIRQ(TIM6_IRQn); NVIC_EnableIRQ(TIM6_IRQn);
}
//时钟配置使能
void Clock_Configuration(void)
{__RCC_TIM6_CLK_ENABLE();
} 定时器配置函数 定时器的定时时间主要取决于预分频系数和定时周期。重要的参数PrescalerPeriod 如果需要修改定时器定时时间只需要修改
TIM_TimeBaseStructure.Period (TIM_CLOCK_FREQ/1000)*500 - 1; // 500ms 修改为
TIM_TimeBaseStructure.Period (TIM_CLOCK_FREQ/1000)*1000 - 1; // 1000ms1s void TIM6_Init(void)
{uint32_t timer_clock; timer_clock RCC_GetPCLK1Freq(); if (RCC_GetHCLKFreq() ! timer_clock) // if hclk/pclk ! 1, then timer clk pclk * 2 {timer_clock timer_clock 1; }TIM_TimeBaseStructure.ClockDivision TIM_CLOCKDIVISION_DIV1; TIM_TimeBaseStructure.CounterMode TIM_COUNTERMODE_UP; TIM_TimeBaseStructure.RepetitionCounter 0; TIM_TimeBaseStructure.Prescaler (timer_clock/TIM_CLOCK_FREQ) - 1; TIM_TimeBaseStructure.Period (TIM_CLOCK_FREQ/1000)*500 - 1; // 500ms TIM_TimeBase_Init(TIM6, TIM_TimeBaseStructure); /* TIM IT enable */TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE); /* TIM6 enable counter */TIM_Cmd(TIM6, ENABLE);
}3.模数转换器ADC
1. ADC简介
将模拟信号连续信号转换为数字信号离散信号的器件就叫模数转换器ADC。 按原理可分为并行比较型A/D转换器(FLASH ADC)、逐次比较型A/D转换器(SAR ADC)和双积分式A/D转换器(Double Integral ADC)。 A/D转换过程通常为4步采样、保持、量化和编码。如图所示。
ADC的主要有三个性能指标分辨率、转换时间和转换精度。
1.1 分辨率
分辨率又称为转换精度指ADC能分辨的最小电压通常使用二进制有效位表示反应了ADC对输入模拟量微小变化的分辨能力。当最大输入电压一定时位数越多量化单位越小误差越小分辨率越高。比如一个12位的ADC参考电压为3.3V则其能分辨的最小电压为
1.2 转换时间
转换时间其倒数为转换速率指ADC从控制信号到来开始到输出端得到稳定的数字信号所经历的时间。转换时间通常与ADC类型有关双积分型ADC的转换时间一般为几十毫秒属于低速ADC逐次逼近型ADC的转换时间一般为几十微妙属于中速ADC并联比较型ADC的转换时间一般为几十纳秒属于高速ADC。
1.3 转换精度
转换精度指ADC输出的数字量所表示的模拟值与实际输入的模拟量之间的偏差通常为1个或半个最小数字量的模拟变化量表示为1LSB或1/2LSB。
2.ACM32G103 ADC资源
ACM32G103芯片有2个12位逐次逼近型ADC。ADC1与ADC2紧密耦合可在双重模式下运行ADC1 为主器件ADC2为从器件。
12 位分辨率可配置10 位、8 位或6 位分辨率转换速率最高可达3Msps20 个可用通道包括外部信号源和内部信号源
3. ADC初始化配置
首先需要定义需要使用的ADC 通道数量以及具体的ADC 通道号。确定需要使用到的工作模式独立模式、双ADC 模式、单端、差分或者是否支持DMA 等设置ADC CLK根据需求进行初始化配置。 ADC采集方式有下面四种轮询方式中断方式外部触发方式DMA 方式。 以DMA为案例进行处理。 ADC_DMA驱动函数
void ADC_DMA_Drive_Iint(void)
{ADC_GPIO_Config();//ADC_GPIO端口引脚初始化配置ADC_Common_Register_Config();//ADC通用寄存器配置ADC_Config();//ADC工作模式配置ADC_DMA_Config();//ADC_DMA请求配置ADC_RegularStart();//使能ADC开始常规通道的转换
}ADC_GPIO端口引脚初始化配置
void ADC_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStruct;__RCC_GPIOC_CLK_ENABLE();/* Configure ADC Channel_13 pin as analog input */GPIO_InitStruct.Pin GPIO_PIN_3;GPIO_InitStruct.Mode GPIO_MODE_ANALOG;GPIO_InitStruct.Pull GPIO_NOPULL;GPIO_Init(GPIOC, GPIO_InitStruct);
}ADC通用寄存器配置
void ADC_Common_Register_Config(void)
{ADC_CommonInitTypeDef ADC_CommonInitStructure;ADC_CommonInitStructure.ADC_Mode ADC_MODE_INDEPENDENT;//双ADC模式选择ADC_CommonInitStructure.ADC_Prescaler ADC_CLOCK_DIV4;//ADC_CLK分频选择ADC_CommonInitStructure.ADC_DMAAccessMode ADC_DMAACCESSMODE_DISABLED;//双ADC下DMA功能选择ADC_CommonInitStructure.ADC_TwoSamplingDelay ADC_TWOSAMPLINGDELAY_5CYCLES;//2个采样阶段之间的延迟ADC_CommonInit(ADC_CommonInitStructure);
}ADC工作模式配置
void ADC_Config(void)
{ADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_Resolution ADC_RESOLUTION_12B;//分辨率ADC_InitStructure.ADC_ContinuousConvMode ADC_CONT_DISABLE;//连续转换模式ADC_InitStructure.ADC_ExternalTrigConvEdge ADC_EXTERNALTRIGCONVEDGE_NONE;//外部触发边沿选择ADC_InitStructure.ADC_ExternalTrigConv ADC_EXTERNAL_TIG0;//触发模式ADC_InitStructure.ADC_DataAlign ADC_DATAALIGN_RIGHT;//数据对齐ADC_InitStructure.ADC_NbrOfConversion ADC_NUM;//规则通道序列长度 传输的数据长度为每个通道采集30次 * 1个通道ADC_Init(ADCX, ADC_InitStructure);//规则通道设置ADC_RegularChannelConfig(ADCX, ADC_CHANNEL_13, ADC_SEQUENCE_SQ1, ADC_SMP_CLOCK_320);
}ADC_DMA请求配置
void ADC_DMA_Config(void)
{__RCC_DMA1_CLK_ENABLE();DMA_BigEndianConfig(DMA1, DISABLE);DMA_DeInit(DMA1_Channel3);DMA_InitStruct.Mode DMA_MODE_CIRCULAR; DMA_InitStruct.DataFlow DMA_DATAFLOW_P2M;DMA_InitStruct.ReqID DMA1_REQ0_ADC1;DMA_InitStruct.RawInt DMA_RAWINT_ENABLE;DMA_InitStruct.SrcInc DMA_SRCINC_DISABLE;DMA_InitStruct.DestInc DMA_DESTINC_ENABLE;DMA_InitStruct.SrcWidth DMA_SRCWIDTH_WORD; DMA_InitStruct.DestWidth DMA_DESTWIDTH_WORD;DMA_InitStruct.SrcBurst DMA_SRCBURST_1;DMA_InitStruct.DestBurst DMA_DESTBURST_1;DMA_InitStruct.SrcAddr (uint32_t)ADC1-DR;DMA_InitStruct.DestAddr (uint32_t)gadcBuffer;DMA_InitStruct.Size 1; DMA_Init(DMA1_Channel3, DMA_InitStruct);// Enable interruptDMA_ClearFlag(DMA1_Channel3, DMA_FLAG_RTC);DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);// Enable NVIC IRQNVIC_ClearPendingIRQ(DMA1_IRQn);NVIC_SetPriority(DMA1_IRQn, 0x00);NVIC_EnableIRQ(DMA1_IRQn); DMA_Cmd(DMA1_Channel3, ENABLE);
}使能ADC开始常规通道的转换
void ADC_RegularStart(void)
{/* Enable ADC DMA mode */ADC_DMACmd(ADCX, ENABLE);/* Enable the ADC peripheral */ADC_Cmd(ADCX, ENABLE);/* Clear the SR register */ADC_ClearFlag(ADCX, ADC_IT_FLAG_ALL); /* Start conversion */ADC_SoftwareStartConv(ADCX);}中断服务函数
void DMA1_IRQHandler(void)
{ADC_DMA_ITC_Callback();
}
void ADC_DMA_ITC_Callback(void)
{ /* Transfer complete interrupt */if (SET DMA_GetFlagStatus(DMA1_Channel3, DMA_FLAG_TC)){gadc1ItcConunt 1;DMA_ClearFlag(DMA1_Channel3, DMA_FLAG_TC);}
}
4.测试
Timer测试函数
#define TIM_CLOCK_FREQ (10000) TIM_Base_InitTypeDef TIM_TimeBaseStructure; volatile uint32_t Timer_Update_Flag; void Clock_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void); void NVIC_Configuration(void)
{NVIC_ClearPendingIRQ(TIM6_IRQn); NVIC_EnableIRQ(TIM6_IRQn);
} void Clock_Configuration(void)
{__RCC_TIM6_CLK_ENABLE();
} void GPIO_Configuration(void)
{// do nothing here
}/************************************************************************* function : TIM6_Update_IRQ* Description: TIM6 user Interrupt Handler ************************************************************************/
void TIM6_Update_IRQ(void)
{if (TIM6-SR TIMER_SR_UIF) {Timer_Update_Flag 1; }}void TIM6_Init(void)
{uint32_t timer_clock; timer_clock RCC_GetPCLK1Freq(); if (RCC_GetHCLKFreq() ! timer_clock) // if hclk/pclk ! 1, then timer clk pclk * 2 {timer_clock timer_clock 1; }TIM_TimeBaseStructure.ClockDivision TIM_CLOCKDIVISION_DIV1; TIM_TimeBaseStructure.CounterMode TIM_COUNTERMODE_UP; TIM_TimeBaseStructure.RepetitionCounter 0; TIM_TimeBaseStructure.Prescaler (timer_clock/TIM_CLOCK_FREQ) - 1; TIM_TimeBaseStructure.Period (TIM_CLOCK_FREQ/1000)*500 - 1; // 500ms TIM_TimeBase_Init(TIM6, TIM_TimeBaseStructure); /* TIM IT enable */TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE); /* TIM6 enable counter */TIM_Cmd(TIM6, ENABLE);
}void Timer_Update_Test(void)
{/* Module Clocks Configuration */Clock_Configuration();/* NVIC Configuration */ NVIC_Configuration();Timer_Update_Flag 0; TIM6_Init(); while(1){if(Timer_Update_Flag) {printfS(Timer Update Occurs\n); Timer_Update_Flag 0; }}
}ADC_DMA测试函数
//采样通道数
#define ADC_NUM (1)uint32_t gadcBuffer[ADC_NUM];
static volatile uint32_t gadc1ItcConunt 0; #define ADCX (ADC1)DMA_InitTypeDef DMA_InitStruct;//需配置为全局变量不然DMA只会触发一次/******************************************************************************
* brief : DMA adc to memory transfer complete interrupt Callback.
* param : None
* return: None
******************************************************************************/
void ADC_DMA_ITC_Callback(void)
{ /* Transfer complete interrupt */if (SET DMA_GetFlagStatus(DMA1_Channel3, DMA_FLAG_TC)){gadc1ItcConunt 1;DMA_ClearFlag(DMA1_Channel3, DMA_FLAG_TC);}
}/******************************************************************************
* brief : ADC GPIO config.
* param : None
* return: None
******************************************************************************/
void ADC_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStruct;__RCC_GPIOC_CLK_ENABLE();/* Configure ADC Channel_13 pin as analog input */GPIO_InitStruct.Pin GPIO_PIN_3;GPIO_InitStruct.Mode GPIO_MODE_ANALOG;GPIO_InitStruct.Pull GPIO_NOPULL;GPIO_Init(GPIOC, GPIO_InitStruct);
}/******************************************************************************
* brief : ADC Common register config.
* param : None
* return: None
******************************************************************************/
void ADC_Common_Register_Config(void)
{ADC_CommonInitTypeDef ADC_CommonInitStructure;ADC_CommonInitStructure.ADC_Mode ADC_MODE_INDEPENDENT;//双ADC模式选择ADC_CommonInitStructure.ADC_Prescaler ADC_CLOCK_DIV4;//ADC_CLK分频选择ADC_CommonInitStructure.ADC_DMAAccessMode ADC_DMAACCESSMODE_DISABLED;//双ADC下DMA功能选择ADC_CommonInitStructure.ADC_TwoSamplingDelay ADC_TWOSAMPLINGDELAY_5CYCLES;//2个采样阶段之间的延迟ADC_CommonInit(ADC_CommonInitStructure);
}/******************************************************************************
* brief : ADC config.
* param : None
* return: None
******************************************************************************/
void ADC_Config(void)
{ADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_Resolution ADC_RESOLUTION_12B;//分辨率ADC_InitStructure.ADC_ContinuousConvMode ADC_CONT_DISABLE;//连续转换模式ADC_InitStructure.ADC_ExternalTrigConvEdge ADC_EXTERNALTRIGCONVEDGE_NONE;//外部触发边沿选择ADC_InitStructure.ADC_ExternalTrigConv ADC_EXTERNAL_TIG0;//触发模式ADC_InitStructure.ADC_DataAlign ADC_DATAALIGN_RIGHT;//数据对齐ADC_InitStructure.ADC_NbrOfConversion ADC_NUM;//规则通道序列长度 传输的数据长度为每个通道采集30次 * 1个通道ADC_Init(ADCX, ADC_InitStructure);//规则通道设置ADC_RegularChannelConfig(ADCX, ADC_CHANNEL_13, ADC_SEQUENCE_SQ1, ADC_SMP_CLOCK_320);
}/******************************************************************************
* brief : ADC DMA config.
* param : None
* return: None
******************************************************************************/
void ADC_DMA_Config(void)
{__RCC_DMA1_CLK_ENABLE();DMA_BigEndianConfig(DMA1, DISABLE);DMA_DeInit(DMA1_Channel3);DMA_InitStruct.Mode DMA_MODE_CIRCULAR; DMA_InitStruct.DataFlow DMA_DATAFLOW_P2M;DMA_InitStruct.ReqID DMA1_REQ0_ADC1;DMA_InitStruct.RawInt DMA_RAWINT_ENABLE;DMA_InitStruct.SrcInc DMA_SRCINC_DISABLE;DMA_InitStruct.DestInc DMA_DESTINC_ENABLE;DMA_InitStruct.SrcWidth DMA_SRCWIDTH_WORD; DMA_InitStruct.DestWidth DMA_DESTWIDTH_WORD;DMA_InitStruct.SrcBurst DMA_SRCBURST_1;DMA_InitStruct.DestBurst DMA_DESTBURST_1;DMA_InitStruct.SrcAddr (uint32_t)ADC1-DR;DMA_InitStruct.DestAddr (uint32_t)gadcBuffer;DMA_InitStruct.Size 1; DMA_Init(DMA1_Channel3, DMA_InitStruct);// Enable interruptDMA_ClearFlag(DMA1_Channel3, DMA_FLAG_RTC);DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);// Enable NVIC IRQNVIC_ClearPendingIRQ(DMA1_IRQn);NVIC_SetPriority(DMA1_IRQn, 0x00);NVIC_EnableIRQ(DMA1_IRQn); DMA_Cmd(DMA1_Channel3, ENABLE);
}/******************************************************************************
* brief: Enable ADC, start conversion of regular channle
* param: None
* return: None
******************************************************************************/
void ADC_RegularStart(void)
{/* Enable ADC DMA mode */ADC_DMACmd(ADCX, ENABLE);/* Enable the ADC peripheral */ADC_Cmd(ADCX, ENABLE);/* Clear the SR register */ADC_ClearFlag(ADCX, ADC_IT_FLAG_ALL); /* Start conversion */ADC_SoftwareStartConv(ADCX);}void ADC_DMA_Drive_Iint(void)
{ADC_GPIO_Config();ADC_Common_Register_Config();ADC_Config();ADC_DMA_Config();ADC_RegularStart();
}/******************************************************************************
* brief : ADC function test.
* param : None
* return: None
******************************************************************************/
void APP_ADC_Test(void)
{uint32_t i;float vol0.0;printfS(ADC DMA test \r\n);ADC_DMA_Drive_Iint();while(1){ADC_SoftwareStartConv(ADCX);while(!gadc1ItcConunt);gadc1ItcConunt 0;for (i 0; i ADC_NUM; i){// printfS(Channel_%d %d\r\n, ((gadcBuffer[i] 16) 0xFF), (gadcBuffer[i] 0xFFF));vol (gadcBuffer[i]0xFFF)*3.3/4095;printf(PA1 Voltage is: %0.1f V \r\n, vol);}DelayMs(1000);}
}测试结果