关于单片机百叶窗控制板设计——入门

此项目通过Proteus软件仿真,证实程序可行性,顺带将上一次做的步进电机部分知识加入进去,继续进行练习。

实际项目也可通过购买相关电路模块,然后通过杜邦线连接来实现其功能。

注*:查找相关类似的即可。

 1.单片机最小系统(本次项目用的是C52单片机)

2.LED1602(显示)

3.PFC8591(AD/DA转换,用于将光敏信号采集和传送)

4.L293(电机驱动芯片)

5.DS18B20(温度采集)

原理图所示:

具体功能说明:手动/自动控制电机完成百叶窗动作,手动方式为按键,自动方式为光敏电阻检测后的反馈,来驱动电机。

主程序:

#include<reg52.h> 
#include<intrins.h>
#include"I2C.h"	
typedef unsigned int u16;	
typedef unsigned char u8;   //对系统默认数据类型进行重定义

#define LCD_PORT  P0
unsigned char  seg_buf[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共阳数码管显示当前值0-83

unsigned char Light_val=0;                //光强度
int real_tempure=0;		                    //实际温度
unsigned char  storage_temperature[10];	  //存储温度

sbit select = P3^2;           //手/自动切换
sbit LED = P1^7;	            
sbit IN1 = P1^5;	           
sbit IN2 = P1^6; 
sbit K2 = P3^3;			          //按键控制正反转
sbit K3 = P3^4;
sbit S1 = P3^6;	              //限位开关
sbit S2 = P3^7;
sbit DQ = P1^0;	            //测温
sbit RS = P2^0;               //1602引脚定义
sbit RW = P2^1;
sbit E = P2^2;


void  delay (u16 x)          //延迟函数,大约延时1ms
{
 u16 y,z;
  for (y = x; y>0; y--)
    for (z = 110; z>0; z--);
}

void write_com(u8 com)      //1602写
{
  RS = 0;
  RW = 0;
  E = 0;
  delay(2);
  LCD_PORT = com;
  delay(2);
  E = 1;
  delay(2);
  E = 0;
}

void write_date(u8 date)   
{
  RS = 1;
  RW = 0;
  E = 0;
  delay(2);
  LCD_PORT = date;
  E = 1;
  delay(2);
  E = 0;
}

void Cursor_XY (u8 x, u8 y)             //1602的光标位置定义
{
  if(y==0)
    write_com(0x80|x);
  if(y==1)
    write_com(0x80|(x-0x40));
}

void Print(u8 *str)                       //1602显示字符串
{
  while(*str!='\0')
  {
    write_date(*str);
    str++;
  }
}

void LCD_Print(u8 x, u8 y, u8 *str)       //1602在指定位置显示字符串
{
  Cursor_XY (x,y);
  Print(str);
}

void LCD_Print_num(u8 x, u8 y, u16 num)   //1602在指定位置显示数字
{
  u8 digital_position [6] = {0};
  digital_position [0] = num/100+'0';
  digital_position [1] = num%100/10+'0';
  digital_position [2] = num%10+'0';
  Cursor_XY (x,y);														  
  Print( digital_position );
}

void init_lcd1602()           //初始化1602
{ 
  E = 0;
  write_com(0x38);
  write_com(0x0c);
  write_com(0x06);
  write_com(0x01);
  write_com(0x80);
}

void transform(u8 *pt)	          //将采集到的温蒂显示出来
{
   const u8 code dotcode[4]={0,25,50,75};
   u8 x = 0x00,y = 0x00;
   u8 t[2];
   t[0] = *pt;
   pt++;
   t[1] = *pt;
   if (t[1]>0x07)                    //判断正负温度
   {
      storage_temperature[0]=0x2d;	 //0x2d为"-"的ASCII码   
	    t[1]=~t[1];			 
	    t[0]=~t[0]; 		 
	    x = t[0]+1;				 
	    t[0] = x;					 
	    if(x>255)                
	    t[1]++;				 
   }
   else storage_temperature[0] = 0x2b;	//0xfe为变"+"的ASCII码

   t[1]<<=4;		
   t[1]=t[1]&0x70;		
   x=t[0];					
   x>>=4;					
   x=x&0x0f;					
   t[1]=t[1]|x;			
   storage_temperature[1]=t[1]/100+0x30;		             

   if( storage_temperature[1]==0x30) storage_temperature[1]=' ';   //消影
   storage_temperature[2]=(t[1]%100)/10+0x30;				
   storage_temperature[3]=(t[1]%100)%10+0x30;	 			
   t[0]=t[0]&0x0c;							
   t[0]>>=2;								
   x=t[0];										
   y=dotcode[x];									
   storage_temperature[5]=y/10+0x30;							
   storage_temperature[6]=y%10+0x30;						
}

void delay_DS18B20(u16 i)
{
	while(i--);
}


void Init_DS18B20(void)          //DS18B20初始化
{
	 u8 x=0;
	 DQ = 1;          //复位
	 delay_DS18B20(8);  
	 DQ = 0;          
	 delay_DS18B20(80); 
	 DQ = 1;          
	 delay_DS18B20(14);
	 x=DQ;            
	 delay_DS18B20(20);
}

u8 DS18B20_read(void)             //DS18B20读字节
{
	u8 i=0;
	u8 dat = 0;
	for (i=8;i>0;i--)
	 {	  DQ = 1;delay_DS18B20(1);
		  DQ = 0; 
		  dat>>=1;
		  DQ = 1; 
		  if(DQ)
		  dat|=0x80;
		  delay_DS18B20(4);
	 }
 	return(dat);
}

void DS18B20_write(u8 dat)        //DS18B20写字节 
{
 	u8 i=0;
 	for (i=8; i>0; i--)
 	{	DQ = 1;delay_DS18B20(1);
  		DQ = 0;
 		DQ = dat&0x01;
    	delay_DS18B20(5);
 		DQ = 1;
    	dat>>=1;
 }
}


u8 *ReadTemperature()             //DS18B20读取当前温度 
{	u8 tt[2];
	Init_DS18B20();
	DS18B20_write(0xCC);    	
	DS18B20_write(0x4E);

	DS18B20_write(120);	
	DS18B20_write(-20);		
	DS18B20_write(0x3f);	

	delay_DS18B20(80);      
	Init_DS18B20();
	DS18B20_write(0xCC);    	
	DS18B20_write(0x44); 

	delay_DS18B20(80);      
	Init_DS18B20();
	DS18B20_write(0xCC); 	
	DS18B20_write(0xBE); 
	delay_DS18B20(80);

	tt[0] = DS18B20_read();    	
	tt[1] = DS18B20_read();   	

	return(tt);
}			

void EX_Init()            //外部中断初始化
{
  EA = 1;
  IT0 = 1;
  EX0 = 1;
}

u8 GetADCValue(u8 chn)   //通过IIC读取AD数值
{
	u8 val;

	I2CStart();
	if(!I2CWrite(0x48<<1))
	{
		I2CStop();
		return 0;
	}
	I2CWrite(0x40 | chn);
	I2CStart();
	I2CWrite(0x48<<1 | 0x01);
	I2CReadACK();
	val = I2CReadNAK();
	I2CStop();

	return val;
}

/lcd指定位置显示数字
void LCD_Print_tempure(u8 x, u8 y, u16 num)
{
  u8 digital_position[6]={0};
  if(num<0)	//负温度
  {
	 digital_position[0] = '-';			 
	 digital_position[1] = num%1000/100+'0';
	 digital_position[2] = num%100/10+'0';
	 digital_position[3] ='.';
	 digital_position[4] = num%10+'0';
  }
  else	    //正温度
  {
	digital_position[0]= num/1000+'0';			 
	digital_position[1]= num%1000/100+'0';
	digital_position[2]= num%100/10+'0';
	digital_position[3]='.';
	digital_position[4]= num%10+'0';
  }

  Cursor_XY (x,y);														  
  Print(digital_position);
}

void Control_motor()          //根据温度和光照控制电机
{
	if(flag==0)	                //自动模式
	{
	  S1 = 1;
	  S2 = 1;
	  LED = 0;
	  _nop_();
	 if((Light_val<30)&&(real_tempure<200)&&(S1==1)) 
	  {IN1 = 1;IN2 = 0;}			
	 else if(((Light_val>50)||(real_tempure>300))&&(S2==1)) 
	  {IN1 = 0;IN2 = 1;}		
	 else
	  {IN1 = 1;IN2 = 1;}
	}
	if(flag==1)	 
	{
	  K3 = 1;
	  K2 = 1;
	  S1 = 1;
	  S2 = 1;
	  LED = 1;	  
	  if((K2==0)&&(S1==1))   
	  {IN1 = 0;IN2 = 1;while(!K2);}
	  if((K3==0)&&(S2==1))
	  {IN1 = 1;IN2 = 0;while(!K3);}
	  else
	  {IN1 = 1;IN2 = 1;}	 
	}
}

u16 Get_Temperature()              //读取温度
{	
	u8 *pt;				
	u16 real_tempure; 
	pt=ReadTemperature();		 
	transform(pt);

   real_tempure = ((storage_temperature[2]-0x30)*10)+storage_temperature[3]-0x30;
   real_tempure =(real_tempure*10) + storage_temperature[5]-0x30; 
   if(storage_temperature[1]==0x31)	 
   {
   	  real_tempure+=1000;
   }
   if(storage_temperature[0]==0x2d)	
   {
		  real_tempure*=-1;
   }
   return real_tempure;
}

void Int0() interrupt 0        //中断函数   
{
  select=~select;  //模式变换
}

void main()			      //主函数
{
  
  EX_Init();  
  init_lcd1602(); 
  Init_DS18B20();
  LCD_Print(0,0,"Light:");
  LCD_Print(0,1,"Temapure:");
  while(1)
  {
  	Light_val=(char)(GetADCValue(0)/3);  
	real_tempure=Get_Temperature();
    LCD_Print_tempure(9,1,real_tempure); 
    LCD_Print_num(6,0,Light_val);	
    Control_motor();	
  } 
}

通讯程序:

#include <reg52.h>
#include <intrins.h>
#include "I2C.h"
#define I2CDelay()  {_nop_();_nop_();_nop_();_nop_();}

void I2CStart()     //产生总线起始信号
{
    I2C_SDA = 1; 
    I2C_SCL = 1;
    I2CDelay();
    I2C_SDA = 0; 
    I2CDelay();
    I2C_SCL = 0; 
}

void I2CStop()      //产生总线停止信号
{
    I2C_SCL = 0;
    I2C_SDA = 0;
    I2CDelay();
    I2C_SCL = 1; 
    I2CDelay();
    I2C_SDA = 1; 
    I2CDelay();
}

bit I2CWrite(unsigned char dat)     //I2C总线写操作
{
  bit ack;  
  unsigned char mask;  

    for (mask=0x80; mask!=0; mask>>=1) 
    {
      if ((mask&dat) == 0)  
       I2C_SDA = 0;
      else
       I2C_SDA = 1;
       I2CDelay();
       I2C_SCL = 1;         
       I2CDelay();
       I2C_SCL = 0;          
    }
  I2C_SDA = 1;  
  I2CDelay();
  I2C_SCL = 1;   
  ack = I2C_SDA; 
  I2CDelay();
  I2C_SCL = 0;   

  return (~ack); 
}

unsigned char I2CReadNAK()    //I2C总线读操作
{
  unsigned char mask;
  unsigned char dat;

  I2C_SDA = 1; 
    for (mask=0x80; mask!=0; mask>>=1) 
    {
      I2CDelay();
      I2C_SCL = 1;     
      if(I2C_SDA == 0)  
        dat &= ~mask; 
      else
        dat |= mask;  
        I2CDelay();
        I2C_SCL = 0;      
    }
  I2C_SDA = 1;   
  I2CDelay();
  I2C_SCL = 1;  
  I2CDelay();
  I2C_SCL = 0;   

  return dat;
}

unsigned char I2CReadACK()      //I2C总线读操作
{
  unsigned char mask;
  unsigned char dat;

  I2C_SDA = 1;  
    for (mask=0x80; mask!=0; mask>>=1) 
    {
      I2CDelay();
      I2C_SCL = 1;      
      if(I2C_SDA == 0)  
        dat &= ~mask; 
      else
        dat |= mask;  
        I2CDelay();
        I2C_SCL = 0;      
    }
  I2C_SDA = 0;   
  I2CDelay();
  I2C_SCL = 1;  
  I2CDelay();
  I2C_SCL = 0;   

  return dat;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值