LED灯是低电平点亮(0),蜂鸣器继电器是高电平打开 (1)
继电器是P04端口,开启继电器是P0=0x10;
蜂鸣器是P08端口,开启蜂鸣器是P0=0x80;
按键按下(S5==0)为低电平
int=32位 char=8位 bit=1位
开关标志变量的话,则定义为bit型数据,例如 SMG_flash=1; LED_off_on=0;
计数变量的话,则定义为unsigned int型数据,例如 unsigned int SMG_count=0; unsigned int LED_count=0。普通变量则定义为unsigned char。
{0xbf,0x7f}// - .
{0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
// 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.
注意变量范围是使用char 还是int (int比char大)
与 & 或 |
0 0 0 0 0 0
0 1 0 0 1 1
1 0 0 1 0 1
1 1 1 1 1 1
0000 | 0 | 0100 | 4 | 1000 | 8 | 1100 | c | |||
0001 | 1 | 0101 | 5 | 1001 | 9 | 1101 | d | |||
0010 | 2 | 0110 | 6 | 1010 | a | 1110 | e | |||
0011 | 3 | 0111 | 7 | 1011 | b | 1111 | f |
0001 | 1 | 0010 | 2 | 0100 | 4 | 1000 | 8 | |||
1110 | e | 1101 | d | 1011 | b | 0111 | 7 |
数码管断码,不亮的是1,亮的是0(共阳极连接)
程序框架
#include "reg52.h"
#include "iic.h"//ICC总线底层驱动
#include "ds1302.h"//DS1302实时时钟底层驱动
#include "onewire.h"//DS18B20温度传感器底层驱动
void main()
{
while(1)
{
}
}
系统初始化
void Init_system()
{
selectHC573(5); //控制蜂鸣器与继电器
P0=0x00;
selectHC573(4); //控制LED灯
P0=0xff;
}
延迟函数
//普通延迟函数(int类型)(延迟时间长)
void delay(unsigned int t)
{
while(t--);
}
//char类型延迟函数(延迟时间短)
void delay_key(unsigned char t)
{
while(t--);
}
数码管数字编码
unsigned char code SMG_duanma[18]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
// 0 1 2 3 4 5 6 7 8 9 A B C D E F - .
unsigned char code SMG_dot[10]=
{0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
// 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.
锁存器选择
I/O模式
跳帽J13的23短接
void selectHC573(unsigned char channel)
{
switch(channel)
{
case 4:P2=(P2&0x1f)|0x80; break; //控制LED灯
case 5:P2=(P2&0x1f)|0xa0; break; //控制蜂鸣器继电器
case 6:P2=(P2&0x1f)|0xc0; break; //控制数码管显示位置
case 7:P2=(P2&0x1f)|0xe0; break; //控制数码管显示数字
case 0:P2=(P2&0x1f)|0x00; break;
}
}
MM模式
跳帽J13的12短接
#include "absacc.h"//引用头文件(里面包含需要用到XBYTE关键字)
XBYTE[0x8000]=0x00; //LED灯 //selectHC573(4); P0=0x00;
XBYTE[0xa000]=0x00; //蜂鸣器与继电器 //selectHC573(5); P0=0x00;
XBYTE[0xc000]=0x01; //数码管位选 //selectHC573(6); P0=0x00;
XBYTE[0xe000]=0x00; //数码管内容 //selectHC573(7); P0=0x00;
LDE独立按键矩阵按键连接
LED灯的连接
sbit L1=P0^0;
sbit L2=P0^1;
sbit L3=P0^2;
sbit L4=P0^3;
sbit L5=P0^4;
sbit L6=P0^5;
sbit L7=P0^6;
sbit L8=P0^7;
独立键盘的连接
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
矩阵按键的连接
//4x4矩阵键盘
sfr P4=0xC0;//头文件reg52.h中没有P4接口,所以当用到P4接口时要加上这一句
sbit R1=P3^0;//行(R)
sbit R2=P3^1;
sbit R3=P3^2;
sbit R4=P3^3;
sbit C4=P3^4;//列(C)
sbit C3=P3^5;
sbit C2=P4^2;
sbit C1=P4^4;
//2x2矩阵键盘(左下方2x2矩阵)
sfr P4=0xC0;//头文件reg52.h中没有P4接口,所以当用到P4接口时要加上这一句
sbit R1=P3^2;//行(R)
sbit R2=P3^3;
sbit C2=P4^2;
sbit C1=P4^4;
//2x2矩阵键盘(右下方2x2矩阵)
sbit R1=P3^2;
sbit R2=P3^3;
sbit C2=P3^4;
sbit C1=P3^5;
LED灯
依次点亮与熄灭
void LEDrunning()
{
unsigned char i;
for(i=0;i<=8;i++)
{
selectHC573(4); //控制LED灯
P0=0xff<<i; //<<左移运算符,将P0从11111111,设置到00000000
delay(60000);
selectHC573(0);
}
for(i=0;i<=8;i++)
{
selectHC573(4); //控制LED灯
P0=~(0xff<<i);
delay(60000);
selectHC573(0);
}
}
LED闪烁五秒后停止
单个LED以0.1秒为间隔闪烁5s后熄灭
void Init_T0()
{
TMOD=0x01; //也就是二进制0001,定时器0定时功能,16位模式
TH0=(65535-10000)/256; //0.1秒
TL0=(65535-10000)%256;
EA=1; //总中断打开
ET0=1; //定时中断使能
TR0=1; //启动定时器
}
bit LED_k=0;//控制数LED开关的标志变量,表示闹铃响起
bit LED_f=0;//控制数LED闪烁的标志变量,当LED_f=1的时候,表示LED等亮起
unsigned int LED_c=0;//控制LED的计数变量变量,LED闪烁的周期为0.1秒,闪烁的时间为5秒
void Service_T0() interrupt 1
{
TH0=(65535-10000)/256; //0.01秒
TL0=(65535-10000)%256;
if(LED_k==1)
{
LED_c++;
if(LED_c % 10 == 0) //0.1秒
{
LED_f=~LED_f; //LED闪烁
if(LED_c>=500) //持续5秒关闭所有标志
{
LED_k=0;
LED_f=0;
LED_c=0;
}
}
}
}
//当需要LED闪烁时候,打开LED开关,即LED_k=1;
//LED_f控制某个特定LED的闪烁
数码管
单个数码管动态显示
void DisSMG_bit(unsigned char dat,unsigned char pos)
{
selectHC573(6); //数码管位选
P0=0x01<<pos;
selectHC573(7); //数码管内容
P0=dat;
delay(500); //数码管动态显示需要的延迟函数
selectHC573(0);
}
数码管统一操作函数
void DisSMG_all(unsigned char dat)//在某些数码管动态后统一关闭数码管
{
selectHC573(6); //数码管位选
P0=0xff;
selectHC573(7); //数码管内容
P0=dat;
selectHC573(0);
}
数码管动态显示
void DisSMG()
{
if(SMG_stat==0)
{
DisSMG_bit(SMG_duanma[0],0);
}
if(SMG_stat==1)
{
DisSMG_bit(SMG_duanma[1],0);
}
if(SMG_stat==2)
{
DisSMG_bit(SMG_duanma[2],0);
}
DisSMG_all(0xff); //统一关闭数码管
}
数码管闪烁
符号“-”一秒闪烁一次
//在定时器中设置SMG_f 1秒反转一次
if(SMG_f==1)
{
DisSMG_bit(SMG_duanma[16],2);
}
//当SMG_f==0时候数码管不显示
时分秒一秒闪烁一次
//SMG_flash=1本身就为1,而且无论什么情况下,SMG_flash一直是1、0、1、0的变化
//四个相或,只要有一个为1最后结果就为1,当SMG_flash在1、0变化时候,这个if条件判断也在1、0之间变换
//k7为0时钟显示,k7为1设置时,k7为2设置分,k7为3设置秒
//在定时器中设置SMG_f 1秒反转一次
if(((k7==1)&(SMG_f==1))|(k7==0)|(k7==2)|(k7==3))//时闪烁
{
DisSMG_bit(SMG_duanma[Timer[2]/16],0);
DisSMG_bit(SMG_duanma[Timer[2]%16],1);
}
DisSMG_bit(SMG_duanma[16],2);
if(((k7==2)&(SMG_f==1))|(k7==0)|(k7==1)|(k7==3))//分闪烁
{
DisSMG_bit(SMG_duanma[Timer[1]/16],3);
DisSMG_bit(SMG_duanma[Timer[1]%16],4);
}
DisSMG_bit(SMG_duanma[16],5);
if(((k7==3)&(SMG_f==1))|(k7==0)|(k7==2)|(k7==1))//秒闪烁
{
DisSMG_bit(SMG_duanma[Timer[0]/16],6);
DisSMG_bit(SMG_duanma[Timer[0]%16],7);
}
数码管计数显示
if(times>999)
{
DisSMG_bit(SMG_duanma[(times/1000)%10],5);
}
if(times>99)
{
DisSMG_bit(SMG_duanma[(times/100)%10],5);
}
if(times>9)
{
DisSMG_bit(SMG_duanma[(times/10)%10],6);
}
DisSMG_bit(SMG_duanma[times%10],7);
按键
独立按键的扫描
void scan_key()
{
if(S7==0)
{
delay_key(20); //此方法可以防止干扰
if(S7==0)
{
while(S7==0)
{
//按键不松开,S7一直为0,一直执行while语句,当S7按键松开,S7为1,才会执行下一条语句
}
}
}
if(S6==0)
{
//.....
}
}
//这里的else必须加上,不然程序会一直往下走,走了一圈,然后回到原本位置
if(SMG_stat==0)
{
SMG_stat=1;
}
else if(SMG_stat==1)
{
k5=0;
SMG_stat=2;
}
else if(SMG_stat==2)
{
SMG_stat=0;
}
矩阵按键的扫描
4x4矩阵键盘
void scan_key()
{
R1=0; //扫描第一行,其他行都为零
R2=R3=R4=1;
C1=C2=C3=C4=1;
if(C1==0) //C1==0时就是按下第一行第一列的时
{
delay_key(20);
if(C1==0)
{
while(C1==0)
{
}
}
}
if(C2==0) //按下第一行第二列的时
{
//.....
}
if(C3==0) //按下第一行第三列的时
{
//.....
}
if(C4==0) //按下第一行第四列的时
{
//.....
}
R2=0; //扫描第二行,其他行都为零
R1=R3=R4=1;
C1=C2=C3=C4=1;
//········
}
2x2矩阵键盘
void scankey()
{
R1=0; //扫描第一行,其他行都为零
R2=1;
C1=C2=1;
if(C1==0)
{
delay_key(20);
if(C1==0)
{
while(C1==0)
{
}
}
}
if(C2==0)
{
//.....
}
R2=0; //扫描第二行,其他行都为零
R1=1;
C1=C2=1;
//......
}
按键的长按与短按
unsigned char k4=0; //S4按键按下标志位,1表示按键按下
void Init_T0()
{
TMOD=0x01;
TH0=(65535-10000)/256; //0.01s
TL0=(65535-10000)%256;
EA=1;
ET0=1;
TR0=1;
}
unsigned int count=0;
void Service_T0() interrupt 1
{
TH0=(65535-10000)/256; //0.01s
TL0=(65535-10000)%256;
if(k4==1) //在按键按下期间进行计数
{
count++; //按键按下的持续时间
}
}
void scan_key
{
if(S4==0)
{
delay_key(50);
if(S4==0)
{
count=0; //从头开始计数
k4=1; //S4按下标志位
while(S4==0)
{
DisSMG();
}
k4=0; //按键松开
if(count>100) //表示按下超过1s
{
//长按相应操作
}
else //按下不超过1s
{
//短按相应操作
}
}
}
}
外部中断0
//初始化函数
void Init_INT0()
{
EA=1; //打开总中断
EX0=1; //打开外部中断使能
IT0=1; //选择外部中断0为下降沿出发,当IT0=0时选项低电平触发
}
//中断服务函数
void Service_INT0() interrupt 0
{
//编写中断服务逻辑代码
}
定时器0
//初始化函数
void Init_T0()
{
TMOD=0x01; //也就是二进制0001,定时器0定时功能,16位模式
TH0=(65535-50000)/256; //0.05秒
TL0=(65535-50000)%256;
EA=1; //总中断打开
ET0=1; //定时中断使能
TR0=1; //启动定时器
}
//中断服务函数
unsigned int count=0; //计数
void Service_T0() interrupt 1
{
TH0=(65535-50000)/256; //0.05s
TL0=(65535-50000)%256;
count++;
//编写中断服务函数逻辑代码
}
PWM调波
unsigned char PWM_c=0; //PWM计数
unsigned char PWM_t=20; //占空比,20表示20%
unsigned char PWM_f=1; //PWM输出表示位,1表示开始输出,0表示停止输出
void Init_T0()
{
TMOD=0x01;
TH0=(65535-100)/256; //0.0001s
TL0=(65535-100)%256;
TR0=1;
ET0=1;
EA=1;
}
void service_T0() interrupt 1
{
TH0=(65535-100)/256;
TL0=(65535-100)%256;
PWM_c++;
if(PWM_c>=PWM_t)
{
PWM_f=0; //0表示停止输出
}
if (PWM_c>=100)
{
PWM_f=1; //1表示开始输出
PWM_c=0;
}
}
//按下按键调整对应占空比PWM_t
//在PWM_out()函数中设置在PWM_f=1时进行相应输出(LED灯、蜂鸣器等),在PWM_f=0时停止相应输出
555模块
//J13中NAL与P34短接,调整Rb3即可调整555定时器的频率
void Init_T()
{
TH0=0xff; //定时器0用作计数,8位重装模式
TL0=0xff;
TH1=(65535-50000+1)/256; //定时器1用作计数,定时时间位50ms(0.05s)
TL1=(65535-50000+1)%256;
TMOD=0x16; //0001 0110
EA=1;
ET0=1;
ET1=1;
TR1=1;
TR0=1;
}
unsigned int count_f=0; //记录脉冲个数
unsigned int count_c=0; //计数
unsigned int dat_f=0; //从count_f中提取的脉冲个数
void service_T0() interrupt 1 //计算脉冲个数
{
count_f++;
}
void service_T1() interrupt 3 //定时1s
{
TH1=(65535-50000+1)/256;
TL1=(65535-50000+1)%256;
count_c++;
if(count_c==20) //此时为1s
{
dat_f=count_f; //取出上秒频率总数
count_f=0; //清零,计算下一秒的频率//此时上一秒的频率储存在dat_f中
count_c=0;
}
}
//dat_f就是测得的555模块的频率,后在数码管中显示出来即可
超声波测距
#include "intrins.h"//需要用到_nop_()
sbit TX=P1^0;
sbit RX=P1^1;
unsigned int distance=0;
void delay12us() //@12.000MHz 延时12us
{
unsigned char i;
_nop_();
_nop_();
i = 33;
while (--i);
}
void Send_wave() //产生8个40KHx超声波信号
{
unsigned char i;
for(i = 0; i < 8; i++)
{
TX = 1;
delay12us();
TX = 0;
delay12us();
}
}
void Measure_Distance() //超声波测距
{
unsigned int time = 0;
TMOD &= 0x0f; //定时器1模式0,13位,最大8192个计数脉冲
TH1 = 0x00;
TL1 = 0x00;
Send_wave(); //发送超声波信号
TR1 = 1; //启动定时器
while((RX == 1) && (TF1 == 0)); //等待超声波信号返回或者等到测量超出范围
TR1 = 0; //停止定时器
if(TF1 == 0) //正常测量范围
{
time = TH1;
time = (time << 8) | TL1;
distance = ((time / 10) * 17) / 100 + 3;
}
else //超出测量范围
{
TF1 = 0;
distance = 999;
}
}
//distance就是测量出的距离,当超过测量范围的时候,distance=999
串口通信
sfr AUXR=0x8e; //新增辅助寄存器,reg52.h头文件没有,是蓝桥杯板子专有的
void Init_uart()
{
TMOD=0x20; //定时器1工作模式为自动重装
TH1=0xfd; //设置波特率为9600
TL1=0xfd; //11.0592或者12HM的12分频
TR1=1; //启动定时器1
SCON=0x50; //八位工作模式,允许接收
AUXR=0x00; //辅助寄存器
ES=1; //使能串口中断
EA=1; //使能串口中断
}
//发送单个字节
void Send_byte(unsigned char dat)
{
SBUF=dat; //将数据放入SBUF缓冲器
while(TI==0); //等待发送完成,发送完成后TI=1;
TI=0; //清除发送完成标志
}
//发送字符串,在c中字符串就是指针
void Send_string(unsigned char *str)//*str是指针
{
while(*str!='\0') //字符串中的字符从第一位一个个发送,直到发送到最后一个字符\0时停止发送
{
Send_byte(*str++); //指针指向下一个字符
}
}
unsigned char urdat;
void Service_uart() interrupt 4
{
if(RI==1) //判断是否接收到完整数据
{
RI=0; //清除接受完成标志
urdat=SBUF; //如果要根据接受的信号做出相应反应则对urdat进行判断
Send_byte(urdat); //发送urdat
}
}
//后面就可以使用Send_byte()和sendstring(),发送字节或者发送字符串
DS1302时间显示
unsigned char Write_DS1302_add[3]={0x80,0x82,0x84};
unsigned char Read_DS1302_add[3]={0x81,0x83,0x85};
// 秒 分 时 星期 日 月 年
unsigned char Timer[3]={0x55,0x59,0x23};
void Init_DS1302()
{
char i;
Write_Ds1302_Byte(0x8e,00); //打开寄存器写保护功能,允许向内存写入地址
for(i=0;i<3;i++)//i根据情况调整 //写入七个字节时间参数
{
Write_Ds1302_Byte(Write_DS1302_add[i],Timer[i]);//写入时间
}
Write_Ds1302_Byte(0x8e,80); //恢复寄存器的写保护,禁止向内存写入数据
}
void Read_time()
{
char i;
for(i=0;i<3;i++)//i根据情况调整 //读取7个字节的实时时间
{
Timer[i]=Read_Ds1302_Byte(Read_DS1302_add[i]);//读出此时的时间
}
}
//Timer[i]就是读取后的时间,随后利用数码管的动态显示,在数码管中显示出来(秒分时的十位与个位除以16)
从DS1302中读出来的时间十BCD码格式的,在进行按键设置的时候,要将BCD转换为十进制数后再更新然后再转回BCD码。(BCD——十进制——加加减减——BCD)
unsigned char BCDtoTEN(unsigned char dat)//BCD转十进制
{
dat = (dat/16)*10 + dat%16;
return dat;
}
unsigned char TENtoBCD(unsigned char dat)//十进制转BCD
{
dat = (dat/10)*16 + dat%10;
return dat;
}
unsigned char timeradd(unsigned char dat)//将BCD转为十进制后加一后再转回BCD
{
dat=BCDtoTEN(dat);
dat=dat++;
dat=TENtoBCD(dat);
return dat;
}
unsigned char timermiuns(unsigned char dat)//将BCD转为十进制后减一后再转回BCD
{
dat=BCDtoTEN(dat);
dat=dat--;
dat=TENtoBCD(dat);
return dat;
}
if(k7==1)//时钟加一
{
Timer[2]=timeradd(Timer[2]);
if(Timer[2]>=TENtoBCD(24))
{
Timer[2]=0;
}
}
if(k7==1)//时钟减一
{
Timer[2]=timermiuns(Timer[2]);
if(Timer[2]<=0)
{
Timer[2]=TENtoBCD(23);//十:23
}
}
//如果只是单独的设置闹铃,显示的数不是从DS1302中提取出来的,则和BCD码没有关系
//而且定义闹铃的时候直接就是clock[3]={0,0,0};//无需加上0x
DS18B20温度读取
unsigned int temper=0; //定义一个存放温度得变量
void DisSMG();
void Read_temper()
{
unsigned char LSB,MSB; //定义两个变量接收温度低八位与高八位
init_ds18b20(); //初始化DS18B20
DisSMG(); //动态刷新数码管
Write_DS18B20(0xcc); //跳过rom指令
Write_DS18B20(0x44); //转换温度,启动DS18B20进行温度转换,结果保存在高速RAM中
DisSMG(); //动态刷新数码管
init_ds18b20(); //初始化DS18B20
DisSMG(); //动态刷新数码管
Write_DS18B20(0xcc); //跳过ROM指令,忽略64位ROM地址,直接向DS18B20发起温度转换指令
Write_DS18B20(0xbe); //读数据指令,读取高速暂存存储器9个字节的内容
DisSMG(); //动态刷新数码管
LSB=Read_DS18B20(); //读取温度低八位
MSB=Read_DS18B20(); //读取温度高八位
temper=MSB; //先把高八位赋给temp
temper=(temper<<=8)|LSB; //将temp左移八位,将低八位空出来后或上LSB组成16位温度数据
//保留整数部分
temper=temper*0.0625;
//保留一位小数
temper=temper*0.0625*10;
//保留二位小数
temper=temper*0.0625*100;
DisSMG();
}
//temper就是读取后的温度,随后利用数码管的动态显示,在数码管中显示出来
PCF8591
光敏电阻电压AD
unsigned int lingt=0;
void Read_lignt()
{
I2CStart(); //IIC总线起始信号
I2CSendByte(0x90); //PCF8951的写设备地址
I2CWaitAck(); //等待从机应答
I2CSendByte(0x01); //写入PCF8591的控制字节, 光敏传感器接到AIN1,通道1;控制寄存器应写入:0x01
I2CWaitAck(); //等待从机应答
I2CStop(); //IIC总线停止信号
DisSMG();
I2CStart(); //IIC总线起始信号
I2CSendByte(0x91); //PCF8951的读设备地址
I2CWaitAck(); //等待从机应答
lignt=I2CReceiveByte(); //读取PCF8591通道3的数据
lignt=lignt*1.961;
I2CSendAck(1); //产生非应答信号
I2CStop(); //IIC总线停止信号
}
//lignt就是读取后的光敏电阻电压,随后利用数码管的动态显示,在数码管中显示出来
可变电阻电压AD
unsigned int rb2 = 0;
void Read_rb2()
{
I2CStart(); //IIC总线起始信号
I2CSendByte(0x90); //PCF8951的写设备地址
I2CWaitAck(); //等待从机应答
I2CSendByte(0x03); //写入PCF8591的控制字节,电位器Rb2接到AIN3,通道3;控制寄存器应写入:0x03
//没有DAC都用0x03,当题目中又DAC则用0x43
I2CWaitAck(); //等待从机应答
I2CStop(); //IIC总线停止信号
DisSMG();
I2CStart(); //IIC总线起始信号
I2CSendByte(0x91); //PCF8951的读设备地址
I2CWaitAck(); //等待从机应答
rb2=I2CWaitAck(); //读取PCF8591通道3的数据
rb2=rb2*1.961;
I2CSendAck(1); //产生非应答信号
I2CStop(); //IIC总线停止信号
}
//rb2就是读取后的电阻电压,随后利用数码管的动态显示,在数码管中显示出来
//看要求是电压显示几位小数,显示5V是显示50还是500
DAC电压输出
unsigned int VANI3=0;
void Read_VANI3()
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x43); //有DAC输出则需要用43
I2CWaitAck();
I2CStop();
DisSMG();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
VANI3=I2CReceiveByte();
VANI3=VANI3*1.961;
I2CSendAck(1);
I2CStop();
}
void Read_DAC(unsigned char dat)
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x43);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
//纯DAC输出 后面要输出什么直接Read_DAC(dat);(数据就可以);
DAC数据输出
当输出关系如上图所示时候输出函数如下(不需要数码管显示)
distance是两位数字
void DAC_out()
{
if(ceju_k==1)
{
if(distance<=20)
{
Read_DAC(255/5); //此时输出电压是1
}
else if(distance>20&&distance<80)
{
Read_DAC((255/5)*(1/15)*(distance-3));
}
else if(distance>80)
{
Read_DAC(255/5*5); //此时输出电压是5
}
}
if(ceju_k==0)
{
Read_DAC(0);
}
}
当输出关系如上图所示时候输出函数如下(需要数码管显示)
temper是四位数字,所以要temper/100
DAC_dat是数码管显示中的数值
void DAC_out()
{
if(K5_mode==1)
{
if(temper<=2000)
{
Read_DAC_dat(255/5); //此时输出电压是1
DAC_dat=100; //输出电压1.00
}
else if(temper<=4000&&temper>=2000)
{
Read_DAC_dat((255/5)*0.15*((temper/100)-2));
DAC_dat=(0.15 * (temper/100) - 2) * 100;
}
else if(temper>=4000)
{
Read_DAC_dat(255/5*4); //此时输出电压是4
DAC_dat=400; //输出电压4.00
}
}
}
24C02储存器
//24C02储存器写操作
void Write_24C02(unsigned char add,unsigned char dat)
{
I2CStart(); //IIC总线起始信号
I2CSendByte(0xa0); //24C02的写设备地址,写操作地址则为:0xa0
I2CWaitAck(); //等待从机应答
I2CSendByte(add); //内存字节字节
I2CWaitAck(); //等待从机应答
I2CSendByte(dat); //写入目标数据
I2CWaitAck(); //等待从机应答
I2CStop(); //IIC总线停止信号
}
//24C02储存器读操作
unsigned char Read_24C02(unsigned char add)
{
unsigned char temp; //进行一个伪写操作
I2CStart(); //IIC总线起始信号
I2CSendByte(0xa0); //24C02写设备地址
I2CWaitAck(); //等待从机应答
I2CSendByte(add); //内存自己地址
I2CWaitAck(); //等待从机应答
I2CStart(); //IIC总线起始信号
I2CSendByte(0xa1); //24C02读设备地址
I2CWaitAck(); //等待从机应答
temp = I2CReceiveByte(); //读取目标数据
I2CSendAck(1); //产生非应答信号
I2CStop(); //IIC总线停止信号
return temp;
}
//将某个数据写入24c02:Write_24C02(地址,数据);
//将写入24c02的数据读出来:Read_24C02(地址);
//如若要断电后存储数据,则在对应数据更新时就可以将数据写入,后在main函数中while函数前读取。
底层驱动程序文件
iic.h
#ifndef _IIC_H
#define _IIC_H
void I2CStart(void);
void I2CStop(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(unsigned char ackbit);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
#endif
iic.c
#include "reg52.h"
#include "iic.h"
#include "intrins.h"
sbit sda=P2^1;
sbit scl=P2^0;
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
ds1302.c
#include "reg52.h"
#include "intrins.h"
#include "ds1302.h"
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3;
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#include "reg52.h"
bit init_ds18b20(void);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
#endif
onewire.c
#include "reg52.h"
#include "onewire.h"
sbit DQ = P1^4;