怎么给公司注册网站,空间查看网站,企业网站推广效果从哪些方面进行分析,软件开发培训中心本文是写第十四届的蓝桥杯省赛代码#xff0c;新手教程作者也写了一篇#xff0c;欢迎去观看作者专门为新手写的一篇。也欢迎收录该专栏。
蓝桥杯单片机STC15F2K60S2第十三届省赛代码详细讲解#xff08;附完整代码#xff09;
专栏#xff1a; 蓝桥杯单片机 然后接下来… 本文是写第十四届的蓝桥杯省赛代码新手教程作者也写了一篇欢迎去观看作者专门为新手写的一篇。也欢迎收录该专栏。
蓝桥杯单片机STC15F2K60S2第十三届省赛代码详细讲解附完整代码
专栏 蓝桥杯单片机 然后接下来是正文
试题 iic.c
/* # I2C代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求进行代码调试和修改。
*/
#include iic.h
#include intrins.h
#define DELAY_TIME 5//
static void I2C_Delay(unsigned char n)
{do{_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); }while(n--);
}//
void I2CStart(void)
{sda 1;scl 1;I2C_Delay(DELAY_TIME);sda 0;I2C_Delay(DELAY_TIME);scl 0;
}//
void I2CStop(void)
{sda 0;scl 1;I2C_Delay(DELAY_TIME);sda 1;I2C_Delay(DELAY_TIME);
}//
void I2CSendByte(unsigned char byt)
{unsigned char i;for(i0; i8; i){scl 0;I2C_Delay(DELAY_TIME);if(byt 0x80){sda 1;}else{sda 0;}I2C_Delay(DELAY_TIME);scl 1;byt 1;I2C_Delay(DELAY_TIME);}scl 0;
}//
unsigned char I2CReceiveByte(void)
{unsigned char da;unsigned char i;for(i0;i8;i){ scl 1;I2C_Delay(DELAY_TIME);da 1;if(sda) da | 0x01;scl 0;I2C_Delay(DELAY_TIME);}return da;
}//
unsigned char I2CWaitAck(void)
{unsigned char ackbit;scl 1;I2C_Delay(DELAY_TIME);ackbit sda; scl 0;I2C_Delay(DELAY_TIME);return ackbit;
}//
void I2CSendAck(unsigned char ackbit)
{scl 0;sda ackbit; I2C_Delay(DELAY_TIME);scl 1;I2C_Delay(DELAY_TIME);scl 0; sda 1;I2C_Delay(DELAY_TIME);
}//输出ADC的值用来计算PCF8591的分压结果实现亮暗检测
unsigned char ADC_Output(char channel)
{unsigned char adc_val; //输出的ADC的值I2CStart();I2CSendByte(0x90); //开启ADC通道0x90是ADC的设备地址,指定为写操作I2CWaitAck();I2CSendByte(channel); //指定要读的ADC通道 0x41是光敏电阻I2CWaitAck();I2CStart();I2CSendByte(0x91); //指定为读操作I2CWaitAck();adc_valI2CReceiveByte();I2CSendAck(1);I2CStop();return adc_val;
}iic.h
#ifndef __IIC_H__
#define __IIC_H__#include stc15.h#define sda P21
#define scl P20unsigned char ADC_Output(char channel);
#endif
display.c
#include STC15F2K60S2.Hcode unsigned char Show_Number[]{
0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, //9
0x88, //A
0x83, //b
0xc6, //C 12
0xa1, //d
0x86, //E
0x8e, //F 15
0xbf, // - 16
0x89, // H 17
0x8C, // P 18
0x88 // R 19
};//0到9的浮点小数
code unsigned char Show_FNumber[]{0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10};//延时函数
void Delayms(int ms) //12.000MHz
{unsigned char data i, j;int k0;for(k0;kms;k){i 12;j 169;do{while (--j);} while (--i);}
}void Select_Hc573(unsigned char Number)
{switch(Number){case 4:P2(P2 0x1f) | 0x80;break; //LED驱动case 5:P2(P2 0x1f) | 0xA0;break; //蜂鸣器和继电器case 6:P2(P2 0x1f) | 0xC0;break; //数码管位选case 7:P2(P2 0x1f) | 0xE0;break; //数码管段选} //将P2位清零不然数码管会闪烁P2 (P2 0x1f) | 0x00;
}//系统初始化将蜂鸣器和数码管关闭
void System_Init(void)
{P00x00;Select_Hc573(5);Select_Hc573(6);P00xff;Select_Hc573(4);
}void Display_Number(unsigned char Pos,unsigned char Data)
{P0 0x01 Pos-1;Select_Hc573(6);P0 Show_Number[Data];Select_Hc573(7);Delayms(1);P0 0x01 Pos -1;Select_Hc573(6);P0 0xff;Select_Hc573(7);
}//显示小数
void Display_FNumber(unsigned char Pos,unsigned char Data)
{P0 0x01 Pos -1;Select_Hc573(6);P0Show_FNumber[Data];Select_Hc573(7);Delayms(1);P0 0x01 Pos -1;Select_Hc573(6);P00xff;Select_Hc573(7);Delayms(1);
}//显示LEDON_OFF 1为开启0为关闭
void Display_LED(unsigned char Pos,unsigned ON_OFF)
{static unsigned char Temp0xff;if(ON_OFF){switch(Pos){case 1: Temp Temp0xfe;break;case 2: Temp Temp0xfd;break;case 3: Temp Temp0xfb;break;case 4: Temp Temp0xf7;break;case 5: Temp Temp0xef;break;case 6: Temp Temp0xde;break;}}else {switch(Pos){case 1:TempTemp | 0x01;break;case 2:TempTemp | 0x02;break;case 3:TempTemp | 0x04;break;case 4:TempTemp | 0x08;break;case 5:TempTemp | 0x10;break;case 6:TempTemp | 0x20;break;}}P0Temp;Select_Hc573(4);
}display.h
#ifndef __DISPLAY_H__
#define __DISPLAY_H__void SelectHc573(unsigned char Number);
void System_Init(void);
void Display_Number(unsigned char Pos,unsigned char Data);
void Display_FNumber(unsigned char Pos,unsigned char Data);
void Display_LED(unsigned char Pos,unsigned ON_OFF);
void Delayms(int ms);#endifds1302.c
/* # DS1302代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求进行代码调试和修改。
*/
#include ds1302.h
#include STC15F2K60S2.Hsbit SCK P1^7;
sbit SDA P2^3;
sbit RST P1^3; //
void Write_Ds1302(unsigned char temp)
{unsigned char i;for (i0;i8;i) { SCK 0;SDA temp0x01;temp1; SCK1;}
} //
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{RST0; _nop_();SCK0; _nop_();RST1; _nop_(); Write_Ds1302(address); Write_Ds1302(dat); RST0;
}//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{unsigned char i,temp0x00;RST0; _nop_();SCK0; _nop_();RST1; _nop_();Write_Ds1302(address);for (i0;i8;i) { SCK0;temp1; if(SDA)temp|0x80; SCK1;} RST0; _nop_();SCK0; _nop_();SCK1; _nop_();SDA0; _nop_();SDA1; _nop_();return (temp);
}//写保护
#define WP 0x8e
#define W_Sec 0x80
#define R_Sec 0x81
#define W_Min 0x82
#define R_Min 0x83
#define W_Hour 0x84
#define R_Hour 0x85//写初始化时间到ds1302
void WriteDate(ds1302 *date)
{unsigned hour, min, sec;hour date-Hour/10*16 date-Hour%10; //十进制转化为十六进制mindate-Min/10*16 date-Min%10;secdate-Sec/10*16 date-Sec%10;//取消写保护Write_Ds1302_Byte(WP,0x00);Write_Ds1302_Byte(W_Hour,hour);Write_Ds1302_Byte(W_Min,min);Write_Ds1302_Byte(W_Sec,sec);//开启写保护Write_Ds1302_Byte(WP,0x00);
}//读取当前时间
ds1302 ReadTime()
{unsigned char hour,min,sec;ds1302 date;hour Read_Ds1302_Byte(R_Hour);min Read_Ds1302_Byte(R_Min);sec Read_Ds1302_Byte(R_Sec);date.Hour hour/16*10 hour%16; //十六进制转化为十进制date.Min min/16*10 min%16;date.Sec sec/16*10 sec%16;return date;
}
ds1302.h
#ifndef __DS1302_H__
#define __DS1302_H__#include intrins.h
#include STC15F2K60S2.H//#define SCK P17
//#define SDA P23
//#define RST P13//定义ds1302的数据类型
typedef struct{unsigned char Hour;unsigned char Min;unsigned char Sec;
}ds1302;void WriteDate(ds1302 *date);
ds1302 ReadTime();#endifonrwire.c
/* # 单总线代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求进行代码调试和修改。
*/
#include onewire.h
//
void Delay_OneWire(unsigned int t)
{unsigned char i;while(t--){for(i0;i12;i);}
}//
void Write_DS18B20(unsigned char dat)
{unsigned char i;for(i0;i8;i){DQ 0;DQ dat0x01;Delay_OneWire(5);DQ 1;dat 1;}Delay_OneWire(5);
}//
unsigned char Read_DS18B20(void)
{unsigned char i;unsigned char dat;for(i0;i8;i){DQ 0;dat 1;DQ 1;Delay_OneWire(1);if(DQ){dat | 0x80;} Delay_OneWire(5);}return dat;
}//
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;
}unsigned char Read_Temperature(void)
{unsigned temp,th,tl;init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0x44);init_ds18b20(); //开启温度转换Write_DS18B20(0xcc);Write_DS18B20(0xbe); //开启温度读取tl Read_DS18B20();th Read_DS18B20();temp (th *256 tl) * 0.0625;return temp;
}onewire.h
#ifndef __ONEWIRE_H__
#define __ONEWIRE_H__#include STC15F2K60S2.H#define DQ P14
unsigned char Read_Temperature(void);
#endif
main.c
#include STC15F2K60S2.H
#include display.h
#include ds1302.h
#include onewire.h
#include iic.h
#include string.hds1302 Date{23,59,50};unsigned int Freq; //NE555的频率
unsigned char Wet_Val; //湿度的数据
unsigned char Adc_Val; //ADC的值
unsigned char Collect_Flag1; //暗亮环境的标志1表示处于亮环境
unsigned char i; //数组的索引
//unsigned char temp0; //温度
unsigned char count2,sec; //暗环境时的计时3秒后退出
unsigned char show; //0为温湿度界面的显示1显示Show_Switch对应的界面
unsigned char t[3],w[3]; //用于保存采集的温度、湿度只保留3组
unsigned char L5_Flag,L6_Flag,L4_Flag; //LED的标志为 1为开启LED
unsigned char count_trigger0; //用来记录触发的次数
unsigned char last_hour,last_min; //最近一次触发的时间
unsigned char Temp_Para30; //温度参数
unsigned char Key_Val; //用来记录按键
unsigned char Switching1; //界面切换 1.时间显示界面 2.回显界面 3.参数显示
unsigned char S5_Flag1; //回显界面下切换温度、湿度、时间回显
unsigned char Count3,Count_Sec; //用于S9长按两秒的计时
unsigned char Temping0; //温度
unsigned char Flag_100ms; //0.1s的标志位L4以0.1秒为间隔进行闪烁
unsigned char Flag_1s; //用来表示1s时间到统计NE555的频率
unsigned char Count; //用于定时器的中断定时void Key_Board(void);
void Show_Switch(void);
void Timer0_Init(void); //12.000MHz;
void Timer1_Init(void); //10毫秒12.000MHz
void Timer2_Init(void); //20毫秒12.000MHzvoid main()
{System_Init();WriteDate(Date);Timer0_Init();Timer1_Init();Timer2_Init();while(1){ if(Freq2000 Freq200)Wet_Val2/45*Freq 1.11;else if(Freq 2000)Wet_Val 90;else if(Freq 200)Wet_Val 10;else Wet_Val 0; //无效数据Adc_Val ADC_Output(0x01); //读取ADC的值if(Adc_Val 100) Collect_Flag1; //ADC值大于100表示处于亮环境if(Adc_Val 100 Collect_Flag 1) //触发数据测量条件{Collect_Flag0; AUXR | 0x10; //启动定时器2show 1;t[i]Temping;if(Wet_Val ! 0){ w[i] Wet_Val; L5_Flag0; }else {L5_Flag1;} //采集到无效数据无效数据不保存点亮LED5count_trigger;if(i0 count_trigger2) //本次采集大小与上次比较{if(Temping t[2] Wet_Val w[2]) L6_Flag1; //采集到的温度湿度均升高LED6点亮else L6_Flag0;}else L6_Flag1;if(i !0 count_trigger2){if(Temping t[i-1]Wet_Valw[i-1]) L6_Flag1; //温湿度都大于上次else L6_Flag0;}else L6_Flag0;i;if(i3) i0;last_hour Date.Hour;last_min Date.Min;if(Temping Temp_Para) L4_Flag1; //采集温度大于温度参数LED4点亮else L4_Flag0;}Key_Board(); //按键检测函数Show_Switch(); //所有显示函数放在此函数内为了使按键按下不影响显示内容}
}//按键检测函数
void Key_Board(void)
{unsigned char Key;//P44为第一列按键P3低四位为每一行第一行为0x01P44 0; P421;P3 |0x0f; //将每一行置1Key P3; Key Key 0x0c;if(Key ! 0x0c){Delayms(5); //消抖if(Key ! 0x0c){switch(Key){case 0x04: Key_Val 4; Switching;if(Switching 3){Switching 1;S5_Flag1;} break; case 0x08: Key_Val5;if(Switching 2) //回显界面{S5_Flag;}if(S5_Flag 3)S5_Flag1;break;}} while(Key ! 0x0c){Key P3; Key Key 0x0c;Show_Switch();}}P441;P420;P3 | 0x0f;Key P3; Key 0x0c;if(Key !0x0c){Delayms(5);if(Key ! 0x0c){switch(Key) //S8 S9--{case 0x04: Key_Val8;if(Switching 3) Temp_Para;if(Temp_Para 99) Temp_Para0;break;case 0x08: Key_Val9;if(Switching 3) Temp_Para--;if(Temp_Para 255) Temp_Para 99;break;}if(S5_Flag 3) { Count3 0; Count_Sec 0;} //时间回显下S9按下两秒计时开始}while(Key ! 0x0c){Key P3; Key Key 0x0c;Show_Switch();if(Count_Sec 2 S5_Flag 3) //时间回显界面长按S9两秒数据清零{memset(t,0,sizeof(t)); memset(w,0,sizeof(w)); //将数组里的全部元素清零count_trigger0; //触发次数清零}}}
}unsigned char max(unsigned char p[])
{unsigned char i;unsigned char Maxp[0];for(i1;i3;i){if(p[i] Max)Maxp[i];}return Max;
}void Show_Switch(void)
{//最大温度和湿度unsigned char t_max,w_max;int t_avr,w_avr; //温湿度平均值Date ReadTime();Temping Read_Temperature();t_maxmax(t); w_maxmax(w);t_avr (t[0] t[1]t[2])/3.0*10;w_avr(w[0]w[1]w[2])/3.0*10;if(show !1){if(Switching 1) //时间显示界面{Display_Number(1,Date.Hour/10);Display_Number(2,Date.Hour%10);Display_Number(3,16);Display_Number(4,Date.Min/10);Display_Number(5,Date.Min%10);Display_Number(6,16);Display_Number(7,Date.Sec/10);Display_Number(8,Date.Sec%10);}if(Switching 2) //回显界面默认温度回显C{switch(S5_Flag) //温度回显C湿度回显H时间回显F{//温度回显case 1: Display_Number(1,12);if(count_trigger !0 ) //触发次数不为0{Display_Number(3,t_max/10);Display_Number(4,t_max%10); //最大温度Display_Number(5,16);Display_Number(6,t_avr/100);Display_FNumber(7,t_avr%100/10);Display_Number(8,t_avr%10);}break;case 2: Display_Number(1,17); //Hif(count_trigger ! 0){Display_Number(3,w_max/10);Display_Number(4,w_max%10);Display_Number(5,16);Display_Number(6,w_avr/100);Display_FNumber(7,w_avr%100/10);Display_Number(8,w_avr%10);}break;case 3:Display_Number(1,15);Display_Number(2,count_trigger/10);Display_Number(3,count_trigger%10); //触发次数显示if(count_trigger ! 0){Display_Number(4,last_hour/10);Display_Number(5,last_hour%10);Display_Number(6,16);Display_Number(7,last_min/10);Display_Number(8,last_min%10);}break;}}if(Switching 3) //参数设置界面{Display_Number(1,18);Display_Number(7,Temp_Para/10);Display_Number(8,Temp_Para%10);}}else //温湿度显示界面每次显示3秒后自动退出{Display_Number(1,14);Display_Number(4,Temping/10);Display_Number(5,Temping%10);Display_Number(6,16);//温度if(Wet_Val ! 0){Display_Number(7,Wet_Val/10);Display_Number(8,Wet_Val%10);}else {Display_Number(7,19);Display_Number(8,19);}}//LED显示switch(Switching){case 1: Display_LED(1,1);Display_LED(2,0);Display_LED(3,0);break;case 2: Display_LED(2,1);Display_LED(1,0);Display_LED(3,0);break;case 3: Display_LED(3,1);Display_LED(1,0);Display_LED(2,0);break;}if(L4_Flag 1){if(Flag_100ms) Display_LED(4,1);else Display_LED(4,0);}else Display_LED(4,0);if(L5_Flag 1){Display_LED(5,1);} else Display_LED(5,0);if(L6_Flag 1){Display_LED(6,1);} else Display_LED(6,0);
}void Timer0_Init(void) //12.000MHz
{AUXR 0x7F; //定时器时钟12T模式TMOD 0xF0; //设置定时器模式TMOD |0x04;TL0 0; //设置定时初始值TH0 0; //设置定时初始值TF0 0; //清除TF0标志ET0 1; //使能定时器0中断TR0 1; //定时器0开始计时
}void Timer1_Init(void) //10毫秒12.000MHz
{AUXR 0xBF; //定时器时钟12T模式TMOD 0x0F; //设置定时器模式TL1 0xF0; //设置定时初始值TH1 0xD8; //设置定时初始值TF1 0; //清除TF1标志TR1 1; //定时器1开始计时ET1 1; //使能定时器1中断EA 1; //使能全局中断确保定时器1能正常中断
}void Timer1(void) interrupt 3
{Count;Count3;if(Count 100){Count 0;Flag_1s1;}if(Count % 10 0){Flag_100ms~Flag_100ms;}if(Flag_1s 1){Flag_1s0; TR0 0;Freq TH0*256 TL0; //定时器0是用P34来读取NE555的频率TH00;TL00;TR01;}if(Count3 100){Count30;Count_Sec;}
}void Timer2_Init(void) //20毫秒12.000MHz
{AUXR 0xFB; //定时器时钟12T模式T2L 0xE0; //设置定时初始值T2H 0xB1; //设置定时初始值
// AUXR | 0x10; //定时器2开始计时AUXR 0xef;IE2 | 0x04; //使能定时器2中断
}void Timer2(void) interrupt 12
{count2;if(count2 50) //1000毫秒{count20;sec;if(sec 3){sec0;show 0; //显示Show_Switch对应的界面AUXR 0xef; //关闭定时器2} }
}