PIC单片机之I2C通信(主模式)

发布者:数字舞者最新更新时间:2020-04-25 来源: eefocus关键字:PIC单片机  I2C通信  主模式 手机看文章 扫描二维码
随时随地手机看文章

    我们今天来讲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;

         }



    }



}

关键字:PIC单片机  I2C通信  主模式 引用地址:PIC单片机之I2C通信(主模式)

上一篇:[PIC12 CORE] PC=0x0002 Stack overflow executing CALL instruction 错误
下一篇:[MPLAB] 分享一款mplab x ide 插件------Code Configurator

推荐阅读最新更新时间:2024-11-05 11:03

PIC单片机printf()函数重定向
基本信息: 系统:Windows10 编译器:MPLAB X IDE V3.26 + XC8 V1.45 单片机:PIC18F66K22 下载器:PICKit3 一、串口初始化 /* 函数名:void USART1_Init( void ) 功能:使用的是串口1,串口初始化 */ void USART1_Init( void ) { TRISC6 = 1; TRISC7 = 1; // 输入模式,作复用功能 TX91 = 0; // 8位发送 TXEN1 = 1; SYNC1 = 0; // 异步模式 BRGH1 = 1; RX91 = 0
[单片机]
基于PIC单片机的智能湿度测量仪电路
  由HM1500/1520型湿度传感器和单片机构成的智能湿度测量仪电路如下图所示。该仪表采用+5V电源,配4只共阴极LED数码管。电路中共使用了3片IC:IC1为HM1500/1520型湿度传感器,IC2是由美国微芯片(Microchip)公司生产的带10位ADC的单片机PIC16F874,IC3为7达林顿反相驱动器阵列MC1413。PIC16F874是一种高性价比的8位单片机,内含8路逐次逼近式10位A/D转换器,最多可对8路湿度信号进行模数转换,现仅用其中一路。JT为4MHz石英晶体,配上振荡器电容C1、C2之后可为单片机提供4MHz时钟频率。PIC16F874的电源电压范围较宽(+2.5~+5V),适合低压供电,静态电流小
[电源管理]
基于<font color='red'>PIC单片机</font>的智能湿度测量仪电路
LCD显示器与PIC16F877单片机连接
一.引言     液晶显示器以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,在袖珍式仪表和低功耗应用系统中得到越来越广泛的应用。而美国Microchip公司生产的PIC系列单片机系用精简指令集(RISC),哈佛总线结构、2级流水线取指令方式,具有实用、低价、指令集小、简单易学、低功耗、高速度、体积小、功能强而逐渐成为8位单片机的新潮流。这里以JHD161A液晶模块与PIC16F877的连接来介绍它的使用方法。 二.JHD161A  LCD显示器及其与PIC16F877单片机的连接     JHD161A液晶模块是一种用5x7点阵图形来显示字符的液晶显示器,是武汉博控科技有限公司生产的1行16个字符的LCD显示模块
[单片机]
LCD显示器与PIC16F877单片机连接
PIC单片机定时器初值计算方法及几种周期小结
PIC定时器也用是蛮多的,据说网上还有计算初值的强力软件,不过我还是手动算下吧。总结了下————2013.8.27 PIC单片机定时器初值计算方法 PIC的指令周期是4个震荡周期,在没有使用分频器的情况下,TMR0 会在每个指令周期信号(等于晶体振荡器产生的主时钟周期的 4 倍)到来时自动加 1。在配置了分频器的情况下,TMR0 会在每次收到由分频器将指令周期信号分频一个固定倍数后产生的信号时自动加 1。如果 TMR0在累加计数的过程中,CPU 执行一条往 TMR0 中写入数据的指令,则累加计数器的加 1 操作将被推迟两个指令周期,重新开始计数。这两个指令周期的偏差在用户编写时间精度要求较高的程序时应引起注意,可以通过在每次写
[单片机]
<font color='red'>PIC单片机</font>定时器初值计算方法及几种周期小结
基于UCC3895与PIC单片机的智能充电器的设计
0 引言 现代通讯设备、电子产品、电动车辆、UPS等普遍采用蓄电池作为电源,然而多数充电设备功能单一,通用性差,维护质量低,导致产品的使用效率大大降低。本文采用UCC3895和PIC单片机,针对常用的铅酸蓄电池,设计开发了一种智能充电器。 UCC3895是TI公司生产的专用于PWM移相全桥DC/DC变换的新型控制芯片,可工作于电压模式,也可工作于电流模式,并且可实现输出脉冲占空比从0到100%相移控制,软启动和软停止可按要求进行调节;内置7MHz带宽的误差比较放大器;具有完善的限流及过流保护、电源欠压保护,基准欠压保护、软启动和软停止等功能。 PICl6F917型单片机与UCC3895共同组成控制器部分,相对于仅使用单片
[单片机]
基于UCC3895与<font color='red'>PIC单片机</font>的智能充电器的设计
PIC单片机的端口RB中断的设计思路及电路设计
1. 设计思路   本例利用PIC16F877的RB端口中断设计一个抢答器,该抢答器可供不多于4个参赛队或者个人的抢答比赛场合使用。   每个参赛队的座位前安装1只抢答按钮开关和1个信号灯。主持人的座位前安装1只复原按钮开关、1只蜂呜器和1个抢答器工作状态指示灯。   每当主持人发出允许抢答的命令之后,哪个队先按下座位J的按钮开关,该座位的信号灯就先被点亮, 司时封锁其他按钮开关的活动,并且熄灭主掎人座位阝的状态指小灯和发出3声类似于电话振铃的提示声,以声明此次抢答动作已经完成。   在主持人确认后,按下“复原”按钮,状态指示灯重新点亮,并且同时发出“笛、笛”声,为下一次的抢答做好准备。   2.电路设计   电路原理
[单片机]
<font color='red'>PIC单片机</font>的端口RB中断的设计思路及电路设计
基于PIC单片机与16位串行D/A转换的原理简介
   下面介绍了基于PIC单片机与16位串行D/A转换的原理:    1.基本原理   D/A转换器相当于一种译码电路,它将数字输入传换为模拟输出:   其中,D是数字输入,VR是模拟参考输入,Vo是模拟输出。这里模拟输出可以是电压,也可以是电流,式中 数字D是一个小于1的值。   式中an为1或0,由数字对应位的逻辑电平来决定,N是数字输入D的位数。由此(3.2)由此(3.1)   当参考电压输入TIp.固定时,转换器的模拟输出D成正比关系。对于单位数字量的变化,模拟输出是按等 幅度的阶跃量变化的。    2.原理图   (1)串行D/A转换器。   串行D/A转换器
[单片机]
基于<font color='red'>PIC单片机</font>与16位串行D/A转换的原理简介
PIC单片机定时器的使用(16F877)
/*******************************************/ //功能:60倒计时,蜂鸣器以及数码管的使用 //开发板:PIC16F877 /*******************************************/ include define uchar unsigned char define uint unsigned int void delay(uchar a,uchar x); uchar table ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x00};//数组 uchar LED ; void init
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多往期活动

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved