嵌入式分享合集105

news2025/7/22 9:39:14

一、智能灯光控制系统(基于stm32)

带你走进物联网的世界说一个整天方案哦 这次是基于stm32的 当然你可以用esp

“智能光照灯”使用STM32作为系统的MCU,由于单片机IO口驱动电流过小,搭配三极管放大电流,从而满足光照强度需求,且将单片机IO配置成PWM输出,以便于调节不同的光强度,也就是一档、二档、三档。在此基础上增加WiFi模块搭配手机APP可实现在手机端控制灯光、使用su-03t语音识别模块可实现语音控制灯光等,其他额外功能在下文介绍。所需材料如表1所示。

表1 材料清单

序号

名称

数量

1

STM32核心板

1

2

三极管

3

3

LED灯板

2

4

WiFi模块

1

5

Su-03t芯片

1

6

oled屏幕

1

7

超声波模块

1

8

dht11

1

9

按键

4

10

蜂鸣器

1

项目整体展示如图1:

需要的模块

01 STM32核心板

STM32是“意法半导体”生产的基于“ARM公司Cortex-M3内核”的32位MCU,其性能强大,资源丰富,被广泛应用于嵌入式系统的开发,也是高校学生接触嵌入式的敲门砖。最小系统板如图2所示,其由处理器、电源、复位、晶振电路等组成,可独立的完成相应的控制任务,在本次工程中核心知识就是PWM输出,I/O口引脚电平判断。

图2  STM32最小系统板 

02 三极管

三极管的放大作用就是:集电极电流受基极电流的控制(假设电源能够提供给集电极足够大的电流的话),并且基极电流很小的变化,会引起集电极电流很大的变化,且变化满足一定的比例关系:集电极电流的变化量是基极电流变化量的β倍,即电流变化被放大了β倍。至于三极管的控制,如图3所示及其简单,在图片中所标的A引脚初,输出高电平就能导通三极管,上方VCC的电源就能流过三极管。

03 WiFi模块

本项目所使用的WiFi模块是ESP-01S,是ESP8266系列的一种,其可以连接环境中的WiFi,从而使设备上网。本项目主要使用了该模块串口功能,通过串口与stm32单片机连接,WiFi模块通过周围环境中的WiFi信号连接云平台,如此将WiFi模块作为中介,可以实现单片机与云平台的信息交互。WiFi模块与单片机连接引脚如图4:

图4  WiFi模块连接图 

04 su-03t语音识别模块

su-03t是一款低成本、低功耗、小体积的离线语音识别的模组,无需编程,使用刷词条的方式进行开发,可谓是不爱编程的福音啊。本项目使用该模块的串口功能,通俗一点讲就是模块识别到相应的语音命令后,通过串口输出一个数据。关于该模块的配置,本文再次不过多阐述。该模块引脚如图5所示:

图5  SU-03T引脚展示图 

05 超声波模块

超声波模块为HC-SR04如图6所示,该超声波测距模块可提供约2cm~400厘米的非接触式距离感测功能,测距精度可达高到3毫米,该模块由发射装置与接受装置组成,发射装置发射超声波,接受装置接受超声波并将电平做出相应转变。

图6 超声波模块

06 OLED屏 

OLED显示屏是利用有机电自发光二极管制成的显示屏。由于同时具备自发光有机电激发光二极管,不需背光源、对比度高、厚度薄、视角广、反应速度快、比LCD屏幕显示效果更好一些,但由于现有技术限制,目前OLED屏幕无法做的很大。本项目主要使用OLED屏幕显示台灯的当前状态、温湿度信息、以及万年历时钟灯,相关显示如图7所示。

制作

01 先让灯亮起来

灯带是通过三极管驱动的,单片机的IO口连接三极管基极,可以将其看成控制信号,当该引脚输出高电平时,可以认为三极管导通,电流由发射极提供,由集电极输出,本设计中发射极连接VCC,也就是用电源给等待供电,这个电流远大于IO口直接输出的电流,足以满足等待的需求。

02 调节灯光亮度

刚刚已经介绍过如何使用三极管点亮灯带。那么又该如何控制灯的亮度哪?也就是如何控制电流呢?这就需要常说的PWM输出了,可以将三极管看成一个“水龙头”,PWM可以理解为我们拧水龙头的力气,通过调节不同的占空比,使得三极管“打开不同的口子”,控制逻辑如下:

PWM占空比大→“打开的口子大”→输出的电流大→灯带更亮

PWM占空比小→“打开的口子小”→输出的电流小→灯带更暗

在程序中首先将IO口配置为PWM输出,本设计选用的定时器4的通道3与通道4产生PWM(两个灯,一个冷光一个暖光,需要两路PWM输出)具体程序见程序1:

程序1:

void Motor_PWM_Init(u16 arr,u16 psc){       GPIO_InitTypeDef GPIO_InitStructure;      TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;      TIM_OCInitTypeDef  TIM_OCInitStructure;           RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);      //使能定时器4时钟       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟               /*****输出TIM4_CH3和TIM4_CH4和的PWM脉冲波形*****/      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; //TIM_CH3和TIM_CH4      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO   /********************初始化TIM3*******************/      TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值      TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值      TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim      TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式      TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位           /*******初始化TIM4 Channel3、TIM4 Channel4 PWM模式********/             TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2       TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性高      TIM_OC3Init(TIM4, &TIM_OCInitStructure);  //初始化外设TIM4 OC3      TIM_OC4Init(TIM4, &TIM_OCInitStructure);  //初始化外设TIM4 OC4   /*******使能预装载寄存器********/      TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);       TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);       TIM_Cmd(TIM4, ENABLE);  //使能TIM4     }

如此PWM的输出就已经配置好了,下面就在主循环中调用修改PWM占空比函数即可,具体程序见程序2,该程序修改了三个不同的占空比,以对应灯光的一档、二档、三档。

程序2:

/********两端都使能 1档**********/TIM_SetCompare3(TIM4,800);                             TIM_SetCompare4(TIM4,800);     /********两端都使能 2档**********/TIM_SetCompare3(TIM4,2000);     TIM_SetCompare4(TIM4,2000);     /********两端都使能 3档**********/TIM_SetCompare3(TIM4,5000);     TIM_SetCompare4(TIM4,5000);

03 远程控制功能

正如上文所说,远程控制功能实现的原理是,手机app开发时连接上云平台,手机APP相应按键触发时,将相应的控制指令上传至云平台,esp-01s通过周围的WiFi信号连接云平台,获取云平台上的数据,并通过串口将该数据传输给STM32单片机,单片机解析数据并完成相应的驱动。接下来就分布实现开发,分为手机端app的制作,手机连接云平台、设备连接云平台。

(1) 手机端app的制作

自行开发哦

(2) 手机端连接云平台

也很简单弄个阿里云 搭建个工程或直接弄个mqtt也都行

(3) 设备(单片机)连接云平台

esp-01s也是一个MCU,通过编程开发,本设计通过arduino平台开发相关的功能,值得注意的是esp-01s通过wifi信号连接云平台,所以环境中必须要有WiFi,由于此处程序过多,仅展示重要的地方。

①云平台定义及主题相关定义见程序3:

程序3:​​​​​​​

#include#include//巴法云服务器地址#define TCP_SERVER_ADDR "bemfa.com"//服务器端口,tcp创客云端口8344#define TCP_SERVER_PORT "8344"//********************需要修改的部分*******************//#define DEFAULT_STASSID  "HUAWEI P30 Pro+"     //WIFI名称,区分大小写,不要写错#define DEFAULT_STAPSW   "18253858772"        //WIFI密码String UID = "23f9a5f2d3584dc8516409db14b4827c";  //用户私钥,可在控制台获取,修改为自己的UIDString TOPIC1 ="TD00light";         //主题名字,可在控制台新建String TOPIC2 = "TD00temp";       //用户私钥,可在控制台获取,修改为自己的UIDconst int LED_Pin = 0;              //单片机LED引脚值,GPIO0引脚int pinDHT11 = 2;//**************************************************//

②接下来是连接服务器,向服务器发送指令cmd=1&uid="+UID+"&topic="+

TOPIC1+"\r\n,其中的UID与TOPIC1就是程序3中相关的定义具体程序见程序4。

程序4:​​​​​​​

void startTCPClient(){if(TCPclient.connect(TCP_SERVER_ADDR,atoi(TCP_SERVER_PORT))){         Serial.print("\nConnected to server:");Serial.printf("%s:%d\r\n",TCP_SERVER_ADDR,atoi(TCP_SERVER_POR      T));    String tcpTemp="";  //初始化字符串    tcpTemp = "cmd=1&uid="+UID+"&topic="+TOPIC1+"\r\n"; //构建订阅指令    sendtoTCPServer(tcpTemp); //发送订阅指令    tcpTemp="";//清空       preTCPConnected = true;    preHeartTick = millis();    TCPclient.setNoDelay(true);  }  else{    Serial.print("Failed connected to server:");    Serial.println(TCP_SERVER_ADDR);    TCPclient.stop();    preTCPConnected = false;  }  preTCPStartTick = millis();}

③获取云平台传来的数据,并通过串口传输给STM32,具体程序见程序5:

程序5:​​​​​​​

if (TCPclient.available()) //若有数据传来{   char c =TCPclient.read();   TcpClient_Buff +=c;        //数据存储   TcpClient_BuffIndex++;   TcpClient_preTick = millis();   if(TcpClient_BuffIndex>=MAX_PACKETSIZE - 1)   {      TcpClient_BuffIndex = MAX_PACKETSIZE-2;      TcpClient_preTick = TcpClient_preTick - 200;    }    preHeartTick = millis(); }if((TcpClient_Buff.length() >= 1) && (millis() - TcpClient_preTick>=200)){   TCPclient.flush();   Serial.println(TcpClient_Buff);    //串口传输   if((TcpClient_Buff.indexOf("&msg=11") > 0)){      turnOnLed();    }else if((TcpClient_Buff.indexOf("&msg=10") > 0)){      turnOffLed();    }   TcpClient_Buff="";   TcpClient_BuffIndex = 0;  }

如此就可以将云平台中的控制指令传输给STM32,STM32进行解析并完成相应的控制,由于本设计还添加了语音识别功能,所以相关控制的实现等讲解完语音识别后在进行讲解。

04 语音识别功能​​​​​​​

语音识别功能主要采用了SU-03T离线语音识别模块,这个模块不需要编程,使用厂家提供的云平台开发,正如前文所说本设计主要用了该模块的串口功能,该模块的串口与STM32单片机的另一个串口连接,当识别到相应的语音时,串口输出相应的控制指令给STM32。该模块相关配置如图10所示。

图10 su-03t平台配置

05 STM32解析指令并完成相关驱动

正如前文所说,WiFi模块与su-03t都是使用串口与STM32单片机建立联系的,所以我们首先需要完成串口的相关配置,在此以WiFi模块对应的usart3为例,配置串口,具体程序见程序5:     

程序5: ​​​​​​​

void usart3_init(u32 bound){ NVIC_InitTypeDef NVIC_InitStructure;      GPIO_InitTypeDef GPIO_InitStructure;      USART_InitTypeDef USART_InitStructure;/***********使能时钟************/      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);            RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);       USART_DeInit(USART3);  //复位串口3/*******配置输出引脚*******/   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;      //复用推挽输出   GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10     /*******配置输入引脚*******/   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入   GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PB11     /********串口相关配置********/      USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;      USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式      USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位      USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;      USART_Init(USART3, &USART_InitStructure); //初始化串口3      USART_Cmd(USART3, ENABLE);                    //使能串口   USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断             /*******设置中断优先级********/      NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;            //子优先级3      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;      //IRQ通道使能      NVIC_Init(&NVIC_InitStructure);      //根据指定的参数初始化VIC寄存器           TIM3_Int_Init(1000-1,7200-1);            //10ms中断      USART3_RX_STA=0;                   //清零      TIM_Cmd(TIM3,DISABLE);                  //关闭定时器7}

至此WiFi模块对应的串口就配置完成,su-0t对应的串口配置与该串口相似,WiFi模块传输来的数据是需要解析的,而su-03t直接传输的十六进制,不需要解析,所以接下来就是解析WiFi模块通过串口传来的数据,具体程序见程序6。

程序6:​​​​​​​

if(USART3_RX_STA&0X8000)            //接收到一次数据了{      rlen=USART3_RX_STA&0X7FFF;      //得到本次接收到的数据长度      USART3_RX_BUF[rlen]=0;            //添加结束符      //数据提取      if(strncmp(USART3_RX_BUF,"cmd=2",5)==0)      {            for(i=0;i<strlen(usart3_rx_buf)+1;i++)< span=""></strlen(usart3_rx_buf)+1;i++)<>            {                  data_tiqu[s]=USART3_RX_BUF[i];                  s++;            }            printf("%s",data_tiqu);            for(i=0;i<strlen(data_tiqu);i++)< span=""></strlen(data_tiqu);i++)<>            {                  if(data_tiqu[i]==cmd[0])                  {                        k=i;                        k++;                        for(j=1;j<strlen(cmd);j++)< span=""></strlen(cmd);j++)<>                        {                              if(data_tiqu[k]==cmd[j])                              {                                    k++;                                    flag=1;                              }                              else                              {                                    flag=0;                              }                        }                  }                             }            s=0;            //数据提取结束            printf("\r\n\r\n");            if(flag==1)            {                  for(i=k+1;i<strlen(data_tiqu)+1;i++) 此时="" i为传输接受数据的索引<="" span="">                  {                        data[s]=data_tiqu[i];                        s++;                  }                  printf("%s",data);                  printf("zaici");     //作用:程序定位                  printf("\r\n");            }      }      if(strncmp(USART3_RX_BUF,"cmd=0&res=1",11)==0)      {            printf("%s",USART3_RX_BUF);      }      USART3_RX_STA=0;}

解析好的数据就存放在data这个数组中,接下来就在主循环中判断data数组中存放的数据以及su-03t通过串口直接传来的十六进制指令即可,根据相应的指令完成相关外设的驱动,具体程序见程序7。

程序7:​​​​​​​

/******************驱动控制**************************///判断APP控制开关灯if((data[0]=='1'&&data[1]=='1') || (temp == 0x11)){      GPIO_SetBits(LED0_PORT,LED0_PIN);   //开LED0      GPIO_ResetBits(LED1_PORT,LED1_PIN); //关LED1      TIM_SetCompare3(TIM4,800);                              //两端都使能 1档      TIM_SetCompare4(TIM4,800);                temp=0;      state_flag_temp=11;      state_flag[0]=1;  //冷亮      state_flag[2]=1;  //一档      display_on[5] = 24;    //已为您打开灯(oled显示的汉字在数组中的索引)      display_on[6] = 0;      //已为您打开灯(oled显示的汉字在数组中的索引)}if((data[0]=='1'&&data[1]=='0') || (temp == 0x10)){      GPIO_ResetBits(LED0_PORT,LED0_PIN); //关LED0      GPIO_ResetBits(LED1_PORT,LED1_PIN); //关LED1      temp=0;      state_flag_temp=10;      state_flag[0]=0;        state_flag[1]=0;      state_flag[2]=0;       display_off[5] = 24;      display_off[6] = 0;}//判断APP控制冷暖光调节if((data[0]=='2'&&data[1]=='1') || (temp == 0x21)) //冷亮暖灭{      GPIO_SetBits(LED0_PORT,LED0_PIN);       //IN1—开冷光LED0      GPIO_ResetBits(LED1_PORT,LED1_PIN); //IN3—关暖光LED1      temp=0;      state_flag_temp=21;      state_flag[0]=1;  //冷亮      state_flag[1]=0;  //暖灭      display_on[5] = 26;                  display_on[6] = 25;            }if((data[0]=='2'&&data[1]=='2') || (temp == 0x22))  //冷灭暖亮{      GPIO_ResetBits(LED0_PORT,LED0_PIN);       //IN1—关冷光LED0      GPIO_SetBits(LED1_PORT,LED1_PIN);             //IN3—开暖光LED1      temp=0;      state_flag_temp=22;      state_flag[0]=0;  //冷灭      state_flag[1]=1;  //暖亮      display_on[5] = 27;               display_on[6] = 25;}                      //判断APP控制1、2、3档位if((data[0]=='3'&&data[1]=='1')|| (temp == 0x31))                    //1档{      TIM_SetCompare3(TIM4,800);                              //两端都使能 1档      TIM_SetCompare4(TIM4,800);           temp=0;      state_flag_temp=31;      state_flag[2]=1;     //一档      display_now[5] = 37;             }if((data[0]=='3'&&data[1]=='2')|| (temp == 0x32))                    //2档{      TIM_SetCompare3(TIM4,2000);                              //两端都使能 2档      TIM_SetCompare4(TIM4,2000);           temp=0;      state_flag_temp=32;      state_flag[2]=2;              //二档      display_now[5] = 38;}if((data[0]=='3'&&data[1]=='3')|| (temp == 0x33))                     //3档{      TIM_SetCompare3(TIM4,5000);                              //两端都使能 3档      TIM_SetCompare4(TIM4,5000);           temp=0;      state_flag_temp=33;      state_flag[2]=3;        //三档      display_now[5] = 39;     }

至此台灯的控制功能已经全部开发完毕,已经实现了APP远程控制、语音控制功能。

06 超声波识别坐姿

还记得在第二章节所介绍的超声波模块HC-SR04,该模块主要是用于把该系统做成台灯时使用,用于检测坐姿规范的,若是开发家里的照明灯,可不加该模块。该模块实现测距的主要原理是:发射装置发射超声波,同时打开定时器,超声波遇到障碍物反弹,被接收装置接受,此时获取定时器的时间,然后根据速度计算距离。其坐姿判断逻辑如下:

HC-SR04测距低于阈值→坐姿不对,距离桌面过近→蜂鸣器报警

HC-SR04测距高于阈值→坐姿正确,距离桌面适宜→蜂鸣器正常

具体程序见程序8:

程序8:​​​​​​​

//一次获取超声波测距数据 两次测距之间需要相隔一段时间,隔断回响信号//为了消除余震的影响,取五次数据的平均值进行加权滤波。float Hcsr04GetLength(void ){      u32 t = 0;      int i = 0;      float lengthTemp = 0;      float sum = 0;      while(i!=5)      {            TRIG_Send = 1;      //发送口高电平输出            Delay_Us(20);            TRIG_Send = 0;            while(ECHO_Reci == 0);      //等待接收口高电平输出            OpenTimerForHc();        //打开定时器            i = i + 1;            while(ECHO_Reci == 1);            CloseTimerForHc();        //关闭定时器            t = GetEchoTimer();        //获取时间,分辨率为1US            lengthTemp = ((float)t/58.0);//cm            sum = lengthTemp + sum ;      }      lengthTemp = sum/5.0;      return lengthTemp;}Hcsr_num++;if(Hcsr_num == 5){      Hcsr_num = 0;      length_C = Hcsr04GetLength();                 //测距离      printf("距离为:%.3f\r\n",length_C);      if(length_C < 20)      {            state_flag[3] =1;            BEEP =~ BEEP;            delay_ms(300);      }      else      {            state_flag[3] =0;            BEEP = 0;      }      if(Hcsr_flag != state_flag[3])      {            Hcsr_flag = state_flag[3];            display_all_flag=1;      }}

07 OLED屏显示状态

这部分实现的原理是,在上方介绍相关控制功能时会更改相应的标志位,然后在主程序中检查该标志位的状态,当标志位发生改变时,修改OLED屏幕的显示,具体程序见程序9。

程序9:​​​​​​​

switch(Dis_mode){      case 0:                                                                //在显示控制状态界面            switch(state_flag_temp)     //定时显示界面            {                  case 11:control_part_display(2,6,display_1,display_on);break;      //显示“以为您打开灯”                  case 10:control_part_display(2,6,display_1,display_off);break;     //显示“以为您关闭灯”                  case 21:control_part_display(1,7,display_1,display_on);break;      //显示“以为您打开冷灯”                  case 22:control_part_display(1,7,display_1,display_on);break;      //显示“以为您打开暖灯”                  case 31:control_part_display(1,7,display_1,display_now);break;     //显示“当前亮度为一档”                  case 32:control_part_display(1,7,display_1,display_now);break;     //显示“当前亮度为二档”                  case 33:control_part_display(1,7,display_1,display_now);break;     //显示“当前亮度为三档”            }            data[0]='0';               //清空控制指令            data[1]='0';            state_flag_temp=0;            if(display_all_flag)       //状态整体显示界面            {                  display_all_flag=0;                  control_all_display(state_flag);                  TIM_Cmd(TIM2,DISABLE);                          //关闭TIM2定时器            }      break;      case 1:                                                       //在始终显示界面            RTC_Display();                                           //显示时钟      break;​​​​​​​

      至此,智能灯光系统的相关功能已全部开发完毕,给电路板接上电源后,可使用APP控制、语音控制两种方式,实现灯光的开关、一档二档三档的的调节、冷暖光的调节、以及姿势纠正等功能。whaosoft aiot  http://143ai.com

二、单片机中用二极管实现不同电压的输出

利用二极管的单向导电性可以设计出好玩、实用的电路。

    分享本文,分析限幅电路和钳位电路,是如何用二极管来实现的。

限幅电路

    如下图所示,当在正半周期,并且VIN大于等于0.7V,二极管正向导通。此时,

VOUT会被钳位在0.7V上。

    而当VIN小于0.7V时二极管是截止状态,在负半周期时相当于电流反向,二极管也是截至状态,此时VOUT=VIN,VOUT波形跟随VIN变化。

限辐电路示意图

根据上面限辐电路的原理,可以设计如下双向限辐电路。

双向限辐电路示意图

然而有时候0.7V电压不能满足要求,那么,怎么产生不同大小的限幅电压?

    在电路中加入偏置电压VBIAS,只有当VIN大于等于VBIAS时二极管才能导通。此时VOUT被钳位,其值是0.7V+VBIAS,如下图所示。

 

偏压限幅电路示意图

钳位电路

    下面是二极管结合电容实现的钳位电路。分析中不考虑二极管的导通压降,假设RC时间常数足够大,从而使输出波形不会失真。

钳位电路原理

    当输入Vin在负半周期为负时,电流如下图中红色箭头所示。二极管导通,电容逐渐充电至V,在此过程中Vout=0。

    当输入Vin在正半周为正时,电流如蓝色箭头所示。二极管截止,Vout等于电容上电压加上正半周电压V,此时Vout=2V。

 

钳位电路原理

偏压钳位电路

    跟限幅电路类似的,为了获得所需要的钳位值,要在电路中加入偏置电压,如下图所示。

偏压钳位电路

    当所加的偏压与二极管导通方向一致,钳位值会提高V1,Vout=2V+V1。

双向二极管钳位电路应用举例

    在某些电路中会利用两个二极管的钳位作用进行保护,如下图所示,假设0.7V为D1和D2的导通电压。

  • Vin大于等于Vmax,D1导通,Vout会被钳位在Vmax

  • Vin小于等于Vmin时,Vout被钳位在Vmin

  • 二极管钳位保护电路 

三、入门级电路

半波整流

    电路是一种利用二极管的单向导通特性来进行整流的常见电路,除去半周、剩下半周的整流方法,叫半波整流。作用是将交流电转换为直流电,也就是整流。

全波整流

    是指能够把交流转换成单一方向电流的电路,最少由两个整流器合并而成,一个负责正方向,一个负责反方向,最典型的全波整流电路是由四个二极管组成的整流桥,一般用于电源的整流。也可由MOS管搭建。

点亮一个LED灯

    使用一个开关,控三极管的基极,当开关按下的时候,三极管被导通,LED灯被点亮,当开关松开的时候,三极管被关闭,LED灯被关闭。

稳压电路

    左边变压器,输入降压后的交流电,经过半波整流,使用稳压管,是最简单的稳压电路,只要改变稳压管的参数,就可以获得不同的电压输出。​​​​​​​
 

功率放大器

    功率放大器(英文名称:power amplifier),简称“功放”,是指在给定失真率条件下,能产生最大功率输出以驱动某一负载(例如扬声器)的放大器。功率放大器在整个音响系统中起到了“组织、协调”的枢纽作用,在某种程度上主宰着整个系统能否提供良好的音质输出。

 

LC 振荡器

    是指用电感L、电容C组成选频网络的振荡电路,用于产生高频正弦波信号,常见的LC正弦波振荡电路有变压器反馈式LC振荡电路、电感三点式LC振荡电路和电容三点式LC振荡电路。LC振荡电路的辐射功率是和振荡频率的四次方成正比的,要让LC振荡电路向外辐射足够强的电磁波,必须提高振荡频率,并且使电路具有开放的形式。

 

四、串口的使用

串口通信介绍

    串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式......这种太过理论了,看似懂了,但又不懂。还是用我笔者自己的话来说吧。

    串口通信就是可以把程序在单片机或者STM32芯片中运行的结果发送到电脑的一种通信方式。

 

如何使用串口通讯,你需要知道的几个重要的知识点:

  • 波特率,数据传输的速度,如上图设置为9600,那么程序中也要设置为9600

  • 硬件连接,接收、发送交叉连接,如上图TxD->RxD,RxD->TxD

  • 停止位

  • 奇偶校验

  • 硬件数据流

    其中,后3项一般不需要改变。

学会串口通信能做什么

    学过C语言的人都知道,程序开发需要不断调试不断验证。很多的语言编程软件都有很完整的程序调试功能。使用起来很方便。而我们的开发虽然也是用C语言,但我们的程序最终运行的环境不是在我们的开平台而是在真正的硬件系统中运行。这时想要查看程序的运行过程或者结果就不像编程软件那么方便了。

    想要解决这个问题,我们这时就可以借助串口通信来把我们需要知道的结果又或者是程序运行的关键步骤发送到电脑上,我们就知道程序在硬件系统中运行是否出现问题。51单片机可以用串口来调试,STM32可以用串口来调试,Linux开发板也是使用串口来调试。

    当你学会串口通信时,你可以开始玩WIFI模块、GSM模块、蓝牙模块、GPS模块、以及各种使用串口通信的传感器等等。有能力你还可以编写上位机软件通过串口通信来控制设备。

串口通信需要什么

    如果你只有STM32核心板,那么你还需要一个串口转USB模块和一个串口数据接收软件还有几根杜邦线就可以了。

    如果你的是比较完整的一款开发板的话,一般都已经带有串口转USB模块,这样使用起来就更简单了。聪明的你是不是发现还缺少了点什么,对。没错因为还缺少了最重要的程序。想要使用串口通信当然还需要写串口通信的程序。

    下文就教你如何去用,而不是写。

串口实验

    而下文中的实验基于标准库实现的,与HAL相比思路是一样的。

    在做一个实验时,最好把这个实验分割成几个关键的步骤,这样做的好处就是可以清晰的知道自己需要做什么,以及做完了哪些。还有哪些还没做。

    下面把串口实验分成几个关键的步骤:
1)串口通信使用到的GPIO引脚配置
    STM32F103系列的芯片一般都有三个串口以上,用来调试使用的串口一般都是使用USART1。其他的串口配置都是一样的。

    下面这段就是串口配置的程序:​​​​​​​

GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能USART1,GPIOA时钟//USART1_TX GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化GPIOA.9//USART1_RX GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  //PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化GPIOA.10 

    串口使用的的GPIO口是PA9和PA10,所以只需配置这两个IO口的输入输出模式就可以了。

2)串口主要参数设置(直接看程序)​​​​​​​

USART_InitTypeDef USART_InitStructure;//USART 初始化设置USART_InitStructure.USART_BaudRate = bound;//串口波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b;//数据格式,8位USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式USART_Init(USART1, &USART_InitStructure); //初始化串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断

    串口参数配置无法就是配置串口的波特率、数据格式、停止位、奇偶校验、硬件流、收发模式。除了波特率需要改变其他的参数都不需要管。直接复制拿来用。

3)串口中断配置
    串口如果使用中断接收,那么就需要配置串口的中断参数,配置项无法就是配置那个的中断源和中断的优先级。​​​​​​​​​​​​​​

NVIC_InitTypeDef NVIC_InitStructure;//Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;  //抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //IRQ通道使能NVIC_Init(&NVIC_InitStructure);   //根据指定的参数初始化VIC寄存器

4)串口使能
    就是你需要什么时候开始使用串口功能,就是一句原有的函数。

USART_Cmd(USART1, ENABLE);  //使能串口1 

5)编写串口中断处理函数
    使用库函数开发,所有的中断函数都是已经存在的,只是中断函数里面没有处理任何事情而已。中断函数如下:

 

 完整的串口中断函数:​​​​​​​

void USART1_IRQHandler(void){int Res=0;  //定义一个变量用来接收串口数据集if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)  {  Res =USART_ReceiveData(USART1);  //读取接收到的数据  USART_SendData(USART1,Res );     //把接收到的数据通过串口1发送出去  }}

    串口数据的接收和发送的函数都是库函数提供的,想用时只需找到它直接拿来用就可以了。

6)实验现象

    把程序编译烧写到STM32然后用串口转USB模块连接到电脑,在串口调试工具设置好波特率,打开串口。正常的话,那发送什么到STM32单片机,串口工具上就会收到什么。

总结

    以上就完成了一个最简单的串口实验。

whaosoft aiot  http://143ai.com 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/17031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全网监控 nginx 部署 zabbix6.0

Zabbix监控 文章目录Zabbix监控一、zabbix6.0部署1、部署zabbix 6.0版本&#xff08;nginxphpzabbix&#xff09;1、nginx配置2、php配置3、mariadb配置二、zabbix配置1、zabbix配置 &#xff08;6.0&#xff09;1、源码安装2、zabbix rpm2、zabbix(5.0安装) -- 补充3、故障汇总…

【Linux】翻山越岭——进程地址空间

文章目录一、是什么写时拷贝二、为什么三、怎么做区域划分和调整一、是什么 回顾我们学习C/C时的地址空间&#xff1a; 有了这个基本框架&#xff0c;我们对于语言的学习更加易于理解&#xff0c;但是地址空间究竟是什么❓我们对其并不了解&#xff0c;是不是内存呢&#xff1…

【创建微服务】创建微服务并使用人人开源代码生成器生成基本代码

创建项目微服务 —— 添加模块 添加依赖 使用 人人开源代码生成器 快速生成 crud 代码 —— https://gitee.com/renrenio 下载导入人人开源项目后&#xff0c;修改 application.yml 文件下的数据库连接配置&#xff1a; 2. 修改 generator.properties 配置文件下的 主路径、包…

CC1101RGPR射频收发器 Low-Power Sub-1GHz 射频收发器

CC1101RGPR射频收发器 Low-Power Sub-1GHz 射频收发器 CC1101RGPR是一种低成本的 sub-1 GHz 收发器专为超低功耗无线应用而设计。该电路主要用于ISM&#xff08;工业、科学和医疗&#xff09;和SRD&#xff08;短程设备&#xff09;频段315、433、868 和 915 MHz&#xff0c;但…

【891. 子序列宽度之和】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 一个序列的 宽度 定义为该序列中最大元素和最小元素的差值。 给你一个整数数组 nums &#xff0c;返回 nums 的所有非空 子序列 的 宽度之和 。由于答案可能非常大&#xff0c;请返回对 109 7 取余 …

UNIAPP实战项目笔记40 设置和地址的页面布局

UNIAPP实战项目笔记40 设置和地址的页面布局 my-config.vue 设置页面布局 具体图片自己替换哈&#xff0c;随便找了个图片的做示例 代码 my-config.vue 页面部分 <template><view class"my-config"><view class"config-item" tap"go…

精益项目管理的流程

我们生活在一个企业家的世界&#xff0c;您可能有许多自己的想法等待实现&#xff0c;但想法在现实中实现是昂贵的。问题是您如何才能获得最大的收益&#xff1f;CEO和管理者如何在追逐梦想和实现目标的同时节省资金&#xff1f;了解初创公司如何进行精益项目管理&#xff0c;它…

第一个汇编程序

第一个汇编程序 文章目录第一个汇编程序1.汇编模拟程序&#xff1a;DOSBox使用2.汇编程序从写出到执行的过程3.程序执行过程跟踪1.汇编模拟程序&#xff1a;DOSBox使用 BOSBox软件常用基本语法&#xff1a; mount c: d:\masn ;挂载磁盘,挂载后用c:切换为C盘才能用debug等工具…

【Java面试八股文宝典之基础篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day09

大家好&#xff0c;我是陶然同学&#xff0c;软件工程大三明年实习。认识我的朋友们知道&#xff0c;我是科班出身&#xff0c;学的还行&#xff0c;但是对面试掌握不够&#xff0c;所以我将用这100多天更新Java面试题&#x1f643;&#x1f643;。 不敢苟同&#xff0c;相信大…

uni-app入门:WXML列表渲染与条件渲染

1.列表渲染 1.1wx:for 1.2wx:key 2.条件渲染 2.1wx:if 2.2 hidden 正文 WXML全称&#xff1a;wexin markup language,微信标签语言&#xff0c;可以理解为web中的html&#xff0c;今天来讲一下列表渲染&#xff0c;通过几个小案例掌…

艾美捷高纯度 Cholesterol胆固醇相关介绍

胆固醇在体内有着广泛的生理作用&#xff0c;但当其过量时便会导致高胆固醇血症&#xff0c;对机体产生不利的影响。现代研究已发现&#xff0c;动脉粥样硬化、静脉血栓形成与胆石症与高胆固醇血症有密切的相关性。 如果是单纯的胆固醇高则饮食调节是最好的办法&#xff0c;如果…

机器人虚拟仿真工作站考试

总共三个步骤&#xff1a; 创建工作台、加工零件、机器人臂 &#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 一、加工零件的创建 1、先打开sw软件&#xff0c;然后点击零件、创建进入到该软件内&#xff1a; 2、点击前视基础面&#xff08;点击后按esc&#x…

RabbitMQ初步到精通-第四章-RabbitMQ工作模式-WORK

第四章-RabbitMQ工作模式-WORK 1.模式介绍 1.1 work模式 Work模式与前面的Simple模式一致&#xff0c;也是消息经由生产者发到Exchange再到queue再被消费者消费。不同点在于SIMPL模式是一个队列对应的一个消费者&#xff0c;此模式会由一个队列对应两个消费者或大于两个消费者。…

MyBatis的配置文件

日志怎么在mybatis中实现呢 1.添加pom.xml依赖 2.添加logback配置文件 mybatisconfig.xml 引入外部属性资源文件 注意:其中使用的较多的需要设置的为&#xff1a; 引入外部属性资源文件 将数据库的蛇形命名映射为驼峰命名 使用typeAliases标签设置里面的package标签,为…

智工教育:环评师考试重要知识点

环境影响评价师的知识点庞杂纷繁&#xff0c;想要顺利通过考试&#xff0c;就要经常复习看过的知识&#xff0c;达到加强记忆的效果。下面是小编整理的环评师考试重要知识点&#xff0c;一起来复习吧! 考试目的及大纲主要内容 通过本科目考试&#xff0c;检验具有一定实践经验…

shell脚本编程基础(中)

目录 (一&#xff09;shell流程控制-for循环语句 1. for 循环介绍 2. for语法 2.1 for 语法一 2.2 for语法二 3.循环控制语句 3.1 sleep N 脚本执行到该步休眠N秒 3.2 continue 跳过循环中的某次循环 3.3 break 跳出循环继续执行后续代码 3.4实例 &#xff08;二&am…

MyBatis大数据量插入方案

1、前言 在开发过程中&#xff0c;有时我们会碰到将大批量的数据入库的场景&#xff0c;那么我们一般有下面三种方式入库&#xff1a; ExecutorType.BATCH批处理方式插入foreach循环标签插入MyBatisPlus自带的saveBatch批量新增方法 下面我们用一个案例来测试一下&#xff0…

让学前端不再害怕英语单词(一)

有很多跟着我学习的学生经常跟我抱怨前端的单词很多&#xff0c;学了css又忘了html的单词&#xff0c;学了js又忘了css 的单词&#xff0c;所以本着给跟着我学习的学生提供一个学习前端不怕英语单词的课程&#xff0c;就打算写一篇博客去讲述如何增强在学习前端的时候巩固语法并…

通过阅读源码解决项目难题:GToken替换JWT实现SSO单点登录

文章目录jwt的问题jwt的请求流程图gtoken的优势注意问题演示demo入门示例运行效果启动项目&#xff1a;访问不认证接口&#xff1a;返回成功未登录时访问认证接口&#xff1a;返回错误提示请求登录接口&#xff1a;返回token携带token再次访问认证接口&#xff1a;返回成功分析…

postgres-operator 原理解析- 章节 I

这篇文章我想写postgres-operator如何利用kubernetes实现高可用功能其中的客户端流量路由部分。 总体的目的呢就是客户端数据库连接请求&#xff0c;如果通过利用kubernetes的机制实现将流量路由到实际的Postgresql主节点。 基础知识 Services without selectors 平常得Ser…