写了这么多个蓝桥杯单片机的文章了,我就不过多赘述了,直接上正文了。
要深度学习就点以下文章。
蓝桥杯单片机STC15F2K60S2第十三届省赛代码详细讲解(附完整代码)
试题
main.c
#include <STC15F2K60S2.H>
#include "distance.h"
#include "display.h"
#include "iic.h"
void Show_Switch(void);
void Key_Board(void);
void Check_Output(void);
void Timer1_Init(void); //50毫秒@12.000MHz
void Timer2_Init(void); //50毫秒@12.000MHz
void Timer3_Init(void); //50毫秒@12.000MHz
unsigned char LED3_Flag=0;
unsigned char LED4_Flag=0;
unsigned char Switching=0;
unsigned int Distance=0;
unsigned char Send1Flag,Send2Flag;
unsigned char Set1Flag=2;Set2Flag=4;
unsigned char S4Flag=1;
unsigned char S5Flag=1;
unsigned char S6Flag=0;
unsigned char SetFlag=1;
unsigned char SetSwitch0=1;
void main(void)
{
Timer0_Init();
Timer1_Init();
Timer2_Init();
Timer3_Init();
System_Init();
Set1Flag=E2PROM_Read(0x01);
Set2Flag=E2PROM_Read(0x02);
while(1)
{
Key_Board();
Check_Output();
Show_Switch();
}
}
void Key_Board(void)
{
unsigned char Key;
P44=0;P3 |=0x0f;
Key=P3;Key &=0x0f;
if(Key !=0x0f)
{
Delayms(5);
if(Key !=0x0f)
{
switch(Key)
{ //S4
case 0x07:
Send1Flag=Set1Flag;
Send2Flag=Set2Flag;
S5Flag=1;
SetSwitch0=0;
if(S4Flag){
Switching=1;
AUXR |=0x10;
S4Flag=0;
Display_Relay(ON);
}
break;
case 0x0B:
if(Switching==1)
{
if(S5Flag){
S5Flag = !S5Flag;
Display_Relay(OFF);
AUXR &= 0xef;
T4T3M |= 0x08;
break;
}
else {
S5Flag = !S5Flag;
Display_Relay(ON);
AUXR |=0x10;
T4T3M &=0xe7;
break;
}
}
case 0x0D:if(S6Flag==0){
SetFlag=0;
Switching=2;
S6Flag=1;
break;
}
else if(S6Flag==1){
S6Flag=2;
break;
}
else if(S6Flag==2)
{
Switching=3;
SetFlag=1;
S6Flag=0;
SetSwitch0=1;
break;
}
case 0x0e:if(S6Flag==1){
Set1Flag++;
if(Set1Flag>10)Set1Flag=1;
E2PROM_Write(0x01,Set1Flag);
break;
}
if(S6Flag==2){
Set2Flag++;
if(Set2Flag>10)Set2Flag=1;
E2PROM_Write(0x02,Set2Flag);
break;
}
}
while(Key !=0x0f)
{
Key=P3;Key &=0x0f;
Show_Switch();
}
}
}
}
void Show_Switch(void)
{
if(Switching==0)
{
Distance=Get_Distance();
Display_Number(1,1);Display_Number(4,Distance/10%10);Display_Number(5,Distance%10);
if(Distance <=30)Display_Number(8,1);
else Display_Number(8,2);
}
if(Switching==1)
{
Display_Number(1,2);
if(Distance <=30){
Display_Number(7,Send1Flag/10%10);Display_Number(8,Send1Flag%10);
}
else {
Display_Number(7,Send2Flag/10%10);Display_Number(8,Send2Flag%10);
}
}
if(Switching==2)
{
Display_Number(1,3);Display_Number(4,Set1Flag/10);Display_Number(5,Set1Flag%10);
Display_Number(7,Set2Flag/10);Display_Number(8,Set2Flag%10);
}
if(Switching ==3)
{
P0=0x00;
Select_HC573(6);
if(Get_Distance())
{
Switching=0;
}
}
}
void Check_Output(void)
{
if(Read_Output()<1){
Display_LED(1,ON);
S4Flag=0;
if(SetFlag)
{
S6Flag=0;
// P0=0x00;
// Select_HC573(6);
Switching=4;
}
}
else{
S6Flag=3;
Display_LED(1,OFF);
}
if((Read_Output()>=1)&&(Read_Output()<4)){
Display_LED(2,ON);
if(SetSwitch0)Switching=0;
S4Flag=1;
}
else Display_LED(2,OFF);
if(Read_Output()>4){
TR1=1;
S4Flag=0;
}
else {
TR1=0;
Display_LED(3,OFF);
}
}
void Timer1_Isr(void) interrupt 3
{
static unsigned char Count;
Count++;
if(Count==10)
{
Count=0;
LED3_Flag=!LED3_Flag;
Display_LED(3,LED3_Flag);
}
}
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 Timer2_Isr(void) interrupt 12
{
static unsigned char Count;
Count++;
if(Count==20)
{
Count=0;
if(Send1Flag !=0&&Distance <=30)Send1Flag--;
else if(Distance <=30&&Send1Flag ==0){
AUXR&=0xef;
S4Flag=1;
S5Flag=0;
Display_Relay(OFF);
}
if(Send2Flag !=0&&Distance >30)Send2Flag--;
else if(Distance >30&&Send2Flag ==0){
AUXR&=0xef;
S4Flag=1;
S5Flag=0;
Display_Relay(OFF);
}
}
}
void Timer2_Init(void) //50毫秒@12.000MHz
{
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0xB0; //设置定时初始值
T2H = 0x3C; //设置定时初始值
// AUXR |= 0x10; //定时器2开始计时
AUXR &= 0xef;
IE2 |= 0x04; //使能定时器2中断
EA=1;
}
void Timer3_Isr(void) interrupt 19
{
static unsigned char Count;
Count++;
if(Count ==10)
{
Count=0;
LED4_Flag=!LED4_Flag;
Display_LED(4,LED4_Flag);
}
}
void Timer3_Init(void) //50毫秒@12.000MHz
{
T4T3M &= 0xFD; //定时器时钟12T模式
T3L = 0xB0; //设置定时初始值
T3H = 0x3C; //设置定时初始值
// T4T3M |= 0x08; //定时器3开始计时
T4T3M &= 0xf7;
IE2 |= 0x20; //使能定时器3中断
}
display.c
#include <STC15F2K60S2.H>
code unsigned char Number[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90
};
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;
case 3:temp &= 0xfb;break;
case 4:temp &= 0xf7;break;
}
}
else
{
switch(Number)
{
case 1:temp |= 0x01;break;
case 2:temp |= 0x02;break;
case 3:temp |= 0x04;break;
case 4:temp |= 0x08;break;
}
}
P0=temp;
Select_HC573(4);
}
void Display_Relay(unsigned char State)
{
static unsigned char temp=0x00;
if(State)
{
temp |=0x10;
}
else temp &=0x00;
P0=temp;
Select_HC573(5);
}
display.h
#ifndef __DISPLAY_H__
#define __DISPLAY_H__
void System_Init(void);
void Display_Number(unsigned char Pos,unsigned char Data);
void Display_LED(unsigned char Number,unsigned char State);
void Delayms(int ms); //@12.000MHz
void Select_HC573(unsigned char Number);
void Display_Relay(unsigned char State);
#define ON 1
#define OFF 0
#endif
distance.c
#include <STC15F2K60S2.H>
#include "intrins.h"
sbit TX=P1^0;
sbit RX=P1^1;
void Delay13us(void) //@12.000MHz
{
unsigned char data i;
_nop_();
_nop_();
i = 36;
while (--i);
}
void Sent_Wave(void)
{
unsigned char i;
for(i=0;i<8;i++)
{
TX=0;
Delay13us();
TX=1;
Delay13us();
}
}
unsigned int Get_Distance(void)
{
unsigned long Distance;
TL0 = 0x00; //设置定时初始值
TH0 = 0x00; //设置定时初始值
Sent_Wave();
TR0=1;
while((RX==1)&&(TF0==0));
TR0=0;
if(TF0==0)
{
Distance=(TH0*256+TL0);
Distance =Distance*344/120000/2;
}
else
{
TF0=0;
Distance=0;
}
return Distance;
}
void Timer0_Init(void) //100微秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
// TR0 = 1; //定时器0开始计时
}
distance.h
#ifndef __DISTANCE_H__
#define __DISTANCE_H__
unsigned int Get_Distance(void);
void Timer0_Init(void); //100微秒@12.000MHz
#endif
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(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 E2PROM_Write(unsigned char addr,unsigned char Data)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(Data);
I2CWaitAck();
I2CStop();
}
unsigned char E2PROM_Read(unsigned char addr)
{
unsigned char Byte;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
Byte =I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return Byte;
}
unsigned char Read_Output(void)
{
unsigned char Byte;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x43);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
Byte=I2CReceiveByte();
I2CSendAck(1);
Byte=Byte*5/255;
return Byte;
}
iic.h
#ifndef __IIC_H__
#define __IIC_H__
#include <stc15.h>
#define sda P21
#define scl P20
void E2PROM_Write(unsigned char addr,unsigned char Data);
unsigned char E2PROM_Read(unsigned char addr);
unsigned char Read_Output(void);
#endif
本次的题也增加了一个距离传感器,距离传感器其实就是发一个13us的波,然后用这个声波传播的时间来算出距离的长短,只要掌握了公式之后就不难了。