我们今天来讲I2C通信。那I2C通信的特点是什么能。我们一般使用的串口 (半双工异步串行通信)与I2C 有什么区别呢。
串口(半双工异步串行通信):就是好像朋友在对话。我可以主动和你讲话,你也可以主动和我讲话。
I2C:就好像上下级对话。一个领导面对一个或者多个员工。只有领导主动说话的份儿,下面的员工不能主动说话。只有领导问了,员工才能答。
I2C通信
I2C通信只需要两个引脚 一个数据线,一个时钟线。 数据线顾名思义就是用来传递数据的。时钟线是来决定数据传输的速度。当时钟线为高电平时,数据线上的数据才会被认为是有效的。
数据线的 数据有四种状态 : 高电平,低电平,下降沿(高电平变低电平),上升沿(低电平变高电平)。
当时钟线为高电平时候这四种状态分别代表:1,0,起始位,停止位。
如果我们发送的数据为十六进制的0x88即是二进制为10001000的数据是怎么发送的呢?我们就以此为例一步步讲解。
1、常态
在不发送任何数据的时候数据线和时钟线都为高电平。一般为了保证能带动128个从设备。大部分芯片的I2C通信接口都是用开漏输出(只能接通地不能输出高电平),所以数据线和时钟线都要加上拉电阻。
2、起始
当开始发送数据的时候 时钟线为高同时数据线从 高电平变低电平,代表开始发送数据。
3、发送数据
发送完起始位后 时钟线变为低电平,在发送每一位的数据之前时钟线有一段低电平,主要的作用是给数据线做电平变化用的。
我们现在要发送的第一个位是 1。
1、时钟线为低,同时数据线从低电平变成高电平。
2、接着时钟线变为高电平,此时接收方得知时钟线为高,便查看数据线为高电平 说明数据为 “1”。
3、我们要发送的下一个位为0。时钟线再变为低,同时数据线从高电平变成低电平。
4、接着时钟线再变为高电平,此时接收方得知时钟线为高,便查看数据线为低电平 说明数据为"0"。
5、再下一个为还为0。时钟线再变为低,同时数据线一直保持低电平不变。
6、接着时钟线再变为高电平,此时接收方得知时钟线为高,便查看数据线为低电平 说明数据为”0“。
以此类推 直到发送完所有的位。
4,应答(ACK)
当接收方接收完一个字节的数据就要告诉对方我收到了。接收方如果接收到数据则控制数据线输出低电平。否则为高电平。
5,停止
没有下一个字节要发送,最后时钟线变为高电平后,数据线从低电平变为高电平。代表数据发送停止。
实例讲解: 使用单片机使用 RSM2257 电子音量控制芯片来控制音量。一个按键按下,声音变大,一个按键按下,声音变小。在加上一个按键,控制一个LED亮灭的程序。而且音量掉电保存。
介绍RSM2257.
子地址
在I2C通信中每一个从设备都有个子地址,因为I2C支持一主多从,也就是说有一个主机可以连接多个从机。每个从机,都有个地址。就好像每个人的名字一样来区分不同的设备。下面是RSM2257接口协议,首先先发送RSM2257 设备地址 10001000.然后再发送数据。
数据
RSM2257的数据是用来表示音量大小的。我们控制两个音频通道,以10dB为单位降低或增加音量。从功能设置位表格中可知数据为 11100B2B1B0.
B2B1B0的数值决定了音量。请详见 衰减设置位。
单片机I2C通信初始化设置
1、设置端口为输入
TRISC0 = input;
TRISC1 = input;
2、设置模式
我们设置ssp1控制寄存器的 SSP1M<3:0>.我们需要的是I2C主模式。设置如下
SSP1CON1bits.SSPM0 = 0;
SSP1CON1bits.SSPM1 = 0;
SSP1CON1bits.SSPM2 = 0;
SSP1CON1bits.SSPM3 = 1;// I2C Master mode ,clock=Fosc/(4*(SSPxADD+1))
3、设置时钟线频率RSM2257最大为100KHZ,我选择设置为50KHZ.
使用计算公式clock=Fosc/(4*(SSPxADD+1)) 计算出SSP1ADD的值为0x9F;
SSP1ADD=0x9F;
4、开启I2C通信
SSP1CON1bits.SSPEN = 1;
单片机I2C发送程序
1、发送起始位
SSP1CON2bits.SEN = 1;//Start condition
while(SSP1CON2bits.SEN == 1);//waiting for Start condition completed.
2、发送地址
PIR1bits.SSP1IF = 0;
SSP1BUF = 0x88;//Device Address
while(PIR1bits.SSP1IF == 0);
PIR1bits.SSP1IF = 0;
// ~ACK 我们不理会接收方有没有应答。
3、发送 10db音量控制的数据
SSP1BUF = tx_data;//Data 10db level
while(PIR1bits.SSP1IF == 0);
PIR1bits.SSP1IF = 0;
4、发送1db音量控制的数据
// ~ACK
SSP1BUF = 0xD0;//Data 1db level
while(PIR1bits.SSP1IF == 0);
PIR1bits.SSP1IF = 0;
5、发送停止位
// ~ACK
SSP1CON2bits.PEN = 1;//Stop condition
关于I2C通信协议,RSM2257,PIC MSSP 模块设置成I2C,更详细的内容就必须去看数据手册了。
实例程序:程序分为main.c 和 define.h两个文件 芯片PIC16LF1823,开发环境MPLAB X IDE.
define.h文件
/**********RA*********/
//B'1111,1000'H F8
#define LED_SW RA5//IN
#define UP_SW RA4//IN
#define DOWN_SW RA3//IN
#define LED RA2//OUT
//RA1
//RA0
/**********RC***********/
//H FF
//RC0 SCL
//RC1 SDA
#define input 1
#define LED_VALUE 1
#define UP_VALUE 2
#define DOWN_VALUE 3
#define key_delay 300
main.c文件
#include #include"define.h" __CONFIG(FOSC_INTOSC&WDTE_OFF&PWRTE_ON&MCLRE_OFF&CP_ON&CPD_OFF&BOREN_ON &CLKOUTEN_OFF&IESO_ON&FCMEN_ON); __CONFIG(PLLEN_OFF&LVP_OFF) ; void tx_pro(unsigned char tx_db); unsigned char DB_VALUE; void init_fosc(void) { OSCCON = 0xF0;//32MHZ } void init_gpio(void) { PORTA=0; LATA =0; ANSELA=0x00; TRISA =0xF8; PORTC=0; LATC=0; ANSELC = 0x00; TRISC =0xFF; } void init_i2c_master() { TRISC0 = input; TRISC1 = input; SSP1CON1bits.SSPM0 = 0; SSP1CON1bits.SSPM1 = 0; SSP1CON1bits.SSPM2 = 0; SSP1CON1bits.SSPM3 = 1;// I2C Master mode ,clock=Fosc/(4*(SSPxADD+1)) SSP1STATbits.SMP = 1; SSP1ADD = 0x9F;//SCL CLOCK Frequency 50KHZ SSP1CON1bits.SSPEN = 1; } void i2c_master_tx(unsigned char tx_data) { SSP1CON2bits.SEN = 1;//Start condition while(SSP1CON2bits.SEN == 1);//waiting for Start condition completed. PIR1bits.SSP1IF = 0; SSP1BUF = 0x88;//Device Address while(PIR1bits.SSP1IF == 0); PIR1bits.SSP1IF = 0; // ~ACK SSP1BUF = tx_data;//Data 10db level while(PIR1bits.SSP1IF == 0); PIR1bits.SSP1IF = 0; // ~ACK SSP1BUF = 0xD0;//Data 1db level while(PIR1bits.SSP1IF == 0); PIR1bits.SSP1IF = 0; // ~ACK SSP1CON2bits.PEN = 1;//Stop condition } void delay(unsigned int n) { while(n--); } unsigned char key_board(void) { if(LED_SW==1) { delay(key_delay); if(LED_SW==1) { while(LED_SW==1); return LED_VALUE; } } if(UP_SW==1) { delay(key_delay); if(UP_SW==1) { while(UP_SW==1); return UP_VALUE; } } if(DOWN_SW==1) { delay(key_delay); if(DOWN_SW==1) { while(DOWN_SW==1); return DOWN_VALUE; } } return 0; } void DB_INC(void) { if(DB_VALUE < 7) { DB_VALUE++; eeprom_write(0x00, DB_VALUE);//将音量值保存到EEPROM这样掉电后数据也不会丢失。 tx_pro(DB_VALUE); } } void DB_DEC(void) { if(DB_VALUE > 0) { DB_VALUE --; eeprom_write(0x00, DB_VALUE); tx_pro(DB_VALUE); } } void tx_pro(unsigned char tx_db) { tx_db |= 0xE0; //将高三位设置为1。表示两个音频通道,以10dB为单位降低或增加音量 i2c_master_tx(tx_db);//I2C发送数据程序 } /* * */ int main(int argc, char** argv) { unsigned char keyvalue; init_fosc(); init_gpio(); init_i2c_master(); LED=0; DB_VALUE= eeprom_read(0x00);//读eeprom 中保存的音量值 if(DB_VALUE > 7)//如果之前没有设置过则音量不衰减 { DB_VALUE = 0; } tx_pro(DB_VALUE);//用I2C通信设置RSM2257的音量 while(1) { keyvalue=key_board();//判断按键程序, switch(keyvalue) { case LED_VALUE://LED按键按下 { LED = ~LED; };break; case UP_VALUE://音量加 { DB_INC(); };break; case DOWN_VALUE://音量减 { DB_DEC(); };break; } } }
上一篇:[PIC12 CORE] PC=0x0002 Stack overflow executing CALL instruction 错误
下一篇:[MPLAB] 分享一款mplab x ide 插件------Code Configurator
推荐阅读最新更新时间:2024-11-05 11:03
设计资源 培训 开发板 精华推荐
- DC1185B-B,使用 LTC3850EUF 的演示板 4.5V = VIN = 14V,VOUT1:1.5V @ 15A,VOUT2:1.2V @ 15A 同步降压转换器
- LT1072CN8 升压型升压转换器的典型应用
- 具有多重线性稳压器的 MCZ33730 - 33730 开关电源的典型应用
- DER-626 - 基于InnoSwitch3 Pro PowiGaN和MinE-CAP的65W USB PD 3.0与3.3 V-21 V PPS电源
- EVAL-AD7891-1CB,用于单电源、12 位、454 kSPS ADC 的评估板
- EVAL-AD7706EBZ,用于 AD7705、5V、3 通道、16 位、Sigma Delta ADC 的评估板
- SPC584B-DISP:在eTQFP144中具有SPC58 4B线MCU的探索套件
- 单相电表
- FlyingRC-F4Wing-MK5
- BD49xxx系列BD49K51电压检测IC的典型应用