1. IIC总线
1.0 概述
IIC总线全称:Inter-Integrated Circuit,是由飞利浦公司开发出来的一种串行总线协议,它是一种多主机的总线,当发生主机竞争时,有总线仲裁机制。
IIC总线只有两根信号线:
* SDA:数据线
* SCL:时钟线
当总线空闲时,这两根数据线均处于高电平的状态,数据传输时由设备拉低总线。
IIC的通信原理可以通过数据手册了解,想要写底层代码的时候对比着写就好,在蓝桥杯中提供了底层代码,因此我们只需要了解官方代码如何使用就好。
蓝桥杯提供的驱动函数:
#ifndef _IIC_H
#define _IIC_H
void IIC_Start(void); //起始信号
void IIC_Stop(void); //停止信号
bit IIC_WaitAck(void); //等待应答
void IIC_SendAck(bit ackbit); //产生应答
void IIC_SendByte(unsigned char byt); //发生数据
unsigned char IIC_RecByte(void); //接受数据
#endif
1.1 IIC数据传输过程
在没有硬件IIC外设的微处理器中,需要根据总线时序设计IIC接口的驱动程序。包括:起始信号、停止信号、产生应答、等待应答、发送数据和接收数据6个函数,如上.h文件当中的函数,那如何利用这些函数实现数据的传输
与接受?
流程
开始信号 | 写入地址 | 等待响应 | 得到响应 | 发送数据 | 等待响应 | 停止信号 |
---|---|---|---|---|---|---|
S | 从机地址 | 0 | A | 数据 | A/非A | P |
ps:当接受信号时,数据后面为非应答信号。
每发送或接受一个数据都需要经过这样的流程,那么利用官方函数代码就可以这样写:
// ***********发送数据****************
IIC_Start(); //IIC总线起始信号
IIC_SendByte(0xxx); //设备地址
IIC_WaitAck(); //等待从机应答
IIC_SendByte(0xxx); //写入数据
IIC_WaitAck(); //等待从机应答
IIC_Stop(); //IIC总线停止信号
//**************接受数据**************
IIC_Start(); //IIC总线起始信号
IIC_SendByte(0xxx); //读设备地址
IIC_WaitAck(); //等待从机应答
dat = IIC_RecByte(); //读取数据
IIC_Ack(0); //产生非应答信号
IIC_Stop(); //IIC总线停止信号
————————————————
2.PCF8591
2.1概述
PCF8591是具有IIC接口的8位A/D和D/A转换芯片,具有4路模拟输入、一路DAC输出和一个IIC总线接口。
原理图:
2.2设备地址
PCF8591设备地址包括固定部分和可编程的部分,
如图:.
在蓝桥杯板子上,A2~A0均已置于0,因此设备的读操作地址为:0x91,写操作地址:0x90
2.3控制
PCF8591内部控制寄存器,当确定地址后,向该地址发送数据来控制器件的功能。
7 | 6 | 5 和4 | 3 | 2 | 1 和0 |
---|---|---|---|---|---|
固定值 | 模拟输出控制 | 模拟量输入方式选择 | 固定值 | 自动增量控制 | A/D通道选择 |
2.4A/D转换流程
- 1–发送写设备地址,选择IIC总线上的PCF8591器件。
- 2–发送控制字节,选择模拟量输入模式和通道。
- 3–发送读设备地址,选择IIC总线上的PCF8591器件。
- 4–读取PCF8591中目标通道的数据。
3.实例
在第十二届蓝桥杯省赛中考察了光敏电阻和电位器电压的采集
在此对电位器的电压进行采样并在数码管进行显示。
#include "reg52.h"
#include "iic.h"
unsigned char Num[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char dat = 0;
void delay(unsigned char T){
while(T--);
}
void select_74HC138(unsigned char num){
switch(num){
case 4:
P2 = (P2 & 0x1f) |0x80; //led
break;
case 5:
P2 = (P2 & 0x1f) |0xa0; //蜂鸣器
break;
case 6:
P2 = (P2 & 0x1f) |0xc0; //位置
break;
case 7:
P2 = (P2 & 0x1f) |0xe0; //数据
break;
case 0:
P2 = P2 & 0x1f ;
break;
}
}
// ******************关闭蜂鸣器和led*************
void system_Init(){
select_74HC138(4);
P0 = 0xff;
select_74HC138(5);
P0 = 0x00;
select_74HC138(0);
}
//**************************************************
//************************数码管显示****************
void Desplay(unsigned char dat , unsigned pos){
P0 = 0xff;
select_74HC138(6);
P0 = 0x01 << pos;
select_74HC138(7);
P0 = dat;
}
void display_smg(){
Desplay(Num[dat/100],5);
delay(100);
Desplay(Num[(dat%100)/10],6);
delay(100);
Desplay(Num[(dat%100)%10],7);
delay(100);
}
void read_rb2(){
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);
IIC_WaitAck();
IIC_Stop();
display_smg();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
dat = IIC_RecByte();
IIC_SendAck(0);
IIC_Stop();
display_smg();
}
最后欢迎大家访问我的博客
希望大家都能坚持学习,一起进步!