ShareIdeas

本博客不再更新,欢迎访问我的github,https://github.com/sunke-github/

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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

电路图

 

 

 

这是程序,、

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

#include"reg52.h"
#include <intrins.h> //包含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;

}

posted on 2012-07-11 10:54  ShareIdeas  阅读(2036)  评论(0编辑  收藏  举报