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

【我爱DIY】基于STM32F446的交流真有效值电压表

[复制链接]
wenyangzeng 发布时间:2017-8-6 16:35
本帖最后由 wenyangzeng 于 2017-8-6 21:13 编辑

基于STM32F446的交流真有效值电压表

    一般的数字万用表的交流电压的测量是采用将交流电压经过整流后测量其有效值,由于整流二极管的非线性,使得该测量结果误差较大,不是真有效值,特别是对非正弦波的测量更是如此。
   本方案基于使用意法半导体的ARM CORTEX内核的STM32F446交流真有效值电压表,克服上述方案的缺点,使得对交流电的测量更加准确。
    交流电的有效值定义为:
无标题1.png


    对其一个周期内连续采样后,根据以下公式进行计算得到结果。
无标题3.png
硬件连接:
无标题2.png


220V交流电经过1:1电压互感器后与STM32F446的ADC0连接。


MX1.png
                             ADC通道配置
MX2.png
                        时钟配置
MX3.png
          ADC参数配置

关键代码:
  1. //MAIN.C

  2. #include "main.h"
  3. #include "stm32f4xx_hal.h"
  4. #include "adc.h"
  5. #include "dma.h"
  6. #include "tim.h"
  7. #include "gpio.h"
  8. #include "math.h"

  9. #include "oled.h"
  10. uint16_t   aADCxConvertedData[48][10];
  11. uint32_t Resture=0;
  12. uint8_t Disp_buf[8],Flag;
  13. uint8_t j=0;
  14. void SystemClock_Config(void);

  15. void Get_ADC(void)
  16. {uint8_t i;
  17.         static uint32_t total;
  18.         double temp;
  19.         

  20.         total=0;
  21.         for(i=0;i<48;i++)
  22.                 {
  23.                 total +=(aADCxConvertedData[i][0]*aADCxConvertedData[i][0]);
  24.                 }
  25.                 total /=48;
  26.                 temp=sqrt(total)        ;
  27.                 Resture +=(uint16_t)temp;
  28.                 j++;
  29.                 if(j==32)
  30.                 {
  31.                 Resture=Resture/64;
  32.                 Disp_buf[0]=(Resture%1000/100)+0x30;        
  33.                 Disp_buf[1]=(Resture%100/10)+0x30;        
  34.                 Disp_buf[2]=(Resture%10)+0x30;        
  35.                 Disp_buf[3]='\0';
  36.                 LCD_Print(40,46,Disp_buf,TYPE16X16,TYPE8X16);        
  37.                 Resture=0;        
  38.                 j=0;
  39.                 }
  40. }




  41. int main(void)
  42. {

  43.   HAL_Init();
  44.   SystemClock_Config();
  45.   MX_GPIO_Init();
  46.   MX_DMA_Init();
  47.   MX_ADC1_Init();
  48.   MX_TIM8_Init();
  49.         HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1);

  50.                 LCD_Init();
  51.                 LCD_Print(0, 0,"STM32F446 Nucleo",TYPE16X16,TYPE8X16);
  52.                 LCD_Print(0, 16, "True effective",TYPE16X16,TYPE8X16);
  53.                 LCD_Print(74,46, "V",TYPE16X16,TYPE8X16);
  54.                
  55.         if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&aADCxConvertedData,480) != HAL_OK)
  56.   {
  57.     Error_Handler();
  58.   }        

  59.   while (1)
  60.   {
  61.         if(Flag==1)
  62.         {        
  63.                 Get_ADC();
  64.                 Flag=0;
  65.         }

  66.   }

  67. }


  68. //ADC.C
  69. #include "adc.h"
  70. #include "gpio.h"
  71. #include "dma.h"
  72. ADC_HandleTypeDef hadc1;
  73. DMA_HandleTypeDef hdma_adc1;
  74. void MX_ADC1_Init(void)
  75. {
  76.   ADC_ChannelConfTypeDef sConfig;
  77.   hadc1.Instance = ADC1;
  78.   hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
  79.   hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  80.   hadc1.Init.ScanConvMode = ENABLE;
  81.   hadc1.Init.ContinuousConvMode = ENABLE;
  82.   hadc1.Init.DiscontinuousConvMode = DISABLE;
  83.   hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  84.   hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  85.   hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  86.   hadc1.Init.NbrOfConversion = 10;
  87.   hadc1.Init.DMAContinuousRequests = ENABLE;
  88.   hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  89.   if (HAL_ADC_Init(&hadc1) != HAL_OK)
  90.   {
  91.     _Error_Handler(__FILE__, __LINE__);
  92.   }
  93.   sConfig.Channel = ADC_CHANNEL_0;
  94.   sConfig.Rank = 1;
  95.   sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
  96.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  97.   {
  98.     _Error_Handler(__FILE__, __LINE__);
  99.   }

  100.   sConfig.Channel = ADC_CHANNEL_1;
  101.   sConfig.Rank = 2;
  102.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  103.   {
  104.     _Error_Handler(__FILE__, __LINE__);
  105.   }

  106.   sConfig.Channel = ADC_CHANNEL_2;
  107.   sConfig.Rank = 3;
  108.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  109.   {
  110.     _Error_Handler(__FILE__, __LINE__);
  111.   }

  112.   sConfig.Channel = ADC_CHANNEL_3;
  113.   sConfig.Rank = 4;
  114.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  115.   {
  116.     _Error_Handler(__FILE__, __LINE__);
  117.   }

  118.   sConfig.Channel = ADC_CHANNEL_4;
  119.   sConfig.Rank = 5;
  120.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  121.   {
  122.     _Error_Handler(__FILE__, __LINE__);
  123.   }

  124.   sConfig.Channel = ADC_CHANNEL_6;
  125.   sConfig.Rank = 6;
  126.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  127.   {
  128.     _Error_Handler(__FILE__, __LINE__);
  129.   }

  130.   sConfig.Channel = ADC_CHANNEL_7;
  131.   sConfig.Rank = 7;
  132.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  133.   {
  134.     _Error_Handler(__FILE__, __LINE__);
  135.   }

  136.   sConfig.Channel = ADC_CHANNEL_8;
  137.   sConfig.Rank = 8;
  138.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  139.   {
  140.     _Error_Handler(__FILE__, __LINE__);
  141.   }

  142.   sConfig.Channel = ADC_CHANNEL_9;
  143.   sConfig.Rank = 9;
  144.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  145.   {
  146.     _Error_Handler(__FILE__, __LINE__);
  147.   }

  148.   sConfig.Channel = ADC_CHANNEL_10;
  149.   sConfig.Rank = 10;
  150.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  151.   {
  152.     _Error_Handler(__FILE__, __LINE__);
  153.   }

  154. }

  155. void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
  156. {

  157.   GPIO_InitTypeDef GPIO_InitStruct;
  158.   if(adcHandle->Instance==ADC1)
  159.   {
  160.     __HAL_RCC_ADC1_CLK_ENABLE();

  161.     GPIO_InitStruct.Pin = GPIO_PIN_0;
  162.     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  163.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  164.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  165.     GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
  166.                           |GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_7;
  167.     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  168.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  169.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  170.     GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
  171.     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  172.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  173.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  174.     hdma_adc1.Instance = DMA2_Stream0;
  175.     hdma_adc1.Init.Channel = DMA_CHANNEL_0;
  176.     hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
  177.     hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
  178.     hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
  179.     hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  180.     hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  181.     hdma_adc1.Init.Mode = DMA_CIRCULAR;
  182.     hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
  183.     hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  184.     if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
  185.     {
  186.       _Error_Handler(__FILE__, __LINE__);
  187.     }

  188.     __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);

  189.   }
  190. }






复制代码
http://player.youku.com/player.php/sid/XMjk0ODczODg5Ng==/v.swf

由于STM32F446的快速处理信号能力,本方案中同时开启10路带DMA的ADC处理10路50HZ交流电压绰绰有余。演示中在OLED屏幕上显示ADC0通道的转换结果。


收藏 3 评论24 发布时间:2017-8-6 16:35

举报

24个回答
zero99 回答时间:2017-8-7 11:15:11
谢谢支持啦~
csgtli5608 回答时间:2017-8-8 14:10:52
楼主你那是什么软件,配置MCU的那个
wenyangzeng 回答时间:2017-8-8 15:57:39
本帖最后由 wenyangzeng 于 2017-8-8 15:59 编辑
csgtli5608 发表于 2017-8-8 14:10
楼主你那是什么软件,配置MCU的那个

STM32CubeMX,到ST官方网站下载。
https://www.stmcu.org.cn/document/detail/index/id-218002


菜鸟&新手 回答时间:2017-8-11 08:05:27
顶一个
ToddYam 回答时间:2017-8-12 09:52:02
epochal 回答时间:2017-8-26 08:05:58
谢谢分享!
猎国倾城 回答时间:2017-9-2 16:39:44
ufo2012 回答时间:2017-9-25 10:51:08
Draway 回答时间:2017-9-25 18:01:59
最后ADC测得应该是半波,即在正弦波X轴上半部分?
123下一页

所属标签

STM32团队

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


最新内容

相似技术帖

官网相关资源

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