|
最近心血来潮,想学学单片机,上淘宝买了些零件,来这里论坛看看,搞电源的挺多,都没有超声波电源的贴子,那我就做这个电源玩玩吧,希望能拉起一些话题来....好了,上图:
般了个八仙桌,老古董了,也没什么好工具,都摆上了 (原文件名:aa.jpg)
stc89c52单片机和dds芯片装到这个电脑电源的铁壳里,防止干扰. (原文件名:dds.jpg)
用实验板焊了个sg3525和igbt驱动板,dds的信号通过高速光偶输入到sg3525同步端 (原文件名:drv.jpg)
这个电脑电源的外壳还真不错,后面是写程序用的com口,一条电源线和1条频率输出线,频率跟踪还没写程序,所以还有些控制线没接出来 (原文件名:dds2.jpg)
变压器用普通电线绕的,要是有纱包线就好了,不知道谁能给我一些,呵呵 (原文件名:bc.jpg)
谐振电感也是用普通电线在塑料水管上绕的 (原文件名:llll.jpg)
谐振电容没有合适的,只好用了48颗0.22uf的突波吸收电容在实验板上焊,3并联合12串联,约0.04uf (原文件名:cccc.jpg)
下面那个胜利的频率发生器被我改装成频率计了,用来测量频率,示波器显示的是谐振波形,蓝色是电压,黄色是电流,不知道为什么不是同相位,有待大家讨论 (原文件名:pppp.jpg)
sg3525输出窄脉冲的时候电压波形(蓝色)不是正弦波,不知道有没有办法让小功率的时候也能输出正弦波呢 (原文件名:bbb.jpg)
功率管是两个igbt组成的半桥 (原文件名:gl.jpg)
频率跟踪还真难搞,用lm339做的采样整形,cd4013做相位识别,因为谐振不是同相位,还加了个CD4538单稳态电路来移动相位,终于可以输出谐振,频率偏高输出1,频率偏低输出0,我程序不怎么会搞,这个信号还没有接到单片机 (原文件名:fff.jpg)
黄色的波形就是那个电脑电源的外壳做的dds经过lm339整形后的同步脉冲信号 (原文件名:xxxxxxx.jpg)
超声波谐振的时候电流最小,频率偏高或偏低电流都会增大,电压也会增大,想写个程序自动跟踪电流的最小值,输出适合的频率,这个程序怎么写呢.........
===================================================主程序=============================================================
#include <reg52.h>
#include <tm1638.h>
#include <stc_eeprom.h>
sfr WDT_CONTR =0xe1; //看门狗寄存器地址
//#include <STRING.H>
//***********外部函数声明******************************************************
//extern void display(unsigned long n);//max7219显示函数
extern void ad9850_reset_serial();//振荡器初始化
extern void ad9850_wr_serial(unsigned char w0,double frequence);//频率设置
//***********全局变量********************************************************
unsigned long frequency=2000000; //输出频率,变量最大值99999999
//**********延时*******************************************************
void delayy(unsigned long i)
{
while(i-->0);
}
void updata()//更新显示器和频率合成器的数据并存入存储器
{
eeprom_write_4byte(0x2e00,frequency);
frequency=eeprom_read_4byte(0x2e00);
ad9850_wr_serial(0x00,frequency*2);//输出频率
tm1638_display(frequency);//显示频率
}
//**********主函数*********************************************************
void main()
{
unsigned char k;
//int i;
P0=0xff;
P1=0xff;
P2=0xff;
P3=0xff;
//WDT_CONTR=0x34; //启动看门狗
init_TM1638();//显示初始化
ad9850_reset_serial();//频率合成器初始化
frequency=eeprom_read_4byte(0x2e00); //读取频率值
updata();
//******************无限循环***********************************************************************
while(1)
{
k=0;
k=Read_key();//读取按钮
//while (Read_key()==k); // 这句话会引起干扰,待查证
switch(k)
{
case 0:
frequency=2000000;
updata();
Write_allLED(1);//输出指示灯状态
break;
case 1:
frequency=3500000;
updata();
Write_allLED(2);//输出指示灯状态
break;
case 2:
frequency-=10000;
updata();
Write_allLED(4);//输出指示灯状态
break;
case 3:
frequency+=10000;
updata();
Write_allLED(8);//输出指示灯状态
break;
case 4:
frequency-=100;
updata();
Write_allLED(16);//输出指示灯状态
break;
case 5:
frequency+=100;
updata();
Write_allLED(32);//输出指示灯状态
break;
case 6:
frequency-=10;
updata();
Write_allLED(64);//输出指示灯状态
break;
case 7:
frequency+=10;
updata();
Write_allLED(128);//输出指示灯状态
break;
}
delayy(1);
WDT_CONTR=0x34; //喂狗
}
}
====================================================dds频率合成器程序=============================================================
#include <reg51.h>
//#include <stdio.h>
//#include <intrins.h>
sbit ad9850_w_clk =P1^0; //P2.2口接ad9850的w_clk脚/PIN7
sbit ad9850_fq_up =P1^1; //P2.1口接ad9850的fq_up脚/PIN8
sbit ad9850_rest =P1^3; //P2.0口接ad9850的rest脚/PIN12
sbit ad9850_bit_data =P1^2; //P1.7口接ad9850的D7脚/PIN25
//***************************************************//
// ad9850复位(串行模式) //
//---------------------------------------------------//
void ad9850_reset_serial()
{
ad9850_w_clk=0;
ad9850_fq_up=0;
//rest信号
ad9850_rest=0;
ad9850_rest=1;
ad9850_rest=0;
//w_clk信号
ad9850_w_clk=0;
ad9850_w_clk=1;
ad9850_w_clk=0;
//fq_up信号
ad9850_fq_up=0;
ad9850_fq_up=1;
ad9850_fq_up=0;
}
//***************************************************//
// 向ad9850中写命令与数据(串行) //
//---------------------------------------------------//
void ad9850_wr_serial(unsigned char w0,double frequence)
{
unsigned char i,w;
long int y;
double x;
//计算频率的HEX值
x=4294967295/125;//适合125M晶振
frequence=frequence/100000000;
frequence=frequence*x;
y=frequence;
//写w4数据
w=(y>>=0);
for(i=0;i<8;i++)
{
ad9850_bit_data=(w>>i)&0x01;
ad9850_w_clk=1;
ad9850_w_clk=0;
}
//写w3数据
w=(y>>8);
for(i=0;i<8;i++)
{
ad9850_bit_data=(w>>i)&0x01;
ad9850_w_clk=1;
ad9850_w_clk=0;
}
//写w2数据
w=(y>>16);
for(i=0;i<8;i++)
{
ad9850_bit_data=(w>>i)&0x01;
ad9850_w_clk=1;
ad9850_w_clk=0;
}
//写w1数据
w=(y>>24);
for(i=0;i<8;i++)
{
ad9850_bit_data=(w>>i)&0x01;
ad9850_w_clk=1;
ad9850_w_clk=0;
}
//写w0数据
w=w0;
for(i=0;i<8;i++)
{
ad9850_bit_data=(w>>i)&0x01;
ad9850_w_clk=1;
ad9850_w_clk=0;
}
//移入始能
ad9850_fq_up=1;
ad9850_fq_up=0;
}
//***************************************************//
// 测试程序1000Hz //
//---------------------------------------------------//
/*
main()
{
P0=0x00;
P1=0x00;
P2=0x00;
P3=0x00;
//---------------------------------------------------//
//---------------------------------------------------//
//串行写1000Hz程序
ad9850_reset_serial();
ad9850_wr_serial(0x00,2000000);
//---------------------------------------------------//
while(1)
{
}
}
*/
========================================================stc89c52内部eeprom存储器读写程序==============================================
// stc单片机EEPROM读写(二)
sfr isp_data=0xe2;
sfr isp_addrh=0xe3;
sfr isp_addrl=0xe4;
sfr isp_cmd=0xe5;
sfr isp_trig=0xe6;
sfr isp_contr=0xe7;
unsigned char eeprom_read(unsigned int addres);
void eeprom_write(unsigned int address,unsigned char wdata);
void eeprom_eares(unsigned int addres);//扇区擦除。
void eeprom_eares(unsigned int addres)//扇区擦除。
{unsigned i;
isp_addrl=addres; //低位地址
isp_addrh=addres>>8; //高位地址
isp_contr=0x01;
isp_contr=isp_contr|0x80; //设时间与充ISP操作。
isp_cmd=0x03; //扇区命命令
isp_trig=0x46; //触发
isp_trig=0xb9; //触发启动。
for(i=0;i<3;i++);
isp_addrl=0xff;
isp_addrh=0xff;
isp_contr=0x00;
isp_cmd=0x00;
isp_trig=0x00;
}
void eeprom_write(unsigned int addres,unsigned char write_data)//写数据。
{unsigned char i;
isp_data=write_data; //要写入的数据。
isp_addrl=addres; //低位地址
isp_addrh=addres>>8; //高位地址
isp_contr=0x01;
isp_contr=isp_contr|0x80; //设时间与充ISP操作。
isp_cmd=0x02; //写命令
isp_trig=0x46; //触发
isp_trig=0xb9; //触发启动。
for(i=0;i<3;i++);
isp_addrl=0xff;
isp_addrh=0xff;
isp_contr=0x00;
isp_cmd=0x00;
isp_trig=0x00;
}
unsigned char eeprom_read(unsigned int addres)
{unsigned char i,z;
isp_addrl=addres; //低位地址
isp_addrh=addres>>8; //高位地址
isp_contr=0x01;
isp_contr=isp_contr|0x80; //设时间与充ISP操作。
isp_cmd=0x01; //写命令
isp_trig=0x46; //触发
isp_trig=0xb9; //触发启动。
for(i=0;i<3;i++);
isp_addrl=0xff;
isp_addrh=0xff;
isp_contr=0x00;
isp_cmd=0x00;
isp_trig=0x00;
z=isp_data;
return(z);
}
void eeprom_write_4byte(unsigned int sector,unsigned long write_data )
{
eeprom_eares(sector); //清除扇区内所有数据
eeprom_write(sector,write_data & 255 );
eeprom_write(sector+1,(write_data >> 8) & 0xff);
eeprom_write(sector+2,(write_data >> 16) & 0xff);
eeprom_write(sector+3,(write_data >> 24) & 0xff);
}
unsigned long eeprom_read_4byte(unsigned int sector)
{
unsigned long r_data;
r_data=eeprom_read(sector);
r_data+=eeprom_read(sector+1)*256;
r_data+=eeprom_read(sector+2)*65536;
r_data+=eeprom_read(sector+3)*16777216;
return r_data;
}
========================================================操作面板和数码管驱动程序================================================
#define DATA_COMMAND 0X40
#define DISP_COMMAND 0x80
#define ADDR_COMMAND 0XC0
//引脚定义
sbit DIO=P2^3;
sbit CLK=P2^4;
sbit STB=P2^2;
unsigned char code tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x80};
void TM1638_Write(unsigned char DATA) //写数据函数
{
unsigned char i;
for(i=0;i<8;i++)
{
CLK=0;
if(DATA&0X01)
DIO=1;
else
DIO=0;
DATA>>=1;
CLK=1;
}
}
unsigned char TM1638_Read(void) //读数据函数
{
unsigned char i;
unsigned char temp=0;
DIO=1; //设置为输入
for(i=0;i<8;i++)
{
temp>>=1;
CLK=0;
if(DIO)
temp|=0x80;
CLK=1;
}
return temp;
}
void Write_COM(unsigned char cmd) //发送命令字
{
STB=0;
TM1638_Write(cmd);
STB=1;
}
unsigned char Read_key(void)
{
unsigned char c[4],i,key_value=0;
STB=0;
TM1638_Write(0x42);
for(i=0;i<4;i++)
c=TM1638_Read();
STB=1; //4个字节数据合成一个字节
for(i=0;i<4;i++)
key_value|=c<<i;
for(i=0;i<8;i++)
if((0x01<<i)==key_value)
break;
return i;
}
void Write_DATA(unsigned char add,unsigned char DATA) //指定地址写入数据
{
Write_COM(0x44);
STB=0;
TM1638_Write(0xc0|add);
TM1638_Write(DATA);
STB=1;
}
/*void Write_oneLED(unsigned char num,unsigned char flag) //单独控制一个LED函数,num为需要控制的led序号,flag为0时熄灭,不为0时点亮
{
if(flag)
Write_DATA(2*num+1,1);
else
Write_DATA(2*num+1,0);
} */
void Write_allLED(unsigned char LED_flag) //控制全部LED函数,LED_flag表示各个LED状态
{
unsigned char i;
for(i=0;i<8;i++)
{
if(LED_flag&(1<<i))
Write_DATA(2*i+1,3);
else
Write_DATA(2*i+1,0);
}
}
void init_TM1638(void)
{
unsigned char i;
Write_COM(0x8a);//亮度
Write_COM(0x40);
STB=0;
TM1638_Write(0xc0);
for(i=0;i<16;i++)
TM1638_Write(0x00);
STB=1;
}
//显示10进制8位数字
/***********************************************************************/
void tm1638_display(unsigned long n)
{
Write_DATA(7*2,tab[n%10]);
Write_DATA(6*2,tab[n%100/10]);
Write_DATA(5*2,tab[n%1000/100]|0x80);
Write_DATA(4*2,tab[n%10000/1000]);
Write_DATA(3*2,tab[n%100000/10000]);
Write_DATA(2*2,tab[n%1000000/100000]);
Write_DATA(1*2,tab[n%10000000/1000000]);
Write_DATA(0*2,tab[n%100000000/10000000]);
}
频率跟踪程序还要琢磨琢磨,,搞个AD转换,跟踪电流的最小值,盼有高手写个跟踪程序 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|