目录
1楼:焊接过程
3楼:速度里程计
4楼:流水灯
5楼:最简单的闪烁灯
6楼:花样流水灯
7楼:液晶显示1602
8楼:定时器的应用--秒表
9楼:数码管滚动显示
10楼:温度显示实验DS18B20
再来张靓照
ysjabcd-制作进程
更有单次行车里程,随时了解我们骑了多远的路了,方便测量两地之间的路程。
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define ISP_BYTE_READ 1 //ISP字节读
#define ISP_BYTE_PROGRAM 2 //ISP直接编程
#define ISP_SECTOR_ERASE 3 //ISP扇区擦除
/*以下是配置STC单片机的寄存器*/
/*相关资料在STC89C51RC的PDF的第35页开始*/
sfr ISP_DATA = 0xE2;
sfr ISP_ADDRH = 0xE3;
sfr ISP_ADDRL = 0xE4;
sfr ISP_CMD = 0xE5;
sfr ISP_TRIG = 0xE6;
sfr ISP_CONTR = 0xE7;
uchar code table[]="km/h km";
uchar code table1[]=" km";
sbit rs=P2^4; // 液晶
sbit rw=P2^5; // 液晶
sbit en=P2^6; // 液晶
uint aa,time,s1,s11;
uchar num,bb,a,b,up,down;
uchar IRCOM[7];//红外数组
unsigned long int quan,s2,s21; //
sbit ACC0 = ACC^0; //1302
sbit ACC7 = ACC^7; //1302
sbit IRIN = P3^2; //红外接收器数据线
sbit T_CLK = P3^6; /*实时时钟时钟线引脚 */
sbit T_IO = P3^4; /*实时时钟数据线引脚 */
sbit T_RST = P3^5; /*实时时钟复位线引脚 */
uchar flag;
uchar sec, min, hour;
void Write_DS1302Init(void);
void display();
void delayhw(uchar x); //x*0.14MS 红外延时
void delay(uint z);//液晶延时
/********************************************************************
* 功能 : EEPROM的扇区擦除
* 输入 : Address(擦除扇区的地址)
***********************************************************************/
void ISP_ERASE(Address)
{
ISP_ADDRL = Address;
ISP_ADDRH = Address >> 8;
ISP_CONTR = 0x81;
ISP_CMD = ISP_SECTOR_ERASE;
ISP_TRIG = 0x46; //PDF手册中说先像 ISP_TRIG 中写入 0x46, 然后写入 0xb9
ISP_TRIG = 0xb9;
_nop_();
_nop_();
}
/********************************************************************
* 输入 : Address(想要读取EEPROM的地址)
*********************************************************************/
uint ISP_READ(Address)
{
uchar Read_Data;
ISP_ADDRL = Address;
ISP_ADDRH = Address >> 8;
// EA = 0;
ISP_CONTR = 0x81;
ISP_CMD = ISP_BYTE_READ;
ISP_TRIG = 0x46;
ISP_TRIG = 0xb9;
_nop_();
_nop_();
Read_Data = ISP_DATA;
return Read_Data;
}
/********************************************************************
* 输入 : Address为编程的地址,Data_temp为想要编程的值
***********************************************************************/
void ISP_PROGRAM(Address, Data_temp)
{
ISP_DATA = Data_temp;
ISP_ADDRL = Address;
ISP_ADDRH = Address >> 8;
ISP_CONTR = 0x81;
ISP_CMD = ISP_BYTE_PROGRAM;
ISP_TRIG = 0x46;
ISP_TRIG = 0xb9;
_nop_();
_nop_();
}
void delay(uint z) //液晶延时
{
uint x,y;
for(x=110;x>0;x--)
for(y=z;y>0;y--);
}
void write_com(uchar com) //液晶写命令
{
rs=0;
P0=com;
delay(1);
en=1;
delay(1);
en=0;
}
void write_data(uchar date) //液晶写数据
{
rs=1;
P0=date;
delay(1);
en=1;
delay(1);
en=0;
}
void init()
{
quan=0;
en=0;
rw=0;
aa=0;
up=0;
down=0;
flag=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
EA=1; //开总中断
EX0=1; //开外部中断0
IT0=1; //外部中断设为下降沿触发
ET0=1; // 开定时器0中断
TMOD=0x11;//定时器0设定为定时器模式
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; //定时器0装初值5ms
TR0=1;//启动定时器0
EX1=1; //开外部中断1
IT1=1; //外部中断1设为下降沿触发
flag=0;
}
void v_RTInputByte(uchar ucDa) //往DS1302写入1Byte数据
{
uchar i;
ACC = ucDa;
T_RST = 1;
for(i=8; i>0; i--)
{
T_IO = ACC0;
T_CLK = 1;
T_CLK = 0;
ACC = ACC >> 1;
}
}
uchar uc_RTOutputByte(void) //读取1byte数据
{
uchar i;
T_RST = 1;
for(i=8; i>0; i--)
{
ACC = ACC >>1;
// T_IO=1;
ACC7 = T_IO;
T_CLK = 1;
T_CLK = 0;
}
return(ACC);
}
void v_W1302(uchar ucAddr, uchar ucDa) //输入 : ucAddr: DS1302地址, ucDa: 要写的数据
{
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); // 写地址
_nop_();
_nop_();
v_RTInputByte(ucDa); // 写1Byte数据
T_CLK = 1;
T_RST = 0;
}
uchar uc_R1302(uchar ucAddr) // 读取DS1302某地址的数据
{
uchar ucDa;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); //写地址,命令
_nop_();
_nop_();
ucDa = uc_RTOutputByte(); //读1Byte数据
T_CLK = 1;
T_RST = 0;
return(ucDa);
}
void keyscan() //设置时钟的键盘扫描程序
{
if(flag!=0)
{
while(flag)
{
if(flag==1)
{
write_com(0x80+0x47);
write_com(0x0f);
}
if(flag==2)
{
write_com(0x80+0x44);
}
if(flag==3)
{
write_com(0x80+0x41);
} //
if(up==1)
{
if(flag==1)
{
sec++;
if(sec==60)
sec=0;
}
if(flag==2)
{
min++;
if(min==60)
min=0;
}
if(flag==3)
{
hour++;
if(hour==24)
hour=0;
}
up=0;
display();
}
if(down==1)
{
if(flag==1)
{
sec--;
if(sec==255)
sec=59;
}
if(flag==2)
{
min--;
if(min==255)
min=59;
}
if(flag==3)
{
hour--;
if(hour==255)
hour=23;
}
down=0;
display();
}
// display();
}
Write_DS1302Init();
}
}
uchar dectobcd(uchar dec)// DEC码转换为BCD码
{
uchar bcd;
bcd = 0;
while(dec >= 10)
{
dec -= 10;
bcd++;
}
bcd <<= 4;
bcd |= dec;
return bcd;
}
uchar bcdtodec(uchar bcd) // BCD码转换为DEC码
{
uchar data1;
data1 = bcd & 0x0f; //取BCD低4位
bcd = bcd & 0x70; //剔除BCD的最高位和低4位。
data1 += bcd >> 1;
data1 += bcd >> 3; //用位移代替乘法运算
return data1;
}
void Write_DS1302Init(void)
{
sec=dectobcd(sec);
min=dectobcd(min);
hour=dectobcd(hour);
v_W1302(0x8e,0);
v_W1302(0x80,sec); //写入秒;
v_W1302(0x82,min); //写入分
v_W1302(0x84,hour); //写入小时
}
void display() //1302显示
{
uchar hourshi,hourge,minshi,minge,secshi,secge;
hourshi=hour/10;
hourge=hour%10;
minshi=min/10;
minge=min%10;
secshi=sec/10;
secge=sec%10;
write_com(0x80+0x40);
write_data(0x30+hourshi);
write_data(0x30+hourge);
write_data(0x3a);
write_data(0x30+minshi);
write_data(0x30+minge);
write_data(0x3a);
write_data(0x30+secshi);
write_data(0x30+secge);
}
void Run_DS1302(void) // 读出DS1302中的数据,并在液晶上进行显示
{ uchar dd;
for(dd=10;dd>0;dd--) //加入循环,防止速度变化太快,不方便度数
{
sec = bcdtodec(uc_R1302(0x81)); //读出DS1302中的秒;
min = bcdtodec(uc_R1302(0x83)); //读出DS1302中的分
hour = bcdtodec(uc_R1302(0x85)); //读出DS1302中的小时
if(hour==0) //时间校准,每天0:30:30减少15s
{
if(min==30)
{
if(sec==45)
{
while(sec)
{
sec = bcdtodec(uc_R1302(0x81));
}
sec=46;
Write_DS1302Init();
}
}
}
display();
keyscan();
}
}
void write_su(uint dat)//速度显示
{
uchar shi,ge;
shi=dat%100/10;
ge=dat%10;
write_com(0x80);
write_data(0x20);
write_com(0x81);
write_data(0x30+shi);
write_data(0x30+ge);
}
void write_s1(uint s1)//一次里程显示
{
uchar bai,shi,ge,dian;
// wan=s1/10000; //s1为一次路程,一般不会超过几百km,故无万千位
// qian=s1%10000/1000;
bai=s1%10000/1000;
shi=s1%1000/100;
ge=s1%100/10;
dian=s1%10;
write_com(0x89);
write_data(0x30+bai);
write_data(0x30+shi);
write_data(0x30+ge);
write_data(0x2e);
write_data(0x30+dian);
}
void write_s2(uint s2)//总里程显示
{
uchar wan,qian,bai,shi,ge,dian;
wan=s2%1000000/100000;
qian=s2%100000/10000;
bai=s2%10000/1000;
shi=s2%1000/100;
ge=s2%100/10;
dian=s2%10;
write_com(0x80+0x49);
write_data(0x30+wan);
write_data(0x30+qian);
write_data(0x30+bai);
write_data(0x30+shi);
write_data(0x30+ge);
write_data(0x2e);
write_data(0x30+dian);
}
void main()
{
init();
write_com(0x83);
for(num=0;num<13;num++) //先显示固定的km/h km
{
write_data(table[num]);
delay(2);
}
write_com(0x80+0x46);
for(num=0;num<10;num++) //先显示固定的km
{
write_data(table1[num]);
delay(2);
}
// ISP_ERASE(0x2000); //
// ISP_PROGRAM(0x2000, 0x05);
// ISP_ERASE(0x2c01);
// ISP_PROGRAM(0x2c01, 0x40);
a=ISP_READ(0x2003);
delay(20);
b=ISP_READ(0x2207);
s21=a*256+b; //读出的两个八位合成一个十六位
// s21=248; //要改,用来清空第一次写入eeprom的数据
write_s2(s21); //显示开机总里程
while(1)
{
s1=quan*0.65; //s1为一次路程 这里一圈按0.65m算
if(s11!=s1) //如果s1发生了变化
{
s2=s21+s1; //s2为总里程 ,s21为开机读出的里程
a=s2/256; //s2为16位,把其分为两个八位分别写入存储器
b=s2%256;
ISP_ERASE(0x2003); // 扇区擦除。无字节擦除
ISP_PROGRAM(0x2003, a);
delay(20);
ISP_ERASE(0x2207);
ISP_PROGRAM(0x2207, b); // 将两组数据写向不同扇区
write_s2(s2);
}
s11=s1;
write_s1(s1); // 一次路程显示
delay(100);
write_com(0x81); //换行
write_su(bb); //速度显示
bb=0;
Run_DS1302();
}
}
void timer0() interrupt 1
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; //定时器0装初值5ms
aa++;
}
void exter1() interrupt 2
{
if(aa>=200)//即车轮转一圈时间超过1秒,认为速度为零
bb=0;
if(aa<200)
{
time=aa*5;//定时器为5ms,为避免带小数点,此乃为正常时间的1000倍
bb=65*36/time;//65为车圈周长的100倍,单位为米,bb为整型变量,舍掉速度小数点
}
aa=0;
quan++;
}
void exter0() interrupt 0
{
unsigned char j,k,N=0;
EX1 = 0;
delayhw(15);
if (IRIN==1)
{ EX1 =1;
return;
}
//确认IR信号出现
while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。
{delayhw(1);}
for (j=0;j<4;j++) //收集四组数据
{
for (k=0;k<8;k++) //每组数据有8位
{
while (IRIN) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
{delayhw(1);}
while (!IRIN) //等 IR 变为高电平
{delayhw(1);}
while (IRIN) //计算IR高电平时长
{
delayhw(1);
N++;
if (N>=30)
{ EX1=1;
return;} //0.14ms计数过长自动离开。
} //高电平计数完毕
IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0”
if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //数据最高位补“1”
N=0;
}//end for k
}//end for j
if (IRCOM[2]!=~IRCOM[3])
{ EX1=1;
return; }
IRCOM[5]=IRCOM[2] & 0x0F; //取键码的低四位
IRCOM[6]=IRCOM[2] >> 4; //右移4次,高四位变为低四位
if(IRCOM[5]>9)
{ IRCOM[5]=IRCOM[5]+0x37;}
else
IRCOM[5]=IRCOM[5]+0x30;
if(IRCOM[6]>9)
{ IRCOM[6]=IRCOM[6]+0x37;}
else
IRCOM[6]=IRCOM[6]+0x30;
if(IRCOM[6]==0x34)
{
if(IRCOM[5]==0x35)
{
flag=flag+1;
if(flag==4)
{
write_com(0x0c);
flag=0;
}
}
}
if(IRCOM[6]==0x34)
{
if(IRCOM[5]==0x34)
{
down=1;
}
}
if(IRCOM[6]==0x34)
{
if(IRCOM[5]==0x30)
{
up=1;
}
}
EX1 = 1;
return;
}
void delayhw(unsigned char x) //x*0.14MS 红外延时
{
unsigned char i;
while(x--)
{
for (i = 0; i<13; i++) {}
}
}#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define ISP_BYTE_READ 1 //ISP字节读
#define ISP_BYTE_PROGRAM 2 //ISP直接编程
#define ISP_SECTOR_ERASE 3 //ISP扇区擦除
/*以下是配置STC单片机的寄存器*/
/*相关资料在STC89C51RC的PDF的第35页开始*/
sfr ISP_DATA = 0xE2;
sfr ISP_ADDRH = 0xE3;
sfr ISP_ADDRL = 0xE4;
sfr ISP_CMD = 0xE5;
sfr ISP_TRIG = 0xE6;
sfr ISP_CONTR = 0xE7;
uchar code table[]="km/h km";
uchar code table1[]=" km";
sbit rs=P2^4; // 液晶
sbit rw=P2^5; // 液晶
sbit en=P2^6; // 液晶
uint aa,time,s1,s11;
uchar num,bb,a,b,up,down;
uchar IRCOM[7];//红外数组
unsigned long int quan,s2,s21; //
sbit ACC0 = ACC^0; //1302
sbit ACC7 = ACC^7; //1302
sbit IRIN = P3^2; //红外接收器数据线
sbit T_CLK = P3^6; /*实时时钟时钟线引脚 */
sbit T_IO = P3^4; /*实时时钟数据线引脚 */
sbit T_RST = P3^5; /*实时时钟复位线引脚 */
uchar flag;
uchar sec, min, hour;
void Write_DS1302Init(void);
void display();
void delayhw(uchar x); //x*0.14MS 红外延时
void delay(uint z);//液晶延时
/********************************************************************
* 功能 : EEPROM的扇区擦除
* 输入 : Address(擦除扇区的地址)
***********************************************************************/
void ISP_ERASE(Address)
{
ISP_ADDRL = Address;
ISP_ADDRH = Address >> 8;
ISP_CONTR = 0x81;
ISP_CMD = ISP_SECTOR_ERASE;
ISP_TRIG = 0x46; //PDF手册中说先像 ISP_TRIG 中写入 0x46, 然后写入 0xb9
ISP_TRIG = 0xb9;
_nop_();
_nop_();
}
/********************************************************************
* 输入 : Address(想要读取EEPROM的地址)
*********************************************************************/
uint ISP_READ(Address)
{
uchar Read_Data;
ISP_ADDRL = Address;
ISP_ADDRH = Address >> 8;
// EA = 0;
ISP_CONTR = 0x81;
ISP_CMD = ISP_BYTE_READ;
ISP_TRIG = 0x46;
ISP_TRIG = 0xb9;
_nop_();
_nop_();
Read_Data = ISP_DATA;
return Read_Data;
}
/********************************************************************
* 输入 : Address为编程的地址,Data_temp为想要编程的值
***********************************************************************/
void ISP_PROGRAM(Address, Data_temp)
{
ISP_DATA = Data_temp;
ISP_ADDRL = Address;
ISP_ADDRH = Address >> 8;
ISP_CONTR = 0x81;
ISP_CMD = ISP_BYTE_PROGRAM;
ISP_TRIG = 0x46;
ISP_TRIG = 0xb9;
_nop_();
_nop_();
}
void delay(uint z) //液晶延时
{
uint x,y;
for(x=110;x>0;x--)
for(y=z;y>0;y--);
}
void write_com(uchar com) //液晶写命令
{
rs=0;
P0=com;
delay(1);
en=1;
delay(1);
en=0;
}
void write_data(uchar date) //液晶写数据
{
rs=1;
P0=date;
delay(1);
en=1;
delay(1);
en=0;
}
void init()
{
quan=0;
en=0;
rw=0;
aa=0;
up=0;
down=0;
flag=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
EA=1; //开总中断
EX0=1; //开外部中断0
IT0=1; //外部中断设为下降沿触发
ET0=1; // 开定时器0中断
TMOD=0x11;//定时器0设定为定时器模式
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; //定时器0装初值5ms
TR0=1;//启动定时器0
EX1=1; //开外部中断1
IT1=1; //外部中断1设为下降沿触发
flag=0;
}
void v_RTInputByte(uchar ucDa) //往DS1302写入1Byte数据
{
uchar i;
ACC = ucDa;
T_RST = 1;
for(i=8; i>0; i--)
{
T_IO = ACC0;
T_CLK = 1;
T_CLK = 0;
ACC = ACC >> 1;
}
}
uchar uc_RTOutputByte(void) //读取1byte数据
{
uchar i;
T_RST = 1;
for(i=8; i>0; i--)
{
ACC = ACC >>1;
// T_IO=1;
ACC7 = T_IO;
T_CLK = 1;
T_CLK = 0;
}
return(ACC);
}
void v_W1302(uchar ucAddr, uchar ucDa) //输入 : ucAddr: DS1302地址, ucDa: 要写的数据
{
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); // 写地址
_nop_();
_nop_();
v_RTInputByte(ucDa); // 写1Byte数据
T_CLK = 1;
T_RST = 0;
}
uchar uc_R1302(uchar ucAddr) // 读取DS1302某地址的数据
{
uchar ucDa;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); //写地址,命令
_nop_();
_nop_();
ucDa = uc_RTOutputByte(); //读1Byte数据
T_CLK = 1;
T_RST = 0;
return(ucDa);
}
void keyscan() //设置时钟的键盘扫描程序
{
if(flag!=0)
{
while(flag)
{
if(flag==1)
{
write_com(0x80+0x47);
write_com(0x0f);
}
if(flag==2)
{
write_com(0x80+0x44);
}
if(flag==3)
{
write_com(0x80+0x41);
} //
if(up==1)
{
if(flag==1)
{
sec++;
if(sec==60)
sec=0;
}
if(flag==2)
{
min++;
if(min==60)
min=0;
}
if(flag==3)
{
hour++;
if(hour==24)
hour=0;
}
up=0;
display();
}
if(down==1)
{
if(flag==1)
{
sec--;
if(sec==255)
sec=59;
}
if(flag==2)
{
min--;
if(min==255)
min=59;
}
if(flag==3)
{
hour--;
if(hour==255)
hour=23;
}
down=0;
display();
}
// display();
}
Write_DS1302Init();
}
}
uchar dectobcd(uchar dec)// DEC码转换为BCD码
{
uchar bcd;
bcd = 0;
while(dec >= 10)
{
dec -= 10;
bcd++;
}
bcd <<= 4;
bcd |= dec;
return bcd;
}
uchar bcdtodec(uchar bcd) // BCD码转换为DEC码
{
uchar data1;
data1 = bcd & 0x0f; //取BCD低4位
bcd = bcd & 0x70; //剔除BCD的最高位和低4位。
data1 += bcd >> 1;
data1 += bcd >> 3; //用位移代替乘法运算
return data1;
}
void Write_DS1302Init(void)
{
sec=dectobcd(sec);
min=dectobcd(min);
hour=dectobcd(hour);
v_W1302(0x8e,0);
v_W1302(0x80,sec); //写入秒;
v_W1302(0x82,min); //写入分
v_W1302(0x84,hour); //写入小时
}
void display() //1302显示
{
uchar hourshi,hourge,minshi,minge,secshi,secge;
hourshi=hour/10;
hourge=hour%10;
minshi=min/10;
minge=min%10;
secshi=sec/10;
secge=sec%10;
write_com(0x80+0x40);
write_data(0x30+hourshi);
write_data(0x30+hourge);
write_data(0x3a);
write_data(0x30+minshi);
write_data(0x30+minge);
write_data(0x3a);
write_data(0x30+secshi);
write_data(0x30+secge);
}
void Run_DS1302(void) // 读出DS1302中的数据,并在液晶上进行显示
{ uchar dd;
for(dd=10;dd>0;dd--) //加入循环,防止速度变化太快,不方便度数
{
sec = bcdtodec(uc_R1302(0x81)); //读出DS1302中的秒;
min = bcdtodec(uc_R1302(0x83)); //读出DS1302中的分
hour = bcdtodec(uc_R1302(0x85)); //读出DS1302中的小时
if(hour==0) //时间校准,每天0:30:30减少15s
{
if(min==30)
{
if(sec==45)
{
while(sec)
{
sec = bcdtodec(uc_R1302(0x81));
}
sec=46;
Write_DS1302Init();
}
}
}
display();
keyscan();
}
}
void write_su(uint dat)//速度显示
{
uchar shi,ge;
shi=dat%100/10;
ge=dat%10;
write_com(0x80);
write_data(0x20);
write_com(0x81);
write_data(0x30+shi);
write_data(0x30+ge);
}
void write_s1(uint s1)//一次里程显示
{
uchar bai,shi,ge,dian;
// wan=s1/10000; //s1为一次路程,一般不会超过几百km,故无万千位
// qian=s1%10000/1000;
bai=s1%10000/1000;
shi=s1%1000/100;
ge=s1%100/10;
dian=s1%10;
write_com(0x89);
write_data(0x30+bai);
write_data(0x30+shi);
write_data(0x30+ge);
write_data(0x2e);
write_data(0x30+dian);
}
void write_s2(uint s2)//总里程显示
{
uchar wan,qian,bai,shi,ge,dian;
wan=s2%1000000/100000;
qian=s2%100000/10000;
bai=s2%10000/1000;
shi=s2%1000/100;
ge=s2%100/10;
dian=s2%10;
write_com(0x80+0x49);
write_data(0x30+wan);
write_data(0x30+qian);
write_data(0x30+bai);
write_data(0x30+shi);
write_data(0x30+ge);
write_data(0x2e);
write_data(0x30+dian);
}
void main()
{
init();
write_com(0x83);
for(num=0;num<13;num++) //先显示固定的km/h km
{
write_data(table[num]);
delay(2);
}
write_com(0x80+0x46);
for(num=0;num<10;num++) //先显示固定的km
{
write_data(table1[num]);
delay(2);
}
// ISP_ERASE(0x2000); //
// ISP_PROGRAM(0x2000, 0x05);
// ISP_ERASE(0x2c01);
// ISP_PROGRAM(0x2c01, 0x40);
a=ISP_READ(0x2003);
delay(20);
b=ISP_READ(0x2207);
s21=a*256+b; //读出的两个八位合成一个十六位
// s21=248; //要改,用来清空第一次写入eeprom的数据
write_s2(s21); //显示开机总里程
while(1)
{
s1=quan*0.65; //s1为一次路程 这里一圈按0.65m算
if(s11!=s1) //如果s1发生了变化
{
s2=s21+s1; //s2为总里程 ,s21为开机读出的里程
a=s2/256; //s2为16位,把其分为两个八位分别写入存储器
b=s2%256;
ISP_ERASE(0x2003); // 扇区擦除。无字节擦除
ISP_PROGRAM(0x2003, a);
delay(20);
ISP_ERASE(0x2207);
ISP_PROGRAM(0x2207, b); // 将两组数据写向不同扇区
write_s2(s2);
}
s11=s1;
write_s1(s1); // 一次路程显示
delay(100);
write_com(0x81); //换行
write_su(bb); //速度显示
bb=0;
Run_DS1302();
}
}
void timer0() interrupt 1
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; //定时器0装初值5ms
aa++;
}
void exter1() interrupt 2
{
if(aa>=200)//即车轮转一圈时间超过1秒,认为速度为零
bb=0;
if(aa<200)
{
time=aa*5;//定时器为5ms,为避免带小数点,此乃为正常时间的1000倍
bb=65*36/time;//65为车圈周长的100倍,单位为米,bb为整型变量,舍掉速度小数点
}
aa=0;
quan++;
}
void exter0() interrupt 0
{
unsigned char j,k,N=0;
EX1 = 0;
delayhw(15);
if (IRIN==1)
{ EX1 =1;
return;
}
//确认IR信号出现
while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。
{delayhw(1);}
for (j=0;j<4;j++) //收集四组数据
{
for (k=0;k<8;k++) //每组数据有8位
{
while (IRIN) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
{delayhw(1);}
while (!IRIN) //等 IR 变为高电平
{delayhw(1);}
while (IRIN) //计算IR高电平时长
{
delayhw(1);
N++;
if (N>=30)
{ EX1=1;
return;} //0.14ms计数过长自动离开。
} //高电平计数完毕
IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0”
if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //数据最高位补“1”
N=0;
}//end for k
}//end for j
if (IRCOM[2]!=~IRCOM[3])
{ EX1=1;
return; }
IRCOM[5]=IRCOM[2] & 0x0F; //取键码的低四位
IRCOM[6]=IRCOM[2] >> 4; //右移4次,高四位变为低四位
if(IRCOM[5]>9)
{ IRCOM[5]=IRCOM[5]+0x37;}
else
IRCOM[5]=IRCOM[5]+0x30;
if(IRCOM[6]>9)
{ IRCOM[6]=IRCOM[6]+0x37;}
else
IRCOM[6]=IRCOM[6]+0x30;
if(IRCOM[6]==0x34)
{
if(IRCOM[5]==0x35)
{
flag=flag+1;
if(flag==4)
{
write_com(0x0c);
flag=0;
}
}
}
if(IRCOM[6]==0x34)
{
if(IRCOM[5]==0x34)
{
down=1;
}
}
if(IRCOM[6]==0x34)
{
if(IRCOM[5]==0x30)
{
up=1;
}
}
EX1 = 1;
return;
}
void delayhw(unsigned char x) //x*0.14MS 红外延时
{
unsigned char i;
while(x--)
{
for (i = 0; i<13; i++) {}
}
}
流水灯实验
视频地址:http://www.tudou.com/v/nA_PvywUGN8/&rpid=104556293/v.swf
/********************************************************************
* 文件名 : 流水灯.c
* 描述 : 该程序实现LED的流水灯显示。
该程序用于学习 LED流水灯 的控制方法。
本例中是调用的 intrins.h 中的函数实现的循环移位。
***********************************************************************/
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
/********************************************************************
* 名称 : Delay()
* 功能 : 延时,延时时间为 10ms * del
* 输入 : del
* 输出 : 无
***********************************************************************/
void Delay(uint del)
{
uint i,j;
for(i=0; i<del; i++)
for(j=0; j<1827; j++)
;
}
/********************************************************************
* 名称 : Main()
* 功能 : 实现灯的闪烁
* 输入 : 无
* 输出 : 无
* 说明 :也可以使用例1的的方法来关闭数码管
***********************************************************************/
void Main(void)
{
uchar i;
P1 = 0x00;
while(1)
{
P1 = 0x7f; //P1.7亮
for(i=0; i<7; i++) //移位7次
{
P1 = _cror_(P1, 1); //_crol_()这个函数在intrins.h中定义了,用于循环右移
Delay(25);
}
P1 = 0xfe;
for(i=0; i<7; i++)
{
P1 = _crol_(P1, 1); //用于循环左移
Delay(25);
}
}
}
最简单的闪烁灯
/***********************************************************************/
#include<reg52.h>
#define uchar unsigned char //这里用"uchar"代替"unsigned char","uchar"用来定义无符号字符型数。
#define uint unsigned int //"uint"用来定义无符号整型数。
sbit Show_LED = P1^0; //用来声明P0.0口为程序所要控制的端口,"sbit"是KEIL专门用来声明某位IO口
/********************************************************************
* 名称 : Delay()
* 功能 : 延时,延时时间为 10ms * del。这是通过软件延时,有一定误差。
* 输入 : del
* 输出 : 无
***********************************************************************/
void Delay(uint del)
{
uint i,j;
for(i=0; i<del; i++)
for(j=0; j<1827; j++) //这个是通过软件仿真得出的数
;
}
/********************************************************************
* 名称 : Main()
* 功能 : 实现灯的闪烁
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Main(void)
{
P0 = 0xff; //用于关闭数码管
while(1)
{
Show_LED = 0;
Delay(20); //Delay(del)中的数为延时的时间参数,延时时间为 10ms * del.
Show_LED = 1;
Delay(20);
}
}
花样流水灯
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
void Delay(uint del)
{
uint i,j;
for(i=0; i<del; i++)
for(j=0; j<1827; j++)
;
}
void Main(void)
{
P0 = 0xff;
P2 = 0x00;
while(1)
{
/*下面四行用于控制LED每隔一个亮*/
P1 = 0xaa;
Delay(50);
P1 = 0x55;
Delay(50);
/*下面四行用于控制LED每隔一个亮*/
P1 = 0xcc;
Delay(50);
P1 = 0x33;
Delay(50);
/*下面四行用于控制LED 高四位 或者 低四位亮*/
P1 = 0x0f;
Delay(50);
P1 = 0xf0;
Delay(50);
/*下面八行用于控制LED的两次全亮 全灭*/
P1 = 0x00;
Delay(25);
P1 = 0xff;
Delay(25);
P1 = 0x00;
Delay(25);
P1 = 0xff;
Delay(25);
Delay(200); //延时两秒
}
}
1602显示实验
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
//这三个引脚参考资料
sbit E=P2^6; //1602使能引脚
sbit RW=P2^5; //1602读写引脚
sbit RS=P2^4; //1602数据/命令选择引脚
void delay()
{
int i,j;
for(i=0; i<=10; i++)
for(j=0; j<=2; j++)
;
}
/*uchar Convert(uchar In_Date)
{
uchar i, Out_Date = 0, temp = 0;
for(i=0; i<8; i++)
{
temp = (In_Date >> i) & 0x01;
Out_Date |= (temp << (7 - i));
}
return Out_Date;
} */
void enable(uchar del)
{
P0 = del;
RS = 0;
RW = 0;
E = 0;
delay();
E = 1;
delay();
}
void write(uchar del)
{
P0 = del;
RS = 1;
RW = 0;
E = 0;
delay();
E = 1;
delay();
}
void L1602_init(void)
{
enable(0x01);
enable(0x38);
enable(0x0c);
enable(0x06);
enable(0xd0);
}
void L1602_char(uchar hang,uchar lie,char sign)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
enable(a);
write(sign);
}
void L1602_string(uchar hang,uchar lie,uchar *p)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
enable(a);
while(1)
{
if(*p == '\0') break;
write(*p);
p++;
}
}
void Main()
{
uchar i = 48;
L1602_init();
L1602_char(1,5,'b');
L1602_string(1,1," EEPW EEPW EEPW ");
L1602_string(2,1," YSJABCD ");
while(1);
}
定时器应用--秒表
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar Count = 0;
uchar code table[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar code LED_W[8] = {0,4,2,6,1,5,3,7};
void Time0_Init()
{
TMOD = 0x01;
IE = 0x82;
TH0 = 0x4c;
TL0 = 0x00;
TR0 = 1;
}
void Time0_Int() interrupt 1
{
TH0 = 0x4c;
TL0 = 0x00;
Count++; //长度加1
}
void main()
{
uchar i = 0;
Time0_Init();
while(1)
{
P0 = table[i % 10]; //取 i 的个位
P2 = LED_W[0];
while(1)
{
if(Count == 20) //当Count为 20 时,i 自加一次,20 * 50MS = 1S
{
Count = 0;
i++;
break;
}
}
}
}
数码管滚动显示
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar code LED_W[8] = {0,1,2,3,4,5,6,7};
uchar Time_temp = 0, LED_temp = 0;
void Delay(uint i)
{
uchar x,j;
for(j=0;j<i;j++)
for(x=0;x<=148;x++);
}
void Time0_Init()
{
TMOD = 0x01;
IE = 0x82;
TH0 = 0x4c;
TL0 = 0x00;
TR0 = 1;
}
void Time0_Int() interrupt 1
{
TH0 = 0x4c;
TL0 = 0x00;
Time_temp++;
if(Time_temp == 4) //定时器溢出时间50毫秒,隔0.2秒,数码管的数据改变一次
{
LED_temp++;
Time_temp = 0;
}
}
void Main(void)
{
uchar i = 0,j = 0;
Time0_Init();
while(1)
{
P0 = table[(i + LED_temp) % 8]; //数码管段值
P2 = LED_W[j]; //点亮某一位数码管
Delay(2);
j++;
i++;
if(j == 8) //每个数码管都点亮了一次。
{
j = 0;
i = 0;
}
}
}
温度显示实验--ds18b20
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define jump_ROM 0xCC
#define start 0x44
#define read_EEROM 0xBE
sbit DQ = P1^3; //DS18B20数据口
unsigned char TMPH,TMPL;
uchar code table[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay_1()
{
int i,j;
for(i=0; i<=10; i++)
for(j=0; j<=2; j++)
;
}
void delay(uint N)
{
int i;
for(i=0; i<N; i++)
;
}
void Delay_1ms(uint i)//1ms延时
{
uchar x,j;
for(j=0;j<i;j++)
for(x=0;x<=148;x++);
}
uchar Reset(void)
{
uchar deceive_ready;
DQ = 0;
delay(29);
DQ = 1;
delay(3);
deceive_ready = DQ;
delay(25);
return(deceive_ready);
}
uchar read_bit(void)
{
uchar i;
DQ = 0;
DQ = 1;
for(i=0; i<3; i++);
return(DQ);
}
void write_bit(uchar bitval)
{
DQ=0;if(bitval==1)
DQ=1;
delay(5);
DQ=1;
}
uchar read_byte(void)
{
uchar i,m,receive_data;
m = 1;
receive_data = 0;
for(i=0; i<8; i++)
{
if(read_bit())
{
receive_data = receive_data + (m << i);
}
delay(6);
}
return(receive_data);
}
void write_byte(uchar val)
{
uchar i,temp;
for(i=0; i<8; i++)
{
temp = val >> i;
temp = temp & 0x01;
write_bit(temp);
delay(5);
}
}
void main()
{
float tt;
uint temp;
P2 = 0x00;
while(1)
{
Reset();
write_byte(jump_ROM);
write_byte(start);
Reset();
write_byte(jump_ROM);
write_byte(read_EEROM);
TMPL = read_byte();
TMPH = read_byte();
temp = TMPL / 16 + TMPH * 16;
P0 = table[temp/10%10];
P2 = 6;
Delay_1ms(5);
P0 = table[temp%10];
P2 = 7;
Delay_1ms(5);
}
}
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
vscode+cmake搭建雅特力AT32L021开发环境被打赏30分 | |
【换取逻辑分析仪】自制底板并驱动ArduinoNanoRP2040ConnectLCD扩展板被打赏47分 | |
【分享评测,赢取加热台】RISC-V GCC 内嵌汇编使用被打赏38分 | |
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 |