Jelajahi Sumber

添加adc驱动

Sen 7 bulan lalu
induk
melakukan
ba5a0225b5
3 mengubah file dengan 143 tambahan dan 11 penghapusan
  1. 136 7
      Src/user/emf_hal/hal_adc.c
  2. 4 4
      Src/user/emf_hal/hal_gpio.c
  3. 3 0
      Src/user/emf_hal/hal_gpio.h

+ 136 - 7
Src/user/emf_hal/hal_adc.c

@@ -14,8 +14,10 @@
 ************************************************************************************************************/
 #include "hw_config.h"
 #include "hw_board.h"
-#ifdef HW_ADC_MAP
+// #ifdef HW_ADC_MAP
+#if 1
 #include  "api/api_adc.h"
+#include "py32f002b_ll_adc.h"
 /******************************************************************************************************
 ** Defined
 *******************************************************************************************************/
@@ -31,10 +33,65 @@
 /*****************************************************************************************************
 **	static Function
 ******************************************************************************************************/
+uint16_t irq_adc[m_adc_num];                //全局变量, 防止adc采样失败数据出错
+uint8_t num = 0;
 
 /*****************************************************************************************************
 **  Function
 ******************************************************************************************************/
+/**
+  * @brief  ADC calibration program.
+  * @param  None
+  * @retval None
+  */
+static void APP_AdcCalibrate(void)
+{
+#if (USE_TIMEOUT == 1)
+  uint32_t Timeout = 0;
+#endif
+
+  if (LL_ADC_IsEnabled(ADC1) == 0)
+  {
+
+    /* Enable ADC calibration */
+    LL_ADC_StartCalibration(ADC1);
+
+#if (USE_TIMEOUT == 1)
+    Timeout = ADC_CALIBRATION_TIMEOUT_MS;
+#endif
+
+    while (LL_ADC_IsCalibrationOnGoing(ADC1) != 0)
+    {
+#if (USE_TIMEOUT == 1)
+      /* Detects if the calibration has timed out */
+      if (LL_SYSTICK_IsActiveCounterFlag())
+      {
+        if(Timeout-- == 0)
+        {
+
+        }
+      }
+#endif
+    }
+
+    /* The delay between the end of ADC calibration and ADC enablement is at least 4 ADC clocks */
+    LL_mDelay(1);
+  }
+}
+
+/**
+  * @brief  Enable ADC.
+  * @param  None
+  * @retval None
+  */
+static void APP_AdcEnable(void)
+{
+  /* Enable ADC */
+  LL_ADC_Enable(ADC1);
+
+  /* The delay between ADC enablement and ADC stabilization is at least 8 ADC clocks */
+  LL_mDelay(1);
+}
 
 /*******************************************************************
 ** Parameters:		
@@ -43,14 +100,13 @@
 *******************************************************************/
 uint16_t hal_adc_to_voltage(uint16_t adc)
 {
-	UNUSED_PARAMETER(adc);
 	return 0;
 }
 bool hal_adc_value(uint8_t id, uint16_t* valp)
 {
-	UNUSED_PARAMETER(id);
-	UNUSED_PARAMETER(valp);
-	return false;
+	if(id >= m_adc_num) return false;
+	valp = irq_adc[id];
+	return true;
 }
 bool hal_adc_start_scan(void)
 {
@@ -58,14 +114,87 @@ bool hal_adc_start_scan(void)
 }
 bool hal_adc_init(void)
 {
-	return false;
+	uint8_t id;
+
+  	LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_ADC1);
+
+	for(id=0; id<m_adc_num; id++){
+		get_gpio_rcc(m_adc_map[id].pin);
+  		LL_GPIO_SetPinMode(get_gpio_port(m_adc_map[id].pin), get_gpio_pin(m_adc_map[id].pin), LL_GPIO_MODE_ANALOG);
+	}
+
+	/* Set ADC clock to pclk/4 */
+	LL_ADC_SetClock(ADC1, LL_ADC_CLOCK_SYNC_PCLK_DIV4);  
+
+	/* Set ADC resolution to 12 bit */
+	LL_ADC_SetResolution(ADC1, LL_ADC_RESOLUTION_12B);
+
+	/* ADC conversion data alignment: right aligned */
+	LL_ADC_SetDataAlignment(ADC1, LL_ADC_DATA_ALIGN_RIGHT);
+
+	/* No ADC low power mode activated */
+	LL_ADC_SetLowPowerMode(ADC1, LL_ADC_LP_MODE_NONE);
+
+	/* Sampling time 239.5 ADC clock cycles */
+	LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_239CYCLES_5);
+
+	/* ADC regular group conversion trigger from external IP: TIM1 TRGO. */
+	LL_ADC_REG_SetTriggerSource(ADC1, LL_ADC_REG_TRIG_EXT_TIM1_TRGO);
+
+	/* Set Trigger edge to rising edge */
+	LL_ADC_REG_SetTriggerEdge(ADC1, LL_ADC_REG_TRIG_EXT_RISING);
+
+	/* Set ADC conversion mode to single mode: one conversion per trigger */
+	LL_ADC_REG_SetContinuousMode(ADC1, LL_ADC_REG_CONV_SINGLE);
+
+	/* ADC regular group behavior in case of overrun: data overwritten */
+	LL_ADC_REG_SetOverrun(ADC1, LL_ADC_REG_OVR_DATA_OVERWRITTEN);
+
+	/* Disable ADC regular group sequencer discontinuous mode  */
+	LL_ADC_REG_SetSequencerDiscont(ADC1, LL_ADC_REG_SEQ_DISCONT_DISABLE);
+	for(id=0; id<m_adc_num; id++){
+		if(id == 0){
+  			LL_ADC_REG_SetSequencerChannels(ADC1, ADC_CH_ATT(id));
+		}else{
+			LL_ADC_REG_SetSequencerChAdd(ADC1, ADC_CH_ATT(id));
+		}
+	}
+
+	/* Dose not enable internal conversion channel */
+	LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_VREFINT );
+		
+	/* Enable EOC IT */
+	LL_ADC_EnableIT_EOC(ADC1);
+
+	NVIC_SetPriority(ADC_COMP_IRQn,1);
+	NVIC_EnableIRQ(ADC_COMP_IRQn);
+		
+	/*  ADC automatic self-calibration */
+	APP_AdcCalibrate();
+
+	/* Enable ADC */
+	APP_AdcEnable();
+
+	/* Start ADC conversion (if it is software triggered then start conversion directly) */
+	LL_ADC_REG_StartConversion(ADC1);
+	return true;
 }
 bool hal_adc_deinit(void)
 {
+	LL_ADC_Disable(ADC1);
 	return false;
 }
 
-
+/******************************************************************************/
+/*           Cortex-M0+ Processor Interruption and Exception Handlers         */
+/******************************************************************************/
+void ADC_COMP_IRQHandler(void)
+{
+	  /* Clear ADC EOC IT flag */
+    LL_ADC_ClearFlag_EOC(ADC1);
+	irq_adc[num++]=ADC1->DR;
+    if(num >= m_adc_num) i = 0;
+}
 #endif
 
 

+ 4 - 4
Src/user/emf_hal/hal_gpio.c

@@ -66,13 +66,13 @@ uint32_t get_gpio_rcc(pin_t io)
     switch (io&HW_PORT_MASK)
     {
     case HW_PORTA_BASE:
-        rcc = LL_IOP_GRP1_PERIPH_GPIOA;
+        LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
         break;
     case HW_PORTB_BASE:
-        rcc = LL_IOP_GRP1_PERIPH_GPIOB;
+        LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);
         break;
     case HW_PORTC_BASE:
-        rcc = LL_IOP_GRP1_PERIPH_GPIOC;
+        LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOC);
         break;
     default:
         break;
@@ -95,7 +95,7 @@ void hal_gpio_dir(pin_t pin, pin_dir_t dir, pin_pull_t pull)
 
     LL_GPIO_InitTypeDef GPIO_InitStructure = {0};
 
-    LL_IOP_GRP1_EnableClock(get_gpio_rcc((pin_t)pin));
+    get_gpio_rcc((pin_t)pin);
 
 	GPIO_InitStructure.Pin = get_gpio_pin(pin);
 	GPIO_InitStructure.Mode = (dir == PIN_OUT ? LL_GPIO_MODE_OUTPUT : LL_GPIO_MODE_INPUT);

+ 3 - 0
Src/user/emf_hal/hal_gpio.h

@@ -35,6 +35,9 @@ extern "C" {
 **	Parameters
 *******************************************************************************************************/
 
+GPIO_TypeDef * get_gpio_port(pin_t io);
+uint32_t get_gpio_rcc(pin_t io);
+uint32_t get_gpio_pin(pin_t io);
 
 
 /*****************************************************************************************************