首页 > 技术文章 > 蓝桥杯单片机练习_第九届彩灯控制器

nsss 2019-03-15 14:26 原文

一、题目要求

二、程序源码

 

  1 #include "stc15.h"
  2 #include "iic.h"
  3 #include <stdio.h>
  4 
  5 #define uchar unsigned char
  6 #define uint unsigned int
  7 
  8 #define KEYCOM P3                    //按键IO
  9 #define KEY_S7 0x01
 10 #define KEY_S6 0x02
 11 #define KEY_S5 0x04
 12 #define KEY_S4 0x08
 13 #define PWM_MAX 19            //pwm周期 <20
 14 
 15 uchar code smg_dis[]= {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40};
 16 uchar code LED_Max[]= {7,7,3,3}; //模式轮转时 数组最大下标
 17 uchar code LED_MODE1[]= {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
 18 uchar code LED_MODE2[]= {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
 19 uchar code LED_MODE3[]= {0x81,0x42,0x24,0x18};
 20 uchar code LED_MODE4[]= {0x18,0x24,0x42,0x81};
 21 uchar code PWM_Val[]= {0,5,10,15,20}; //亮度调节PWM值
 22 
 23 uchar Smg_Buf[8]= {10,10,10,10,10,10,10,10};
 24 uchar Led_Time[4]= {4,4,4,4}; //轮转时间
 25 
 26 bit LED_Switch=0;//led轮转开关
 27 bit KEY_Flag=0;
 28 bit ADC_Flag=0;
 29 bit SET_Flag=0;
 30 bit Blink_Flag=0;//0.8s闪烁
 31 
 32 uchar Trg, Cont; //键值
 33 uchar Rank=1;//光照等级
 34 
 35 void Delay2ms();//写入延时
 36 void UartInit(void);
 37 void Timer0Init(void)    ;
 38 void KeyRead ();
 39 void KEY_Dispose (void);//按键处理
 40 void Set_Show (uchar mode);
 41 void Write_AT24 (uchar add,uchar dat);
 42 uchar Read_AT24 (uchar add);
 43 uchar Read_ADC (uchar add);//读取adc
 44 uchar KEY_Resize (uchar sum,uchar Max,uchar Min);//按键调整数值
 45 
 46 void main (void)
 47 {
 48     uchar ADC_Val;
 49     P0=0x00;P2=0xa0;P2=0x00;
 50     P0=0xff,P2=0x80,P2=0x00;
 51     UartInit();
 52     Timer0Init();
 53     Led_Time[0]=Read_AT24(0x01);
 54     Led_Time[1]=Read_AT24(0x02);
 55     Led_Time[2]=Read_AT24(0x03);
 56     Led_Time[3]=Read_AT24(0x04);
 57     
 58     if( Led_Time[0]>=4 && Led_Time[1]>=4 && Led_Time[2]>=4 && Led_Time[3]>=4  &&
 59                 Led_Time[0]<=12 && Led_Time[1]<=12 && Led_Time[2]<=12 && Led_Time[3]<=12
 60             );//判断读取到的间隔是否在规定范围
 61     else //不在范围重新赋值
 62     {
 63         Led_Time[0]=4;
 64         Led_Time[1]=4;
 65         Led_Time[2]=4;
 66         Led_Time[3]=4;
 67     }
 68     while(1)
 69     {
 70         if(KEY_Flag)
 71         {
 72             KEY_Flag=0;
 73             KEY_Dispose();//处理按键事件
 74             if(!SET_Flag && (Trg & KEY_S4 || Cont & KEY_S4))//普通状态显示亮度
 75             {
 76                 Smg_Buf[6]=11;
 77                 Smg_Buf[7]=Rank;
 78             }
 79             else if (!SET_Flag)
 80             {
 81                 Smg_Buf[6]=10;
 82                 Smg_Buf[7]=10;
 83             }
 84         }
 85         if(ADC_Flag)//亮度判断
 86         {
 87             ADC_Flag=0;
 88             ADC_Val=Read_ADC(0x03);
 89             if(ADC_Val<=69)
 90                 Rank=1;
 91             else if (ADC_Val>69&&ADC_Val<=131)
 92                 Rank=2;
 93             else if (ADC_Val>131&&ADC_Val<=193)
 94                 Rank=3;
 95             else if (ADC_Val>193&&ADC_Val<=255)
 96                 Rank=4;
 97         }
 98     }
 99 }
100 
101 void Timer0Init(void)        //1ms@11.0592MHz
102 {
103     AUXR |= 0x80;
104     TMOD &= 0xF0;
105     TL0 = 0xCD;
106     TH0 = 0xD4;
107     TF0 = 0;
108     TR0 = 1;
109     ET0 = 1;
110     EA  = 1;
111 }
112 
113 void TIME0() interrupt 1
114 {
115     static uint LedCount =0;
116     static uchar KeyCount =0;
117     static uchar SmgCount =0;
118     static uchar SmgLen=0;
119     static uchar AdcCount=0;
120     static uint BlinkCount=0;
121     static uchar i =0;
122     static uchar PWM;
123     static uchar  Run_Mode =1;
124 
125     if(++KeyCount>10)
126     {
127         KeyCount=0;
128         KEY_Flag=1;
129     }
130 
131     if(++AdcCount>100)
132     {
133         AdcCount=0;
134         ADC_Flag=1;
135     }
136 
137     if(SET_Flag)//设置下闪烁所选位
138     {
139         if( ++BlinkCount>800)
140         {
141             BlinkCount=0;
142             Blink_Flag=~Blink_Flag;//不可手动清0
143         }
144     }
145     if(++SmgCount>1)
146     {
147         SmgCount=0;
148         P0=~smg_dis[Smg_Buf[SmgLen]];P2=0xe0;P2=0x00;
149         P0=1<<SmgLen;P2=0xc0;P2=0x00;
150         if(++SmgLen>7)SmgLen=0;
151     }
152     /*****************/
153     PWM++;
154     if(PWM <= PWM_Val[Rank])
155     {
156         switch(Run_Mode)//模式
157         {
158         case 1 :
159             P0=~LED_MODE1[i];
160             break;
161         case 2 :
162             P0=~LED_MODE2[i];
163             break;
164         case 3 :
165             P0=~LED_MODE3[i];
166             break;
167         case 4 :
168             P0=~LED_MODE4[i];
169             break;
170         }
171         P2=0x80;P2=0x00;
172     }
173     else if(PWM < PWM_MAX&&PWM>PWM_Val[Rank])//pwm周期小于20ms 视觉残留
174     {
175         P0=~0x00;P2=0x80;P2=0x00;
176     }
177     else
178     {
179         PWM=0;
180     }
181     /*****************/
182     if(!LED_Switch)//暂停时 不影响亮度
183     {
184         ++LedCount;
185         if(LedCount > Led_Time[Run_Mode-1]*100)
186         {
187             LedCount=0;
188             ++i;
189             if( i > LED_Max[Run_Mode-1])
190             {
191                 i=0;
192                 Run_Mode++;//模式切换
193                 if(Run_Mode==5)Run_Mode=1;
194             }
195         }
196     }
197 }
198 
199 void KeyRead (void)
200 {
201     uchar ReadData = KEYCOM ^ 0xff;
202     Trg = ReadData & (ReadData ^ Cont);
203     Cont = ReadData;
204 }
205 
206 void KEY_Dispose (void)
207 {
208     static uchar SET_MODE=0,mode1=0;
209     KeyRead();
210     if( Trg & KEY_S7 )
211     {
212         LED_Switch=~LED_Switch;
213     }
214     if( Trg & KEY_S6 )
215     {
216         if(!SET_Flag)
217         {
218             SET_MODE=0;
219             SET_Flag=1;
220             mode1=0;
221         }
222         else
223             SET_MODE++;
224         if(SET_MODE>=2)//退出设置 清空显示缓存 便于亮度显示 向EEPROM写入间隔
225         {
226             SET_MODE=0;
227             SET_Flag=0;
228             Smg_Buf[0]=10;
229             Smg_Buf[1]=10;
230             Smg_Buf[2]=10;
231             Smg_Buf[3]=10;
232             Smg_Buf[4]=10;
233             Smg_Buf[5]=10;
234             Smg_Buf[6]=10;
235             Smg_Buf[7]=10;
236             Write_AT24(0x01,Led_Time[0]);//写入间隔
237             Delay2ms();//必须延时
238             Write_AT24(0x02,Led_Time[1]);
239             Delay2ms();
240             Write_AT24(0x03,Led_Time[2]);
241             Delay2ms();
242             Write_AT24(0x04,Led_Time[3]);
243             Delay2ms();
244         }
245     }
246     if(SET_Flag)//设置模式
247     {
248         if(SET_MODE==0)
249         {
250             mode1=KEY_Resize(mode1,3,0);
251             Set_Show(mode1);
252             if(Blink_Flag)//闪烁模式位
253             {
254                 Smg_Buf[1]=10;
255             }
256         }
257         else
258         {
259             Led_Time[mode1]=KEY_Resize(Led_Time[mode1],12,4);
260             Set_Show(mode1);
261             if(Blink_Flag)//闪烁轮转间隔
262             {
263                 Smg_Buf[4]=10;
264                 Smg_Buf[5]=10;
265                 Smg_Buf[6]=10;
266                 Smg_Buf[7]=10;
267             }
268         }
269     }
270 }
271 
272 uchar KEY_Resize (uchar sum,uchar Max,uchar Min)
273 {
274     char Temp;//无字符型uchar <0时会超过取值范围
275     Temp=sum;
276     if(Trg & KEY_S5)
277     {
278         if( ++Temp > Max ) Temp=Max;
279     }
280     if(Trg & KEY_S4)
281     {
282         if( --Temp < Min ) Temp=Min;
283     }
284     return Temp;
285 }
286 
287 void UartInit(void)        //9600bps@11.0592MHz
288 {
289     SCON = 0x50;
290     AUXR |= 0x01;
291     AUXR |= 0x04;
292     T2L = 0xE0;
293     T2H = 0xFE;
294     AUXR |= 0x10;
295     TI=1;
296 }
297 
298 void Set_Show (uchar mode)
299 {
300     Smg_Buf[0]=11;
301     Smg_Buf[1]=mode+1;
302     Smg_Buf[2]=11;
303     Smg_Buf[3]=10;
304     if(Led_Time[mode]<10)//当轮转时间小于1000时 即<10 不显示千位
305         Smg_Buf[4]=10;
306     else
307         Smg_Buf[4]=Led_Time[mode]/10;//1000位
308     Smg_Buf[5]=Led_Time[mode]%10;//100位
309     Smg_Buf[6]=0;
310     Smg_Buf[7]=0;//个位与十位一直为0
311 }
312 
313 uchar Read_ADC (uchar add)//读取adc
314 {
315     uchar Temp;
316     IIC_Start();
317     IIC_SendByte(0x90);
318     IIC_WaitAck();
319     IIC_SendByte(add);
320     IIC_WaitAck();
321     IIC_Start();
322     IIC_SendByte(0x91);
323     IIC_WaitAck();
324     Temp=IIC_RecByte();
325     IIC_WaitAck();
326     IIC_Stop();
327     return Temp;
328 }
329 
330 void Write_AT24 (uchar add,uchar dat)
331 {
332     IIC_Start();
333     IIC_SendByte(0xa0);
334     IIC_WaitAck();
335     IIC_SendByte(add);
336     IIC_WaitAck();
337     IIC_SendByte(dat);
338     IIC_WaitAck();
339     IIC_Stop();
340 }
341 
342 uchar Read_AT24 (uchar add)
343 {
344     uchar Temp;
345     IIC_Start();
346     IIC_SendByte(0xa0);
347     IIC_WaitAck();
348     IIC_SendByte(add);
349     IIC_WaitAck();
350     IIC_Start();
351     IIC_SendByte(0xa1);
352     IIC_WaitAck();
353     Temp=IIC_RecByte();
354     IIC_WaitAck();
355     IIC_Stop();
356     return Temp;
357 }
358 
359 void Delay2ms()        //@11.0592MHz
360 {
361     unsigned char i, j;
362 
363     _nop_();
364     _nop_();
365     i = 22;
366     j = 128;
367     do
368     {
369         while (--j);
370     } while (--i);
371 }

 

推荐阅读