A50 - 基于51单片机的太阳能充电路灯设计

任务

本文以太阳能路灯设计为例,针对太阳能路灯的优势以及发展背景,对太阳能路灯的基本原理和构成进行介绍。根据对太阳能电池板、蓄电池、控制器芯片等部件的方案论证。最终确定利用光伏发电由太阳能电池板以及蓄电池提供电能支持,在控制器的作用下,对时间显示模块以及LED驱动模块进行控制。通过对太阳能路灯的调试以及测试,最终的太阳能路灯具有安全性高、易于维修、不会造成任何污染以及自动化的特点。

实物图

A50 - 基于51单片机的太阳能充电路灯设计_第1张图片

原理设计

A50 - 基于51单片机的太阳能充电路灯设计_第2张图片
A50 - 基于51单片机的太阳能充电路灯设计_第3张图片
A50 - 基于51单片机的太阳能充电路灯设计_第4张图片
A50 - 基于51单片机的太阳能充电路灯设计_第5张图片

充放电模块

本装置采用太阳能发电,通过涓流对电池模组进行充电。电池模组进行电源输出,本次系统实物模拟采用的是3.7V输出的锂电池,因系统需要5V电压,故而采用了一个升压模组,将电池输出的3.7V电压转化为5V后再对系统进行供电,如图4-3所示为系统的电源输出电路,如图4-4所示为本次采用的升压模块电路图。
A50 - 基于51单片机的太阳能充电路灯设计_第6张图片

源代码

/*******************************************************************************

\* 文件名称:基于51单片机的太阳能充电路灯设计

\* 实验目的:1.

\* 2.

\* 程序说明:定制可联系Q:2772272579;@: itworkstation@ hotmail.com

\* 日期版本:本项目已分享全部代码,熟悉使用单片机的可做参考代码。可定制。

*******************************************************************************/
#include
#include
/*******************************定义全局变量********************************/
unsigned char data1;  //AD转换值
long Value;           //光照强度值
unsigned int baojing=300;  //开灯阀值
/******************引脚定义********************/
sbit bADcs=P1^3;//ADC0832 引脚定义
sbit bADcl=P1^4;
sbit bADda=P1^5;
sbit  key1 = P3^7;//加键
sbit  key2 = P3^6;//减键
sbit  led = P1^6; //LED灯控制引脚
/*******************************函数声明********************************/
unsigned char IntToString(unsigned char *str, int dat);	 	//数字转字符串函数
extern void InitLcd1602();	//液晶初始化函数
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str); //液晶显示字符串函数
/*******************延时函数*******************/
void Delay_Ms (unsigned int a)
{
	unsigned int i;
	while( a-- != 0)
	{
		for(i = 0; i < 600; i++);
	}
}
 /**********模数转换,光照检测子程序****************/ 
long kssj()   //开始收集
 {
   unsigned char i;

     bADcs = 0;//当ADC0832未工作时其CS输入端应为高电平,此时芯片禁用.
	 bADcl=0;
	 bADda=1;
	 bADcl=1;
	 bADcl=0;//i down
	 bADda=1;
	 bADcl=1;
	 bADcl=0;	//   2 down
	 bADda=0;
	 bADcl=1;
	 bADcl=0;	//   3 down
	 bADda=1;
	 bADcl=1;
	 bADcl=0;	//   4 down
	 for(i=8;i>0;i--)
	 	{
		
	 	data1<<=1;
	 	bADcl=0;
		bADcl=1;
		if(bADda==1) data1|=0x01;
		   	bADda=1;
	 	}
		 bADcs=1;
	  if(data1!=128)
	  {
	    Value=500-data1*1.96;	//ADC转换器的分辨率是255,转换成500要乘以1.96 得出A。   然后由于电路中光照越强A越小,所以再让500-A。
	
	  }	      	   
	   return Value;
 }
 /*****************按键扫描子程序*******************************/
void Key_set_scan()
{    
   unsigned char buff[5];//设置值 	
	if(key1==0)	  //加键按下
	{
	   Delay_Ms(10);    //延时消抖
		if(key1==0)
		{  
		  // while(!key1);
		   baojing++;		//开灯阀值加1
		   if(baojing>=500) baojing = 500;	//最大为500
		    buff[0] = baojing/100+0x30;		//获取开灯阀值百位,并转换为字符
            buff[1] = baojing%100/10+0x30;	//十位
            buff[2] = baojing%10+0x30;		//个位
            buff[3] = '\0';				    //结束符
            LcdShowStr(4, 1,buff);			//液晶显示开灯阀值		  
		}
	}	
	if(key2==0)	   //减键按下
	{
	   Delay_Ms(10); //延时消抖
		if(key2==0)
		{  
		  // while(!key2);
		   baojing--;	  //开灯阀值减1
		   if(baojing<=0) baojing = 0;	//最小为0
		     buff[0] = baojing/100+0x30;  	//百位
            buff[1] = baojing%100/10+0x30;	//十位
            buff[2] = baojing%10+0x30;		//个位
            buff[3] = '\0';					//结束符
            LcdShowStr(4, 1,buff);			//液晶显示开灯阀值		  
		}
	}		 
}
/*------------------------------------------------
                    系统主程序
------------------------------------------------*/
void main()
{
  unsigned char str_yw[12];//光照强度显示缓存
  InitLcd1602();     //初始化液晶
  LcdShowStr(0, 0,"Light:   Lx");	//显示初始界面	光照单位勒克斯(lux或lx)
  LcdShowStr(0, 1,"Set:300Lx");	   //显示初始界面
  while(1)
 {
   
   Key_set_scan(); //按键扫描 
   kssj();  //模数转换,采集检测光照强度
   str_yw[0] = Value/100+0x30;	  //获取光照值百位,并转换为字符
   str_yw[1] = Value%100/10+0x30; //十位
   str_yw[2] = Value%10+0x30;	  //个位
   str_yw[3] = '\0';			  //结束符
   LcdShowStr(6, 0,str_yw);    //显示检测到的光照强度

   if(Value<=baojing) //光照值小于开灯阀值
	led = 0 ;	     //LED灯亮
   else
    led = 1;	     //LED灯灭 
   Delay_Ms(10);//延时防止刷新太快
 }
}
/* 整型数转换为字符串,str-字符串指针,dat-待转换数,返回值-字符串长度 */
unsigned char IntToString(unsigned char *str, int dat)
{
    signed char i = 0;
    unsigned char len = 0;
    unsigned char buf[6];
    
    if (dat < 0)  //如果为负数,首先
	
    {
        dat = -dat;
        *str++ = '-';
        len++;
    }
    do {          //先转换为低位在前的十进制数组
        buf[i++] = dat % 10;
        dat /= 10;
    } while (dat > 0);
    len += i;     //i最后的值就是有效字符的个数
    while (i-- > 0)   //将数组值转换为ASCII码反向拷贝到接收指针上
    {
        *str++ = buf[i] + '0';
    }

    *str = '\0';  //添加字符串结束符
    
    return len;   //返回字符串长度
}

LCD1602液晶驱动

#include 

#define LCD1602_DB  P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E  = P1^2;

/* 等待液晶准备好 */
void LcdWaitReady()
{
    unsigned char sta;
    
    LCD1602_DB = 0xFF;
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    do {
        LCD1602_E = 1;
        sta = LCD1602_DB; //读取状态字
        LCD1602_E = 0;
    } while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{
    LcdWaitReady();
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_DB = cmd;
    LCD1602_E  = 1;
    LCD1602_E  = 0;
}
/* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{
    LcdWaitReady();
    LCD1602_RS = 1;
    LCD1602_RW = 0;
    LCD1602_DB = dat;
    LCD1602_E  = 1;
    LCD1602_E  = 0;
}
/* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
void LcdSetCursor(unsigned char x, unsigned char y)
{
    unsigned char addr;
    
    if (y == 0)  //由输入的屏幕坐标计算显示RAM的地址
        addr = 0x00 + x;  //第一行字符地址从0x00起始
    else
        addr = 0x40 + x;  //第二行字符地址从0x40起始
    LcdWriteCmd(addr | 0x80);  //设置RAM地址
}
/* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
    LcdSetCursor(x, y);   //设置起始地址
    while (*str != '\0')  //连续写入字符串数据,直到检测到结束符
    {
        LcdWriteDat(*str++);
    }
}
/* 初始化1602液晶 */
void InitLcd1602()
{
    LcdWriteCmd(0x38);  //16*2显示,5*7点阵,8位数据接口
    LcdWriteCmd(0x0C);  //显示器开,光标关闭
    LcdWriteCmd(0x06);  //文字不动,地址自动+1
    LcdWriteCmd(0x01);  //清屏
}

你可能感兴趣的:(单片机嵌入式,51单片机,单片机,stm32)