蓝桥杯之ADDA数模转换

1. 芯片

使用的PCF8591,同样是使用IIC通信协议,相关的底层驱动代码都会提供。包括

  • 开始信号
  • 终止信号
  • 写应答
  • 读应答
  • 写一个字节
  • 读一个字节

我们要写的是两个函数  

  • 写函数
  • 读函数

2. 编程的步骤

(1)对于写函数(地址:0x90)要有两个形参,因为是写函数,就要知道往哪里写,写什么数据。

  1. 开始信号
  2. 发送地址(0x90)
  3. 写应答
  4. 发送想要写的地址
  5. 写应答
  6. 发送数据
  7. 写应答
  8. 终止信号
  9. 专用延时函数()

(2)对于读函数(地址:0x91)要有一个形参,并且带有返回值。因为是读函数,就要知道在哪里读,读到的数据放哪里。

  1. 开始信号
  2. 发送地址(0x90)
  3. 写应答
  4. 发送想要在哪里读的地址 (蓝桥杯一般用到两个 0x01 (光敏)0x03(电位器))
  5. 写应答
  6. 终止信号
  7. 开始信号
  8. 发送地址(0x91)
  9. 写应答
  10. 接收数据
  11. 延时
  12. 终止信号

 

 

/*==================================
功能:旋转Rb2 通过数码管 观察其示数的变化。
模块:ADDA 
芯片:PCF8591
//==================================*/
#include 
#include 
#define uchar unsigned char
#define uint unsigned int
#define DELAY_TIME 5
unsigned char code SMG_NoDot[18] = {0xc0,0xf9,0xa4,
	0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,
	0xc0,0x86,0x8e,0xbf,0xff};
uchar ddat;

//==========IIC总线协议源代码====================
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */

void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}
//总线启动条件
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//总线停止条件
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答
void IIC_readAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit;  					// 0:应答,1:非应答
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//等待应答
bit IIC_writeAck(void)
{
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
    SCL = 1;
	IIC_Delay(DELAY_TIME);
	da <<= 1;
	if(SDA) da |= 1;
	SCL = 0;
	IIC_Delay(DELAY_TIME);
    }
    return da;    
}
void operate_delay(unsigned char t)
{
	unsigned char i;
	
	while(t--)
	{
		for(i=0; i<112; i++);
	}
}
//===============================================

//=============PCF8591写函数=================
void PCF8591write (uchar add,uchar dat)
{
  IIC_Start();
  IIC_SendByte(0x90);
  IIC_writeAck();
  IIC_SendByte(add);
  IIC_writeAck();
  IIC_SendByte(dat);
  IIC_writeAck();
  IIC_Stop();
  operate_delay(10);	  
}
//===============================================

//=============PCF8591读函数=========================
 uchar PCF8591read  (uchar cmd)
 {
   uchar temp;
   IIC_Start();
   IIC_SendByte(0x90);
   IIC_writeAck();
   IIC_SendByte(cmd);
   IIC_writeAck();
   IIC_Stop();

   IIC_Start();
   IIC_SendByte(0x91);
   IIC_writeAck();
   temp =  IIC_RecByte();
   IIC_readAck(1);
   operate_delay(10);
   IIC_Stop();

   return temp;
 }
//===============================================

//===========数码管显示函数及初始化函数===========
void HC138init (uchar n)
{
   switch (n)
   {
   	 case 4:
	   P2 = (P2&0x1f)|0x80;
	 break;
	 
	 case 5:
	   P2 = (P2&0x1f)|0xa0;
	 break;

	 case 6:
	   P2 = (P2&0x1f)|0xc0;
	 break;

	 case 7:
	   P2 = (P2&0x1f)|0xe0;
	 break;
   }
}

void allinit ()
{
  HC138init (4);
  P0 = 0xff;

  HC138init (5);
  P0 = 0x00;

  HC138init (6);
  P0 = 0xff;

  HC138init (7);
  P0 = 0xff;
}

void displaybit (uchar pos,uchar dat)
{
  HC138init (6);
  P0 = (0x01<<(pos-1));
  HC138init (7);
  P0 = SMG_NoDot[dat];
}
void Delay_ms (uchar t)
{
  uchar i,j;
  for(i=t;i>0;i--)
  for(j=845;j>0;j--);
}
void display (uchar dat)
{
  displaybit (1,dat / 100);
    Delay_ms (50);
 
  displaybit (2,(dat / 10)%10);
    Delay_ms (50);

  displaybit (3,dat%10);
    Delay_ms (50);
} 
void delay_smg  (uchar t)
{
   while(t--)
  {
  	  display (ddat);
  }
} 
//===============================================

void main ()
{

  allinit ();
  while(1)
  { 
    ddat =  PCF8591read (0x03);	// 读取电位器的电压
    display (ddat);
	delay_smg(100);
  }

}

 

你可能感兴趣的:(蓝桥杯之ADDA数模转换)