在蓝桥杯单片机比赛中,有几种常见的外设,只要你学会了这些外设,你就可以处理比赛。 省赛考点:LED、蜂鸣器、继电器、数字管、独立键盘、矩阵键盘、实时钟、数模\模数转换、EEPROM存储器、温度传感器、定时计数器、中断等 国赛考点:LED、蜂鸣器、继电器、数字管、独立键盘、矩阵键盘、实时钟、数模\模数转换、EEPROM存储器、温度传感器、定时计数器、中断、超声波距离传感器NE555、串口通信(第十届)等。
#include "reg52.h" #include "iic.h" #include "onewire.h" #include "ds1302.h" ///矩阵按钮 sfr P4 = 0xc0; sbit R1 = P3^0; sbit R2 = P3^1; sbit R3 = P3^2; sbit R4 = P3^3; sbit C1 = P4^4; sbit C2 = P4^2; sbit C3 = P3^5; sbit C4 = P3^4; void scankeys() {
R1 = 0; R2 = R3 = R4 = 1; C1 = C2 = C3 = C4 = 1; if (C1 == 0) {
delay(1000); if (C1 == 0) {
//添加所需功能 while(C1 == 0); } } else if (C2 == 0) {
delay(1000);
if (C2 == 0)
{
//添加所需功能
while(C2 == 0);
}
}
else if (C3 == 0)
{
delay(1000);
if (C3 == 0)
{
//添加所需功能
while(C3 == 0);
}
}
else if (C4 == 0)
{
delay(1000);
if (C4 == 0)
{
//添加所需功能
while(C4 == 0);
}
}
R2 = 0;
R1 = R3 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if (C1 == 0)
{
delay(1000);
if (C1 == 0)
{
//添加所需功能
while(C1 == 0);
}
}
else if (C2 == 0)
{
delay(1000);
if (C2 == 0)
{
//添加所需功能
while(C2 == 0);
}
}
else if (C3 == 0)
{
delay(1000);
if (C3 == 0)
{
//添加所需功能
while(C3 == 0);
}
}
else if (C4 == 0)
{
delay(1000);
if (C4 == 0)
{
//添加所需功能
while(C4 == 0);
}
}
R3 = 0;
R1 = R2 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if (C1 == 0)
{
delay(1000);
if (C1 == 0)
{
//添加所需功能
while(C1 == 0);
}
}
else if (C2 == 0)
{
delay(1000);
if (C2 == 0)
{
//添加所需功能
while(C2 == 0);
}
}
else if (C3 == 0)
{
delay(1000);
if (C3 == 0)
{
//添加所需功能
while(C3 == 0);
}
}
else if (C4 == 0)
{
delay(1000);
if (C4 == 0)
{
//添加所需功能
while(C4 == 0);
}
}
R4 = 0;
R1 = R2 = R3 = 1;
C1 = C2 = C3 = C4 = 1;
if (C1 == 0)
{
delay(1000);
if (C1 == 0)
{
//添加所需功能
while(C1 == 0);
}
}
else if (C2 == 0)
{
delay(1000);
if (C2 == 0)
{
//添加所需功能
while(C2 == 0);
}
}
else if (C3 == 0)
{
delay(1000);
if (C3 == 0)
{
//添加所需功能
while(C3 == 0);
}
}
else if (C4 == 0)
{
delay(1000);
if (C4 == 0)
{
//添加所需功能
while(C4 == 0);
}
}
}
//数码管
void select_HC573(unsigned char n)
{
switch(n)
{
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;
}
}
void delay(unsigned int t)
{
while(t--);
}
void display_smg(unsigned char pos,unsigned char value)
{
select_HC573(7);
P0 = 0xff;
select_HC573(6);
P0 = 0x01 << pos;
select_HC573(7);
P0 = value;
}
void closeall()
{
select_HC573(6);
P0 = 0xff;
select_HC573(7);
P0 = 0xff;
}
//实时时钟
write_1302[7] = {
0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
read_1302[7] = {
0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
timer[7] = {
0x00,0x59,0x06}; //秒,分,时,日,月,周,年
void timeconfing()
{
unsigned char i = 0;
Write_Ds1302_Byte(0x8e,0x00);
for (i = 0;i < 3;i ++)
{
Write_Ds1302_Byte(write_1302[i],timer[i]);
}
Write_Ds1302_Byte(0x8e,0x80);
}
void time_show()
{
unsigned char i = 0;
for (i = 0;i < 3;i ++)
{
timer[i] = Read_Ds1302_Byte(read_1302[i]);
}
Write_Ds1302_Byte(0x8e,0x80);
}
duanma[10] = {
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
void display_1302time()
{
display_smg(0,duanma[time[2] / 16]);
delay(300);
display_smg(1,duanma[time[2] % 16]);
delay(300);
display_smg(2,0xff);
delay(300);
display_smg(3,duanma[time[1] / 16]);
delay(300);
display_smg(4,duanma[time[1] % 16]);
delay(300);
display_smg(5,0xff);
delay(300);
display_smg(6,duanma[time[1] / 16]);
delay(300);
display_smg(7,duanma[time[1] % 16]);
delay(300);
closeall();
delay(300);
}
//BCD码的加减
unsigned char Timeradd(unsigned char dat)
{
dat = dat + 1;
switch(dat)
{
case 10:
dat = 16;break; //BCD的10
case 26:
dat = 32;break; //BCD的20
case 42:
dat = 48;break; //BCD的30
case 58:
dat = 64;break; //BCD的40
case 74:
dat = 80;break; //BCD的50
case 90:
dat = 96;break; //BCD的60
}
return dat;
}
unsigned char Timerminus(unsigned char dat)
{
dat = dat - 1;
switch(dat)
{
case 79:
dat = 73;break;
case 63:
dat = 57;break;
case 47:
dat = 41;break;
case 31:
dat = 25;break;
case 15:
dat = 9;break;
case -1:
dat = 89;break;
}
return dat;
}
//温度
void read_temperature()
{
unsigned char LSB,MSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
delay(10000);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
init_ds18b20();
temp = 0x0000;
temp = MSB;
temp = (temp << 8) | LSB;
if((temp & 0xf800) == 0x0000)
{
temp >>= 4;
temp *= 10;
temp += (LSB & 0x0f) * 0.625; //这个是实际温度的十倍
//若一直显示不出来可将onewire.c中的延迟时间都增加十倍
}
}
//PCF8591
void write_8591(unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
void read_8591()
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(addr); //只有A/D功能是0x01光敏电阻,0x03电位器;A/D和D/A功能都有则0x41光敏电阻,0x43电位器
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
msg = IIC_RecByte();
IIC_WaitAck();
IIC_SendAck(0);
IIC_WaitAck();
IIC_Stop();
}
//AT24C02
void write_C02(unsigned char addr,unsigned char dat) //两次写之间需要延时一下
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
void read_C02(unsigned char addr)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
msg = IIC_RecByte();
IIC_WaitAck();
IIC_SendAck(0);
IIC_WaitAck();
IIC_Stop();
}
//NE555
void init_time()
{
TMOD = 0x16;
TH0 = 0xff; //八位重装计数
TL0 = 0xff;
TH1 = (65535 - 50000) / 256;
TL1 = (65535 - 50000) % 256; //50ms
EA = 1;
ET0 = 1;
ET1 = 1;
TR0 = 1;
TR1 = 1;
}
void service_f() interrupt 1
{
count_f ++;
}
void service_t() interrupt 3
{
TH1 = (65535 - 50000) / 256