实验目的:
用AT89C51+ADC0808,实现PWM控制直流电机转速。ADC0808检测变阻器上的电压,反馈到C51上,C51输出对应的PWM占空比,控制直流电机。
原理图如下:
用定时器0来输出PWM,定时器1给ADC0808做时钟。
proteus模拟,用示波器看,C51用定时器输出1KHz的频率,波形还勉勉强强。但是ADC0808最低时钟要求也要10KHz,输出的波形简直是一塌糊涂,不过看起来,模拟运行还是正常跑起来了。
定时器0,1代码:
void T0_init(void)
{
TMOD|= 0X01;
TH0 = (65536-100)/256;
TL0 = (65536-100)%256;
ET0 = 1;
EA = 1;
TR0 = 1;
}
void T1_init(void)
{
TMOD|= 0X20;
TH1 = 0xCD; //50us定时
TL1 = 0xCD;
ET1 = 1;
EA = 1;
TR1 = 1;
}
void Timer0() interrupt 1
{
TH0 = (65536-100+12)/256; //100us,减以下指令运行时长,实现1kHz PWM
TL0 = (65536-100+12)%256;
count++;
if(count == 10) count = 0; //占空比步长10%
if(count < pwm_duty/10) out=0; //低电平导通
else out=1;
}
void Timer1() interrupt 3
{
CLK=~CLK;
}
ADC0808时序比较简单,启动脚START需要一个低-高-低电平,表示已经启动转换,EOC脚由芯片自动拉低,转换结束后自动拉高,此时只需要一直检测EOC,直到高电平出现。
这时,AD转换已完成,打开OE使能脚,读取对应数据。
void ADC_read() //ADC0808取值
{
ST = 0;
OE = 0;
ST = 1;
ST = 0;
while(!EOC) {}
OE = 1;
ADC_temp = P1;
OE = 0;
}
主程序,将读取的ADC值,转换成对应的占空比就行了。这个转换公式感觉不太对,有些小差别。
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit CLK = P2^4;
sbit ST = P2^5;
sbit EOC = P2^6;
sbit OE = P2^7;
sbit out = P3^7;
uchar count=0;
uchar pwm_duty=50;
uchar ADC_temp;
void main(void)
{
T0_init();
T1_init();
while(1)
{
ADC_read();
pwm_duty = ADC_temp*100/255;
}
}