备战蓝桥杯单片机倒数第四天 小蜜蜂老师公众号更新内容

  • Post author:
  • Post category:其他


揽江楼一楼在装修

夜里熬到了两点左右,早上九点多起来,状态比较低迷,有点困的状态持续到了现在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;
}
  • 确认头文件是否完整



版权声明:本文为silver321原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。