本帖最后由 RISCVLAR 于 2020-12-24 19:01 编辑
CH32V103应用教程——ADC-注入通道管理(触发注入)
本章主要在第三十二章以及第三十四章基础上进行ADC注入通道管理(触发注入)。
1、ADC简介及相关函数介绍 关于ADC触发注入:IAUTO位为 0,当在扫描规则组通道过程中,发生了注入组通道转换的触发事件,当前转换被复位,注入通道的序列被以单次扫描方式进行,在所有选中的注入组通道扫描转换结束后,恢复上次被中断的规则组通道转换。
如果当前在扫描注入组通道序列时,发生了规则通道的启动事件,注入组转换不会被中断,而是在注入序列转换完成后再执行规则序列的转换。
注意:使用触发注入转换时,必须保证触发事件的间隔长于注入序列。例如,完成注入序列的转换总体时间需要28个ADCCLK,那么触发注入通道的事件间隔时间最小值为 29个ADCCLK。
关于ADC具体信息,可参考CH32V103应用手册。关于ADC库函数,在第十章节已进行过介绍,在此不再赘述。
2、硬件设计 本章教程主要采用触发注入方式进行注入通道管理,需要用到ADC1通道1(PA1)和ADC1通道2(PA2)分别作为规则通道和注入通道以及EXTI线15(即PA15)作为触发端,同时将PA1引脚和PA2引脚与3.3V引脚和GND引脚连接进行ADC值读取输出。
3、软件设计 本章主要进行ADC注入通道管理(触发注入)实验,本章教程在第三十二章以及第三十四章基础上进行,相关内容可参考前面章节。ADC注入通道管理(触发注入)应用程序具体如下: adc.h文件 #ifndef __ADC_H
#define __ADC_H
#include "ch32v10x_conf.h"
void ADC_Function_Init(void);
void EXTI_Event_Init(void);
#endif
adc.h文件主要进行相关函数的声明; adc.c文件 #include "adc.h"
void ADC1_2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
/*******************************************************************************
* Function Name : ADC_Function_Init
* Description : Initializes ADC collection.
* Input : None
* Return : None
*******************************************************************************/
void ADC_Function_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
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 = 1;
ADC_Init(ADC1, &ADC_InitStructure);
//规则通道组
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5 ); //为所选ADC规则通道配置其转换顺序及其采样时间。
//注入通道组相关配置
//ADC_InjectedDiscModeCmd(ADC1,DISABLE); //启用ADC1注入通道连续模式
ADC_InjectedSequencerLengthConfig(ADC1, 1); //配置注入通道序列长度
ADC_InjectedChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_239Cycles5); //为所选ADC注入通道配置其转换顺序及其采样时间。
ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_Ext_IT15_TIM8_CC4); //设置注入通道外部触发,此处选择EXTI线15触发
ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE); //设置通过外部触发启用注入通道转换
//ADC_AutoInjectedConvCmd(ADC1, DISABLE); //关闭注入通道组在规则转换完成之后进行自动转换
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
ADC_ITConfig( ADC1, ADC_IT_JEOC, ENABLE);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
/*******************************************************************************
* Function Name : EXTI_Event_Init
* Description : Initializes EXTI.
* Input : None
* Return : None
*******************************************************************************/
void EXTI_Event_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE );
GPIO_EXTILineConfig( GPIO_PortSourceGPIOA, GPIO_PinSource15 );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //下拉输入模式
GPIO_Init(GPIOA, &GPIO_InitStructure);
EXTI_InitStructure.EXTI_Line = EXTI_Line15;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
/*******************************************************************************
* Function Name : ADC1_2_IRQHandler
* Description : This function handles analog watchdog exception.
* Input : None
* Return : None
*******************************************************************************/
void ADC1_2_IRQHandler()
{
u16 jadc;
if(ADC_GetITStatus( ADC1, ADC_IT_JEOC))
{
printf("ADC外部触发注入转换\r\n");
jadc = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1);
printf( "jadc=%d\r\n", jadc );
}
ADC_ClearITPendingBit( ADC1, ADC_IT_JEOC);
}
adc.c文件主要进行ADC初始化配置以及规则通道和注入通道配置,与第三十二章以及第三十四章相比,主要进行以下改动: 开启ADC扫描模式以及连续转换模式: ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
对注入通道组进行相关配置,配置注入通道序列长度,配置注入通道转换顺序及采样时间,启用外部触发触发注入通道转换,具体如下: ADC_InjectedSequencerLengthConfig(ADC1, 1); //配置注入通道序列长度
ADC_InjectedChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_239Cycles5); //为所选ADC注入通道配置其转换顺序及其采样时间。
ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_Ext_IT15_TIM8_CC4); //设置注入通道外部触发,此处选择EXTI线15触发
ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE); //设置通过外部触发启用注入通道转换
开启ADC注入转换中断: ADC_ITConfig( ADC1, ADC_IT_JEOC, ENABLE);
在中断服务函数中,读取并打印输出注入通道ADC值: void ADC1_2_IRQHandler()
{
u16 jadc;
if(ADC_GetITStatus( ADC1, ADC_IT_JEOC))
{
printf("ADC外部触发注入转换\r\n");
jadc = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1);
printf( "jadc=%d\r\n", jadc );
}
ADC_ClearITPendingBit( ADC1, ADC_IT_JEOC);
}
main.c文件 int main(void)
{
u16 adc;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n",SystemCoreClock);
printf("This is ADC example\r\n");
ADC_Function_Init();
EXTI_Event_Init();
while(1)
{
while( !ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) );
adc = ADC_GetConversionValue(ADC1);
Delay_Ms(500);
printf( "adc=%d\r\n", adc );
Delay_Ms(2);
}
}
main.c文件主要进行函数初始化以及规则通道ADC值打印输出。
4、下载验证 将编译好的程序下载到开发板并复位,同时将PA1引脚和PA2引脚与开发板3.3V引脚或GND引脚连接起来,将PA15与3.3V引脚连接时,触发注入转换,串口显示如下:
|