简介

以STM32F103C8T6单片机为核心的小型音乐喷泉控制系统。通过一个简洁的单片机控制电路,分析了音频输出电路和输入电路,介绍了从特定构造的音频信号中获得决定喷池动作的喷池数据的原理。给出了主程序框图和采用程序控制来控制花型,音频信号还影响灯光光线明暗的变化。从而使灯光的闪烁和喷泉水姿随音乐节奏而变化。

单片机作为一种控制用微处理器,包含有基本的软硬件资源。采用单片机控制技术,给出了单片机控制电路,水泵控制电路,流水灯控制电路及部分单片机I/O口初始化程序。随着科学技术突飞猛进的发展,变频调速器技术正大步走进喷泉控制领域,发挥着不可替代的作用。单片机的输出通过数模转换通过水泵驱动电路驱动水泵,通过变频调速技术对电泵进行调速,实现程序控制喷泉的高度,不仅能够进行多种水型切换,而且能控制喷泉水柱上下起伏。同时单片机通过I/O来控制LED灯的亮灭。实现了对喷泉的水、光协同控制。

系统概述

功能

  • 可以播放电脑、手机、MP3里面的音乐。
  • 产品具有8个LED频谱彩灯,随音乐变化闪烁。
  • 音乐停止,喷水电机停止工作。
  • AD对音频信号的采集,转换为数字信号给单片机PWM控制水泵,实现水柱高低变化。

方案设计与论证

芯片选择方案

STM32单片机是整个温度控制系统的核心部分。因为对温度控制器具有较高的要求,例如高执行速度,高控制精度,高稳定性以及高灵敏度等,所以选择一个具有较高性能而又经济的单片机就成为必然。本设计选用属于STM32系列的STM32F103C8T6单片机作为控制电路的核心部件,该单片机属于ST意法半导体公司生产的32位高性能、低成本、低功耗的增强型系列单片机,它的内核采用的是ARM公司最新研发的Cortex-M3架构,该内核是专门设计于满足用户对高性能、低功耗和经济实用的要求

系统概述

STM32F103C8T6单片机有3 个不同的时钟源可供选择用以驱动系统时钟,分别为HSI振荡器时钟、HSE振荡器时钟和PLL时钟。这些设备还具有2个二级时钟源,分别是40KHz的低速内部RC和32.768KHz的低速外部时钟源,可以用来驱动看门狗时钟和RTC。任何一个时钟源在不被使用时,都可以被独立的关闭或者开启,以实现对系统功耗的优化。

系统总体设计思路

通过单片机程序来控制喷泉的水姿变化,成为一种新的喷泉艺术形式。单片机作为一种控制用微处理器,包含有基本的软硬件资源。本文采用了单片机控制技术,给出了单片机控制电路,水泵控制电路,流水灯控制电路及部分单片机I/O口初始化程序。单片机的输出通过数模转换通过水泵驱动电路驱动水泵,通过变频调速技术对电泵进行调速,实现程序控制喷泉的高度,不仅能够进行多种水型切换,而且能控制喷泉水柱上下起伏。同时单片机通过I/O来控制LED灯的亮灭。实现了对喷泉的水、光协同控制。

各功能模块程序实现原理分析

系统主要有STM32F103C8T6单片机和、音频功率放大电流和水泵驱动电路等组成。

水泵驱动模块

根据单片机的电流特性,不足以直接驱动水泵。有三极管的输出特性,利用晶体管的饱和和截止特性构成开关电路。通过二级三极管电流放大实现对水泵控制,P20为高电平时基极与集电极之间反向偏置,不导通;当P20为低电平时,基极与集电极之间正向偏置,导通。电路工作,水泵工作工作,单片机只需要吸收娇小的输入电流。

音频输入及LM386的设计及原理

  • 1与8脚为增益调整端,当两脚开路时,电压放大数为20倍,当两脚间接10uf电容时,电压放大倍数为200倍;

  • 2脚为反相输入端接地;

  • 3脚为同相输入端,在信号输入前加电容将方波信号转换成正弦波信号

  • 4脚为地端;

  • 5脚为输出端,外接电路具有隔直和耦合的作用。隔断直流电压,直流电压过大有可能会损坏喇叭线圈;耦合音频的交流信号。它与扬声器负载构成了一阶高通滤波器。减小该电容值,可使噪声能量冲击的幅度变小、宽度变窄;太低还会使截止频率(fc=1/(2π_RL_Cout))提高。

  • 6脚为电源正端,6脚与地之间接10uf电容可消除可能产生的自激震荡,7脚接100uf。

STM32性能介绍及硬件设计

STM32单片机性能介绍

STM32它拥有的资源包括:48KB SRAM、256KB FLASH、2 个基本定时器、4 个通用定时器、2个高级定时器、2个DMA 控制器(共 12 个通道)、3 个SPI、2个IIC、5个串口、1个USB、1个CAN、3个12位ADC、1个12位DAC、1个SDIO接口及51 个通用IO口,该芯片性价比极高。

STM32单片机是整个温度控制系统的核心部分。因为对温度控制器具有较高的要求,例如高执行速度,高控制精度,高稳定性以及高灵敏度等,所以选择一个具有较高性能而又经济的单片机就成为必然。本设计选用属于STM32系列的STM32F103C8T6单片机作为控制电路的核心部件,该单片机属于ST意法半导体公司生产的32位高性能、低成本、低功耗的增强型系列单片机,它的内核采用的是ARM公司最新研发的Cortex-M3架构,该内核是专门设计于满足用户对高性能、低功耗和经济实用的要求。ARM Cortex-M3处理器的架构在系统结构上的增强,使得STM32增强型系列单片机受益无穷,其采用的THUMB-2指令集使得其指令效率更高和而且性能更强。

各个引脚说明如下

  • PA0 作用1,按键 KEY_UP 2,可以做待机唤醒脚(WKUP) 3,可以接 DS18B20 传感器接口(P2 设置)
  • PA1作用1,NRF24L01 接口 IRQ 信号 2,接 HS0038 红外接收头(P2 设置)
  • PA2 作用 作为W25Q64 的片选信号
  • PA3 作用 作为SD 卡接口的片选脚
  • PA4 作用 作为NRF24L01 接口的 CE 信号
  • PA5 作用 作为W25Q64、SD 卡和 NRF24L01 接口的 SCK 信号
  • PA6 作用 作为 W25Q64、SD 卡和 NRF24L01 接口的 MISO 信号
  • PA7 作用 作为 W25Q64、SD 卡和 NRF24L01 接口的 MOSI 信号
  • PA8 作用 作为 接 DS0 LED 灯(红色)
  • PA9 作用 作为串口 1 TX 脚,默认连接 CH340 的 RX(P4 设置)
  • PA10 作用 作为串口 1 RX 脚,默认连接 CH340 的 TX(P4 设置)
  • PA11 作用 作为接 USB D-引脚
  • PA12 作用 作为接 USB D+引脚
  • PA13作用 作为JTAG/SWD 仿真接口,没接任何外设
  • PA14 作用 作为JTAG/SWD 仿真接口,没接任何外设PA15 作用 作为1,JTAG 仿真口(JTDI) 2,PS/2 接口的 CLK 信号 3,接按键 KEY1

音乐喷泉系统硬件设计

该程序所需要的电源电路,功率放大电路,音频输入电路,LED灯显示电路,水泵驱动电路,次如下图所示

水泵驱动电路图

根据单片机的电流特性,不足以直接驱动水泵。有三极管的输出特性,利用晶体管的饱和和截止特性构成开关电路。通过二级三极管电流放大实现对水泵控制,P20为高电平时基极与集电极之间反向偏置,不导通;当P20为低电平时,基极与集电极之间正向偏置,导通。电路工作,水泵工作工作,单片机只需要吸收娇小的输入电流。

音频输入电路图如下图

通过LINEIN输入外部音频信号经LM386对音频信号进行功率放大,实现对音乐的播放。

LED电路图如下图

原理图

PCB

BOM

系统程序

主程序设计如下

音乐喷泉系统主要由单片机通过红外通信控制,当其完成红外信号,读取数据,其数据的传输根据协议的内容,音乐喷泉系统程序需要完成以下的功能:

  • Led灯随音频信号起伏;
  • 水泵的喷水量随音量的变化而变化。

程序流程图如下:

img

# 主程序内容

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f1xx_hal.h"

/* USER CODE BEGIN Includes */
#include <math.h>
#include <stdio.h>

/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;

IWDG_HandleTypeDef hiwdg;

TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;

UART_HandleTypeDef huart1;

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

//宏定义灯IO
#define LED0_0  HAL_GPIO_WritePin(GPIOA,GPIO_PIN_15,GPIO_PIN_RESET)
#define LED0_1  HAL_GPIO_WritePin(GPIOA,GPIO_PIN_15,GPIO_PIN_SET)

#define LED1_0  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,GPIO_PIN_RESET)
#define LED1_1  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,GPIO_PIN_SET)

#define LED2_0  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET)
#define LED2_1  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET)

#define LED3_0  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET)
#define LED3_1  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET)

#define LED4_0  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET)
#define LED4_1  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET)

#define LED5_0  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET)
#define LED5_1  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET)

#define LED6_0  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET)
#define LED6_1  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET)

#define LED7_0  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET)
#define LED7_1  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET)


unsigned char PWM_falg=1;

uint8_t ch;
 uint8_t ch_r;
//重写这个函数,重定向printf函数到串口,意思就是说printf直接输出到串口,其默认输出到控制台的
 /*fputc*/
 int fputc(int c, FILE * f)
 {
     ch=c;
     HAL_UART_Transmit(&huart1,&ch,1,1000);//发送串口
     return c;
 }



 //重定向scanf函数到串口 意思就是说接受串口发过来的数据,其默认是接受控制台的数据
 /*fgetc*/
 int fgetc(FILE * F)    
 {
     HAL_UART_Receive (&huart1,&ch_r,1,0xffff);//接收
     return ch_r;
 }




//下面定义关于串口的
unsigned char Uart1_Buff[1024];  //串口1缓冲数组
unsigned char Uart1_Count=0;     //串口1累加变量
uint8_t aRxBuffer[3];            //定义一个暂存数组

//下面定义关于定时器的
unsigned int  Time4_ms=0;

//下面定义关于读取ADC的
unsigned char Scan_Fre=0;
unsigned int  ADC_Dat=0;

//下面定义有关傅里叶的-> 移植的





//下面定义启停部分
unsigned char Open_Close=1;
unsigned char System_Count=0;
unsigned int Open_Flsh=0;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM4_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM3_Init(void);
static void MX_IWDG_Init(void);
static void MX_USART1_UART_Init(void);

void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);


/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

struct Complex {
char real;//实部
char imag;//虚部
}; //构造复数结构
typedef struct Complex COMPLEX;  
#define  N    128   //FFT点数(长度)
#define  PI2 128        //一周期分成128点
COMPLEX  S[N]; //FFT复数数组  
unsigned char  iw[128]={0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,10,11,11,12,12,12,13,13,14,14,14,15,15,15,16,16,16,17,17,17,17,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,22,22,22,22,23,23,23,23,23,24,24,24,24,25,25,25,25,25,26,26,26,26,26,27,27,27,27,27,27,28,28,28,28,28,29,29,29,29,29,29,30,30,30,30,30,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31};
char  costab[PI2]={
127,127,127,126,125,124,122,120,118,115,112,109,106,102,
98,94,90,85,81,76,71,65,60,54,48,43,37,31,24,18,12,6,0,
-6,-12,-18,-24,-31,-37,-43,-48,-54,-60,-65,-71,-76,-81,
-85,-90,-94,-98,-102,-106,-109,-112,-115,-118,-120,-122,
-124,-125,-126,-127,-127,-128,-127,-127,-126,-125,-124,
-122,-120,-118,-115,-112,-109,-106,-102,-98,-94,-90,-85,
-81,-76,-71,-65,-60,-54,-48,-43,-37,-31,-24,-18,-12,-6,0,
6,12,18,24,31,37,43,48,54,60,65,71,76,81,85,90,94,98,
102,106,109,112,115,118,120,122,124,125,126,127,127
//127,127,126,126,125,123,122,120,117,115,112,109,106,102,
//98,94,90,85,81,76,71,65,60,54,49,43,37,31,25,19,12,6,0,
//-6,-12,-19,-25,-31,-37,-43,-49,-54,-60,-65,-71,-76,-81,
//-85,-90,-94,-98,-102,-106,-109,-112,-115,-117,-120,-122,
//-123,-125,-126,-126,-127,-127,-127,-126,-126,-125,-123,
//-122,-120,-117,-115,-112,-109,-106,-102,-98,-94,-90,-85,
//-81,-76,-71,-65,-60,-54,-49,-43,-37,-31,-25,-19,-12,-6,
//0,6,12,19,25,31,37,43,49,54,60,65,71,76,81,85,90,94,98,
//102,106,109,112,115,117,120,122,123,125,126,126,127
};
char sintab[PI2]={
0,6,12,18,24,31,37,43,48,54,60,65,71,76,81,85,90,94,98,
102,106,109,112,115,118,120,122,124,125,126,127,127,128,
127,127,126,125,124,122,120,118,115,112,109,106,102,98,
94,90,85,81,76,71,65,60,54,48,43,37,31,24,18,12,6,0,-6,
-12,-18,-24,-31,-37,-43,-48,-54,-60,-65,-71,-76,-81,-85,
-90,-94,-98,-102,-106,-109,-112,-115,-118,-120,-122,-124,
-125,-126,-127,-127,-128  ,-127,-127,-126,-125,-124,-122,
-120,-118,-115,-112,-109,-106,-102,-98,-94,-90,-85,-81,
-76,-71,-65,-60,-54,-48,-43,-37,-31,-24,-18,-12,-6
//0,6,12,19,25,31,37,43,49,54,60,65,71,76,81,85,90,94,98,
//102,106,109,112,115,117,120,122,123,125,126,126,127,127,
//127,126,126,125,123,122,120,117,115,112,109,106,102,98,
//94,90,85,81,76,71,65,60,54,49,43,37,31,25,19,12,6,0,-6,
//-12,-19,-25,-31,-37,-43,-49,-54,-60,-65,-71,-76,-81,-85,
//-90,-94,-98,-102,-106,-109,-112,-115,-117,-120,-122,-123,
//-125,-126,-126,-127,-127,-127,-126,-126,-125,-123,-122,
//-120,-117,-115,-112,-109,-106,-102,-98,-94,-90,-85,-81,
//-76,-71,-65,-60,-54,-49,-43,-37,-31,-25,-19,-12,-6
};
/****************************************************
x:输入数据实部,输出数据实部(有符号数)
y:输入数据虚部,输出数据虚部(有符号数)
n:点数
*************************************************/
void fft(COMPLEX *XX,unsigned char n)
{//x[]为实部,y[]为虚部(全为0),n为点数
 int tr,ti,p,q;
 unsigned char i,j,k,qn,a,b,c,cen,zu,ge;
 a=n-1;
 for(i=0,j=0;i<a;i++)//循环n-1次
 {                                              
  if(i<j)                                     
  {
   tr=XX[j].real;
   XX[j].real=XX[i].real;
   XX[i].real=tr; 
   ti=XX[j].imag;
   XX[j].imag=XX[i].imag;
   XX[i].imag=ti;
  }//交换x[i]<->x[j],y[i]<->y[j]
  k=n/2;
  while(k<(j+1))
  {
   j=j-k;
   k=k/2;
  }
  j=j+k;
 }//此循环把原序列变成2点奇偶序列

 /****************************************/
 for(i=1,j=1;i<8;i++)
 {
   j=2*j;//j=2^p
   if(j>=n)break;
 }
 //2的i次方=n
 cen=i;                           //如果n=8,则cen=3;
 zu=n;
 for(i=0;i<cen;i++)           //层数(0,1,2)
 {
  zu=zu/2;           //组数(4,2,1)
  for(j=0;j<zu;j++)           //第i 层中的第 j组
  {  
   ge=(n/zu)/2;//一组中蝶形的个数(1,2,4)      
   for(k=0;k<ge;k++)       //第 j 组中的第k个
   {                       //第 a 和第 b 个元素作蝶形运算,WNC
    a=j*ge*2+k;               //(0,2,4,6)(0,1,4,5)(0,1,2,3)
    b=a+ge;                   //(ge=1,2,4)
    c=k*zu;                   //(0,0,0,0)(0,2,0,2)(0,1,2,3)
       qn=(PI2/n)*c;
    //注意sign
      tr=(XX[b].real*costab[qn]+XX[b].imag*sintab[qn])>>7;//由于正余弦表放大128倍,此处缩小128倍
    ti=(XX[b].imag*costab[qn]-XX[b].real*sintab[qn])>>7;
    p=XX[a].real;
    q=XX[a].imag;
    //蝶形运算
    XX[a].real=(p+tr)>>1;//防止数据溢出
    XX[a].imag=(q+ti)>>1;
    XX[b].real=(p-tr)>>1;
    XX[b].imag=(q-ti)>>1;
   }
  } 
 }
}


unsigned char  FFTvaule[64];//输出的频谱值(转换到0~31)
unsigned char  TopPoint[64];//顶点值 [顶部的绿点]
unsigned char  Keep[64];  //顶点停留
unsigned char  LINE;
unsigned char  ADC_Count;

//对fft数据进行处理
void FFTK()
{ 
unsigned char pt=0,j; 
for(pt=0;pt<N;pt++)
{
    S[pt].imag=0; //清零虚部 
    S[pt].real=(S[pt].real-128);//电压转换128
}
////////////////////////////////////
fft(S,N);//对当前数据进行傅立叶变换  
FFTvaule[0]=0x00;
//处理顶点        
for(pt=0;pt<N/2;pt++) 
{

    S[pt].real=sqrtf(S[pt].real*S[pt].real+S[pt].imag*S[pt].imag);//求模
    if((unsigned char)(S[pt].real)<255) 
        FFTvaule[pt] =iw[(unsigned char)(S[pt].real)];
    //处理顶点值 
    if(FFTvaule[pt]>=TopPoint[pt])
    {
        TopPoint[pt] = FFTvaule[pt]+1;
        Keep[pt] = 12;
    }
    else if(TopPoint[pt]>1)
    { 
        if(Keep[pt])      Keep[pt]--;
        else   
        {
          TopPoint[pt]--;
        }
    }
    else 
    TopPoint[j] = 1; 
}
}

unsigned int Get_ADC()
{
    unsigned int ADC_Back;
        HAL_ADC_Start(&hadc1);  
        HAL_ADC_PollForConversion(&hadc1,0xffff); //等待检测结束
        ADC_Back=((HAL_ADC_GetValue(&hadc1)));  
        HAL_ADC_Stop(&hadc1); //结束AD检测
      ADC_Dat=ADC_Back;

      if(Open_Close==1) 
        {
          if(Open_Flsh!=ADC_Dat)
            {
              if(Open_Flsh>ADC_Dat)
                {
                  if(Open_Flsh-ADC_Dat >70) 
                    {
                      System_Count++;

                        if(System_Count>=5) 
                        {
                          System_Count=0;
                            Open_Close=0;
                        }
                    }
                }
                else 
                {
                  if(ADC_Dat-Open_Flsh >70) 
                    {
                       System_Count++;
                         if(System_Count>=5) 
                         {
                          System_Count=0;
                            Open_Close=0;
                         }
                    }
                }
                Open_Flsh=ADC_Dat;
            }
        }
        else 
        {
          if(Open_Flsh!=ADC_Dat)
            {
              if(Open_Flsh>ADC_Dat)
                {
                  if(Open_Flsh-ADC_Dat <70) 
                    {
                      System_Count++;

                        if(System_Count>=5) 
                        {
                          System_Count=0;
                            Open_Close=1;
                        }
                    }
                }
                else 
                {
                  if(ADC_Dat-Open_Flsh <70) 
                    {
                       System_Count++;
                         if(System_Count>=5) 
                         {
                          System_Count=0;
                            Open_Close=1;
                         }
                    }
                }
                Open_Flsh=ADC_Dat;
            }
        }

    return ADC_Back;
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 
{
    if(htim==&htim4)
      {
         Time4_ms++;
                 if(Time4_ms%80==0) 
                 {
                     Time4_ms=0;
                   Scan_Fre =1;
                     GPIOC->ODR^=GPIO_PIN_13;
                 }
            }
}
void LED_Dispose(unsigned char Dat_) 
{
  if(Dat_>31) LED0_0;
    else        LED0_1;
    if(Dat_>62) LED1_0;
    else         LED1_1;
    if(Dat_>93) LED2_0;
    else    LED2_1;

    if(Dat_>124) LED3_0;
    else LED3_1;

    if(Dat_>155) LED4_0;
    else LED4_1;

    if(Dat_>186) LED5_0;
    else LED5_1;

    if(Dat_>217)LED6_0; 
    else LED6_1;

    if(Dat_>240)LED7_0; 
    else LED7_1;
}


void Debug_Output()
{

   unsigned char Coun=0;

//   printf("\r\n%s\r\n","-------------------- Star --------------------"); 
//     printf("\r\n%s","Read_AD:"); 
//      printf("%d\r\n",ADC_Dat);

     for(Coun=0;Coun<30;Coun++) 
     {
         if(FFTvaule[0]<22)
         {
              LED0_1 ;
              LED1_1 ;
              LED2_1 ;
              LED3_1 ;
              LED4_1 ;
              LED5_1 ;
              LED6_1 ;
              LED7_1 ;
              HAL_TIM_PWM_Stop(&htim3,TIM_CHANNEL_4);
              PWM_falg=1;
         }
         else  
         {
             if(PWM_falg==1)
             {
               HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_4);
                 PWM_falg=0;
             }
             if(FFTvaule[Coun]*257<65535)   TIM3->CCR4 = FFTvaule[Coun]*257;
           LED_Dispose(FFTvaule[Coun]);
         }

         printf("%d,",FFTvaule[Coun]);

     }
      printf("\r\n%d",ADC_Dat); 

      printf("%s","\r\n");
//   printf("\r\n%s\r\n","--------------------  End  --------------------");  
//        
}


/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  *
  * @retval None
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

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

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM4_Init();
  MX_ADC1_Init();
  MX_TIM3_Init();
  MX_IWDG_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

   HAL_TIM_Base_Start_IT(&htim4); 
   HAL_UART_Transmit(&huart1,(unsigned char *)"System_Star\r\n",13,100);
   HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_4);
   TIM3->CCR4 =0;


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

        Get_ADC();  //多执行一次,简单粗暴

        if(Open_Close ==0) 
        {
            for(ADC_Count=0;ADC_Count<N;ADC_Count++)
            {
                S[ADC_Count].real =Get_ADC()/4;
                S[ADC_Count].imag =0;    
            }    

            FFTK();    //FFT

            if(Scan_Fre==1) 
            {
                Scan_Fre=0;
                Debug_Output();

            }
        }





     HAL_IWDG_Refresh(&hiwdg); 
  }
  /* USER CODE END 3 */

}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInit;

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time 
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* ADC1 init function */
static void MX_ADC1_Init(void)
{

  ADC_ChannelConfTypeDef sConfig;

    /**Common config 
    */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure Regular Channel 
    */
  sConfig.Channel = ADC_CHANNEL_8;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

/* IWDG init function */
static void MX_IWDG_Init(void)
{

  hiwdg.Instance = IWDG;
  hiwdg.Init.Prescaler = IWDG_PRESCALER_32;
  hiwdg.Init.Reload = 800;
  if (HAL_IWDG_Init(&hiwdg) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

/* TIM3 init function */
static void MX_TIM3_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 63;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 1000;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  HAL_TIM_MspPostInit(&htim3);

}

/* TIM4 init function */
static void MX_TIM4_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 63;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 1000;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

/* USART1 init function */
static void MX_USART1_UART_Init(void)
{

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

/** Configure pins as 
        * Analog 
        * Input 
        * Output
        * EVENT_OUT
        * EXTI
*/
static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6 
                          |GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_SET);

  /*Configure GPIO pin : PC13 */
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PA15 */
  GPIO_InitStruct.Pin = GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PB3 PB4 PB5 PB6 
                           PB7 PB8 PB9 */
  GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6 
                          |GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  file: The file name as string.
  * @param  line: The line in file as a number.
  * @retval None
  */
void _Error_Handler(char *file, int line)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  while(1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/