普冉单片机MCU PY32 ADC多通道切换的使用方法

下面是PY32F030/003/002A/PY32C61xx 各ADC通道切换并采集的程序!

首先我们先看看采集函数怎么写,这里直接使用寄存器操作:

uint16_t GetAdc12Bit(uint32_t channel)
{  
	ADC1->CR |= (1<<4);// 停止 ADC
	
	ADC1->CHSELR =(1<<channel);//选择通道
 
	ADC1->CR |= (1<<0);//使能 ADC
	
	ADC1->CR |= (1<<2);//启动 ADC, 同HAL_ADC_Start();
	
	while(!(ADC1->ISR & ADC_ISR_EOC));//等待转换完成,同HAL_ADC_PollForConversion();
	
	return ADC1 -> DR;//返回采样值,同HAL_ADC_GetValue();
}

随后看看ADC的初始化函数,通道我们是不需要配置的,因为上面那个函数可以选:

void ADC_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};
  /* 先复位ADC值 */
  __HAL_RCC_ADC_FORCE_RESET();
  __HAL_RCC_ADC_RELEASE_RESET();

  /*ADC校准*/
  hadc.Instance = ADC1;
  hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_HSI_DIV2;              //设置ADC时钟
  if (HAL_ADC_Init(&hadc) != HAL_OK)
  {
    Error_Handler();
  }

  if (HAL_ADCEx_Calibration_Start(&hadc) != HAL_OK)                  //AD校准
  {
    Error_Handler();
  }

  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc.Instance = ADC1;
  hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;              //ADC_CLOCK_SYNC_PCLK_DIV2;  ADC_CLOCK_SYNC_PCLK_DIV4
  hadc.Init.Resolution = ADC_RESOLUTION_12B;                        //设置ADC采样位数
  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;                        //右对齐
  hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;              //扫描方向设置
  hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;                      //ADC_EOC_SINGLE_CONV:单次采样 ; ADC_EOC_SEQ_CONV:序列采样
  hadc.Init.LowPowerAutoWait = ENABLE;                              //ENABLE=读取ADC值后,开始下一次转换 ; DISABLE=直接转换
  hadc.Init.ContinuousConvMode = DISABLE;                            //ENABLE=连续模式, DISABLE=单次模式
  hadc.Init.DiscontinuousConvMode = DISABLE;                        //非连续转换模式设置
  hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;                  //触发模式设置
  hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;   //外部触发沿设置
  hadc.Init.DMAContinuousRequests = DISABLE;                        //DMA连续模式设置
  hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;                     //ADC_OVR_DATA_OVERWRITTEN=过载时覆盖,ADC_OVR_DATA_PRESERVED=保留旧值
  hadc.Init.SamplingTimeCommon=ADC_SAMPLETIME_13CYCLES_5;           //设置采样周期

  if (HAL_ADC_Init(&hadc) != HAL_OK)                                //初始化ADC
  {
    Error_Handler();
  }

}

msp.c文件中补充IO初始化函数:

void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  //=============
  //PA0/1/2初始化
  //=============
  if (hadc->Instance == ADC1)
  {
    /* Peripheral clock enable */
    __HAL_RCC_ADC_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**ADC GPIO Configuration
    PA0     ------> ADC_IN0
    PA1     ------> ADC_IN1
    PA4     ------> ADC_IN5
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }
}

然后看看就是main.c函数怎么写,初始化ADC后,只需要传入需要转换的通道就可以了:

uint16_t adc_value[3];

int main(void)
{
  HAL_Init();                                   //初始化systick
  SystemClock_Config();                         //时钟初始化
  ADC_Init();                                   //ADC初始化
  DEBUG_USART_Config();                         //UART初始化
  
  while (1)
  {
		adc_value[0] = GetAdc12Bit(ADC_CHANNEL_0);
		adc_value[1] = GetAdc12Bit(ADC_CHANNEL_1);
		adc_value[2] = GetAdc12Bit(ADC_CHANNEL_4);
  }
}

-----------------------------------------------------------分割线-------------------------------------------------------------

类似的,下面是PY32002B/PY32C64xx 各ADC通道切换并采集的程序!

uint16_t adc_buf[4];

uint16_t GetADCValue(uint32_t ADC_Channel)
{
	LL_ADC_Disable(ADC1);
	/* 设定ADC的采样通道*/
	LL_ADC_REG_SetSequencerChannels(ADC1, ADC_Channel);
	/* ADC使能*/
	APP_AdcEnable();
	
	/* ADC 开始转换 */
	LL_ADC_REG_StartConversion(ADC1);

	while(LL_ADC_IsActiveFlag_EOC(ADC1) != 1);

	return LL_ADC_REG_ReadConversionData12(ADC1);
}

static void APP_AdcConfig(void)
{
	__IO uint32_t wait_loop_index = 0;
  LL_ADC_InitTypeDef ADC_Init;
  LL_ADC_REG_InitTypeDef LL_ADC_REG_InitType;

  /* Enable ADC clock */
  LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_ADC1);

  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);

  /* Configure PA7 pin in analog input mode */
  LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_7, LL_GPIO_MODE_ANALOG);
  LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_1, LL_GPIO_MODE_ANALOG);
	
  /* Initialize partical features of ADC instance */
  ADC_Init.Clock=LL_ADC_CLOCK_SYNC_PCLK_DIV4;
  ADC_Init.DataAlignment=LL_ADC_DATA_ALIGN_RIGHT;
  ADC_Init.LowPowerMode=LL_ADC_LP_MODE_NONE;
  ADC_Init.Resolution=LL_ADC_RESOLUTION_12B;
  LL_ADC_Init(ADC1,&ADC_Init);
  /* Sampling time 239.5 ADC clock cycles */
  LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_41CYCLES_5);

  /* Initialize partical features of ADC instance */
  LL_ADC_REG_InitType.ContinuousMode=LL_ADC_REG_CONV_SINGLE;
  LL_ADC_REG_InitType.Overrun=LL_ADC_REG_OVR_DATA_OVERWRITTEN;
  LL_ADC_REG_InitType.SequencerDiscont=LL_ADC_REG_SEQ_DISCONT_DISABLE;
  LL_ADC_REG_InitType.TriggerSource=LL_ADC_REG_TRIG_SOFTWARE;
  LL_ADC_REG_Init(ADC1,&LL_ADC_REG_InitType);

	LL_ADC_REG_SetSequencerChannels(ADC1, LL_ADC_CHANNEL_0|LL_ADC_CHANNEL_4|LL_ADC_CHANNEL_VREFINT|LL_ADC_CHANNEL_TEMPSENSOR);//
  /* Enable internal conversion channel */
  LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1),LL_ADC_PATH_INTERNAL_VREFINT|LL_ADC_PATH_INTERNAL_TEMPSENSOR); 
	
//  /* Set vrefbuffer voltage to 1.5V */
//  LL_ADC_SetVrefBufferVoltage(ADC1,LL_ADC_VREFBUF_1P5V);

//  /* Enable Vrefbuffer output */
//  LL_ADC_EnableVrefBufferVoltage(ADC1);

  /* Delay for VREFINT stabilization time */
  wait_loop_index = ((LL_ADC_DELAY_VREFINT_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
  while(wait_loop_index != 0)
  {
    wait_loop_index--;
  }
}

int main(void)
{
  /* Enable SYSCFG clock and PWR clock */
  LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG);
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);

  /* Configure Systemclock */
  APP_SystemClockConfig();

  /* Initialize USART(for printf use) */
  BSP_USART_Config();

  /* Enable ADC1 clock */
  LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_ADC1);

  /* Configure ADC parameters */
  APP_AdcConfig();

  /*  ADC automatic self-calibration */
  APP_AdcCalibrate();

//  AD_1V5 = HW32_REG(0x1FFF002C);

	APP_AdcEnable();
	
	printf("ok\r\n");
	
  while (1)
  {
#if 1 //全通道配置
		LL_ADC_REG_StartConversion(ADC1);//ADC 开始转换
		
		for(uint16_t i=0;i<4;i++)
		{
			while(LL_ADC_IsActiveFlag_EOC(ADC1) != 1);//等待转换完成
			adc_buf[i] = LL_ADC_REG_ReadConversionData12(ADC1);
		}
		
		printf("CH0 PB1:%d\r\n",adc_buf[0]);
		printf("CH4 PA7:%d\r\n",adc_buf[1]);
		printf("TEMPSENSOR:%d\r\n",__LL_ADC_CALC_TEMPERATURE(3300,adc_buf[2],LL_ADC_RESOLUTION_12B));
		printf("VRF:%d\r\n",1200*4095/adc_buf[3]);
		
#else	//单通道切换		
		printf("CH0 PB1:%d\r\n",GetADCValue(LL_ADC_CHANNEL_0));
		printf("CH4 PA7:%d\r\n",GetADCValue(LL_ADC_CHANNEL_4));
		printf("VRF:%d\r\n",1200*4095/GetADCValue(LL_ADC_CHANNEL_VREFINT));
		printf("TEMPSENSOR:%d\r\n",__LL_ADC_CALC_TEMPERATURE(3300,GetADCValue(LL_ADC_CHANNEL_TEMPSENSOR),LL_ADC_RESOLUTION_12B));
#endif		
		printf("\r\n");
		LL_mDelay(100);
  }
}

完结撒花✿✿ヽ(°▽°)ノ✿

>>>【点击进入,普冉PY32仿真烧录工具】icon-default.png?t=N7T8https://blog.csdn.net/weixin_65738402/article/details/139574735

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鲜衣怒马少年时'''

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值