【藍橋杯單片機組第九屆省賽】— “彩燈控制器”的程序設計與調試

1、試題

一、基本要求

1.1 使用 CT107D 單片機競賽板,完成“彩燈控制器” 功能的程序設計與調試;
1.2 設計與調試過程中,可參考組委會提供的“資源數據包”;
1.3 Keil 工程文件以准考證號命名,完成設計後,提交完整、可編譯的 Keil工程文件到服務器。

二、硬件框圖

三、功能描述 

3.1 基本功能描述

       通過單片機控制 8 個 LED 指示燈按照特定的順序(工作模式) 亮滅; 指示燈的流轉間隔可通過按鍵調整,亮度可由電位器 RB2 進行控制; 各工作模式的流轉間隔時間需在 E2PROM 中保存,並可在硬件重新上電後,自動載入。

3.2 設計說明

(1)關閉蜂鳴器、繼電器等與本試題程序設計無關的外設資源
(2)設備上電後默認數碼管、 LED 指示燈均爲熄滅狀態;
(3)流轉間隔可調整範圍爲 400ms-1200ms;
(4)設備固定按照模式 1、模式 2、模式 3、 模式 4 的次序循環往復運行。

3.3 LED 指示燈工作模式

(1)模式 1: 按照 L1、 L2…L8 的順序, 從左到右單循環點亮。

(2)模式 2: 按照 L8、 L7…L1 的順序, 從右到左單循環點亮。

(3)模式 3:

(4)模式4:

3.4 亮度等級控制

       檢測電位器 RB2 的輸出電壓,控制 8 個 LED 指示燈的亮度,要求在 0V-5V的可調區間內,實現 4 個均勻分佈的 LED 指示燈亮度等級。

3.5 按鍵功能

(1)按鍵 S7 定義爲“啓動/停止”按鍵,按下後啓動或停止 LED 的流轉。

(2)按鍵 S6 定義爲“設置”按鍵,按鍵按下後數碼管進入“流轉間隔”設置界面,如下圖所示:

   通過按鍵 S6 可切換選擇“運行模式” 和“流轉間隔” 兩個顯示單元,當前被選擇的顯示單元以 0.8 秒爲間隔亮滅。

 (3)按鍵 S5 定義爲“加”按鍵,在設置界面下,按下該鍵,若當前選擇的是運行模式,則運行模式編號加 1,若當前選擇的是流轉間隔,則流轉間隔增加 100ms。

(4)按鍵 S4 定義爲“減”按鍵,在設置界面下,按下該鍵,若當前選擇的是運行模式,則運行模式編號減 1,若當前選擇的是流轉間隔,則流轉間隔減少 100ms。

(5)按鍵功能說明:

     (a)按鍵 S4、 S5 的“ 加”、 “ 減” 功能只在“設置狀態”下有效,數值的調整應注意邊界屬性。

     (b)在非“設置狀態”下,按下 S4 按鍵可顯示指示燈當前的亮度等級, 4 個亮度等級從暗到亮,依次用數字 1、 2、 3、 4 表示; 鬆開S4 按鍵,數碼管顯示關閉, 亮度等級的顯示格式如下圖所示:

2、試題分析

模擬輸入:要掌握PCF8591芯片上的AD轉換。

按鍵控制:S7(P30),S6(P31),S5(P32),S4(P33)。

LED指示燈:初始化、P0端口低電平亮。

IIC總線控制、數碼管顯示。

E2PROM讀取斷電後的數據。

最後是PWM脈衝寬度調製技術控制led的亮度。對於PWM的解釋可見博客:

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

還有一些細節上的連接問題,需要自己動手操作。

藍橋杯第九屆省賽和第八屆省賽,賽題還是比較相似的,按鍵控制方式都基本上一樣的模式,第八屆有實時時鐘、溫度傳感器等,第九屆是AD、IIC總線、EEPROM、PWM控制,另外PWM可能是個問題點。

3、代碼

 iic.c

#include "iic.h"

//總線啓動條件
void IIC_Start(void)
{
	SDA = 1;
	SCL = 1;
	somenop;
	SDA = 0;
	somenop;
	SCL = 0;	
}

//總線停止條件
void IIC_Stop(void)
{
	SDA = 0;
	SCL = 1;
	somenop;
	SDA = 1;
}

//等待應答
bit IIC_WaitAck(void)
{
	SDA = 1;
	somenop;
	SCL = 1;
	somenop;
	if(SDA)    
	{   
		SCL = 0;
		IIC_Stop();
		return 0;
	}
	else  
	{ 
		SCL = 0;
		return 1;
	}
}

//通過I2C總線發送數據
void IIC_SendByte(unsigned char byt)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{   
		if(byt&0x80) 
		{	
			SDA = 1;
		}
		else 
		{
			SDA = 0;
		}
		somenop;
		SCL = 1;
		byt <<= 1;
		somenop;
		SCL = 0;
	}
}

//從I2C總線上接收數據
unsigned char IIC_RecByte(void)
{
	unsigned char da;
	unsigned char i;
	
	for(i=0;i<8;i++)
	{   
		SCL = 1;
		somenop;
		da <<= 1;
		if(SDA) 
		da |= 0x01;
		SCL = 0;
		somenop;
	}
	return da;
}

unsigned char AD_Read(unsigned char add)
{
		unsigned char temp;
		IIC_Start(); 
		IIC_SendByte(0x90);
		IIC_WaitAck();
	
		IIC_SendByte(add);
		IIC_WaitAck();
	
		IIC_Stop();

	
		IIC_Start(); 
		IIC_SendByte(0x91);
		IIC_WaitAck();
	
		temp=IIC_RecByte();
	
		IIC_Stop();
		return temp;
}

//EEPROM讀
unsigned char EEPROM_Read(unsigned char add)
{
		unsigned char temp;
		IIC_Start(); 
		IIC_SendByte(0xa0);
		IIC_WaitAck();
		IIC_SendByte(add);
		IIC_WaitAck();
		IIC_Stop();

		IIC_Start(); 
		IIC_SendByte(0xa1);
		IIC_WaitAck();
		temp=IIC_RecByte(); 
		IIC_Stop();
	 
		return temp;
}


//EEPROMD寫
void EEPROM_Write(unsigned char dat,unsigned char add)
{
		IIC_Start();
		IIC_SendByte(0xa0);
		IIC_WaitAck();
		IIC_SendByte(add);
		IIC_WaitAck();
	
		IIC_SendByte(dat);
		IIC_WaitAck();
	
		IIC_Stop();
	 
}

 iic.h

#ifndef _IIC_H
#define _IIC_H

#include "stc15f2k60s2.h"
#include "intrins.h"

#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();}
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//總線引腳定義
sbit SDA = P2^1;  /* 數據線 */
sbit SCL = P2^0;  /* 時鐘線 */

//函數聲明
void IIC_Start(void); 
void IIC_Stop(void);  
void IIC_Ack(unsigned char ackbit); 
void IIC_SendByte(unsigned char byt); 
bit IIC_WaitAck(void);  
unsigned char IIC_RecByte(void); 

unsigned char AD_Read(unsigned char add);
unsigned char EEPROM_Read(unsigned char add);
void EEPROM_Write(unsigned char dat,unsigned char add);

#endif

 text.c

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

uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};

uchar start=0;
uchar moshi=1;
uchar zhuanhua=0;
uint jiange=400;
uint led_t=0;
uint zhuanhua_t=0;
uint ad_t=0;
uint RB2=0;
uchar flag=0;
uchar led_n=0;
uchar led_TT=0,light=0;
uchar f1,f2,f3,f4,f5,f6,f7,f8;

void allinit();
void delayms(uchar ms);
void keyscan();
void Time0_init();
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 main(){
allinit();
Time0_init();
moshi=EEPROM_Read(0x10);
delayms(5);
jiange=EEPROM_Read(0x20)*100;
delayms(5);
f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=11;f8=11;
while(1){
    if((zhuanhua==0)&&(flag==1))
	{
	   if(RB2<64)
	   {
	     f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=10;f8=1;
	   }
	   else if((RB2>=64)&&(RB2<128))
	   {
	     f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=10;f8=2;
	   }
	   else if((RB2>=128)&&(RB2<192))
	   {
	     f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=10;f8=3; 
	   }
	   else if((RB2>=192)&&(RB2<255))
	   {
	     f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=10;f8=4;
	   }
	}
	else if(zhuanhua==0)
	 {
	   f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=11;f8=11;
	 }
	 keyscan();
	 display12(f1,f2);
	 display34(f3,f4);
	 display56(f5,f6);
	 display78(f7,f8);
}

}
void keyscan(){
if(P30==0)
{
  delayms(5);
  if(P30==0)
  {
    if(start==0)
	{
	  start=1;
	}
	else if(start==1)
	{
	  start=0;
	}
}
while(!P30);
}

else if(P31==0)
{
  delayms(5);
  if(P31==0)
  {
    if(zhuanhua==0)
	{
	  zhuanhua=1;zhuanhua_t=0;
	  if(jiange>=1000)
	  {
	    f1=10;f2=moshi;f3=10;f4=11;f5=jiange/1000;f6=jiange%1000/100;f7=jiange%100/10;f8=jiange%10;
	  }
	  else
	  {
	    f1=10;f2=moshi;f3=10;f4=11;f5=11;f6=jiange/100;f7=jiange%100/10;f8=jiange%10;
	  }
	}
	else if(zhuanhua==1)
	{
	  zhuanhua=2;zhuanhua_t=0;
	  if(jiange>=1000)
	  {
	    f1=10;f2=moshi;f3=10;f4=11;f5=jiange/1000;f6=jiange%1000/100;f7=jiange%100/10;f8=jiange%10;
	  }
	  else
	  {
	    f1=10;f2=moshi;f3=10;f4=11;f5=11;f6=jiange/100;f7=jiange%100/10;f8=jiange%10;
	  }
	}
	else if(zhuanhua==2)
	{
	  zhuanhua=0;zhuanhua_t=0;
	  f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=11;f8=11;
	  EEPROM_Write(moshi,0x10);
	  delayms(5);
	  EEPROM_Write(jiange/100,0x20);
	  delayms(5);
	}
}
while(!P31);
}

else if(P32==0)
{
  delayms(5);
  if(P32==0)
  {
     if(zhuanhua==1)
	 {
	   moshi+=1;
	   if(moshi==5)
	   {
	     moshi=1;
	   }
	 }
	 else if(zhuanhua==2)
	 {
	   jiange+=100;
	   if(jiange==1300)
	   {
	     jiange=400;
	   }
	 }
   }
while(!P32);
}

else if(P33==0)
{
  delayms(5);
  if(P33==0)
  {
    flag=1;
  }
}

if((P33==1)&&(flag==1))
{
  flag=0;
  if(zhuanhua==1)
  {
    moshi-=1;
	if(moshi==0)
	{
	  moshi=4;
	}
  }
  else if(zhuanhua==2)
  {
    jiange-=100;
	if(jiange==300)
	{
	  jiange=1200;
	}
  }
}
}

void Time0_init(){
TMOD=0X01;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
TR0=1;
EA=1;
ET0=1;
}

void Time0_service() interrupt 1
{
 TH0=(65536-1000)/256;
 TL0=(65536-1000)%256;
 zhuanhua_t++;
 led_t++;
 ad_t++;
 if((led_t==1)&&(start==1))
 {
   if(moshi==1)
   {
    P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
	P0=~(0X01<<led_n);
   }
   else if(moshi==2)
   {
    P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
	P0=~(0X80>>led_n);
   }
   else if(moshi==3)
   {
     P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
	 if(led_n==0) P0=0X7E;
	 else if(led_n==1) P0=0XBD;
	 else if(led_n==2) P0=0XDB;
	 else if(led_n==3) P0=0XE7;
   }
   else if(moshi==4)
   {
     P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
	 if(led_n==0) P0=0XE7;
	 else if(led_n==1) P0=0XDB;
	 else if(led_n==2) P0=0XBD;
	 else if(led_n==3) P0=0X7E;
   }
 }
 else if(led_t==light)
 {
   	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
 }
 else if(led_t==20)
 {
    led_t=0;led_TT++;
	if(20*led_TT>=jiange)
	{
	  led_TT=0;
	  if(moshi==1)
	  {
	     led_n++;
		 if(led_n>=8)
		 {
		   led_n=0;
		 }
	  }
	  else if(moshi==2)
	  {
	     led_n++;
		 if(led_n>=8)
		 {
		   led_n=0;
		 }
	  }
	  else if(moshi==3)
	  {
	     led_n++;
		 if(led_n>=4)
		 {
		   led_n=0;
		 }
	  }
	  else if(moshi==4)
	  {
	    led_n++;
		if(led_n>=4)
		{
		  led_n=0;
		}
	  }
	}
  }
  if(ad_t==200)
  {
    ad_t=0;
	RB2=AD_Read(0x03);
	if(RB2<64) light=2;
	else if((RB2>=64)&&(RB2<128)) light=5;
	else if((RB2>=128)&&(RB2<192)) light=10;
	else if((RB2>=192)&&(RB2<255)) light=19;
  }

  if(zhuanhua_t==800)
  {
     if(zhuanhua==1)
	 {
	   if(jiange>=1000)
	   {
	      f1=11;f2=11;f3=11;f4=11;f5=jiange/1000;f6=jiange%1000/100;f7=jiange%100/10;f8=jiange%10;
	   }
	   else
	   {
	      f1=11;f2=11;f3=11;f4=11;f5=11;f6=jiange/100;f7=jiange%100/10;f8=jiange%10;
	   }
	 }
	 else if(zhuanhua==2)
	 {
	   if(jiange>=1000)
	   {
	      f1=10;f2=moshi;f3=10;f4=11;f5=11;f6=11;f7=11;f8=11;
	   }
	   else
	   {
	      f1=10;f2=moshi;f3=10;f4=11;f5=11;f6=11;f7=11;f8=11;
	   }
	 }
  }

  if(zhuanhua_t==1600)
  {
    zhuanhua_t=0;
	if(zhuanhua==1)
	{
	   if(jiange>=1000)
	   {
	     f1=10;f2=moshi;f3=10;f4=11;f5=jiange/1000;f6=jiange%1000/100;f7=jiange%100/10;f8=jiange%10;
	   }
	   else
	   {
	      f1=10;f2=moshi;f3=10;f4=11;f5=11;f6=jiange/100;f7=jiange%100/10;f8=jiange%10;
	   }
	}
	else if(zhuanhua==2)
	{
	   if(jiange>=1000)
	   {
	     f1=10;f2=moshi;f3=10;f4=11;f5=jiange/1000;f6=jiange%1000/100;f7=jiange%100/10;f8=jiange%10;
	   }
	   else
	   {
	      f1=10;f2=moshi;f3=10;f4=11;f5=11;f6=jiange/100;f7=jiange%100/10;f8=jiange%10;
	   }
	} 
 }
} 
 
void allinit(){
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}

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

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

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

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

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

 

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