硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1903|回复: 1
收起左侧

[运放/比较器] STM32H7运放自校准实现方法

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106760
QQ
发表于 2018-9-15 02:19:32 | 显示全部楼层 |阅读模式
官方对此有一个例子:OPAMP_CALIBRATION

实际应用推荐使用自校准,不要用出厂校准,出厂校准的输入失调电压有点高,达到10mV。自校准可做到1.5mV左右。

效果:
999.png

QQ截图20180915013336.png

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106760
QQ
 楼主| 发表于 2018-9-15 02:20:44 | 显示全部楼层
代码也贴一下,方便以后直接查阅:



  1. /* Private typedef -----------------------------------------------------------*/
  2. /* Private define ------------------------------------------------------------*/
  3. /* Private macro -------------------------------------------------------------*/
  4. /* Private variables ---------------------------------------------------------*/
  5. DAC_HandleTypeDef    DacHandle;
  6. OPAMP_HandleTypeDef  OpampHandle;
  7. TIM_HandleTypeDef    htim;

  8. __IO uint32_t UserButtonStatus = 0;  /* set to 1 after User push-button interrupt  */

  9. uint32_t factorytrimmingvaluep = 0, factorytrimmingvaluen = 0;
  10. uint32_t oldtrimmingvaluep = 0, oldtrimmingvaluen = 0;
  11. uint32_t newtrimmingvaluep = 0, newtrimmingvaluen = 0;

  12. uint32_t ledblinkingduration = 0;

  13. static DAC_ChannelConfTypeDef sConfig;

  14. const uint16_t Sine12bit[32] = {510, 610, 700, 790, 840, 870, 980, 1010, 1020,
  15.                                 1010, 980, 930, 870, 790, 700, 610, 510, 410,
  16.                                 310, 220, 140, 140, 40, 0, 00, 10, 40, 90, 150, 230,
  17.                                 320, 41};

  18. /* Private function prototypes -----------------------------------------------*/
  19. static void DAC_Config(void);
  20. static void TIM_Config(void);
  21. static void OPAMP_Config(void);
  22. static void OPAMP_Calibrate_Before_Run (void);
  23. static void OPAMP_Calibrate_After_Run(void);

  24. static void SystemClock_Config(void);
  25. static void Error_Handler(void);
  26. static void CPU_CACHE_Enable(void);
  27. /* Private functions ---------------------------------------------------------*/

  28. /**
  29.   * @brief  Main program.
  30.   * @param  None
  31.   * @retval None
  32.   */
  33. int main(void)
  34. {

  35.   /* Enable the CPU Cache */
  36.   CPU_CACHE_Enable();

  37.   /* STM32H7xx HAL library initialization:
  38.        - Systick timer is configured by default as source of time base, but user
  39.          can eventually implement his proper time base source (a general purpose
  40.          timer for example or other time source), keeping in mind that Time base
  41.          duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
  42.          handled in milliseconds basis.
  43.        - Set NVIC Group Priority to 4
  44.        - Low Level Initialization
  45.      */
  46.   HAL_Init();

  47.   /* Configure the system clock to 400 MHz */
  48.   SystemClock_Config();

  49.   /* Configure LED1 & LED3 */
  50.   BSP_LED_Init(LED1);
  51.   BSP_LED_Init(LED3);

  52.   /* Configure Tamper push-button in Interrupt mode */
  53.   BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);

  54.   /* Configure the TIM to control the DAC */
  55.   TIM_Config();

  56.   /* Configure the DAC to generator sine wave */
  57.   DAC_Config();

  58.   /*##-1- Configure OPAMP    #################################################*/
  59.   /* Set OPAMP instance */
  60.   OpampHandle.Instance = OPAMP2;
  61.   
  62.   /* Configure the OPAMPx */
  63.   OPAMP_Config();

  64.   /*##-2- Calibrate OPAMP    #################################################*/
  65.   
  66.   /* Press user button to launch calibration */
  67.   //printf("\n\n\r STM32H7Press user button to launch calibration \n\r");
  68.    printf("\n\n\r STM32H7自带运放校准流程 \n\r");
  69.   
  70.   while(UserButtonStatus != 1);

  71.   HAL_Delay(100);
  72.   UserButtonStatus = 0;
  73.   
  74.   OPAMP_Calibrate_Before_Run();

  75.   printf("\n\r The LED blinks rapidly if ");
  76.   printf("\n\r Calibrated trimming are different from Factory Trimming \n\r");
  77.   
  78.   printf("\n\r The LED blinks slowly if ");
  79.   printf("\n\r Calibrated trimming same as Factory Trimming \n\r");
  80.   
  81.   /*##-3- Start OPAMP    #####################################################*/

  82.   /* Press user button to launch OPAMP */
  83.   
  84.   while(UserButtonStatus != 1)
  85.   {
  86.     BSP_LED_Toggle (LED1);
  87.     HAL_Delay(ledblinkingduration);
  88.   }
  89.   BSP_LED_Off(LED1);
  90.   
  91.   UserButtonStatus = 0;

  92.   /* Configure the OPAMPx (configuration of internal switches needed after calibration) */
  93.   HAL_OPAMP_Init(&OpampHandle);
  94.   
  95.   /* Enable OPAMP */
  96.   HAL_OPAMP_Start(&OpampHandle);
  97.   
  98.   /*##-3- Modify OPAMP setting while OPAMP ON ################################*/
  99.   
  100.   /* Press user button to change OPAMP setting on the fly (dummy change,      */
  101.   /* without application purpose in this example: change non-inverting input  */
  102.   /* source).                                                                 */
  103.   printf("\n\n\r Press user button to modify OPAMP non-inverting input source \n\r");
  104.   printf("       i.e. non-inverting input source is changed on the fly \n\r");

  105.   while(UserButtonStatus != 1);
  106.   HAL_Delay(500);
  107.   UserButtonStatus = 0;
  108.   /* Change the OPAMP input selection */
  109.   OpampHandle.Init.NonInvertingInput = OPAMP_NONINVERTINGINPUT_IO0;
  110.   /* Update OMAP config */
  111.   HAL_OPAMP_Init(&OpampHandle);

  112.   
  113.   /*##-4- Stop OPAMP #########################################################*/
  114.   
  115.   /* Press user button to stop OPAMP */
  116.   printf("\n\n\r Press user button to stop OPAMP \n\r");
  117.   
  118.   while(UserButtonStatus != 1);
  119.   HAL_Delay(500);
  120.   UserButtonStatus = 0;

  121.   /* Disable OPAMP */
  122.   HAL_OPAMP_Stop(&OpampHandle);
  123.   
  124.   /*##-5- Calibrate OPAMP    #################################################*/
  125.   /* Press user button to launch calibration */
  126.   /* printf("\n\n\r Press user button to launch calibration \n\r"); */
  127.   
  128.   while(UserButtonStatus != 1);
  129.   HAL_Delay(500);
  130.   UserButtonStatus = 0;

  131.   OPAMP_Calibrate_After_Run();
  132.    
  133.   printf("\n\r The LED blinks rapidly if: ");
  134.   printf("\n\r New calibrated trimming are different from ones calibrated before run \n\r");
  135.   
  136.   printf("\n\r The LED blinks slowly if: ");
  137.   printf("\n\r New calibrated trimming are same as ones calibrated before run\n\r");
  138.          
  139.    while(UserButtonStatus != 1)
  140.   {
  141.     BSP_LED_Toggle (LED1);
  142.     HAL_Delay(ledblinkingduration);
  143.   }
  144.   BSP_LED_Off(LED1);
  145.   
  146.   /*##-4- End of tests       #################################################*/
  147.   
  148.   printf("\n\n\r End of example \n\r");
  149.   while (1);
  150. }

  151. /**
  152.   * @brief  System Clock Configuration
  153.   *         The system Clock is configured as follow :
  154.   *            System Clock source            = PLL (HSE BYPASS)
  155.   *            SYSCLK(Hz)                     = 400000000 (CPU Clock)
  156.   *            HCLK(Hz)                       = 200000000 (AXI and AHBs Clock)
  157.   *            AHB Prescaler                  = 2
  158.   *            D1 APB3 Prescaler              = 2 (APB3 Clock  100MHz)
  159.   *            D2 APB1 Prescaler              = 2 (APB1 Clock  100MHz)
  160.   *            D2 APB2 Prescaler              = 2 (APB2 Clock  100MHz)
  161.   *            D3 APB4 Prescaler              = 2 (APB4 Clock  100MHz)
  162.   *            HSE Frequency(Hz)              = 8000000
  163.   *            PLL_M                          = 4
  164.   *            PLL_N                          = 400
  165.   *            PLL_P                          = 2
  166.   *            PLL_Q                          = 4
  167.   *            PLL_R                          = 2
  168.   *            VDD(V)                         = 3.3
  169.   *            Flash Latency(WS)              = 4
  170.   * @param  None
  171.   * @retval None
  172.   */
  173. static void SystemClock_Config(void)
  174. {
  175.   RCC_ClkInitTypeDef RCC_ClkInitStruct;
  176.   RCC_OscInitTypeDef RCC_OscInitStruct;
  177.   HAL_StatusTypeDef ret = HAL_OK;
  178.   
  179.   /*!< Supply configuration update enable */
  180.   MODIFY_REG(PWR->CR3, PWR_CR3_SCUEN, 0);

  181.   /* The voltage scaling allows optimizing the power consumption when the device is
  182.      clocked below the maximum system frequency, to update the voltage scaling value
  183.      regarding system frequency refer to product datasheet.  */
  184.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  185.   while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  186.   
  187.   /* Enable HSE Oscillator and activate PLL with HSE as source */
  188.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  189.   RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  190.   RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
  191.   RCC_OscInitStruct.CSIState = RCC_CSI_OFF;
  192.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  193.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

  194.   RCC_OscInitStruct.PLL.PLLM = 4;
  195.   RCC_OscInitStruct.PLL.PLLN = 400;
  196.   RCC_OscInitStruct.PLL.PLLP = 2;
  197.   RCC_OscInitStruct.PLL.PLLR = 2;
  198.   RCC_OscInitStruct.PLL.PLLQ = 4;

  199.   RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  200.   RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
  201.   ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
  202.   if(ret != HAL_OK)
  203.   {
  204.     Error_Handler();
  205.   }
  206.   
  207. /* Select PLL as system clock source and configure  bus clocks dividers */
  208.   RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_D1PCLK1 | RCC_CLOCKTYPE_PCLK1 | \
  209.                                  RCC_CLOCKTYPE_PCLK2  | RCC_CLOCKTYPE_D3PCLK1);

  210.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  211.   RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  212.   RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  213.   RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;  
  214.   RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  215.   RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  216.   RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
  217.   ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4);
  218.   if(ret != HAL_OK)
  219.   {
  220.     Error_Handler();
  221.   }
  222. }
  223. /**
  224.   * @brief  This function is executed in case of error occurrence.
  225.   * @param  None
  226.   * @retval None
  227.   */
  228. static void Error_Handler(void)
  229. {
  230. /* Turn LED3 on */
  231.   BSP_LED_On(LED3);
  232.   while (1)
  233.   {
  234.   }
  235. }

  236. static void DAC_Config(void)
  237. {
  238.   /* Configure the DAC peripheral instance */
  239.   DacHandle.Instance = DACx;

  240.   /*##-1- Initialize the DAC peripheral ######################################*/
  241.   if (HAL_DAC_Init(&DacHandle) != HAL_OK)
  242.   {
  243.     /* Initialization Error */
  244.     Error_Handler();
  245.   }

  246.   /*##-1- DAC channel Configuration ###########################################*/
  247.   sConfig.DAC_Trigger = DAC_TRIGGER_T2_TRGO;
  248.   sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  249.   sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_ENABLE;
  250.   
  251.   if(HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DACx_CHANNELa) != HAL_OK)
  252.   {
  253.     /* Channel configuration Error */
  254.     Error_Handler();
  255.   }

  256.   /*##-2- Enable DAC Channel and associeted DMA ##############################*/
  257.   if(HAL_DAC_Start_DMA(&DacHandle, DACx_CHANNELa, (uint32_t*)Sine12bit,
  258.                        sizeof (Sine12bit) / sizeof (uint32_t),
  259.                        DAC_ALIGN_12B_R) != HAL_OK)
  260.   {
  261.     /* Start DMA Error */
  262.     Error_Handler();
  263.   }

  264. }

  265. /**
  266.   * @brief  TIM Configuration
  267.   * @note   TIM configuration is based on APB1 frequency
  268.   * @note   TIM Update event occurs each TIMxCLK/65535   
  269.   * @param  None
  270.   * @retval None
  271.   */
  272. void TIM_Config(void)
  273. {
  274.   TIM_MasterConfigTypeDef sMasterConfig;
  275.   
  276.   /*##-1- Configure the TIM peripheral #######################################*/

  277.   /* Time base configuration */
  278.   htim.Instance = TIM2;
  279.   
  280.   htim.Init.Period = 0xFFFF;         
  281.   htim.Init.Prescaler = 0;      
  282.   htim.Init.ClockDivision = 0;   
  283.   htim.Init.CounterMode = TIM_COUNTERMODE_UP;
  284.   htim.Init.RepetitionCounter = 0;
  285.   
  286.   HAL_TIM_Base_Init(&htim);

  287.   /* TIM2 TRGO selection */
  288.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  289.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

  290.   HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig);

  291.   /*##-2- Enable TIM peripheral counter ######################################*/
  292.   HAL_TIM_Base_Start(&htim);
  293.   }

  294. /**            
  295.   * @brief  OPAMP Calibration before OPAMP runs
  296.   * @note   
  297.   * @note   
  298.   * @param  None
  299.   * @retval None
  300.   */
  301. void OPAMP_Calibrate_Before_Run(void)
  302. {

  303.   /* Retrieve Factory Trimming */
  304.    factorytrimmingvaluep = HAL_OPAMP_GetTrimOffset(&OpampHandle, OPAMP_FACTORYTRIMMING_P);
  305.    factorytrimmingvaluen = HAL_OPAMP_GetTrimOffset(&OpampHandle, OPAMP_FACTORYTRIMMING_N);
  306.    
  307.    /* Run OPAMP calibration */
  308.    HAL_OPAMP_SelfCalibrate(&OpampHandle);
  309.    
  310.    /* Store trimming value */
  311.    oldtrimmingvaluep = OpampHandle.Init.TrimmingValueP;
  312.    oldtrimmingvaluen = OpampHandle.Init.TrimmingValueN;

  313.    /* Are just calibrated trimming same or different from Factory Trimming */
  314.    if  ((oldtrimmingvaluep != factorytrimmingvaluep) || (oldtrimmingvaluen != factorytrimmingvaluen))
  315.    {
  316.      /* Calibrated trimming are different from Factory Trimming */
  317.      /* printf("....... Calibrated trimming are different from Factory Trimming \n\r"); */
  318.      /* LED blinks quickly */
  319.      ledblinkingduration = 50;      
  320.    }
  321.    
  322.    else
  323.    {
  324.      /* Calibrated trimming same as Factory Trimming */  
  325.      /* printf("....... Calibrated trimming same as Factory Trimming \n\r"); */
  326.      /* LED blinks slowly */
  327.      ledblinkingduration = 1500;
  328.    }
  329.   
  330.    /* With use temperature sensor   */
  331.    /* Calibration */
  332.   }

  333. /**            
  334.   * @brief  OPAMP Calibration after OPAMP runs
  335.   * @note   
  336.   * @note   
  337.   * @param  None
  338.   * @retval None
  339.   */
  340. void OPAMP_Calibrate_After_Run(void)
  341.   {
  342.    /* Run OPAMP calibration */
  343.    HAL_OPAMP_SelfCalibrate(&OpampHandle);
  344.    
  345.    /* Store trimming value */
  346.    newtrimmingvaluep = OpampHandle.Init.TrimmingValueP;
  347.    newtrimmingvaluen = OpampHandle.Init.TrimmingValueN;

  348.    /* Are just calibrated trimming same or different from Factory Trimming */
  349.    if  ((oldtrimmingvaluep != newtrimmingvaluep) || (oldtrimmingvaluen != newtrimmingvaluen))
  350.    {
  351.      /* New calibrated trimming are different from ones calibrated before run */
  352.       /* printf("....... New calibrated trimming are different from ones calibrated before run \n\r"); */
  353.      /* LED blinks quickly */
  354.      ledblinkingduration = 50;
  355.    }
  356.    
  357.    else
  358.    {
  359.      /* New calibrated trimming are same as ones calibrated before run */
  360.      /* printf("....... New calibrated trimming are same as ones calibrated before run \n\r"); */
  361.      /* LED blinks slowly */
  362.      ledblinkingduration = 1500;
  363.    }
  364.   }


  365. /**            
  366.   * @brief  OPAMP Configuration
  367.   * @note   
  368.   * @note   
  369.   * @param  None
  370.   * @retval None
  371.   */
  372. void OPAMP_Config(void)
  373. {
  374.   /* Select power mode */
  375.   OpampHandle.Init.PowerMode = OPAMP_POWERMODE_NORMAL;
  376.   
  377.   /* Select FOLLOWER_MODE */
  378.   OpampHandle.Init.Mode = OPAMP_FOLLOWER_MODE;         

  379.   /* Select the user trimming (just calibrated) */
  380.   OpampHandle.Init.UserTrimming = OPAMP_TRIMMING_USER;
  381.   
  382.   /* Select internal connection to DAC channel as input for OPAMP */
  383.   OpampHandle.Init.NonInvertingInput = OPAMP_NONINVERTINGINPUT_DAC_CH;
  384.   
  385.   /* Select the inverting input of the OPAMP: no inverting input connection since OPAMP is on follower mode */
  386.   /* Init */
  387.   HAL_OPAMP_Init(&OpampHandle);
  388. }

  389. /**
  390.   * @brief  EXTI line detection callbacks.
  391.   * @param  GPIO_Pin: Specifies the pins connected EXTI line
  392.   * @retval None
  393.   */
  394. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  395. {
  396.   if (GPIO_Pin == USER_BUTTON_PIN)
  397.   {
  398.     UserButtonStatus = 1;
  399.   }
  400. }
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-5 01:30 , Processed in 0.160529 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表