你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

NUCLEO-G431RB:基于STM32G431 OPAMP的热电偶测温程序

[复制链接]
dsjsjf 发布时间:2020-11-11 18:59
先上主角儿。板载的ST-LINK V3有点抢眼了。。。
图片1.png
拿到开发板后,一直在纠结做什么好,工作之余就翻开资料看看,发现STM32G431有三个可编程运放,对于我们工作上经常用到小信号放大的情况,倒是一个不错的方案。可以省掉一个运放及外围电路。
图片2.png
刚开始被搞懵了,手册上只讲了三种模式
图片3.png
而CubeMX中有一堆模式可选
图片4.png
本来从手册的字面意思上,比较好选的,但到了CubeMX中,无从下手了,没办法,只好再去啃手册。
本来想用差分输入方式的,但它这个好像不支持(也没再去深究),目前就用单端输入方式。
下面正式开始:(因为MCU属于新款的,所以该升级到最新版本的软件工具要升到最新版,否则可能不支持)
一、利用STM32CubeMX创建并配置工程
图片5.png
直接选择NUCLEO-G431RB板,并初始化为缺省模式(这种方式和板子最搭)。
二、配置OPAMP2,选择PGA Not Connected 模式,Gain我选择的是64(最大)。配置后,会看到PA6PA7被分配成了OPA的输出端和输入端。因为我要连接到内部的ADC,这里其实是不需要输出的,不过我暂时还没找到怎么把OUT管脚用于其他功能。
图片6.png
三、配置ADC2,选择通道为VOPAMP2 Channel。下面的参数就不细说了,和其他系列的MCU基本差别不大,再配置一下DMAAD转换需要用到DMA
图片7.png
四、配置完成,生成代码,运行效果。通过板载的虚拟串口发出温度数据,没有做数据处理以及校准,精度还是可以的。
图片8.png 图片9.png 图片10.png


以下为main.c中的代码,其它代码为CubeMX生成的,未作改动。
  1. /* USER CODE BEGIN Header */
  2. /**
  3.   ******************************************************************************
  4.   * @file           : main.c
  5.   * @brief          : Main program body
  6.   ******************************************************************************
  7.   * @attention
  8.   *
  9.   * <h2><center>© Copyright (c) 2019 STMicroelectronics.
  10.   * All rights reserved.</center></h2>
  11.   *
  12.   * This software component is licensed by ST under BSD 3-Clause license,
  13.   * the "License"; You may not use this file except in compliance with the
  14.   * License. You may obtain a copy of the License at:
  15.   *                        opensource.org/licenses/BSD-3-Clause
  16.   *
  17.   ******************************************************************************
  18.   */
  19. /* USER CODE END Header */

  20. /* Includes ------------------------------------------------------------------*/
  21. #include "main.h"

  22. /* Private includes ----------------------------------------------------------*/
  23. /* USER CODE BEGIN Includes */
  24. #include <string.h>
  25. #include <stdio.h>
  26. /* USER CODE END Includes */

  27. /* Private typedef -----------------------------------------------------------*/
  28. /* USER CODE BEGIN PTD */

  29. /* USER CODE END PTD */

  30. /* Private define ------------------------------------------------------------*/
  31. /* USER CODE BEGIN PD */
  32. #define ADC_DMA_LENGTH          32

  33. /* USER CODE END PD */

  34. /* Private macro -------------------------------------------------------------*/
  35. /* USER CODE BEGIN PM */

  36. /* USER CODE END PM */

  37. /* Private variables ---------------------------------------------------------*/
  38. ADC_HandleTypeDef hadc2;
  39. DMA_HandleTypeDef hdma_adc2;

  40. UART_HandleTypeDef hlpuart1;

  41. OPAMP_HandleTypeDef hopamp2;

  42. /* USER CODE BEGIN PV */
  43. uint32_t AdcData[ADC_DMA_LENGTH];
  44. uint16_t RealTemp = 0;
  45. uint32_t VolmV = 0;
  46. /* USER CODE END PV */

  47. /* Private function prototypes -----------------------------------------------*/
  48. void SystemClock_Config(void);
  49. static void MX_GPIO_Init(void);
  50. static void MX_LPUART1_UART_Init(void);
  51. static void MX_OPAMP2_Init(void);
  52. static void MX_DMA_Init(void);
  53. static void MX_ADC2_Init(void);
  54. /* USER CODE BEGIN PFP */

  55. /* USER CODE END PFP */

  56. /* Private user code ---------------------------------------------------------*/
  57. /* USER CODE BEGIN 0 */
  58. /*******************************************************************************
  59. ** 函数名: Quick_Sort
  60. ** 功  能: 选择排序法
  61. ** 参  数: unsigned int *a  待排列的数组指针
  62. **         unsigned int i   待排列的数组起始元素下标
  63. **         unsigned int j   待排列的数组结束元素下标
  64. ** 返  回: 无
  65. ** 备  注:
  66. *******************************************************************************/
  67. void Quick_Sort(int *a, int i, int j)
  68. {
  69.   int m,n,temp;
  70.   int k;
  71.   m = i;
  72.   n = j;
  73.   k = a[(i+j) / 2];/*选取的参照*/
  74.   do{
  75.     while((a[m] < k) && (m < j))
  76.     {/*从左到右找比k大的元素*/
  77.       m++;
  78.     }
  79.     while((a[n] > k) && (n > i))
  80.     {/*从右到左找比k小的元素*/
  81.       n--;
  82.     }
  83.     if(m <= n)
  84.     {/*若找到且条件满足,则交换*/
  85.       temp = a[m];
  86.       a[m] = a[n];
  87.       a[n] = temp;
  88.       m++;
  89.       n--;
  90.     }
  91.   }while(m <= n);
  92.   if(m < j)
  93.   {
  94.     Quick_Sort(a, m, j);/*运用递归*/
  95.   }
  96.   if(n > i)
  97.   {
  98.     Quick_Sort(a, i, n);
  99.   }
  100. }
  101. uint32_t Get_Temp(uint32_t *pArray)
  102. {
  103.   uint32_t Value = 0;
  104.   uint32_t SortArray[ADC_DMA_LENGTH];
  105.   
  106.   for(uint32_t i=0; i<ADC_DMA_LENGTH; i++)
  107.   {
  108.     SortArray[i] = *(pArray + i);
  109.   }
  110.   Quick_Sort((int *)SortArray, 0, ADC_DMA_LENGTH-1);
  111.   
  112.   for(uint32_t i=4; i<(ADC_DMA_LENGTH-4); i++)
  113.   {
  114.     Value += SortArray[i];
  115.   }
  116.   Value /= (ADC_DMA_LENGTH-8);
  117.   //换算成mV值(0.1mV)
  118.   Value *= 33000;
  119.   Value /= 4096;
  120.   //换算成温度值,1000度对应41mV
  121.   Value *= 100;
  122.   Value /= 41;
  123.   //最后把增益除掉
  124.   Value /= 64;
  125.   Value += 60;//没有做校准,所以程序里直接加上一个偏置值
  126.   return Value;
  127. }

  128. /* USER CODE END 0 */

  129. /**
  130.   * @brief  The application entry point.
  131.   * @retval int
  132.   */
  133. int main(void)
  134. {
  135.   /* USER CODE BEGIN 1 */
  136.   static char TempStr[64];

  137.   /* USER CODE END 1 */
  138.   

  139.   /* MCU Configuration--------------------------------------------------------*/

  140.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  141.   HAL_Init();

  142.   /* USER CODE BEGIN Init */

  143.   /* USER CODE END Init */

  144.   /* Configure the system clock */
  145.   SystemClock_Config();

  146.   /* USER CODE BEGIN SysInit */

  147.   /* USER CODE END SysInit */

  148.   /* Initialize all configured peripherals */
  149.   MX_GPIO_Init();
  150.   MX_LPUART1_UART_Init();
  151.   MX_OPAMP2_Init();
  152.   MX_DMA_Init();
  153.   MX_ADC2_Init();
  154.   /* USER CODE BEGIN 2 */
  155.   HAL_ADC_Start_DMA(&hadc2, (uint32_t *)AdcData, ADC_DMA_LENGTH);
  156.   /* USER CODE END 2 */

  157.   /* Infinite loop */
  158.   /* USER CODE BEGIN WHILE */
  159.   while (1)
  160.   {
  161. //    HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
  162.     RealTemp = Get_Temp(AdcData);
  163.     sprintf((char *)TempStr, "\r\nthe temperature is %d ℃\r\n\0", RealTemp);
  164.     HAL_UART_Transmit(&hlpuart1, (uint8_t *)TempStr, strlen(TempStr), 500);
  165.     HAL_Delay(500);
  166.     /* USER CODE END WHILE */

  167.     /* USER CODE BEGIN 3 */
  168.   }
  169.   /* USER CODE END 3 */
  170. }

  171. /**
  172.   * @brief System Clock Configuration
  173.   * @retval None
  174.   */
  175. void SystemClock_Config(void)
  176. {
  177.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  178.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  179.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  180.   /** Configure the main internal regulator output voltage
  181.   */
  182.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
  183.   /** Initializes the CPU, AHB and APB busses clocks
  184.   */
  185.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  186.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  187.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  188.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  189.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  190.   RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4;
  191.   RCC_OscInitStruct.PLL.PLLN = 85;
  192.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  193.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  194.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  195.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  196.   {
  197.     Error_Handler();
  198.   }
  199.   /** Initializes the CPU, AHB and APB busses clocks
  200.   */
  201.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  202.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  203.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  204.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  205.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  206.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  207.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_8) != HAL_OK)
  208.   {
  209.     Error_Handler();
  210.   }
  211.   /** Initializes the peripherals clocks
  212.   */
  213.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1|RCC_PERIPHCLK_ADC12;
  214.   PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1;
  215.   PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
  216.   if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  217.   {
  218.     Error_Handler();
  219.   }
  220. }

  221. /**
  222.   * @brief ADC2 Initialization Function
  223.   * @param None
  224.   * @retval None
  225.   */
  226. static void MX_ADC2_Init(void)
  227. {

  228.   /* USER CODE BEGIN ADC2_Init 0 */

  229.   /* USER CODE END ADC2_Init 0 */

  230.   ADC_ChannelConfTypeDef sConfig = {0};

  231.   /* USER CODE BEGIN ADC2_Init 1 */

  232.   /* USER CODE END ADC2_Init 1 */
  233.   /** Common config
  234.   */
  235.   hadc2.Instance = ADC2;
  236.   hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16;
  237.   hadc2.Init.Resolution = ADC_RESOLUTION_12B;
  238.   hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  239.   hadc2.Init.GainCompensation = 0;
  240.   hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
  241.   hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  242.   hadc2.Init.LowPowerAutoWait = DISABLE;
  243.   hadc2.Init.ContinuousConvMode = ENABLE;
  244.   hadc2.Init.NbrOfConversion = 1;
  245.   hadc2.Init.DiscontinuousConvMode = DISABLE;
  246.   hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  247.   hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  248.   hadc2.Init.DMAContinuousRequests = ENABLE;
  249.   hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  250.   hadc2.Init.OversamplingMode = DISABLE;
  251.   if (HAL_ADC_Init(&hadc2) != HAL_OK)
  252.   {
  253.     Error_Handler();
  254.   }
  255.   /** Configure Regular Channel
  256.   */
  257.   sConfig.Channel = ADC_CHANNEL_VOPAMP2;
  258.   sConfig.Rank = ADC_REGULAR_RANK_1;
  259.   sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
  260.   sConfig.SingleDiff = ADC_SINGLE_ENDED;
  261.   sConfig.OffsetNumber = ADC_OFFSET_NONE;
  262.   sConfig.Offset = 0;
  263.   if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  264.   {
  265.     Error_Handler();
  266.   }
  267.   /* USER CODE BEGIN ADC2_Init 2 */

  268.   /* USER CODE END ADC2_Init 2 */

  269. }

  270. /**
  271.   * @brief LPUART1 Initialization Function
  272.   * @param None
  273.   * @retval None
  274.   */
  275. static void MX_LPUART1_UART_Init(void)
  276. {

  277.   /* USER CODE BEGIN LPUART1_Init 0 */

  278.   /* USER CODE END LPUART1_Init 0 */

  279.   /* USER CODE BEGIN LPUART1_Init 1 */

  280.   /* USER CODE END LPUART1_Init 1 */
  281.   hlpuart1.Instance = LPUART1;
  282.   hlpuart1.Init.BaudRate = 115200;
  283.   hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
  284.   hlpuart1.Init.StopBits = UART_STOPBITS_1;
  285.   hlpuart1.Init.Parity = UART_PARITY_NONE;
  286.   hlpuart1.Init.Mode = UART_MODE_TX_RX;
  287.   hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  288.   hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  289.   hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  290.   if (HAL_UART_Init(&hlpuart1) != HAL_OK)
  291.   {
  292.     Error_Handler();
  293.   }
  294.   if (HAL_UARTEx_SetTxFifoThreshold(&hlpuart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  295.   {
  296.     Error_Handler();
  297.   }
  298.   if (HAL_UARTEx_SetRxFifoThreshold(&hlpuart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  299.   {
  300.     Error_Handler();
  301.   }
  302.   if (HAL_UARTEx_DisableFifoMode(&hlpuart1) != HAL_OK)
  303.   {
  304.     Error_Handler();
  305.   }
  306.   /* USER CODE BEGIN LPUART1_Init 2 */

  307.   /* USER CODE END LPUART1_Init 2 */

  308. }

  309. /**
  310.   * @brief OPAMP2 Initialization Function
  311.   * @param None
  312.   * @retval None
  313.   */
  314. static void MX_OPAMP2_Init(void)
  315. {

  316.   /* USER CODE BEGIN OPAMP2_Init 0 */

  317.   /* USER CODE END OPAMP2_Init 0 */

  318.   /* USER CODE BEGIN OPAMP2_Init 1 */

  319.   /* USER CODE END OPAMP2_Init 1 */
  320.   hopamp2.Instance = OPAMP2;
  321.   hopamp2.Init.PowerMode = OPAMP_POWERMODE_NORMAL;
  322.   hopamp2.Init.Mode = OPAMP_PGA_MODE;
  323.   hopamp2.Init.NonInvertingInput = OPAMP_NONINVERTINGINPUT_IO0;
  324.   hopamp2.Init.InternalOutput = ENABLE;
  325.   hopamp2.Init.TimerControlledMuxmode = OPAMP_TIMERCONTROLLEDMUXMODE_DISABLE;
  326.   hopamp2.Init.PgaConnect = OPAMP_PGA_CONNECT_INVERTINGINPUT_NO;
  327.   hopamp2.Init.PgaGain = OPAMP_PGA_GAIN_64_OR_MINUS_63;
  328.   hopamp2.Init.UserTrimming = OPAMP_TRIMMING_FACTORY;
  329.   if (HAL_OPAMP_Init(&hopamp2) != HAL_OK)
  330.   {
  331.     Error_Handler();
  332.   }
  333.   /* USER CODE BEGIN OPAMP2_Init 2 */
  334.   HAL_OPAMP_Start(&hopamp2);
  335.   /* USER CODE END OPAMP2_Init 2 */

  336. }

  337. /**
  338.   * Enable DMA controller clock
  339.   */
  340. static void MX_DMA_Init(void)
  341. {

  342.   /* DMA controller clock enable */
  343.   __HAL_RCC_DMAMUX1_CLK_ENABLE();
  344.   __HAL_RCC_DMA1_CLK_ENABLE();

  345.   /* DMA interrupt init */
  346.   /* DMA1_Channel1_IRQn interrupt configuration */
  347.   HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  348.   HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

  349. }

  350. /**
  351.   * @brief GPIO Initialization Function
  352.   * @param None
  353.   * @retval None
  354.   */
  355. static void MX_GPIO_Init(void)
  356. {
  357.   GPIO_InitTypeDef GPIO_InitStruct = {0};

  358.   /* GPIO Ports Clock Enable */
  359.   __HAL_RCC_GPIOC_CLK_ENABLE();
  360.   __HAL_RCC_GPIOF_CLK_ENABLE();
  361.   __HAL_RCC_GPIOA_CLK_ENABLE();
  362.   __HAL_RCC_GPIOB_CLK_ENABLE();

  363.   /*Configure GPIO pin Output Level */
  364.   HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);

  365.   /*Configure GPIO pin : B1_Pin */
  366.   GPIO_InitStruct.Pin = B1_Pin;
  367.   GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  368.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  369.   HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);

  370.   /*Configure GPIO pin : LD2_Pin */
  371.   GPIO_InitStruct.Pin = LD2_Pin;
  372.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  373.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  374.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  375.   HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);

  376. }

  377. /* USER CODE BEGIN 4 */

  378. /* USER CODE END 4 */

  379. /**
  380.   * @brief  This function is executed in case of error occurrence.
  381.   * @retval None
  382.   */
  383. void Error_Handler(void)
  384. {
  385.   /* USER CODE BEGIN Error_Handler_Debug */
  386.   /* User can add his own implementation to report the HAL error return state */

  387.   /* USER CODE END Error_Handler_Debug */
  388. }

  389. #ifdef  USE_FULL_ASSERT
  390. /**
  391.   * @brief  Reports the name of the source file and the source line number
  392.   *         where the assert_param error has occurred.
  393.   * @param  file: pointer to the source file name
  394.   * @param  line: assert_param error line source number
  395.   * @retval None
  396.   */
  397. void assert_failed(uint8_t *file, uint32_t line)
  398. {
  399.   /* USER CODE BEGIN 6 */
  400.   /* User can add his own implementation to report the file name and line number,
  401.      tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  402.   /* USER CODE END 6 */
  403. }
  404. #endif /* USE_FULL_ASSERT */

  405. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码


收藏 评论1 发布时间:2020-11-11 18:59

举报

1个回答
STMCU 回答时间:2020-11-23 10:40:12
感谢分享

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版