基于单片机的数字稳压电源

        

本设计基于单片机和AD转换器实现电压值的显示。采用ADC0804,实现由模拟电压转换到数字信号,通过单片机系统处理后,由LCD显示输入的电压的数值。测量范围为1.24~12V,精度大于98%。


 

仿真电路原理设计

 

 


软件代码设计

pwm占空比调节位于key.c文件,io口定义一般在各部分的头文件。

主函数:

#include <reg52.h>
#include "delay.h"
#include "key.h"
#include "lcd1602.h"
#include "pwm.h"
#include "adc.h"



unsigned int vol;

void main(void)
{
	timer0_Init();//初始化并输出pwm
	LCD_Init();		//LCD初始化
  LCD_ShowString(1,1,"voltage:");//在屏幕显示“voltage”

		
	while(1)
	{
		scanf_key();	//键盘扫描
		
		vol=ADC0804_Read(); //读取ad转换值
		Disp_vol(vol);			//在lcd1602上显示
		
		mdelay(50);			//间隔50ms刷新
	}

}

pwm部分:(源文件)

#include "pwm.h"


unsigned char times=0;
unsigned char duty_cycle=42;

void timer0_Init(void)
{
	TMOD=0x01;//定时器0工作方式1
	TH0=0xff;//(65536-10)/256;//赋初值定时
	TL0=0x91;//(65536-10)%256;//0.01ms
	EA=1;//开总中断
	ET0=1;//开定时器0中断
	TR0=1;//启动定时器0 

}

void tim0() interrupt 1
{
	TR0=0;//赋初值时,关闭定时器
	TH0=0xff;//(65536-10)/256;//赋初值定时
	TL0=0x91;//(65536-10)%256;//0.01ms
	TR0=1;//打开定时器
 
	times++;
	if(times>=100)  //1khz
	  times=0;   
	if(times<=duty_cycle)   //占空比%,可改         
	  pwm=1;  
	else pwm=0;
}

 (头文件)

#ifndef _PWM_H_
#define _PWM_H_

#include <reg52.h>
sbit pwm=P0^4;
void timer0_Init(void);


#endif

按键部分:(源文件)

#include "key.h"


//1V:6%  2V:13%  3V:20%  4V:27%   5V:35%  6V:42%
//7V:49%  8V:57%  9V:64%  10V:72% 11V:79%  12V:87%  
unsigned int percentage[12]={6,13,20,27,35,42,49,57,64,72,79,86};
unsigned int i=5;			//初始为6V
extern unsigned char duty_cycle;

void scanf_key()
{	
	if(i>=11 || i<0)	{i=0;}
	
			if(key_up==0 || key_down==0)
			{
				mdelay(20);
				if(key_up==0 || key_down==0)
				{
							if(key_up==0) 
							{
									while(!key_up);
								 duty_cycle=percentage[++i];								
							}		
							
							else if(key_down==0)
							{	
									while(!key_down);	
								 duty_cycle=percentage[--i];		
							}		
					}
				}	
}

(头文件)

#ifndef _KEY_H_
#define _KEY_H_

#include <reg52.h>
#include "pwm.h"
#include "delay.h"

sbit key_up=P3^2;
sbit key_down=P3^3;

void scanf_key();

#endif

adc部分:

#include "adc.h"


unsigned int ADC0804_Read(void)
{
	unsigned int adtemp=0;
	ADC0804_Port = 0xff;
	ADC0804_WR = 0;
	delay(200);
	ADC0804_WR = 1;
	delay(1000);
	ADC0804_RD = 0;
  delay(200);
	adtemp=ADC0804_Port*5.88235;
	return adtemp;
	ADC0804_RD = 1;
}
#ifndef _ADC_H
#define _ADC_H_


#include "delay.h"
#include "lcd1602.h"

//sbit ADC0804_CS  = P3^5;//ADC_CS低电平有效
sbit ADC0804_WR  = P3^6;//ADC_WR低电平有效
sbit ADC0804_RD  = P3^7;//ADC_RD低电平有效
#define ADC0804_Port P1

unsigned int ADC0804_Read(void);//ADC0804读取数据0-255

#endif

delay部分:

#include "delay.h"



void delay(unsigned char x)
{	
		while(x--);
}



void mdelay(unsigned int ms)
{
	unsigned int i;
	for(i=0;i<ms;i++)
	{
			Timer1Init();
	}


}

void Timer1Init(void)		//1毫秒@11.0592MHz
{
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x10;		//设置定时器模式
	TL1 = 0x66;		//设置定时初值
	TH1 = 0xFC;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
}

//12MHz调用可延时1ms
void LCD_Delay()
{
    unsigned char i, j;
 
    i = 2;
    j = 239;
    do
    {
        while (--j);
    } while (--i);
}
#ifndef _DELAY_H_
#define _DELAY_H_

#include <reg52.h>

void delay(unsigned char x);
void Timer1Init(void);
void mdelay(unsigned int ms);
void LCD_Delay();
#endif

LCD1602部分:

#include "lcd1602.h"



/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
    LCD_RS=0;
    LCD_RW=0;
    LCD_DataPort=Command;
    LCD_EN=1;
    LCD_Delay();
    LCD_EN=0;
    LCD_Delay();
}
 
/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)
{
    LCD_RS=1;
    LCD_RW=0;
    LCD_DataPort=Data;
    LCD_EN=1;
    LCD_Delay();
    LCD_EN=0;
    LCD_Delay();
}
 
/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
    if(Line==1)
    {
        LCD_WriteCommand(0x80|(Column-1));
    }
    else if(Line==2)
    {
        LCD_WriteCommand(0x80|(Column-1+0x40));
    }
}
 
/**
  * @brief  LCD1602初始化函数
  * @param  无
  * @retval 无
  */
void LCD_Init()
{
    LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
    LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
    LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
    LCD_WriteCommand(0x01);//光标复位,清屏
}
 
/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
    LCD_SetCursor(Line,Column);
    LCD_WriteData(Char);
}
 
/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=0;String[i]!='\0';i++)
    {
        LCD_WriteData(String[i]);
    }
}
 
/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
    unsigned char i;
    int Result=1;
    for(i=0;i<Y;i++)
    {
        Result*=X;
    }
    return Result;
}
 
/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
    }
}
 
/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
    unsigned char i;
    unsigned int Number1;
    LCD_SetCursor(Line,Column);
    if(Number>=0)
    {
        LCD_WriteData('+');
        Number1=Number;
    }
    else
    {
        LCD_WriteData('-');
        Number1=-Number;
    }
    for(i=Length;i>0;i--)
    {
        LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
    }
}
 
/**
  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFF
  * @param  Length 要显示数字的长度,范围:1~4
  * @retval 无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i,SingleNumber;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        SingleNumber=Number/LCD_Pow(16,i-1)%16;
        if(SingleNumber<10)
        {
            LCD_WriteData(SingleNumber+'0');
        }
        else
        {
            LCD_WriteData(SingleNumber-10+'A');
        }
    }
}
 
/**
  * @brief  在LCD1602指定位置开始以二进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
    }
}

/*显示电压*/
void Disp_vol(unsigned int VolValue)
{
	if(VolValue<1000)
	{
				uchar i;
			 char NumCode[5];
			NumCode[0]=VolValue/100;
			NumCode[1]='.'-0x30;
			NumCode[2]=VolValue%100/10;
			NumCode[3]=VolValue%10;
			NumCode[4]='V'-0x30;
			for(i=0;i<5;i++)
			{
				LCD_Disp(0,8+i,0x30+NumCode[i]);	
			}
	}
	else
	{
			uchar i;
			 char NumCode[6];
			NumCode[0]=VolValue/1000;
			NumCode[1]=VolValue/100%10;
			NumCode[2]='.'-0x30;
			NumCode[3]=VolValue%100/10;
			NumCode[4]=VolValue%10;
			NumCode[5]='V'-0x30;
			for(i=0;i<5;i++)
			{
				LCD_Disp(0,8+i,0x30+NumCode[i]);	
			}
	}
}

//数据显示
void LCD_Disp(uchar i,uchar j,uchar ch)
{
	uchar addr;
	if(i==0)addr=0x80+j;
	else    addr=0xc0+j;
	LCD_WriteCommand(addr);
	LCD_WriteData(ch);
}

#ifndef _LCD1602_H_
#define _LCD1602_H_

#include <reg52.h>
#include "delay.h"
#define  uchar unsigned char
	

 //引脚配置:
sbit LCD_RS=P0^5;
sbit LCD_RW=P0^6;
sbit LCD_EN=P0^7;
#define LCD_DataPort P2

//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void Disp_vol(unsigned int VolValue);
void LCD_Disp(uchar i,uchar j,uchar ch);

#endif

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无問.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值