×
单片机 > 单片机程序设计 > 详情

51单片机控制舵机实验

发布时间:2021-07-07 发布时间:
|

简介:这里用到PCF8591 ADDA芯片和51单片机和一个电位器。通过控制电位器,产生PWM波,控制舵机旋转。并在数码管上显示角度。

电路图

这是程序,、


/*-----------------------------------------------


名称:IIC协议 PCF8591ADDA转换


内容:此程序通过IIC协议对DAAD芯片操作,读取电位器的电压,并输出模拟量,用LED亮度渐变指示,晶体选用12MHz


------------------------------------------------*/


#include"reg52.h"


#include //包含NOP空指令函数_nop_();


#define AddWr 0x90 //写数据地址


#define AddRd 0x91 //读数据地址


sbit Sda=P1^2; //定义总线连接端口


sbit Scl=P1^1;


sbit control_signal=P1^5;


data unsigned int Display[8];//定义临时存放数码管数值


unsigned char code Datatab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//7段数共阴码管段码表


unsigned int ADtemp; //定义全局变量


unsigned int high,low;


static unsigned int count1;


/*------------------------------------------------


延时程序


------------------------------------------------*/


void mDelay(unsigned char j)


{


unsigned int i;


for(;j>0;j--)


{


for(i=0;i<125;i++)


{;}


}


}


/*------------------------------------------------


初始化定时器0


------------------------------------------------*/


void Init_Timer0(void)


{


TMOD |=0x01; //定时器设置 0.1ms in 11.0592M crystal


TH0=(65536-78)/256;


TL0=(65536-78)%256; //定时0.1mS


ET0=1;//定时器中断打开


EA=1;//总中断


TR0=1; //启动定时器0


}


/*------------------------------------------------


启动IIC总线


------------------------------------------------*/


void Start(void)


{


Sda=1;


_nop_();


Scl=1;


_nop_();


Sda=0;


_nop_();


Scl=0;


}


/*------------------------------------------------


停止IIC总线


------------------------------------------------*/


void Stop(void)


{


Sda=0;


_nop_();


Scl=1;


_nop_();


Sda=1;


_nop_();


Scl=0;


}


/*------------------------------------------------


应答IIC总线


------------------------------------------------*/


void Ack(void)


{


Sda=0;


_nop_();


Scl=1;


_nop_();


Scl=0;


_nop_();


}


/*------------------------------------------------


非应答IIC总线


------------------------------------------------*/


void NoAck(void)


{


Sda=1;


_nop_();


Scl=1;


_nop_();


Scl=0;


_nop_();


}


/*------------------------------------------------


发送一个字节


------------------------------------------------*/


void Send(unsigned char Data)


{


unsigned char BitCounter=8;


unsigned char temp;


do


{


temp=Data;


Scl=0;


_nop_();


if((temp&0x80)==0x80)


Sda=1;


else


Sda=0;


Scl=1;


temp=Data<<1;


Data=temp;


BitCounter--;


}


while(BitCounter);


Scl=0;


}


/*------------------------------------------------


读入一个字节并返回


------------------------------------------------*/


unsigned char Read(void)


{


unsigned char temp=0;


unsigned char temp1=0;


unsigned char BitCounter=8;


Sda=1;


do


{


Scl=0;


_nop_();


Scl=1;


_nop_();


if(Sda)


temp=temp|0x01;


else


temp=temp&0xfe;


if(BitCounter-1)


{


temp1=temp<<1;


temp=temp1;


}


BitCounter--;


}


while(BitCounter);


return(temp);


}


/*------------------------------------------------


读取AD模数转换的值,有返回值


------------------------------------------------*/


unsigned int ReadADC(unsigned char Chl)


{


unsigned int Data;


Start(); //启始信号


Send(AddWr);//0x90


Ack();


Send(0x40|Chl);//写入选择的通道,本程序只用单端输入,差分部分需要自行添加


//Chl的值分别为0、1、2、3,分别代表1-4通道


Ack();


Start();


Send(AddRd); //读入地址


Ack();


Data=Read(); //读数据


Scl=0;


NoAck();


Stop();


return Data; //返回值


}


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


/* 主程序 */


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


void main()


{


Init_Timer0();


while(1)


{


unsigned int angle;


ADtemp=ReadADC(0); //ADtemp的取值范围是0-255,定时的时间范围是0.5-2.5ms


high=65075-7.2*ADtemp; // ( high=65035-7.8*ADtemp;12MHz)(65535-(460+7.2*ADtemp 11.0592MHz)


low=47563+7.2*ADtemp; // ( low=46035+7.8*ADtemp; ) ( 65535-(17972-7.2*ADtemp 11.0592MHz )


angle=ADtemp*0.7;


Display[0]=Datatab[angle/100];//处理0通道电压显示


Display[1]=Datatab[(angle%100)/10];


Display[2]=Datatab[angle%10];


while(1)


{


P0=Display[count1];//用于动态扫描数码管


P2=count1;


mDelay(1);


count1++;


if(count1==3) //表示扫描3个数码管


{


count1=0;


break;


}


}


}


}


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


/* 定时器中断函数


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


void tim(void) interrupt 1 using 1


{


static unsigned char count;


if (!count)


{


control_signal = 1; //给高电平


TH0=high/256;


TL0=high%256; }


else


{


control_signal=0 ;


TH0=low/256;


TL0=low%256;


}


count=~count;


}



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32单片机的复用端口初始化的步骤及方法