目錄
一,前言
二,系統方案選擇
三,實體展示
工程分類
?四,相關代碼
PWM.c
PWM.h
AD.c
AD.h
電機驅動程序
舵機驅動
一,前言
? 當今生活中,風扇已成為人們解暑的重要工具,然而使用風扇緩解夏日酷熱的同時也存在著一些問題,傳統風扇只能根據選擇的檔位來設置轉速,而不能根據周圍環境溫度的變化而自動調節轉速。基于以上設計了自動調速風扇系統。
二,系統方案選擇
本系統由按鍵控制和液晶顯示兩部分組成。工作區內由單片機stm32F103C8熱敏電阻傳感器,當溫度達到設定閾值時,從而通過PWM控制電機做相應動作。
環境溫度采集模塊:采用熱敏電阻,可滿足 40 攝氏度至 90 攝氏度測量范圍
電機模塊:采用舵機同直流電機搭配,舵機具有扭力大容易控制。小型直流減速電機,減速電機控制精度低,且速度均勻性好,控制簡單,電源要求低,易于實現。
T86612FNG電機驅動? ?,直流電機130
顯示模塊:OLED顯示屏,快速插接小巧設計,是內容顯示和程序調試的利器,從此程序清晰可見。
舵機:SG90
?如圖2為STM32F103單片機最小系統電路原理圖。該最小系統電路主要包括時鐘、按鍵復位和供電電路三部分。
三,實體展示
工程分類
?
?
?
?四,相關代碼
PWM.c
#include "stm32f10x.h" // Device headervoid PWM_Init1(void)
{GPIO_InitTypeDef GPIO_InitStructure; //定義GPIO初始化結構體變量TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_OCInitTypeDef TIM_OCInitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //開啟定時器2RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//通道2時鐘使能函數GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //設置GPIO為推挽輸出模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //PA1 PA2 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度設置為 50MHzGPIO_Init(GPIOA, &GPIO_InitStructure); //按照以上參數進行 GPIO的初始化TIM_InternalClockConfig(TIM2);//TIM的時基單元由內部時鐘控制TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1; //ARR 自動重裝器的值TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC 預分頻器的值 對72M(720000000)進行 7200分頻 即10K的頻率下 計10000個數 1s的時間TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重復計數器的值 CCRTIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure); TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//輸出極性選擇TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//輸出狀態使能TIM_OCInitStructure.TIM_Pulse = 20;//CCR,即占空比為 10%TIM_OC2Init(TIM2,&TIM_OCInitStructure);//OC編號要與通道編號對應TIM_Cmd(TIM2,ENABLE);
}void PWM_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure; //定義GPIO初始化結構體變量TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_OCInitTypeDef TIM_OCInitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //開啟定時器3RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//通道2時鐘使能函數GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //設置GPIO為推挽輸出模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度設置為 50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); //按照以上參數進行 GPIO的初始化TIM_InternalClockConfig(TIM3); //內部時鐘配置TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR 自動重裝器的值TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC 預分頻器的值 TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重復計數器的值 CCRTIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure); TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//輸出極性選擇TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//輸出狀態使能TIM_OCInitStructure.TIM_Pulse = 50;//CCR,即占空比為 10%TIM_OC3Init(TIM3,&TIM_OCInitStructure);//OC編號要與通道編號對應//TIM_OC2Init(TIM3,&TIM_OCInitStructure);//OC編號要與通道編號對應TIM_Cmd(TIM3,ENABLE);
}void PWM_SetCompare_Servo(uint16_t Compare) //舵機
{TIM_SetCompare2(TIM2, Compare);
}void PWM_SetCompare_Motor(uint16_t Compare) //風扇
{TIM_SetCompare3(TIM3, Compare);}
PWM.h
#ifndef __PWM_H
#define __PWM_Hvoid PWM_Init(void);
void PWM_Init1(void);void PWM_SetCompare_Motor(uint16_t Compare);
void PWM_SetCompare_Servo(uint16_t Compare);#endif
AD.c
#include "stm32f10x.h" // Device headervoid AD_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_ADCCLKConfig(RCC_PCLK2_Div6);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);ADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;ADC_InitStructure.ADC_ScanConvMode = DISABLE;ADC_InitStructure.ADC_NbrOfChannel = 1;ADC_Init(ADC1, &ADC_InitStructure);ADC_Cmd(ADC1, ENABLE);ADC_ResetCalibration(ADC1);while (ADC_GetResetCalibrationStatus(ADC1) == SET);ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1) == SET);
}uint16_t AD_GetValue(void)
{ADC_SoftwareStartConvCmd(ADC1, ENABLE);while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);return ADC_GetConversionValue(ADC1);
}
AD.h
#ifndef __AD_H
#define __AD_Hvoid AD_Init(void);
uint16_t AD_GetValue(void);#endif
電機驅動程序
#include "stm32f10x.h" // Device header
#include "PWM.h"
#include "Delay2.h"
#include "OLED.h"
#include "LED1.h"
#include "Key.h"float Speed=0;
void Motor_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);PWM_Init1();
}void Motor_SetSpeed(int8_t Speed)
{if (Speed >= 0){GPIO_ResetBits(GPIOA, GPIO_Pin_4);GPIO_SetBits(GPIOA, GPIO_Pin_5);PWM_SetCompare_Motor(Speed);}else{GPIO_SetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_5);PWM_SetCompare_Motor(-Speed);}
}
void Motor_Speed_Set(uint8_t KeyNum)
{//Key_Init1();//Key_Init();//KeyNum = Key_GetNum();if(KeyNum == 1){Speed += 20;if(Speed > 80){Speed =0;}}void LED11_OFF(void);void LED22_ON(void);OLED_ShowNum(3,7,Speed,3);OLED_ShowNum(2,8,KeyNum,1);Motor_SetSpeed(Speed);}
舵機驅動
#include "stm32f10x.h" // Device header
#include "PWM.h"#include "OLED.h"#include "Key.h"
#include "LED1.h"float Angle;void Servo_Init(void)
{PWM_Init();
}void Servo_SetAngle(float Angle)
{PWM_SetCompare_Servo(Angle / 180 * 2000 + 500);
}
void Servo_Turn(uint8_t KeyNum)
{ KeyNum = Key_GetNum();if (KeyNum == 2){Angle += 30;if (Angle > 180){Angle = 0;}}Servo_SetAngle(Angle);OLED_ShowNum(2,8,KeyNum,1);OLED_ShowNum(1, 7, Angle, 3);}