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

51单片机PCF8591 AD DA转换电位器控制舵机旋转的源程序

发布时间:2020-06-18 发布时间:
|

这里用到PCF8591  AD DA芯片    和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;
}

关键字:51单片机  PCF8591  AD  DA转换  控制舵机

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

热门文章 更多
如何升级STM32单片机的代码