一、单片机通信基础概念
全双工和半双工的区别:
一、全双工(Full Duplex)通信允许数据在两个方向上同时传输,它在能力上相当于两个单工通信方式的结合。全双工指可以同时(瞬时)进行信号的双向传输(A→B且B→A)。指A→B的同时B→A,是瞬时同步的。
二、半双工(Half Duplex)数据传输指数据可以在一个信号载体的两个方向上传输,但是不能同时传输。
MCU中常见的通信协议:
二、推挽输出和开漏输出
推挽输出:
推挽输出结构是由两个MOS或者三极管 收到互补控制的信号控制,两个管子时钟一个在导通,一个在截止,如图1所示:
特点:
推挽输出可以输出高电平和低电平,在两种电平下都具有驱动能力。
相比于后面介绍的开漏输出,输出高电平时的驱动能力强很多
缺点:推挽输出不能实现" 线与"。
开漏输出:
常说的与推挽输出相对的就是开漏输出,抽象地说就是COMS反相器去掉了NMOS部分,PMOS管漏极输出,即开漏输出。PMOS管由高电平导通输出低电平,高电平没有驱动能力,需要借助“上拉电阻” (一般上拉电阻值较大,即弱上拉模式)什么是弱上拉?
开漏输出的另一个优点在于可以实现"线与"功能,所谓的"线与"指的是多个信号线直接连接在一起,只有当所有信号全部为高电平时,合在一起的总线为高电平;只要有任意一个或者多个信号为低电平,则总线为低电平(这就是为什么后面用到IIC通信,当一个信号线为低电平,要"释放总线")。
而推挽输出就不行,如果高电平和低电平连在一起,会出现电流倒灌,损坏器件
IIC为什么要开漏输出模式?
三、I2C总线介绍:
I2C总线(Inter IC BUS)是由Philips公司开发的一种通用数据总线
两根通信线:SCL(Serial Clock)、SDA(Serial Data)
同步、半双工,带数据应答
通用的I2C总线,可以使各种设备的通信标准统一,对于厂家来说,使用成熟的方案可以缩短芯片设计周期、提高稳定性,对于应用者来说,使用通用的通信协议可以避免学习各种各样的自定义协议,降低了学习和应用的难度
四、I2C电路规范
五、I2C时序结构
总结:IIC的 时序模块
起始条件
中止条件
发送一个字节
接收一个字节
接收应答
发送应答
蓝桥杯相关
IIC模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 #include "iic.h" #define DELAY_TIME 5 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; 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; } 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 ; } 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; }
AD/DA转换模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 unsigned char AD_Read (unsigned char addr) { unsigned char temp; IIC_Start(); IIC_SendByte(0x90 ); IIC_WaitAck(); IIC_SendByte(addr); IIC_WaitAck(); IIC_Start(); IIC_SendByte(0x91 ); IIC_WaitAck(); temp = IIC_RecByte(); IIC_SendAck(1 ); IIC_Stop(); return temp; } void DA_Write (unsigned char Data) { IIC_Start(); IIC_SendByte(0x90 ); IIC_WaitAck(); IIC_SendByte(0x41 ); IIC_WaitAck(); IIC_SendByte(Data); IIC_WaitAck(); IIC_Stop(); }
AT24C02(EPPROM)模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 void EEPROM_Write (unsigned char *EEPROM_String,unsigned char addr,unsigned char num) { IIC_Start(); IIC_SendByte(0xA0 ); IIC_WaitAck(); IIC_SendByte(addr); IIC_WaitAck(); while (num--) { IIC_SendByte(*EEPROM_String++); IIC_WaitAck(); IIC_Delay(200 ); } IIC_Stop(); } void EEPROM_Read (unsigned char *EEPROM_String,unsigned char addr,unsigned char num) { IIC_Start(); IIC_SendByte(0xA0 ); IIC_WaitAck(); IIC_SendByte(addr); IIC_WaitAck(); IIC_Start(); IIC_SendByte(0xA1 ); IIC_WaitAck(); while (num--) { *EEPROM_String++=IIC_RecByte(); if (num) { IIC_SendAck(0 ); } else { IIC_SendAck(1 ); } } IIC_Stop(); }