⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 很实用的单片机例程
💻 C
字号:
/*-----------------------------------------------
  名称:IIC协议 PCF8591ADDA转换	 显示有4个,注意只有一个可以调节电压的
  内容:此程序通过IIC协议对DAAD芯片操作,读取电位器的电压通过液晶显示,并输出模拟量,用LED亮度渐变指示
------------------------------------------------*/
 #include<reg52.h>    //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
 #include <intrins.h> //包含NOP空指令函数_nop_();

 #define AddWr 0x90   //写数据地址(理解手册) 
 #define AddRd 0x91   //读数据地址  
 
 sbit Sda=P2^0;   //定义总线连接端口
 sbit Scl=P2^1;
 
 sbit dula=P2^6;
 sbit wela=P2^7;

 bit ADFlag;          //定义AD采样标志位

char code dm[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //7段数共阴码管段码表0~9
//char wm[]={0XFE,0XFD,0XFB,0XF7,0XEF,0XDF}; //从左到右6位数码管(P0^0为0时,左1选中)

/****************************数码管显示有关***********************************/
void delayuint(unsigned int i)
{
  while(i--);
}

//把三位整数的每一位取出
char q,b,s,g;
void convert(int DATA)
{ 
  q=DATA/1000;
  b=DATA%1000/100; 
  s=DATA%100/10;
  g=DATA%10;
}

int DATA0;   //用来存放上次的DATA值
void show_led8(float t)  //把t送到数码管上扫描一遍 (0<t<100的四位浮点数(带2位小数))
{
 int DATA=t*100;  //若t带了多位小数也只取2位,赋给int型小数放弃
 if(DATA0!=DATA)
   convert(DATA0=DATA);  

//处理千位
 if(q!=0)       
  {
   wela=1;
   P0=0xfe;
   wela=0;   
 //送百位段码
   dula=1;
   P0=dm[q];
   dula=0;
   delayuint(250); //delay(100)是916us(12M) 
  } 

//处理百位 (对应小数的个位,须点亮dp点)
//先关段码(送暗码),再开下一位
   dula=1;
   P0=0;
   dula=0;
   
   wela=1;
   P0=0xfd;
   wela=0;
   dula=1;
   P0=dm[b]|0x80;    //包含小数点
   dula=0;
   delayuint(250);
 
//处理十位  (对应小数的十分位)
//先关段码(送暗码),再开下一位
   dula=1;
   P0=0;
   dula=0;
   
   wela=1;
   P0=0xfb;
   wela=0;   
   dula=1;
   P0=dm[s];
   dula=0;
   delayuint(250);
   
//处理个位  (对应小数的百分位)
//先关段码(送暗码),再开下一位
   dula=1;
   P0=0;
   dula=0;
   
   wela=1;
   P0=0xf7;
   wela=0;   
   dula=1;
   P0=dm[g];
   dula=0;
   delayuint(250);   

/*退出前关闭所有数码管,是必须要的,否则会可能出现单个数码管持续亮*/
   dula=1;
   P0=0;
   dula=0; 
}
/****************************数码管显示有关(OVER)********************************************/

/*------------------------------------------------
                    初始化定时器1
------------------------------------------------*/
void Init_Timer1(void)
{
 TMOD |= 0x10;	 //T1方式1
	     
 TH1=0x0B;	    //Init value
 TL1=0xDC;     
 //PT1=1;       // 优先级

 EA=1;                      /* interupt enable */
 ET1=1;                     /* enable timer1 interrupt */
 TR1=1;  
}
/*------------------------------------------------
                    启动IIC总线
------------------------------------------------*/
  void Start(void)
  {
   Sda=1;
   _nop_();
   Scl=1;
   _nop_();
   Sda=0;
   _nop_();   //成功启动 
   Scl=0;    //允许SDA改变
  }

/*------------------------------------------------
                    停止IIC总线
------------------------------------------------*/
  void Stop(void)
  {
   Sda=0;
   _nop_();
   Scl=1;
   _nop_();
   Sda=1;
   _nop_();   //成功停止
   Scl=0;     //允许SAD改变以准备数据
   }

/*------------------------------------------------
               (主机)应答IIC总线
------------------------------------------------*/
   void Ack(void)    //时钟有效期间,SDA保持0
   {
    Sda=0;
	_nop_();
	Scl=1;
	_nop_();
	Scl=0;
	_nop_();
	}

/*------------------------------------------------
                (主机)非应答IIC总线
------------------------------------------------*/
	void NoAck(void)    //时钟有效期间,SDA保持1
	{
	 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;   //让出数据总线给8591

	   do
	     {
		    Scl=0;    //允许8591改变(准备)SDA数据
          _nop_();  //等待数据有效
		    Scl=1;    //使数据有效(单片机可用)
		    _nop_();
		    if(Sda)   //单片机读SDA并判断
		      temp=temp|0x01;
		    else
		      temp=temp&0xfe;

		    if(BitCounter-1!=0)
		     {
			    temp1=temp<<1;
			    temp=temp1;
			  }
			 BitCounter--;
		  }
		while(BitCounter);

		return(temp);
	  }  

/*------------------------------------------------
         读取ch通道AD转换的值,有返回值
------------------------------------------------*/
	  unsigned char ReadADC(unsigned char Ch)
	  {
       unsigned char Data;
		   Start();   //启动     
		   Send(AddWr);  //写入芯片地址——写数据地址0x90
		   Ack();    //应该是等8591应答吧?
		   //发送”控制字“
 		   Send(0x40|Ch); //写入选择的通道,本程序只用单端输入,差分部分需要自行设置
		                  //Chl的值分别为0、1、2、3,分别代表1-4通道
						      //0100 00xx
		   Ack();

		   Start();
		   Send(AddRd);    //写入地址---读数据地址0x91
		   Ack();
		   Data=Read();    //读数据
		   Scl=0;
		   NoAck();
		   Stop();
		   return Data;   //返回值
	  }
/*------------------------------------------------
                   主程序
------------------------------------------------*/
	void main()
	{
	 unsigned char ADtemp;                //定义中间变量
	 float U=0;    //电压值
     //unsigned int TempData[6];

    Init_Timer1();

	 while(1)
	   { 
		  if(ADFlag)      //定时采集输入模拟量
         {
			  ADFlag=0;
			  ADtemp=ReadADC(0);     //8位二进制温度值
			  U=ADtemp*5.0/255;      //把采样的数字值再还原为模拟值
		   }
   	  show_led8(U);
	   }
	}

/*------------------------------------------------
                   定时器中断程序
------------------------------------------------*/
void Timer1_isr(void) interrupt 3 using 1//定时器1执行数码管动态扫描
{
 static unsigned int j;

 TL1=0xDC;    //重新赋值  62500US=62.5MS中断一次
 TH1=0x0B;
	
 j++;
 if(j==4)     //62.5*4=250ms  一秒钟采样四次
  {j=0;ADFlag=1;} //定时置位AD采样标志位  
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -