揽江楼一楼在装修
夜里熬到了两点左右,早上九点多起来,状态比较低迷,有点困的状态持续到了现在14:48,发现小蜜蜂老师的微信公众号进行了一波更新,而且基本上都是凌晨更新的,有被激励到,来了点工作的感觉(其实也是因为迷糊够了醒困了),废话不多说,把相关内容整理整理
目录
【进阶01】灯光闪烁与数码管计数
【进阶02】长按与短按控制数码管显示
【进阶03】24C02的基本读写操作
【进阶04】24C02存储按键触发次数
【进阶05】采样光敏电阻与可调电阻的电压
【进阶06】基于PCF8591的DAC模拟电压输出
【特训案例1】基于PCF8591的智能照明控制器
【特训案例2】DS18B20温度传感器数据采样与显示
【底层驱动代码移植与应用】
【进阶01】灯光闪烁与数码管计数
这个主要是解决LED和数码管冲突问题,对锁存器初始化的写法加上了所有锁存器都不选择的代码,更好的可以避免不同操作之间的影响,并且先将要赋的值送到端口然后在打开锁存器
特训案例【进阶02】长按与短按控制数码管显示
#include "reg52.h"
sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L8 = P0^7;
unsigned char led_stat = 0xff;
unsigned char num1 = 0,num2 = 0;
unsigned char code smg_data[] = {0xc0,0xf9,0xA4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
void SMG_Display_Data(void);//1.简单延时
void delay(unsigned int t)
{
while(t--);
}
void Delay_s(unsigned int t)
{
while(t--)
{
SMG_Display_Data(); //在延时期间保持数码管刷新
}
}
void Init_74HC138(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;//所有锁存器不选择
}
P2 = (P2 & 0x1f) | 0x00;//所有锁存器不选择
}
void SMG_DisplayBit(unsigned char pos,unsigned char dat)//先输送内容,再打开响应的端口
{
P0 = (0x01 << pos);
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void SMG_All(unsigned char dat)
{
P0 = 0xff;
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void Init_System()
{
P0 = 0xff;
Init_74HC138(4);
P0 = 0x00;
Init_74HC138(5);
SMG_All(0xff);
}
void SMG_Display_Data(void)
{
SMG_DisplayBit(0,smg_data[num1]);
delay(200);
SMG_DisplayBit(1,0xff);
delay(200);
SMG_DisplayBit(2,0xff);
delay(200);
SMG_DisplayBit(3,0xff);
delay(200);
SMG_DisplayBit(4,0xff);
delay(200);
SMG_DisplayBit(5,0xff);
delay(200);
SMG_DisplayBit(6,smg_data[num2/10]);
delay(200);
SMG_DisplayBit(7,smg_data[num2%10]);
delay(200);
SMG_All(0xff);
delay(200);
}
void Led()
{
led_stat &= ~0x80; //L8电亮
P0 = led_stat;
Init_74HC138(4);
Delay_s(200); //在进行LED操作的时候也对数码管进行刷新
led_stat |= 0x80; //熄灭
P0 = led_stat;
Init_74HC138(4);
Delay_s(200);
value2++;
if(value2 == 100)
{
value2 = 0;
}
//L1 和L2 灯同时翻转
if((led_stat & 0x03) == 0x03)
{
led_stat &= ~0x03;
}
else
{
led_stat |= 0x03;
}
P0 = led_stat;
Init_74HC138(4);
value1++;
if(value1 > 9)
{
value1 = 0;
}
}
void main(void)
{
Init_System();
while(1)
{
Led();
SMG_Display_Data();
}
}
【进阶02】长按与短按控制数码管显示
之前一直没学长按短按,但是既然小蜜蜂老师写了这个,就学一下,然后看完老师给出的代码恍然大悟,原来就是一个定时器就搞定了呀!这下考到也不担心了
#include "reg52.h"
sbit S4 = P3^3;
unsigned char count = 0,press = 0,num =28; //计时,按键长按标志,数值
unsigned char code smg_data[18]={0xc0,0xf9,
0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f}; //段码
void delay(unsigned int t)
{
while(t--);
}
void Init_74HC138(unsigned char channel)
{
switch(channel)
{
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;
case 0:P2 = (P2 & 0x1f) | 0x00;break;
}
P2 = (P2 & 0x1f) | 0x00;
}
void SMG_All(unsigned char dat)
{
P0 = 0xff;
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
P0 = (0x01 << pos);
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void SMG_Display_Data()
{
SMG_DisplayBit(6,smg_data[value/10]);
delay(200);
SMG_DisplayBit(6,0xff);
delay(200);
SMG_DisplayBit(7,smg_data[value%10]);
delay(200);
SMG_DisplayBit(7,0xff);
SMG_All(0xff);
delay(200);
}
void Init_System(void)
{
P0 = 0xff;
Init_74HC138(4);
P0 = 0x00;
Init_74HC138(5);
SMG_All(0xff);
}
void Scan_Keys()
{
if(S4 == 0)
{
delay(1000); //去抖动处理
if(S4 == 0) //确认为按下信号
{
count = 0; //时间计数变量清0
press = 1; //标志按键按下状态
while(S4 == 0) //等待按键松开
{
SMG_Display_Data(); //在按下期间保持数码管正常显示
}
press = 0; //标志按键松开状态
if(count > 100) //按下时间大于1秒,长按
{
num = 0; //数码管计数清除为00
}
else //按下时间小于1秒,短按
{
num++; //数码管计数加1
if(num == 100)
{
num = 0; //计数超出最大值99后恢复00
}
}
}
}
}
void Init_Timer()
{
TMOD = 0x01;
TH0 =(65535-10000)/256; //10ms
TL0 =(65535-10000)%256;
ET0 = 1;
TR0 = 1;
EA = 1;
}
void main(void)
{
Init_System();
Init_Timer();
while(1)
{
Scan_Keys();
SMG_Display_Data();
}
}
void Server_Timer0() interrupt 1
{
TH0 = (65535-10000)/256;
TL0 = (65535-10000)%256;
if(press==1)
{
count++;
}
}
【进阶03】24C02的基本读写操作
#include "reg52.h"
#include "iic.h"
unsigned char dat1=0,dat2=0,dat3=0;
unsigned char code smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90};
void delay(unsigned int t)
{
while(t--);
}
void Init_74HC138(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;
case 0:P2 = (P2 & 0x1f) | 0x00;break;
}
P2 = (P2 & 0x1f) | 0x00;
}
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
P0 = (0x01 << pos);
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void SMG_Close()
{
P0 = 0xff;
Init_74HC138(6);
P0 = 0xff;
Init_74HC138(7);
}
void Init_System()
{
Init_74HC138(0);
P0 = 0x00;
Init_74HC138(5);
P0 = 0xff;
Init_74HC138(4);
}
void SMG_Display_Data()
{
SMG_DisplayBit(0,smg_data[dat1/10]);
delay(200);
SMG_DisplayBit(1,smg_data[dat1%10]);
delay(200);
SMG_DisplayBit(2,0xbf);
delay(200);
SMG_DisplayBit(3,smg_data[dat2/10]);
delay(200);
SMG_DisplayBit(4,smg_data[dat2%10]);
delay(200);
SMG_DisplayBit(5,0xbf);
delay(200);
SMG_DisplayBit(6,smg_data[dat3/10]);
delay(200);
SMG_DisplayBit(7,smg_data[dat3%10]);
delay(200);
SMG_Close();
delay(200);
}
AT24c02单字节写
void AT24C02_Write(unsigned char addr,unsigned char dat)
{
IIC_Start(); //起始信号
IIC_SendByte(0xa0); //EEPROM的写设备地址
IIC_WaitAck(); //等待从机应答
IIC_SendByte(addr); //内存单元地址
IIC_WaitAck(); //等待从机应答
IIC_SendByte(dat); //内存写入数据
IIC_WaitAck(); //等待从机应答
IIC_Stop(); //停止信号
}
//AT24C02数据读
unsigned char AT24C02_Read(unsigned char addr)
{
unsigned char tmp = 0;
//首先,进行一个伪写操作
IIC_Start(); //起始信号
IIC_SendByte(0xa0); //EEPROM的写设备地址
IIC_WaitAck(); //等待从机应答
IIC_SendByte(addr); //内存单元地址
IIC_WaitAck(); //等待从机应答
//然后,开始字节读操作
IIC_Start(); //起始信号
IIC_SendByte(0xa1); //EEPROM的读设备地址
IIC_WaitAck(); //等待从机应答
tmp = IIC_RecByte(); //读取内存中的数据
IIC_SendAck(1); //产生非应答信号
IIC_Stop(); //停止信号
return tmp;
}
ATC02读取与写入
void Read_Write_Data(void)
{
//先读取数据
dat1 = AT24C02_Read(0x01);
dat2 = AT24C02_Read(0x03);
dat3 = AT24C02_Read(0x05);
dat1 = dat1 +1;
dat2 = dat2 +2;
dat3 = dat3 + 3 ;
if( dat1 > 10)
{
dat1 = 0;
}
if(dat2 > 20)
{
dat2 = 0;
}
if(dat3 > 30)
{
dat3 = 0;
}
AT24C02_Write(0x01,dat1);
delay(1000);
AT24C02_Write(0x03,dat2);
delay(1000);
AT24C02_Write(0x05,dat3);
delay(1000);
}
void main(void)
{
Init_System();
Read_Write_Data();
while(1)
{
SMG_Display_Data();
}
}
【进阶04】24C02存储按键触发次数
#include "iic.h"
#include "reg52.h"
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
unsigned char dat1 = 0,dat2 = 0,dat3 = 0;
unsigned char code smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90};
void delay(unsigned int t)
{
while(t--);
}
void Init_74HC138(unsigned char channel)
{
switch(channel)
{
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;
case 0:P2 = (P2 & 0x1f) | 0x00;break;
}
P2 = (P2 & 0x1f) | 0x00;
}
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
P0 = (0x01 << pos);
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void SMG_All(unsigned char dat)
{
P0 = 0xff;
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void Init_System()
{
P0 = 0xff;
Init_74HC138(4);
P0 = 0x00;
Init_74HC138(5);
SMG_All(0xff);
}
void SMG_Display_Data()
{
SMG_DisplayBit(0,smg_data[dat1/10]);
delay(200);
SMG_DisplayBit(1,smg_data[dat1%10]);
delay(200);
SMG_DisplayBit(2,0xbf);
delay(200);
SMG_DisplayBit(3,smg_data[dat2/10]);
delay(200);
SMG_DisplayBit(4,smg_data[dat2%10]);
delay(200);
SMG_DisplayBit(5,0xbf);
delay(200);
SMG_DisplayBit(6,smg_data[dat3/10]);
delay(200);
SMG_DisplayBit(7,smg_data[dat3%10]);
delay(200);
SMG_All(0xff);
delay(200);
}
void AT24C02_Write(unsigned char addr,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
unsigned char AT24C02_Read(unsigned char addr)
{
unsigned char temp = 0;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return temp;
}
void Read_AT24C02_Init()
{
dat1 = AT24C02_Read(0x00);
delay(1000);
dat2 = AT24C02_Read(0x01);
delay(1000);
dat3 = AT24C02_Read(0x02);
delay(1000);
}
void Key_Scans()
{
if(S4 == 0)
{
delay(20);
if(S4 == 0)
{
dat1++;
if(dat1 > 13)
{
dat1 = 0;
}
AT24C02_Write(0x00,dat1);
}
}
else if(S5 == 0)
{
delay(20);
if(S5 == 0)
{
dat2++;
if(dat2 > 13)
{
dat2 = 0;
}
AT24C02_Write(0x01,dat2);
}
}
if(S6 == 0)
{
delay(20);
if(S6 == 0)
{
dat3++;
if(dat3 > 13)
{
dat3 = 0;
}
AT24C02_Write(0x02,dat3);
}
}
}
void main(void)
{
Init_System();
Read_AT24C02_Init();
while(1)
{
SMG_Display_Data() ;
Key_Scans();
}
}
【进阶05】采样光敏电阻与可调电阻的电压
#include "reg52.h"
#include "iic.h"
unsigned char adc1_value = 0; //AIN1的采样数据
float adc1_volt = 0; //AIN1的换算电压
unsigned int smg1_volt = 0; //AIN1的显示电压
unsigned char adc3_value = 0; //AIN3的采样数据
float adc3_volt = 0; //AIN3的换算电压
unsigned int smg3_volt = 0; //AIN3的显示电压
unsigned char code smg_data[18]={0xc0,0xf9,
0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
unsigned char code smg_data_dot[10]={0x40,0x79,
0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
void delay(unsigned int t)
{
while(t--);
}
void Init_74HC138(unsigned char channel)
{
switch(channel)
{
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;
case 0:P2 = (P2 & 0x1f) | 0x00;break;
}
P2 = (P2 & 0x1f) | 0x00;
}
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
P0 = (0x01 << pos);
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void DisplaySMG_ADC()
{
SMG_DisplayBit(0,smg_data_dot[smg1_volt/100]);
delay(200);
SMG_DisplayBit(0,0xff);
delay(200);
SMG_DisplayBit(1,smg_data[smg1_volt/10%10]);
delay(200);
SMG_DisplayBit(1,0xff);
delay(200);
SMG_DisplayBit(2,smg_data[smg1_volt%10]);
delay(200);
SMG_DisplayBit(2,0xff);
delay(200);
SMG_DisplayBit(5,smg_data_dot[smg3_volt/100]);
delay(200);
SMG_DisplayBit(5,0xff);
SMG_DisplayBit(6,smg_data[smg3_volt/10%10]);
delay(200);
SMG_DisplayBit(6,0xff);
delay(200);
SMG_DisplayBit(7,smg_data[smg3_volt%10]);
delay(200);
SMG_DisplayBit(7,0xff);
delay(200);
SMG_All(0xff);
delay(200);
}
unsigned char Read_PCF8591_ADC(unsigned char ain)
{
unsigned char tmp;
IIC_Start();
IIC_SendByte(0x90); //PCF8591的写设备地址
IIC_WaitAck();
if(ain == 1)
{
IIC_SendByte(0x01); //通道1,光敏电阻电压
}
else if(ain == 3)
{
IIC_SendByte(0x03); //通道3,可调电阻电压
}
IIC_WaitAck();
IIC_Stop();
DisplaySMG_ADC(); //等待电压转换完成
IIC_Start();
IIC_SendByte(0x91); //PCF8591的读设备地址
IIC_WaitAck();
tmp = IIC_RecByte(); //读出AD采样数据
IIC_SendAck(1); //产生非应答信号
IIC_Stop();
return tmp;
}
void Read_AIN1_AIN3()
{
adc1_value = Read_PCF8591_ADC(1);
adc1_volt = adc1_value * (5.0 / 255);
smg1_volt = adc1_volt * 100;
adc3_value = Read_PCF8591_ADC(3);
adc3_volt = adc3_value * (5.0 / 255);
smg3_volt = adc3_volt * 100;
}
void Init_System()
{
P0 = 0xff;
Init_74HC138(4);
P0 = 0x00;
Init_74HC138(5);
SMG_All(0xff);
}
void main()
{
Init_sys(); //系统初始化
while(1)
{
Read_AIN1_AIN3(); //循环采样电压
DisplaySMG_ADC(); //动态刷新数码管
}
}
【进阶06】基于PCF8591的DAC模拟电压输出
其实就是一个很简单的数码管、按键和某一个特殊模块的综合
#include "reg52.h"
#include "iic.h"
sbit S4 = P3^3;
unsigned char mode = 1; //输出模式
unsigned int volt_value = 0,ad_value = 0; //数码管显示电压、采样变量
unsigned char code smg_data[18]={0xc0,0xf9,
0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
unsigned char code smg_data_dot[10]={0x40,0x79,
0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
void delay(unsigned int t )
{
while(t--);
}
void Init_74HC138(unsigned char channel)
{
switch(channel)
{
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;
case 0:P2 = (P2 & 0x1f) | 0x00;break;
}
P2 = (P2 & 0x1f) | 0x00;
}
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
P0 = (0x01 << pos);
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void SMG_All(unsigned char dat)
{
P0 = 0xff;
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void SMG_Display_Data(void)
{
SMG_DisplayBit(0,0xbf);
delay(200);
SMG_DisplayBit(0,0xff);
delay(200);
SMG_DisplayBit(1,smg_data[mode]);
delay(200);
SMG_DisplayBit(1,0xff);
delay(200);
SMG_DisplayBit(2,0xbf);
delay(200);
SMG_DisplayBit(2,0xff);
delay(200);
SMG_DisplayBit(5,smg_data_dot[volt_value/100]);
delay(200);
SMG_DisplayBit(5,0xff);
delay(200);
SMG_DisplayBit(6,smg_data[volt_value/10%10]);
delay(200);
SMG_DisplayBit(6,0xff);
delay(200);
SMG_DisplayBit(7,smg_data[volt_value%10]);
delay(200);
SMG_DisplayBit(7,0xff);
delay(200);
SMG_All(0xff);
delay(200);
}
//PCF8591数据读取
void Read_ADC()
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
ad_value = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
volt_value = ad_value * (5.0/255)* 100;
}
void Read_DAC(float dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
void Init_System()
{
P0 = 0xff;
Init_74HC138(4);
P0 = 0x00;
Init_74HC138(5);
SMG_All(0xff);
}
void Key_Scans()
{
if(S4 == 0)
{
delay(20);
if(S4 == 0)
{
while(S4 == 0)
{
SMG_Display_Data();
}
if(mode == 1)
{
mode = 2;
Read_DAC(204);
volt_value = 4*100;break;
}
else if(mode == 2)
{
mode = 3;
}
else if(mode == 3)
{
mode = 1;
Read_DAC(102);
volt_value = 2*100;
}
}
}
}
void main(void)
{
Init_System();
while(1)
{
Key_Scans();
SMG_Display_Data();
}
}
【特训案例1】基于PCF8591的智能照明控制器
#include "reg52.h"
#include "iic.h"
sbit S4 = P3^3;
sbit S5 = P3^2;
unsigned char code SMG_NoDot[18]={0xc0,0xf9,
0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
unsigned char code SMG_Dot[10]={0x40,0x79,
0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned char adc_value = 0; //采样数据
float adc_volt = 0; //换算电压
unsigned int smg_volt = 0; //显示电压
unsigned char stat_led = 0xff; //定义LED灯当前状态
unsigned char level = 0; //灯光控制等级
void delay(unsigned int t )
{
while(t--);
}
void Init_74HC138(unsigned char channel)
{
switch(channel)
{
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;
case 0:P2 = (P2 & 0x1f) | 0x00;break;
}
P2 = (P2 & 0x1f) | 0x00;
}
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
P0 = (0x01 << pos);
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void SMG_All(unsigned char dat)
{
P0 = 0xff;
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void SMG_Display_Data()
{
SMG_DisplayBit(0,0xbf);
delay(200);
SMG_DisplayBit(0,0xff);
delay(200);
SMG_DisplayBit(1,SMG_NoDot[level]);
delay(200);
SMG_DisplayBit(1,0xff);
delay(200);
SMG_DisplayBit(2,0xbf);
delay(200);
SMG_DisplayBit(2,0xff);
delay(200);
SMG_DisplayBit(5,SMG_Dot[smg_volt / 100]);
delay(200);
SMG_DisplayBit(5,0xff);
delay(200);
SMG_DisplayBit(6,SMG_NoDot[(smg_volt / 10) % 10]);
delay(200);
SMG_DisplayBit(6,0xff);
delay(200);
SMG_DisplayBit(7,SMG_NoDot[smg_volt % 10]);
delay(200);
SMG_DisplayBit(7,0xff);
delay(200);
SMG_All(0xff);
delay(200);
}
//24C02单字节写入
void Write_24C02(unsigned char addr, unsigned char dat)
{
IIC_Start(); //起始信号
IIC_SendByte(0xa0); //EEPROM的写设备地址
IIC_WaitAck(); //等待从机应答
IIC_SendByte(addr); //内存单元地址
IIC_WaitAck(); //等待从机应答
IIC_SendByte(dat); //内存写入数据
IIC_WaitAck(); //等待从机应答
IIC_Stop(); //停止信号
}
//24C02单字节读取
unsigned char Read_24C02(unsigned char addr)
{
unsigned char tmp;
//首先,进行一个伪写操作
IIC_Start(); //起始信号
IIC_SendByte(0xa0); //EEPROM的写设备地址
IIC_WaitAck(); //等待从机应答
IIC_SendByte(addr); //内存单元地址
IIC_WaitAck(); //等待从机应答
//然后,开始字节读操作
IIC_Start(); //起始信号
IIC_SendByte(0xa1); //EEPROM的读设备地址
IIC_WaitAck(); //等待从机应答
tmp = IIC_RecByte(); //读取内存中的数据
IIC_SendAck(1); //产生非应答信号
IIC_Stop(); //停止信号
return tmp;
}
//PCF8591电压采样处理函数
void Read_PCF8591_AIN1()
{
IIC_Start();
IIC_SendByte(0x90); //PCF8591的写设备地址
IIC_WaitAck();
IIC_SendByte(0x01); //通道1,光敏电阻电压
IIC_WaitAck();
IIC_Stop();
DisplaySMG_Info(); //等待电压转换完成
IIC_Start();
IIC_SendByte(0x91); //PCF8591的读设备地址
IIC_WaitAck();
adc_value = IIC_RecByte(); //读出AD采样数据
IIC_SendAck(1); //产生非应答信号
IIC_Stop();
//将ADC采样到的数据换算成对应的电压值
adc_volt = adc_value * (5.0 / 255);
smg_volt = adc_volt * 100;
SMG_Display_Data();
}
//照明自动控制函数
void LED_Auto_Control()
{
Read_PCF8591_AIN1(); //获取当前光照电压
if(adc_volt > 4.0)
{
stat_led = 0xfe; //L1点亮
level = 1;
}
else if(adc_volt > 3.0)
{
stat_led = 0xfc; //L1至L2点亮
level = 2;
}
else if(adc_volt > 2.0)
{
stat_led = 0xf0; //L1至L4点亮
level = 3;
}
else if(adc_volt > 1.0)
{
stat_led = 0xc0; //L1至L6点亮
level = 4;
}
else
{
stat_led = 0x00; //L1至L8点亮
level = 5;
}
P0 = stat_led; //更新灯光控制数据
Init_74HC138(4); //控制LED灯
}
//保存当前控制数据
void Save_to_24C02()
{
Write_24C02(0x01, level);
DisplaySMG_Info();
Write_24C02(0x02, adc_value);
DisplaySMG_Info();
}
//读取历史控制数据
void Read_from_24C02()
{
level = Read_24C02(0x01);
adc_value = Read_24C02(0x02);
adc_volt = adc_value * (5.0 / 255);
smg_volt = adc_volt * 100;
}
//独立按键扫描处理
void Scan_Keys()
{
//按键S4的扫描处理
if(S4 == 0)
{
delay(100); //去抖动
if(S4 == 0)
{
Save_to_24C02(); //保存当前数据
while(S4 == 0) //松手检测
{
SMG_Display_Data();
}
}
}
//按键S5的扫描处理
if(S5 == 0)
{
delay(100); //去抖动
if(S5 == 0)
{
P0 = 0xff;
Init_74HC138(4); //关闭全部灯光
Read_from_24C02(); //读取历史数据
while(S5 == 0) //松手检测
{
SMG_Display_Data(); //显示历史数据
}
}
}
}
void Init_System()
{
P0 = 0xff;
Init_74HC138(4);
P0 = 0x00;
Init_74HC138(5);
SMG_All(0xff);
}
//主函数
void main()
{
Init_System(); //系统初始化
while(1)
{
Scan_Keys(); //扫描按键
LED_Auto_Control(); //照明自动控制
}
}
【特训案例2】DS18B20温度传感器数据采样与显示
若提供的DS18B20底层驱动的头文件是基于12T的89C52运行环境,则需要将底层驱动文件中的延时参数放大10倍
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
while(t--);
}
可修改为:
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
unsigned int n; //新定义一个延时参数
n = t * 10; //放大10倍延时参数
while(n--);
}
#include "reg52.h"
#include "onewire.h"
unsigned char code SMG_NoDot[18]={0xc0,0xf9,
0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
unsigned char code SMG_Dot[10]={0x40,0x79,
0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
float temp_ds18b20 = 0; //实际温度值
unsigned int smg_ds18b20 = 0; //数码管显示温度值
void delay(unsigned int t )
{
while(t--);
}
void Init_74HC138(unsigned char channel)
{
switch(channel)
{
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;
case 0:P2 = (P2 & 0x1f) | 0x00;break;
}
P2 = (P2 & 0x1f) | 0x00;
}
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
P0 = (0x01 << pos);
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void SMG_All(unsigned char dat)
{
P0 = 0xff;
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void Read_Dsiplay_DS18B20()
{
if(smg_ds18b20>99)
{
SMG_DisplayBit(5,SMG_NoDot[smg_ds18b20 / 100]);
delay(500);
SMG_DisplayBit(5,0xff); //消隐
}
SMG_DisplayBit(6,SMG_Dot[(smg_ds18b20 / 10) % 10]);
delay(200);
SMG_DisplayBit(6,0xff);
delay(200);
SMG_DisplayBit(7,SMG_NoDot[smg_ds18b20 % 10]);
delay(200);
SMG_DisplayBit(7,0xff);
delay(200);
SMG_All(0xff);
delay(200);
}
//==============DS18B20温度读出与显示==============
void Read_Dsiplay_DS18B20()
{
unsigned char LSB,MSB;
unsigned int temp = 0;
init_ds18b20(); //初始化DS18B20
Write_DS18B20(0xcc); //忽略ROM操作
Write_DS18B20(0x44); //启动温度转换
DisplaySMG_Temp();
init_ds18b20(); //初始化DS18B20
Write_DS18B20(0xcc); //忽略ROM操作
Write_DS18B20(0xbe); //读出内部存储器
LSB = Read_DS18B20(); //第0字节:温度低8位
MSB = Read_DS18B20(); //第1字节:温度高8位
init_ds18b20(); //初始化,停止读取
temp = MSB; //合成16位温度原始数据
temp = (temp << 8) | LSB;
if((temp & 0xf800) == 0x0000) //处理正温度
{
temp_ds18b20 = temp * 0.0625; //计算实际温度值
}
smg_ds18b20 = temp_ds18b20 * 10;
DisplaySMG_Temp();
}
void Init_System()
{
P0 = 0xff;
Init_74HC138(4);
P0 = 0x00;
Init_74HC138(5);
SMG_All(0xff);
}
void main()
{
Init_System();
while(1)
{
Read_Dsiplay_DS18B20();
}
}
【底层驱动代码移植与应用】
- DS18B20的单总线底层驱动代码:若提供的是52的,需要将时序*10,但要注意到底需要不需要进行修改
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;
}
时序修正后,该复位函数的代码是:
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(120);
DQ = 0;
Delay_OneWire(800);
DQ = 1;
Delay_OneWire(100);
initflag = DQ;
Delay_OneWire(50);
return initflag;
}
- 确认头文件是否完整