蓝桥杯常见代码
一.基础类
1. 关闭基本外设
void close_perl(void)
{
P0 = 0xff;
P2 = P2&0x1f|0x80;
P2 = P2&0x1f;
P0 = 0x00;
P2 = P2&0x1f|0xa0;
P2 = P2&0x1f;
}
2.数码管转制与显示
unsigned char seg_tran(int num)
{
unsigned char date;
switch(num)
{
case 0 : date = 0xc0 ; break;
case 1 : date = 0xf9 ; break;
case 2 : date = 0xa4 ; break;
case 3 : date = 0xb0 ; break;
case 4 : date = 0x99 ; break;
case 5 : date = 0x92 ; break;
case 6 : date = 0x82 ; break;
case 7 : date = 0xf8 ; break;
case 8 : date = 0x80 ; break;
case 9 : date = 0x90 ; break;
case 10 : date = 0xbf ; break;//-
case 11 : date = 0xc6 ; break;//c
case 12 : date = 0x8c ; break;//p
case 13 : date = 0x86 ; break;//e
case 14 : date = 0xc7 ; break;//L
case 15 : date = 0xc8 ; break;//a
}
return date;
}
void seg_disp(int adr,int num)
{
unsigned char seg_adr[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
P2 = P2&0x1f|0xe0;
P2 = P2&0x1f;
P0 = seg_adr[adr];
P2 = P2&0x1f|0xc0;
P2 = P2&0x1f;
P0 = seg_tran(num);
P2 = P2&0x1f|0xe0;
P2 = P2&0x1f;
}
//若需要显示小数点
void seg_disp_f(int adr,int num)
{
unsigned char seg_adr[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
P2 = P2&0x1f|0xe0;
P2 = P2&0x1f;
P0 = seg_adr[adr];
P2 = P2&0x1f|0xc0;
P2 = P2&0x1f;
P0 = seg_tran(num)&0x7f;
P2 = P2&0x1f|0xe0;
P2 = P2&0x1f;
}
3.按键
(1) 独立按键扫描
int key_scan(void)
{
int key_mark;
P3 = 0x0f;
if(P30 == 0) key_mark = 7;
else if(P31 == 0) key_mark = 6;
else if(P32 == 0) key_mark = 5;
else if(P33 == 0) key_mark = 4;
return key_mark;
}
(2) 矩阵按键扫描
int key_scan(void)
{
int key,key_mark;
P3 = 0x0f;
P44 = 0;P42 = 1;P35 = 1;P34 = 1;key = P3;
P44 = 1;P42 = 0; key = (key<<4)|(P3&0x0f);
P42 = 1;P35 = 0; key = (key<<4)|(P3&0x0f);
P35 = 1;P34 = 0; key = (key<<4)|(P3&0x0f);
switch(~key)
{
case 0x8000: key_mark = 4;break;
case 0x4000: key_mark = 5;break;
case 0x2000: key_mark = 6;break;
case 0x1000: key_mark = 7;break;
case 0x0800: key_mark = 8;break;
case 0x0400: key_mark = 9;break;
case 0x0200: key_mark = 10;break;
case 0x0100: key_mark = 11;break;
case 0x0080: key_mark = 12;break;
case 0x0040: key_mark = 13;break;
case 0x0020: key_mark = 14;break;
case 0x0010: key_mark = 15;break;
case 0x0008: key_mark = 16;break;
case 0x0004: key_mark = 17;break;
case 0x0002: key_mark = 18;break;
case 0x0001: key_mark = 19;break;
default : key_mark = 0 ;break;//这句很重要,必须有!
}
return key_mark;
}
(3) 按键主函数
分为是否需要长按短按判断
以下为不需要:
unsigned char key_old;
void key_pro(void)
{
unsigned char key_vol,key_down;
key_vol = key_scan();
key_down = key_vol&(key_vol^key_old);
key_old = key_vol;
switch(key_down)
{
case 4:
//a
break;
case 5:
//b
break;
//....
}
}
以下为需要:
unsigned char key_old;//存放上一次按键值
unsigned char long_press_flag;//是否允许长按
unsigned char long_press_count;//记录长按时长
void Timer0Init(void) //1毫秒中断@12.0MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初值
TH0 = 0xD1; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
}
void key_pro(void)
{
unsigned char key_vol,key_down;
key_vol = key_scan();
key_down = key_vol&(key_vol^key_old);
key_old = key_vol;
switch(key_down)
{
case 4:
//a
break;
case 5:
long_press_flag = 1;
break;
//....
}
}
void timer0(void) interrupt 1
{
if((long_press_flag == 1)&&(key_old != 0))
{
long_press_count ++;
}
else
{
//假设 1s 以上为长按(包括 1s )
if(long_press_count >= 1000)//长按
{
//b
}
else if((long_press_flag > 0)&&(long_press_flag < 1000>))//短按
{
//c
}
long_press_count = 0;
long_press_flag = 0;
}
}
二.中等类
1.温度(DS18B20)
(1) 整数
unsigned char temp_read(void)
{
unsigned char low,high,temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(200);//延时700ms左右
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
temp = (high << 4)|(low >> 4);
return temp;
}
(2) 浮点数
float temp_read(void)
{
unsigned char low,high,temp;
float temp_f;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(200);//延时700ms左右
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
temp = (high << 4)|(low >> 4);
temp_f = temp + (low&0x0f)*0.0625;
return temp_f;
}
2.时间(DS1302)
//该模块底层驱动官方所给文件已经给好。
unsigned char write_adress[8] = {0x80,0x82,0x84};//芯片手册有
unsigned char read_adress[8] = {0x81,0x83,0x85};//芯片手册有
unsigned char time_first[8] = {0x50,0x59,0x16};//写入初始时间 16点59分50秒
void write_into_ds1302(void)
{
int i;
Write_Ds1302(0x8e,0);//关闭写保护
for(i=3;i>0;i--)
{
Write_Ds1302(write_adress[i],time_first[i]);
}
Write_Ds1302(0x8e,1);//开启写保护
}
3.ADC与DAC(PCF8591)
unsigned char pcfadc(void)//adc读取电压值
{
unsigned char adc;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);//根据题目要求调整地址
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
adc = IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
return adc;
}
void pcfdac(unsigned char dac)//dac写入电压值
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_SendByte(dac);
IIC_WaitAck();
IIC_Stop();
}
4.EEPROM读与写(AT24C02)
void eewrite(unsigned char adress,unsigned char date)
{
EA = 0;
IIC_Start();
IIC_SendByte(0xa0);
IIC_SendAck();
IIC_SendByte(adress);
IIC_SendAck();
IIC_SendByte(date);
IIC_SendAck();
IIC_Stop();
EA = 1;
}
unsigned char eeread(unsigned char adress)
{
unsigned char date;
EA = 0;
IIC_Start();
IIC_SendByte(0xa0);
IIC_SendAck();
IIC_SendByte(adress);
IIC_SendAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_SendAck();
date = IIC_RecByte();
IIC_SendAck();
IIC_Stop();
EA = 1;
return date;
}
5.NE555频率计
unsigned int count;
unsigned int frequence;
unsigned int timer1_up;
//同时利用计数器和定时器
void timer_init(void)
{
TMOD = 0x16;
TH0 = 0xff;//**
TL0 = 0xff;//**
TH1 = (65535 - 50000+1)/256;
TL1 = (65535 - 50000+1)%256;
TF0 = 0;
TR0 = 1;
ET0 = 1;
TF1 = 0;
TR1 = 1;
ET1 = 1;
EA = 1;
}
void timer0(void) interrupt 1
{
count ++;
}
void timer1(void) interrupt 3
{
timer1_up++;
if(timer1_up == 20)
{
frequence = count;
count = 0;
timer1_up = 0;
}
}
三.国赛类
1.超声波
sbit TX=P1^0;//发送端
sbit RX=P1^1;//接收端
unsigned int distance;//定义距离
void Delay12us() //@11.0592MHz
{
unsigned char i;
_nop_();
_nop_();
_nop_();
i = 30;
while (--i);
}
void send_wave(void)//发送8个40KHz超声波信号
{
int i;
for(i = 0;i < 8;i ++)
{
TX = 1;
Delay12us();
TX = 0;
Delay12us();
}
}
void distance_get(void)
{
unsigned int time = 0;
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x00; //设置定时初值
send_wave();
TR0 = 1;//开始计时
while((RX == 1)&&(TF0 == 0));//等待接受
TR0 = 0;//关闭定时器
if(TF0 == 0)//没有溢出(定时器溢出标志位不为1)
{
time = TH0;
time = (time << 8)|TL0;//***左移8位
distance = time*0.017;
}
else //超出距离
{
TF0 = 0;//定时器溢出标志位置0
distance = 999;
}
}
2.串口通讯
unsigned char command;//储存从电脑读出的数据
void UartInit(void) //9600bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xE0; //设定定时初值
TH1 = 0xFE; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA = 1;//开启中断
ES = 1;//开启串口通讯
}
void SendByte(unsigned char date)
{
SBUF = date;//将数据写入缓冲寄存器
while(TI == 0);//等待发送完成
TI = 0;//关闭标志位,保证下次传输
}
void uart(void) interrupt 4
{
if(RI == 1)//单片机是否接收完数据
{
command = SBUF;
RI = 0;//标志位置0
SendByte(command+1);//给电脑发一个数据表示收到了 ***
}
}