蓝桥杯模块|蓝桥杯单片机模块代码(PCF8591)(代码+注释)

官方提供的底层代码,本次未做任何修改:

/* 程序说明: IIC总线驱动程序 软件环境: Keil uVision 4.10 硬件环境: CT107单片机综合实训平台 8051,12MHz 日期: 2011-8-9 */#include "reg52.h" #include "intrins.h"#define DELAY_TIME 5#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_SendAck(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_WaitAck(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; }

#ifndef _IIC_H #define _IIC_Hvoid IIC_Start(void); void IIC_Stop(void); bitIIC_WaitAck(void); void IIC_SendAck(bit ackbit); void IIC_SendByte(unsigned char byt); unsigned char IIC_RecByte(void); #endif

该部分的理解可以完全基于前文对于底层代码的理解,参照文件PCF8591.pdf可以在文章末尾下载,本处不做过多解释。
蓝桥杯单片机模块代码(DS18B20温度测量)(代码+注释)_tuygre的博客-CSDN博客c
下面我们进入main.c:
#include "STC15F2K60S2.H"#include "STC15F2K60S2.H" #include "stdio.h" #include "iic.h"typedef unsigned char u8; typedef unsigned int u16; u8 org[9],tran[9],wei,delay; void close() { P0=0; P2=P2&0X1F|0XA0; P2=P2&0X1F; P0=0XFF; P2=P2&0X1F|0X80; P2=P2&0X1F; }void open() { EA=1; ET0=1; }void Timer0Init(void)//1毫秒@12.000MHz { AUXR |= 0x80; //定时器时钟1T模式 TMOD &= 0xF0; //设置定时器模式 TL0 = 0x20; //设置定时初值 TH0 = 0xD1; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 }void translate(u8 org[],u8 tran[]) { u8 k,j,mid; for(j=0,k=0; j<8; j++,k++) { switch(org[k]) { case '0': mid = 0xc0; break; case '1': mid = 0xf9; break; case '2': mid = 0xa4; break; case '3': mid = 0xb0; break; case '4': mid = 0x99; break; case '5': mid = 0x92; break; case '6': mid = 0x82; break; case '7': mid = 0xf8; break; case '8': mid = 0x80; break; case '9': mid = 0x90; break; case '-': mid = 0xbf; break; default: mid = 0xff; } if(org[k+1]=='.') { mid=mid&0x7f; k++; } tran[j]=mid; } }u8 adc(u8 adress) { u8 mid; IIC_Start(); IIC_SendByte(0x90); IIC_WaitAck(); IIC_SendByte(adress); IIC_WaitAck(); IIC_Start(); IIC_SendByte(0x91); IIC_WaitAck(); mid=IIC_RecByte(); IIC_SendAck(1); IIC_Stop(); return mid; }void display(u8 tran[],u8 wei) { P0=0XFF; P2=P2&0X1F|0XE0; P2&=0X1F; P0=1<

不难发现和前方代码差距最大的内容为adc函数,我们将其单独提取出来:
u8 adc(u8 adress) { u8 mid; IIC_Start(); IIC_SendByte(0x90); IIC_WaitAck(); IIC_SendByte(adress); IIC_WaitAck(); IIC_Start(); IIC_SendByte(0x91); IIC_WaitAck(); mid=IIC_RecByte(); IIC_SendAck(1); IIC_Stop(); return mid; }

和前一篇文章类似,首先我们要初始化,也就是IIC_Start(),第二步均为传输地址,规则见下图:蓝桥杯模块|蓝桥杯单片机模块代码(PCF8591)(代码+注释)
文章图片

A2,A1,A0本单片机已经确定,高7位为1001000,仅最低位不确定。原因见下图:蓝桥杯模块|蓝桥杯单片机模块代码(PCF8591)(代码+注释)
文章图片

所以最低位为1代表读,为0代表写。
如为写操作,第二步读取数据的方式遵循以下规则:蓝桥杯模块|蓝桥杯单片机模块代码(PCF8591)(代码+注释)
文章图片

高4位为0100,第六位为1,表示允许模拟量转换并允许输出。第五位、第四位为00代表选择单端输入,竞赛一般不使用差分。第二位自动增益一般不用为0,最后两位选择通道。
蓝桥杯模块|蓝桥杯单片机模块代码(PCF8591)(代码+注释)
文章图片

通道AIN1为光敏电阻控制电压, 通道AIN3为滑动变阻器控制电压。其余两个通道不常用。
其余:IIC_RecByte(); 读取转换后的数据。
IIC_SendAck(1); 表示非应答,代表读取结束。
IIC_Stop(); 使用该模块结束,关闭防止干扰。
IIC_WaitAck(); 等待应答,每次操作后习惯性写上,防止传输相互干扰。

官方提供的原理图,用户手册等下载地址如下:
链接:https://pan.baidu.com/s/1y8lRYHxLKojL4_r0PZPYRw
提取码:19so
注释无法插入图片,相关信息读者自己在文件夹中寻找。
南京信息工程大学本科学生学习笔记,供大家参考。
【蓝桥杯模块|蓝桥杯单片机模块代码(PCF8591)(代码+注释)】如有错误,联系QQ3182097183。

    推荐阅读