【藍橋杯單片機組第七屆省賽】— “模擬風扇控制系統”設計任務書

1、試題

(1)功能簡述

  “模擬風扇控制系統”能夠模擬電風扇工作,通過按鍵控制風扇的轉動速度和定時時間,數碼管實時顯示風扇的工作模式,動態倒計時顯示剩餘的定時時間,系統主要由數碼管顯示、單片機最小系統、按鍵輸入和電機控制保護電路組成,系統框圖如圖 1 所示:

 (2)設計任務及要求

    1、工作模式

    設備具有“睡眠風”、“自然風”和“常風”三種工作模式可以通過按鍵切換,通過單片機 P34 引腳輸出脈寬調製信號控制電機運行狀態,信號頻率爲 1KHz。

    1.1  “睡眠風”模式下,對應 PWM 佔空比爲 20%;

    1.2  “自然風”模式下,對應 PWM 佔空比爲 30%;

    1.3  “常風”模式下,對應 PWM 佔空比爲 70%;

    2、數碼管顯示
    數碼管實時顯示設備當前工作模式和剩餘工作時間(倒計時),如圖 2 所示。

    “睡眠風”狀態下,對應數碼管顯示數值爲 1,自然風模式下,顯示數值爲 2,常風模式下,顯示數值爲 3。

    3.、按鍵控制

    使用 S4、S5、S6、S7 四個按鍵完成按鍵控制功能。

    3.1 按鍵 S4 定義爲工作模式切換按鍵,每次按下 S4,設備循環切換三種工作模式。工作過程如下:

    3.2 按鍵 S5 定義爲“定時按鍵”每次按下 S5,定時時間增加 1 分鐘,設備的剩餘工作時間重置爲當前定時時間,重新開始倒計時,工作過程如下:

    3.3 按鍵 S6 定義爲“停止”按鍵,按下 S6 按鍵,立即清零剩餘工作時間,PWM信號停止輸出,直到通過 S5 重新設置定時時間。

    3.4 按鍵 S7 定義爲“室溫”按鍵,按下 S7,通過數碼管顯示當前室溫,數碼管顯示格式如圖 3 所示,再次按下 S7,返回圖 2 所示的工作模式和剩餘工作時間顯示界面,如此往復。

室溫測量、顯示功能不應影響設備正在執行的 PWM 信號輸出、停止、模式切換和計時等功能。

    4、LED 指示燈

    “睡眠風”模式下,L1 點亮,“自然風”模式下 L2 點亮,“常風”模式下 L3 點亮;按下停止按鍵或倒計時結束時,LED 全部熄滅。

    5、電路原理圖設計

    電機過熱檢測及驅動電路設計:假定設備使用的是 12V 直流電機,過熱檢測傳感器輸出爲小電壓信號 Vs,設計過熱檢測及電機驅動電路,當檢測到 Vs 信號幅度大於 10mV 時,電機停止轉動,簡述電路的工作原理與設計思路,並繪製出電路原理圖。

2、試題分析

\blacktriangle 對於DS18B20芯片,溫度傳感器來說,只需知道溫度讀取函數:

unsigned char Get_wendu(){
unsigned char high,low;
unsigned char temp;
Init_DS18B20();
Write_DS18B20(0XCC);
Write_DS18B20(0X44);
Delay_OneWire(200);
Init_DS18B20();
Write_DS18B20(0XCC);
Write_DS18B20(0XBE);
 
low=Read_DS18B20();
high=Read_DS18B20();
temp=(low>>4)|(high<<4);
 
return temp;
}

  按鍵、數碼管、LED燈都是省賽必考項,對於他們之間的連接不再多說。

PWM控制佔空比,通過P34口輸出。信號頻率爲1000HZ=0.001s=1ms=1000us。

可以通過定時器0每次定時100us,總計10次;

如果PWM佔空比爲20%,說明在一個PWM週期內,P34口高電平佔20%,其餘同理。

PWM脈衝寬度調製技術控制可參考:

https://blog.csdn.net/fanjufei123456/article/details/105025590

如果發現數碼管用顯示的字符用眼睛可以看出閃動時,說明延時過長,可以修改下延時函數。通過程序發現:

void display12(uchar f1,uchar f2){
P2=0XC0;P0=0X01;P2=0XFF;P0=tab[f1];
delay();
P2=0XC0;P0=0X02;P2=0XFF;P0=tab[f2];
delay();
}
void delay(){
uchar i,j;
for(i=10;i>0;i--)
for(j=200;j>0;j--);
}

 這個延時對於數碼管的顯示比較理想。 

3、實現代碼

onewire.c

#include "onewire.h"

//單總線延時函數
void Delay_OneWire(unsigned int t)
{
  t=12*t;
  while(t--);
}

//DS18B20芯片初始化
bit Init_DS18B20(void)
{
	bit initflag = 0;
	DQ = 1;
	Delay_OneWire(12);
	DQ = 0;
	Delay_OneWire(80); 
	DQ = 1;
	Delay_OneWire(10); 
	initflag = DQ;    
	Delay_OneWire(5);
  
	return initflag;
}

//通過單總線向DS18B20寫一個字節
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

//從DS18B20讀取一個字節
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

unsigned char Get_wendu(){
unsigned char high,low;
unsigned char temp;
Init_DS18B20();
Write_DS18B20(0XCC);
Write_DS18B20(0X44);
Delay_OneWire(200);
Init_DS18B20();
Write_DS18B20(0XCC);
Write_DS18B20(0XBE);
 
low=Read_DS18B20();
high=Read_DS18B20();
temp=(low>>4)|(high<<4);
 
return temp;
}

 onewire.h

#ifndef _ONEWIRE_H
#define _ONEWIRE_H

#include "stc15f2k60s2.h"

#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe

//IC引腳定義
sbit DQ = P1^4;

//函數聲明
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
bit Init_DS18B20(void);
unsigned char Read_DS18B20(void);
unsigned char Get_wendu();
#endif

 text.c

#include<stc15f2k60s2.h>
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int

uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF,0XC6};
uchar f1,f2,f3,f4,f5,f6,f7,f8;
uchar moshi=1;
uchar wendu;
uchar dingshi=0;
uchar flag=0;
uchar pwm_zhankongbi=0;
uchar n=0;
uint count=0;

void delayms(uchar ms);
void display12(uchar f1,uchar f2);
void display34(uchar f3,uchar f4);
void display56(uchar f5,uchar f6);
void display78(uchar f7,uchar f8);
void allinit();
void Time0_init();
void keyscan();
void delay();

void main(){
allinit();
Time0_init();
f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=11;f8=11;

while(1)
{
   wendu=Get_wendu();
   if(flag==0)
   {
     f1=10;f2=moshi;f3=10;f4=11;f5=0;f6=dingshi/100;f7=dingshi%100/10;f8=dingshi%10;
   }
   else if(flag==1)
   {
     f1=10;f2=4;f3=10;f4=11;f5=11;f6=wendu/10;f7=wendu%10;f8=12;
   }

   if(dingshi>0)
   {
     if(moshi==1)
	 {
	   P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
	   P00=0;
	 }
	 else if(moshi==2)
	 {
	   P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
	   P01=0;
	 }
	 else if(moshi==3)
	 {
	   P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
	   P02=0;
	 }
   }
   else if(dingshi==0)
   {
	  P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
	  P0=0XFF;
   }

   keyscan();
   display12(f1,f2);
   display34(f3,f4);
   display56(f5,f6);
   display78(f7,f8);
 }
}

void keyscan(){
if(P33==0)	//切換轉換模式
{
  delayms(5);
  if(P33==0)
  {
     if(moshi==1)
	 {
	    moshi=2;
	 }
	 else if(moshi==2)
	 {
	    moshi=3;
	 }
	 else if(moshi==3)
	 {
	    moshi=1;
	 }
  }
while(!P33);
}

if(P32==0)	 //定時設置
{
  delayms(5);
  if(P32==0)
  {
     if(dingshi==0)
	 {
	    dingshi=60;
	 }
	 else if(dingshi<=60)
	 {
	    dingshi=120;
	 }
	 else if(dingshi<=120)
	 {
	    dingshi=0;
	 }
  }
while(!P32);
}

if(P31==0)		//清零剩餘工作時間
{
  delayms(5);
  if(P31==0)
  {
    dingshi=0;
  }
while(!P31);
}

if(P30==0)		  //溫度和剩餘工作時間轉換
{
   delayms(5);
   if(P30==0)
   {
	 if(flag==0)
	 {
	   flag=1;
	 }
	 else if(flag==1)
	 {
	   flag=0;
	 }
   }
while(!P30);
}
}

//1000hz=0.001s=1ms=1000us,每次定時100us。     
void Time0_init(){
TMOD=0X01;
TH0=(65536-100)/256;
TL0=(65536-100)%256;
TR0=1;
ET0=1;
EA=1;
}

void Time0_service() interrupt 1
{
  TH0=(65536-100)/256;
  TL0=(65536-100)%256;
  n++;
  count++;
  pwm_zhankongbi++;
  if(count==10000)
  {
    count=0;
	if(dingshi>0)
	{
	  dingshi--;
	}
  }

  if(dingshi>0)
  {
  if(moshi==1)
  {
     if(pwm_zhankongbi==3)
	 {
	    P34=1;
	 }
	 else
	 {
	    P34=0;
	 }
  }
  else if(moshi==2)
  {
     if(pwm_zhankongbi==4)
	 {
	    P34=1;
	 }
	 else
	 {
	    P34=0;
	 }
  }
  else if(moshi==3)
  {
     if(pwm_zhankongbi==8)
	 {
	    P34=1;
	 }
	 else
	 {
	    P34=0;
	 }
  }
 }
  if(n==11)
  {
	 n=0;
	 pwm_zhankongbi=0;
  }
}

void delayms(uchar ms){
uchar i,j,k;
for(k=ms;k>0;k--){
  i=12;
  j=169;
  do
  {
    while(j--);
  }
   while(i--);
}
}

void allinit(){
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}

void display12(uchar f1,uchar f2){
P2=0XC0;P0=0X01;P2=0XFF;P0=tab[f1];
delay();
P2=0XC0;P0=0X02;P2=0XFF;P0=tab[f2];
delay();
}

void display34(uchar f3,uchar f4){
P2=0XC0;P0=0X04;P2=0XFF;P0=tab[f3];
delay();
P2=0XC0;P0=0X08;P2=0XFF;P0=tab[f4];
delay();
}

void display56(uchar f5,uchar f6){
P2=0XC0;P0=0X10;P2=0XFF;P0=tab[f5];
delay();
P2=0XC0;P0=0X20;P2=0XFF;P0=tab[f6];
delay();
}

void display78(uchar f7,uchar f8){
P2=0XC0;P0=0X40;P2=0XFF;P0=tab[f7];
delay();
P2=0XC0;P0=0X80;P2=0XFF;P0=tab[f8];
delay();
}

void delay(){
uchar i,j;
for(i=10;i>0;i--)
for(j=200;j>0;j--);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章