目录
1.HC573锁存器选择
2.系统初始化关闭LED、蜂鸣器和继电器
3.LED
4.蜂鸣器和继电器
5.数码管
6.定时器按键扫描
7.DS18B20(基于2023年第十四届底层代码)
8.DS1302(基于2023年第十四届底层代码)
9.PCF8591(基于2023年第十四届底层代码)
10.超声波PCA版(可节省出一个定时器)
11.NE555测量频率
1.HC573锁存器选择
void Select_Hc573(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;}P2 = P2 & 0x1f;
}
2.系统初始化关闭LED、蜂鸣器和继电器
void Sys_Init()
{P0 = 0x00;Select_Hc573(5);P0 = 0xff;Select_Hc573(4);
}
3.LED
void Led(unsigned addr,enable)//LED底层代码
{static unsigned char temp = 0x00;static unsigned char temp_old = 0xff;if(enable)temp |= 0x01 << addr;elsetemp &= ~(0x01 << addr);if(temp != temp_old){P0 = ~temp;Select_Hc573(4);temp_old = temp;}
}
4.蜂鸣器和继电器
void Beep(unsigned addr,enable)
{static unsigned char temp = 0x00;static unsigned char temp_old = 0xff;if(enable)temp |= 0x01 << addr;elsetemp &= ~(0x01 << addr);if(temp != temp_old){P0 = temp;Select_Hc573(5);temp_old = temp;}
}
5.数码管
code unsigned char SMG[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};void Delay_ms(unsigned int t) //@12.000MHz
{while(t--){unsigned char i, j;i = 12;j = 169;do{while (--j);} while (--i);}
}void Select_Bit(unsigned char pos,dat)
{P0 = 0x01 << pos;Select_Hc573(6);P0 = dat;Select_Hc573(7);Delay_ms(1);P0 = 0xff;Select_Hc573(7);
}void Display_temp()//温度数据界面
{Select_Bit(0,SMG[10]);Select_Bit(5,SMG[temp / 100]);Select_Bit(6,SMG[temp / 10 % 10] - 0x80);Select_Bit(7,SMG[temp % 10]);
}
注意:共阳数码管-0x80为加上小数点,共阴数码管+0x80为加上小数点。
6.定时器按键扫描
以独立按键为例,矩阵键盘同理
void Timer2Init(void) //10毫秒@12.000MHz
{AUXR &= 0xFB; //定时器时钟12T模式T2L = 0xF0; //设置定时初值T2H = 0xD8; //设置定时初值AUXR |= 0x10; //定时器2开始计时IE2 |= (1 << 2);EA = 1;
}void Timer2_Service() interrupt 12
{Key_Scan();//每隔10ms扫描一次按键
}void Key_Scan()
{static unsigned char cnt0 = 0;//按键计时消抖static unsigned char cnt1 = 0;//按键计时消抖static unsigned char cnt2 = 0;//按键计时消抖static unsigned char cnt3 = 0;//按键计时消抖if(S7 == 0)//记录按键低电平时间{cnt0++;}if(S7 == 1)//按键释放/按键未按下/按键按下的抖动{if(cnt0 > 100)//说明是长按{//长按执行的内容}else if(cnt0 > 2)//说明是短按{//短按执行内容}cnt0 = 0;//清除计数变量}if(S6 == 0)//记录按键低电平时间{cnt1++;}if(S6 == 1)//按键释放/按键未按下/按键按下的抖动{if(cnt1 > 100)//说明是长按{//长按执行的内容}else if(cnt1 > 2)//说明是短按{//短按执行内容}cnt1 = 0;//清除计数变量}if(S5 == 0)//记录按键低电平时间{cnt2++;}if(S5 == 1)//按键释放/按键未按下/按键按下的抖动{if(cnt2 > 100)//说明是长按{//长按执行的内容}else if(cnt2 > 2)//说明是短按{//短按执行内容}cnt2 = 0;//清除计数变量}if(S4 == 0)//记录按键低电平时间{cnt3++;}if(S4 == 1)//按键释放/按键未按下/按键按下的抖动{if(cnt3 > 100)//说明是长按{//长按执行的内容}else if(cnt3 > 2)//说明是短按{//短按执行内容}cnt3 = 0;//清除计数变量}
}
7.DS18B20(基于2023年第十四届底层代码)
onewire.c
/* # 单总线代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求,进行代码调试和修改。
*///
#include <STC15F2K60S2.H>
#include <onewire.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;
}
onewire.h
#ifndef __onewire_h
#define __onewire_hvoid Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);#endif
温度读取代码
unsigned int read_wd()//读取温度
{unsigned char LSB,MSB;unsigned int Temp;init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0x44);init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0xbe);LSB = Read_DS18B20();MSB = Read_DS18B20();Temp = MSB << 8 | LSB;return (Temp * 0.0625);
}
注意:×0.0625为保留0位小数,×0.625为保留1为小数,×6.25为保留2位小数。保留1位和2位小数实际为一个百位数和一个千位数,在显示的时候只是人为添加了小数点而已。
8.DS1302(基于2023年第十四届底层代码)
ds1302.c
/* # DS1302代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求,进行代码调试和修改。
*/ //
#include <STC15F2K60S2.H>
#include <ds1302.H>
#include <intrins.H>sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;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);
}
ds1302.h
#ifndef __ds1302_h
#define __ds1302_hvoid Write_Ds1302(unsigned char temp) ;
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte ( unsigned char address );#endif
写时间,读时间代码
code unsigned char write_addr[] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};//写地址
code unsigned char read_addr[] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};//读地址unsigned char time[] = {0x50,0x59,0x16};//初始化时间void write_time()//写时间
{Write_Ds1302_Byte(0x8e,0x00);for(i = 0;i < 3;i++)Write_Ds1302_Byte(write_addr[i],time[i]);Write_Ds1302_Byte(0x8e,0x80);
}void read_time()//读时间
{for(i = 0;i < 3;i++)time[i] = Read_Ds1302_Byte (read_addr[i]);
}
BCD码转十进制(转化为十进制加减后再还原为BCD码)
int bcd_shi(int bcd)//BCD码转十进制
{return (bcd - (bcd >> 4) * 6);
}
十进制转BCD码
int shi_bcd(int shi)//十进制转BCD码
{return (shi+(shi / 10) * 6);
}
9.PCF8591(基于2023年第十四届底层代码)
iic.c
/* # I2C代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求,进行代码调试和修改。
*/#include <STC15F2K60S2.H>
#include <iic.H>
#include <intrins.H>sbit scl = P2^0;
sbit sda = P2^1;#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);
}
iic.h
#ifndef __iic_h
#define __iic_hstatic void I2C_Delay(unsigned char n);
void I2CStart(void);
void I2CStop(void);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(unsigned char ackbit);#endif
读取光敏电阻电压代码
unsigned int read_PCF8591()//读取光敏电阻电压
{unsigned int Temp;I2CStart();I2CSendByte(0x90);I2CWaitAck();I2CSendByte(0x01);I2CWaitAck();I2CStart();I2CSendByte(0x91);I2CWaitAck();Temp = I2CReceiveByte();I2CSendAck(1);I2CStop();return Temp;
}
读取滑动变阻器电压代码
unsigned int PCF8591_Read()
{unsigned int temp;IIC_Start();IIC_SendByte(0x90);IIC_WaitAck();IIC_SendByte(0x03);IIC_WaitAck();IIC_Start();IIC_SendByte(0x91);IIC_WaitAck();temp = IIC_RecByte();IIC_SendAck(1);IIC_Stop();return temp;
}
输出电压代码
void PCF8591_Write(dat)
{IIC_Start();IIC_SendByte(0x90);IIC_WaitAck();IIC_SendByte(0x40);IIC_WaitAck();IIC_SendByte(dat);IIC_WaitAck();IIC_Stop();
}
注意:读取光敏电阻和滑动变阻器电压直接得到的是一个0~255的数,需要用如下代码转换:
read_PCF8591() / 51.0 * 100;
同理,输出电压时,应该为0~255的数。
只AD时,可只用0x01,0x03。
只DA时,可只用0x40。
既要AD又要DA时,需用0X41,0X43。
10.超声波PCA版(可节省出一个定时器)
sbit TX = P1^0;
sbit RX = P1^1;void Delay12us() //@12.000MHz
{unsigned char i;_nop_();_nop_();i = 33;while (--i);
}void Ut_Wave_Init()
{char i;for(i = 0;i < 8;i++){TX = 1;Delay12us();TX = 0;Delay12us();}
}unsigned int Send()
{unsigned int time;CMOD = 0x00;CH = CL = 0x00;Ut_Wave_Init();CR = 1;while((RX == 1) && (CF == 0));CR = 0;if(CF == 0){time = CH << 8 | CL;return (time * 0.017);}else{CF = 0;return 999;}
}
11.NE555测量频率
unsigned int count,Fre;void Time_Init()
{TMOD = 0x05;TH0 = 0x00;TL0 = 0x00;TH1 = (65535 - 50000) / 256;TL1 = (65535 - 50000) % 256;TR0 = TR1 = 1;ET0 = ET1 = 1;EA = 1;
}void Service_Time1() interrupt 3
{count++;if(count == 20){Fre = TH0 << 8 | TL0;count = 0;TL0 = 0;TH0 = 0;}
}