第七届的省赛相比于其他几届也比较常规了,只不过第七届考了PWM的使用,PWM其实也就是控制高低电平而已,我在这里就直接放出试题和我自己写的代码了,如果想更深入的学习各模块怎么写,欢迎去阅读我写的另外一篇更加详细的文章。
蓝桥杯单片机STC15F2K60S2第十三届省赛代码详细讲解(附完整代码)
以下是第七届省赛的试题
以下是完整的代码
main.c
#include <STC15F2K60S2.H>
#include "display.h"
#include "onewire.h"
sbit PWM=P3^4;
void Show_Switch(void);
void Key_Board(void);
void Timer0_Init(void); //@12.000MHz
void Timer1_Init(void); //20毫秒@12.000MHz
void LED(void);
unsigned char Switching=0;
unsigned int PWM_Duty=200;
unsigned char Time=0;
unsigned char TimeFlag=0;
unsigned char S6Flag=1;
unsigned char temp=0;
unsigned char SwitchFlag;
unsigned char LEDFlag=1;
void main(void)
{
System_Init();
Timer0_Init();
Timer1_Init();
while(1)
{
Show_Switch();
Key_Board();
LED();
}
}
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)
{
case 0x07:if(Switching==0){
Switching=1;
PWM_Duty=300;
break;
}
if(Switching==1){
Switching=2;
PWM_Duty=700;
break;
}
if(Switching==2){
Switching=0;
PWM_Duty=200;
break;
}
case 0x0b:S6Flag=1;LEDFlag=1;
if(TimeFlag==0){
Time=60;
TimeFlag=Time;
TR0=1;
TR1=1;
break;
}
if(TimeFlag==60){
Time=120;
TimeFlag=Time;
TR0=1;
TR1=1;
break;
}
if(TimeFlag==120){
Time=0;
TimeFlag=Time;
TR0=0;
TR1=0;
break;
}
case 0x0d:if(S6Flag){
S6Flag=0;
LEDFlag=0;
Time=0;
TR0=0;
}break;
case 0x0e:
if(Switching != 3){
SwitchFlag=Switching;
Switching=3;
break;
}
else if(Switching==3){
Switching=SwitchFlag;
break;
}
}
}
while(Key!=0x0f)
{
Key =P3;Key &=0x0f;
Show_Switch();
}
}
}
void Show_Switch(void)
{
if(Switching==0)
{
Display_Number(1,10);Display_Number(2,1);Display_Number(3,10);
Display_Number(5,0);Display_Number(6,Time/100);Display_Number(7,Time/10%10);Display_Number(8,Time%10);
}
if(Switching==1)
{
Display_Number(1,10);Display_Number(2,2);Display_Number(3,10);
Display_Number(5,0);Display_Number(6,Time/100);Display_Number(7,Time/10%10);Display_Number(8,Time%10);
}
if(Switching==2)
{
Display_Number(1,10);Display_Number(2,3);Display_Number(3,10);
Display_Number(5,0);Display_Number(6,Time/100);Display_Number(7,Time/10%10);Display_Number(8,Time%10);
}
if(Switching==3)
{
temp=Read_Temp();
Display_Number(1,10);Display_Number(2,4);Display_Number(3,10);
Display_Number(6,temp/10);Display_Number(7,temp%10);Display_Number(8,11);
}
}
void Timer0_Isr(void) interrupt 1
{
static unsigned int Count;
TH0 = (65535-1000)/256; //设置定时初始值
TL0 = (65535-1000)%256; //设置定时初始值
Count++;
Count %=1000;
if(Count>=PWM_Duty)
{
PWM=0;
}
else
{
PWM=1;
}
}
void Timer0_Init(void) //@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = (65535-1000)%256; //设置定时初始值
TH0 = (65535-1000)/256; //设置定时初始值
TF0 = 0; //清除TF0标志
// TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA=1;
}
void Timer1_Isr(void) interrupt 3
{
static unsigned char count=0;
count++;
if(count==20)
{
count=0;
if(Time !=0)
{
Time--;
}
if(Time==0){
TR1=0;
TR0=0;
LEDFlag=0;
}
}
}
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中断
}
void LED(void)
{
if(LEDFlag)
{
if(Switching==0)Display_LED(1,ON);
else Display_LED(1,OFF);
if(Switching==1)Display_LED(2,ON);
else Display_LED(2,OFF);
if(Switching==2)Display_LED(3,ON);
else Display_LED(3,OFF);
}
else {
Display_LED(1,OFF);
Display_LED(2,OFF);
Display_LED(3,OFF);
}
}
display.c
#include <STC15F2K60S2.H>
code unsigned char Number[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0xbf, //- 10
0xc6 //C 11
};
void Delayms(int ms)
{
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 System_Init(void)
{
P0=0x00;
Select_HC573(5);
Select_HC573(6);
P0=0xff;
Select_HC573(4);
}
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 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;
}
}
else
{
switch(Number)
{
case 1:temp |=0x01;break;
case 2:temp |=0x02;break;
case 3:temp |=0x04;break;
}
}
P0=temp;
Select_HC573(4);
}
display.h
#ifndef __DISPLAY_H
#define __DISPLAY_H
void System_Init(void);
void Delayms(int ms);
void Display_LED(unsigned char Number,unsigned char State);
void Display_Number(unsigned char Pos,unsigned char Data);
#define ON 1
#define OFF 0
#endif
onewire.c
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "onewire.h"
//
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;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_Temp(void)
{
unsigned char Temp;
unsigned char 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_Temp(void);
#endif
希望本文章能够对你学习蓝桥杯单片机有所帮助。