一下是往年蓝桥杯单片机省赛试题考到的全部内容,根据学习难度划分了基础部分与进阶部分,基础部分的内容相对来说比较简单,这些内容也一定会考到的,如果这部分内容没用熟练的掌握,那后面的功能显示操作就不能完成,所以说这部分内容非常的重要。进阶部分的内容就相对难一些,这就涉及到对外部芯片的操作使用,但是如果了解芯片的工作原理,使用起来也并非难事。
基础部分:
LED指示灯
数码管显示
独立,矩阵按键
蜂鸣器,继电器
定时器
进阶部分:
DS18B20温度传感器
DS1302时钟芯片
EEPROM存储芯片
PCF8591模数/数模转换芯片
NE555芯片
超声波传感器
主程序:
#include <STC15F2K60S2.H>
#include "intrins.h"
#include "DS1302.h" //时钟芯片驱动(DS1302时钟芯片)
#include "onewire.h" //单总线通信(DS18B20温度传感器)
#include "iic.h" //双总线通信(AT24C02存储芯片,PCF8591模数/数模转换芯片)
//LED灯的亮灭
unsigned char LED_Bit=0XFF;
#define LEDx_ON(n) { LED_Bit&=_crol_(0XFE,n-1); P0=LED_Bit; P2|=0X80; P2&=0X9F; P2&=0X1F; }
#define LEDx_OFF(n) { LED_Bit|=_crol_(0X01,n-1); P0=LED_Bit; P2|=0X80; P2&=0X9F; P2&=0X1F; }
//蜂鸣器的启停
unsigned char Relay_Bit=0X00;
#define Relay_ON Relay_Bit|=0X10; P0=Relay_Bit; P2|=0XA0; P2&=0XBF; P2&=0X1F;
#define Relay_OFF Relay_Bit&=0XEF; P0=Relay_Bit; P2|=0XA0; P2&=0XBF; P2&=0X1F;
//数码管的段码值
code unsigned char Seg_Table[] = { 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, \
0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10, \
0xbf,0xff,0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e };
unsigned char Dey_B[8]={21,21,21,21,21,21,21,21}; //数码管选择显示的段码
unsigned char Dey_C=0;
unsigned char SMG_A=2;
unsigned int SMG_tt=0;
bit SMG_Flag=0;
//按键
typedef enum //按键执行步骤结构体
{
KEY_1, //第一步:检测是否有按键按下
KEY_2, //第二步:将按下的按键进行赋值
KEY_3 //第三步:进行延时消抖
}KEY_Statc;
KEY_Statc Key_Statc=KEY_1; //定义结构体变量,赋初值
unsigned char KEY_A=0;
unsigned int KEY_T=20;
unsigned int KEY_tt=0;
bit KEY_Flag=0;
unsigned char Set_Time[7]={50,59,23,0,0,1,0};
unsigned char Time_Get[7];
unsigned int DS_tt=0;
bit DS_Flag=0;
unsigned long temp=0;
unsigned int Temp_tt=0;
bit Temp_Flag=0;
unsigned char ad=0;
unsigned int AD_tt=0;
bit AD_Flag=0;
unsigned char at=0;
//调用函数声明
void Allinit(void);
void Delayms(unsigned int ms);
void Timer0Init(void);
void KEY_Scan(void);
void KEY_Task(void);
void SMG_Task(void);
void Task_Clock(void) //在中断服务函数中不停的扫描一下调用的函数
{
if(++KEY_tt==10) { KEY_tt=0; KEY_Scan(); }
if(++SMG_tt==50) { SMG_tt=0; SMG_Flag=1; }
if(++DS_tt==1000) { DS_tt=0; DS_Flag=1; }
if(++Temp_tt==300) { Temp_tt=0; Temp_Flag=1; }
if(++AD_tt==300) { AD_tt=0; AD_Flag=1; }
}
void main(void)
{
Allinit(); //硬件初始化
Timer0Init(); //定时器初始化
EA=1;ET0=1; //打开总中断、定时器中断
DS_init(); //DS18B20初始化
DS_get(); //获取第一次时间
Temp_get(); //获取温度
Delayms(500); //等待温度数值转化
temp=Temp_get()*625; //获取第一次温度数值
at=AT24C02_read(0X00); //读取AT24C02单元内存储的数值
AT24C02_write(0X00,++at); //每次开机数值加一并存储(可检测共开机多数次)
DA_write(50);
while(1)
{
if(KEY_Flag==1) //按键扫描执行
{
KEY_Flag=0;
KEY_Task();
}
if(SMG_Flag==1) //数码管显示
{
SMG_Flag=0;
SMG_Task();
}
if(DS_Flag==1) //时钟获取
{
DS_Flag=0;
DS_get();
}
if(Temp_Flag==1) //温度转换
{
Temp_Flag=0;
temp=Temp_get()*625;
}
if(AD_Flag==1) //AD转换
{
AD_Flag=0;
ad=AD_read(0X01);
}
}
}
void KEY_Task(void) //按键功能函数
{
if(KEY_A==7) //打开第一个LED灯
{
KEY_A=0;
LEDx_ON(1);
}
if(KEY_A==6) //关闭第一个LED灯
{
KEY_A=0;
LEDx_OFF(1);
}
if(KEY_A==5) //打开蜂鸣器
{
KEY_A=0;
Relay_ON;
}
if(KEY_A==4) //关闭蜂鸣器
{
KEY_A=0;
Relay_OFF;
}
}
void SMG_Task(void) //数码管显示函数
{
if(SMG_A==1) //界面1显示时间
{
Dey_B[0]=Time_Get[2]/10;
Dey_B[1]=Time_Get[2]%10;
Dey_B[2]=20;
Dey_B[3]=Time_Get[1]/10;
Dey_B[4]=Time_Get[1]%10;
Dey_B[5]=20;
Dey_B[6]=Time_Get[0]/10;
Dey_B[7]=Time_Get[0]%10;
}
if(SMG_A==2) //界面2显示AD转换数值、at24c02存储数据、温度
{
Dey_B[0]=ad/100;
Dey_B[1]=ad%100/10;
Dey_B[2]=ad%10;
Dey_B[3]=at/10;
Dey_B[4]=at%10;
Dey_B[5]=temp/100000;
Dey_B[6]=temp%100000/10000+10;
Dey_B[7]=temp%10000/1000;
}
}
void KEY_Scan(void) //获取按键键码函数
{
switch(Key_Statc)
{
//1、检测按键是否按下
case KEY_1: if( (P30==0) || (P31==0) || (P32==0) || (P33==0) ) Key_Statc=KEY_2; break;
//2、给按下按键进行赋值
case KEY_2:
{
if(P30==0) KEY_A=7;
else if(P31==0) KEY_A=6;
else if(P32==0) KEY_A=5;
else if(P33==0) KEY_A=4;
Key_Statc=KEY_3;
}
break;
//3、延时消抖
case KEY_3:
{
if( (P30==0) || (P31==0) || (P32==0) || (P33==0) ) //有按键按下,消抖30ms
{
KEY_T=KEY_T+10;
}
else //若没有按键按下则重新返回第一步
{
Key_Statc=KEY_1;
KEY_Flag=1;
}
}
break;
default: break;
}
}
void Timer0Init(void) //定时器函数(1毫秒@12.000MHz)
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初始值
TH0 = 0xD1; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void Timer0(void) interrupt 1 //中断服务函数
{
P0 =0X00;
P2|=0XC0;
P2&=0XDF;
P2&=0X1F;
P0 =Seg_Table[Dey_B[Dey_C]];
P2|=0XE0;
P2&=0XFF;
P2&=0X1F;
P0 =0X01<<Dey_C;
P2|=0XC0;
P2&=0XDF;
P2&=0X1F;
if(++Dey_C==8) Dey_C=0;
Task_Clock();
}
void Allinit(void) //初始化函数
{
P0 =0XFF;
P2|=0X80;
P2&=0X9F;
P2&=0X1F;
P0 =0X00;
P2|=0XA0;
P2&=0XBF;
P2&=0X1F;
P0 =0X00;
P2|=0XC0;
P2&=0XDF;
P2&=0X1F;
}
void Delayms(unsigned int ms) //延时函数
{
unsigned int i,j;
for(i=0;i<ms;i++)
for(j=910;j>0;j--);
}
IIC通信协议程序:EEPROM存储芯片、 PCF8591模数/数模转换芯片
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <STC15F2K60S2.H>
#include "intrins.h"
sbit sda = P2^1;
sbit scl = P2^0;
#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);
}
unsigned char AD_read(unsigned char add)
{
unsigned char ad;
I2CStart();
I2CSendByte(0X90); //写地址
I2CWaitAck();
I2CSendByte(add);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0X91); //读地址
I2CWaitAck();
ad=I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return ad;
}
void DA_write(unsigned char dat)
{
I2CStart();
I2CSendByte(0X90); //写
I2CWaitAck();
I2CSendByte(0X40);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
unsigned char AT24C02_read(unsigned char add)
{
unsigned char ad;
I2CStart();
I2CSendByte(0XA0);
I2CWaitAck();
I2CSendByte(add);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0XA1);
I2CWaitAck();
ad=I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return ad;
}
void AT24C02_write(unsigned char add,unsigned char dat)
{
I2CStart();
I2CSendByte(0XA0);
I2CWaitAck();
I2CSendByte(add);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
#ifndef __iic_H_
#define __iic_H_
unsigned char AD_read(unsigned char add);
void DA_write(unsigned char dat);
unsigned char AT24C02_read(unsigned char add); //读出存储的数据
void AT24C02_write(unsigned char add,unsigned char dat);//写入存储的数据
#endif
单总线通信协议程序:DS18B20温度传感器
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <STC15F2K60S2.H>
#include "intrins.h"
sbit DQ = P1^4;
//
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;
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 long Temp_get(void)
{
unsigned char low,high;
unsigned long temp;
init_ds18b20();
Write_DS18B20(0XCC);
Write_DS18B20(0X44);
Delay_OneWire(20);
init_ds18b20();
Write_DS18B20(0XCC);
Write_DS18B20(0XBE);
low=Read_DS18B20();
high=Read_DS18B20();
temp=(0X0F&high);
temp<<=8;
temp|=low;
return temp;
}
#ifndef __onewire_H_
#define __onewire_H_
unsigned long Temp_get(void);
#endif
时钟通信协议:DS1302时钟芯片
/* # DS1302代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <STC15F2K60S2.H>
#include "intrins.h"
sbit RST = P1^3;
sbit SDA = P2^3;
sbit SCK = P1^7;
extern unsigned char Set_Time[7];
extern unsigned char Time_Get[7];
//
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);
}
void DS_init(void)
{
unsigned char add,i;
add=0X80;
Write_Ds1302_Byte( 0X8E,0X00 );
for(i=0;i<7;i++)
{
Write_Ds1302_Byte( add,(Set_Time[i]/10<<4) | (Set_Time[i]%10) );
add=add+2;
}
Write_Ds1302_Byte( 0X8E,0X80 );
}
void DS_get(void)
{
unsigned add,dat,i;
add=0X81;
for(i=0;i<3;i++)
{
dat=Read_Ds1302_Byte ( add );
Time_Get[i]=dat/16*10+dat%16;
add=add+2;
}
}
#ifndef __DS1302_H_
#define __DS1302_H_
void DS_init(void);
void DS_get(void);
#endif