惊险刺激的蓝桥杯省赛也是在就圆满结束了,相比于往年第十四届的题目,今年的蓝桥杯省赛题目难度降低了不少,我也尝试把题目做了一下,发现还行,功能也基本上都实现了,接下来我将把代码放在下面,读者可自取学习。如果对蓝桥杯单片机还是很不熟悉的,欢迎去阅读我的更详细的代码讲解。
蓝桥杯单片机STC15F2K60S2第十三届省赛代码详细讲解(附完整代码)
省赛题目
详细代码
iic.c
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "iic.h"
#include "intrins.h"
#define DELAY_TIME 10
//
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(i=0; i<8; 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(i=0;i<8;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);
}
void FecOutput(unsigned char Data)//unsigned char Addr,
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x40);
I2CWaitAck();
I2CSendByte(Data);
I2CWaitAck();
I2CStop();
}
iic.h
#ifndef __IIC_H__
#define __IIC_H__
#include <STC15F2K60S2.H>
#define sda P21
#define scl P20
void FecOutput(unsigned char Data);
#endif
ds1302.c
/* # DS1302代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <STC15F2K60S2.H>
#include "ds1302.h"
sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;
//
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;
temp>>=1;
SCK=1;
}
}
//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _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
void ds1302_write(ds1302* date)
{
unsigned char hour,min,sec;
hour =date->Hour/10*16+date->Hour%10;
min =date->Min/10*16+date->Min%10;
sec =date->Sec/10*16+date->Sec%10;
Write_Ds1302_Byte(WP,0x00);
Write_Ds1302_Byte(W_Sec,sec);
Write_Ds1302_Byte(W_Min,min);
Write_Ds1302_Byte(W_Hour,hour);
Write_Ds1302_Byte(WP,0x00);
}
ds1302 ds1302_read(void)
{
ds1302 date;
unsigned char hour,min,sec;
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"
typedef struct{
unsigned char Hour;
unsigned char Min;
unsigned char Sec;
}ds1302;
extern struct ds1302;
void ds1302_write(ds1302* date);
ds1302 ds1302_read(void);
#endif
display.c
#include <STC15F2K60S2.H>
code unsigned char Number[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x8e, //F 10
0x8c, //P 11
0xbf, //- 12
0x89, //H 13
0x88, //A 14
0xc7 //L 15
};
void Delayms(int ms) //@12.000MHz
{
unsigned char data i, j;
int k=0;
for(k=0;k<ms;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;
case 5:P2=(P2&0x1f)|0xA0;break;
case 6:P2=(P2&0x1f)|0xC0;break;
case 7:P2=(P2&0x1f)|0xE0;break;
}
P2=(P2&0x1f)|0x00;
}
void Display_Number(unsigned char Pos,unsigned char Data)
{
P0=0x01<<Pos-1;
Select_HC573(6);
P0=Number[Data];
Select_HC573(7);
Delayms(1);
P0=0x01<<Pos-1;
Select_HC573(6);
P0=0xff;
Select_HC573(7);
}
void System_Init(void)
{
P0=0x00;
Select_HC573(5);
Select_HC573(6);
P0=0xff;
Select_HC573(4);
}
void Display_LED(unsigned char Number,unsigned char State)
{
static unsigned char temp=0xff;
if(State)
{
switch(Number)
{
case 1:temp &=0xfe;break;
case 2:temp &=0xfd;break;
}
}
else
{
switch(Number)
{
case 1:temp |=0x01;break;
case 2:temp |=0x02;break;
}
}
P0=temp;
Select_HC573(4);
}
display.h
#ifndef __DISPLAY_H__
#define __DISPLAY_H__
void Delayms(int ms); //@12.000MHz
void Display_Number(unsigned char Pos,unsigned char Data);
void System_Init(void);
void Display_LED(unsigned char Number,unsigned char State);
#endif
main.c
#include <STC15F2K60S2.H>
#include "ds1302.h"
#include "display.h"
#include "iic.h"
void Key_Board(void);
void Timer0_Init(void); //20毫秒@12.000MHz
void Timer1_Init(void); //20毫秒@12.000MHz
void Show_Switch(void);
void Timer2_Init(void); //50毫秒@12.000MHz
void LED(void);
void PCF(void);
void Max(void);
ds1302 Date={13,03,05};
ds1302 DateCount={13,03,05};
long Fec=0;
unsigned char switching=0;
unsigned int OverPara=2000;
long SetPara=0;
unsigned char Output=0;
unsigned char ParaFlag=1;
unsigned char BackFlag=1;
unsigned char LED1Flag=1;
unsigned char LED2ShowFlag=0;
unsigned char LED2Flag=1;
unsigned long FecMax=0;
void main(void)
{
System_Init();
ds1302_write(&Date);
Timer0_Init();
Timer1_Init();
Timer2_Init();
while(1)
{
PCF();
Show_Switch();
Key_Board();
LED();
Max();
}
}
void Key_Board(void)
{
unsigned char Key;
P44=0;P42=1;P3 |=0x0f;
Key=P3;Key &=0x0c;
if(Key!=0x0c)
{
Delayms(5);
if(Key !=0x0c)
{
switch(Key)
{ //s4
case 0x04:switching++;
ParaFlag=1;BackFlag=1;
if(switching==4)switching=0;
break;
case 0x08:if(switching==1){
ParaFlag=!ParaFlag;
}
else if(switching==3){
BackFlag =!BackFlag;
}
break;
}
}
while(Key!=0x0c)
{
Key=P3;Key &=0x0c;
Show_Switch();
}
}
P44=1;P42=0;P3 |=0x0f;
Key=P3;Key &=0x0c;
if(Key!=0x0c)
{
Delayms(5);
if(Key !=0x0c)
{
switch(Key)
{ //s8
case 0x04:if(switching==1){
if(ParaFlag){
OverPara +=1000;
if(OverPara==10000) OverPara=9000;
}
else{
SetPara +=100;
if(SetPara==1000) SetPara=900;
}
}break;
//s9
case 0x08:if(switching==1){
if(ParaFlag){
OverPara -=1000;
if(OverPara==0) OverPara=1000;
}
else{
SetPara-=100;
if(SetPara==-1000) SetPara=-900;
}
}break;
}
}
while(Key!=0x0c)
{
Key=P3;Key &=0x0c;
Show_Switch();
}
}
}
void Show_Switch(void)
{
if(switching==0)//频率
{
Display_Number(1,10);
if(Fec<10000)
{
Display_Number(5,Fec/1000%10);Display_Number(6,Fec/100%10);
Display_Number(7,Fec/10%10);Display_Number(8,Fec%10);
}
else
{
Display_Number(4,Fec/10000);
Display_Number(5,Fec/1000%10);Display_Number(6,Fec/100%10);
Display_Number(7,Fec/10%10);Display_Number(8,Fec%10);
}
}
if(switching==1)//参数
{
if(ParaFlag)
{
Display_Number(1,11);Display_Number(2,1);
Display_Number(5,OverPara/1000);Display_Number(6,OverPara/100%10);
Display_Number(7,OverPara/10%10);Display_Number(8,OverPara%10);
}
else
{
Display_Number(1,11);Display_Number(2,2);
if(SetPara<0)
{
Display_Number(5,12);Display_Number(6,-SetPara/100%10);
Display_Number(7,-SetPara/10%10);Display_Number(8,-SetPara%10);
}
else if(SetPara>0)
{
Display_Number(6,SetPara/100);
Display_Number(7,SetPara/10%10);Display_Number(8,SetPara%10);
}
else
{
Display_Number(8,0);
}
}
}
if(switching==2) //时间
{
Date = ds1302_read();
Display_Number(1,Date.Hour/10);Display_Number(2,Date.Hour%10);Display_Number(3,12);
Display_Number(4,Date.Min/10);Display_Number(5,Date.Min%10);Display_Number(6,12);
Display_Number(7,Date.Sec/10);Display_Number(8,Date.Sec%10);
}
if(switching==3) //回显
{
if(BackFlag)
{
if(FecMax<10000)
{
Display_Number(1,13);Display_Number(2,10);
Display_Number(5,FecMax/1000%10);Display_Number(6,FecMax/100%10);
Display_Number(7,FecMax/10%10);Display_Number(8,FecMax%10);
}
else
{
Display_Number(1,13);Display_Number(2,10);
Display_Number(4,FecMax/10000);
Display_Number(5,FecMax/1000%10);Display_Number(6,FecMax/100%10);
Display_Number(7,FecMax/10%10);Display_Number(8,FecMax%10);
}
}
else
{
Display_Number(1,13);Display_Number(2,14);
Display_Number(3,DateCount.Hour/10);Display_Number(4,DateCount.Hour%10);
Display_Number(5,DateCount.Min/10);Display_Number(6,DateCount.Min%10);
Display_Number(7,DateCount.Sec/10);Display_Number(8,DateCount.Sec%10);
}
}
if(switching==4)
{
Display_Number(1,10);
Display_Number(7,15);Display_Number(8,15);
}
}
void Timer0_Init(void) //20毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 00; //设置定时初始值
TH0 = 00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void Timer1_Isr(void) interrupt 3
{
static unsigned char count;
static unsigned char count1;
count++;
count1++;
if(count1==4)
{
count1 =0;
if(LED2ShowFlag){
Display_LED(2,LED2Flag);
LED2Flag =!LED2Flag;
}else Display_LED(2,0);
}
if(count==20)
{
count=0;
TR0=0;
Fec=TH0*256+TL0;
Fec +=SetPara;
TH0=TL0=0;
TR0=1;
}
}
void Timer1_Init(void) //50毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xB0; //设置定时初始值
TH1 = 0x3C; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
EA=1;
}
void PCF(void)
{
long temp;
temp=Fec;
if(temp<0){
switching =4;
Display_LED(2,1);
LED2ShowFlag=0;
FecOutput(0);
}
else if(temp>= 0)
{
if(temp<500) Output=1;
else if(temp>OverPara) Output=5;
else {
Output=(4/(500*OverPara-500))*temp+1-(4/(OverPara-1));
}
FecOutput(Output);
}
}
void Timer2_Isr(void) interrupt 12
{
static unsigned char count;
count++;
if(count==4)
{
count =0;
Display_LED(1,LED1Flag);
LED1Flag =!LED1Flag;
}
}
void Timer2_Init(void) //50毫秒@12.000MHz
{
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0xB0; //设置定时初始值
T2H = 0x3C; //设置定时初始值
// AUXR |= 0x10; //定时器2开始计时
AUXR &=0xef;
IE2 |= 0x04; //使能定时器2中断
}
void LED(void)
{
if(switching==0){
AUXR |= 0x10;
}else {
AUXR &=0xef;
Display_LED(1,0);
}
if(Fec>OverPara) {
LED2ShowFlag=1;
}else{
LED2ShowFlag=0;
}
}
void Max(void)
{
if(Fec>FecMax)
{
FecMax=Fec;
DateCount.Hour=Date.Hour;
DateCount.Min=Date.Min;
DateCount.Sec=Date.Sec;
}
}