目录
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;
else
temp &= ~(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;
else
temp &= ~(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_h
void 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_h
void 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_h
static 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;
}
}