天马行空工作室

 找回密码
 加入天马
搜索
查看: 4994|回复: 1

基于PIC18F系列单片机的IIC通信协议(IO口模拟)

[复制链接]
发表于 2012-6-16 14:38:57 | 显示全部楼层 |阅读模式
  1. #include<p18f67j11.h>

  2.     #define SDA_SET         TRISCbits.TRISC4=1;           /*将数据线置1*/
  3.     #define SDA_CLR         {TRISCbits.TRISC4=0;LATCbits.LATC4=0;}    /*将数据线置0*/
  4.     #define SDA_R           PORTCbits.RC4        /*数据线的状态*/

  5.     #define SCL_SET         TRISCbits.TRISC3=1;    /*将时钟线置1*/
  6.     #define SCL_CLR         {TRISCbits.TRISC3=0;LATCbits.LATC3=0;}          /*将时钟线置0*/
  7.     #define SCL_R                PORTCbits.RC3    /*时钟线的状态*/

  8.     unsigned char LCD_ACK;
  9.     #define DELAY_4U           {Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();}


  10.     //IIC起始位发送函数
  11.     void IIC_Start(void)
  12.     {

  13.                     SDA_SET
  14.                     Nop();
  15.                     SCL_SET        //在至少4u秒期间SDA从高电平到低电平
  16.                     DELAY_4U
  17.                     Nop();
  18.                     SDA_CLR
  19.                     DELAY_4U
  20.                     Nop();
  21.                     SCL_CLR
  22.                     Nop();
  23.                     Nop();
  24.                     Nop();

  25.     }
  26.     //停止位发送
  27.     void IIC_Stop(void)
  28.     {

  29.                     SDA_CLR
  30.                     Nop();
  31.                     SCL_SET
  32.                     DELAY_4U

  33.                     SDA_SET      //在至少4u秒期间SDA从低电平到高电平
  34.                     DELAY_4U
  35.     }



  36.     //IIC数据发送函数
  37.     //带入参数:欲发送的字节数
  38.     unsigned char  IIC_Send(unsigned char data)
  39.     {
  40.         unsigned char i;

  41.                     for(i=0;i<8;i++)
  42.                     {
  43.                                     if((data&0x80)==0x80)
  44.                                                     SDA_SET
  45.                                     else
  46.                                                     SDA_CLR
  47.                                     Nop();
  48.                            
  49.                                     SCL_SET
  50.                                     DELAY_4U        
  51.                                     Nop();
  52.                                     Nop();
  53.                                     SCL_CLR
  54.                                     data <<= 1;
  55.                     }
  56.                     SCL_SET
  57.                     Nop();
  58.                     Nop();
  59.                     if(SDA_R)
  60.                          LCD_ACK=1;
  61.                     else
  62.                             LCD_ACK=0;
  63.                     SCL_CLR;
  64.                     return LCD_ACK;        
  65.     }
  66.     //IIC数据读入函数
  67.     //返回值:读入的字节数
  68.     unsigned char IIC_Receive(void)
  69.     {
  70.         unsigned char Re_temp;
  71.                     unsigned char i;

  72.                     for(i=0;i<8;i++)
  73.                     {
  74.                                     Re_temp<<=1;
  75.                                     SCL_CLR
  76.                                     DELAY_4U
  77.                                     SCL_SET
  78.                                     DELAY_4U
  79.                                     if(SDA_R)Re_temp|=0x01;
  80.                                     Nop();
  81.                                     Nop();                        
  82.                     }
  83.                     SCL_CLR
  84.                     Nop();
  85.                     Nop();
  86.                     return Re_temp;
  87.     }
复制代码
只需要改一下宏定义,就可以移植到别的单片机上了。
解释一下宏定义中为什么这样输出高低电平 :
I2C 是双向总线,标准器件(比如BL55070(A))都是以漏极或集电极开
路形式接入的,总线上的高电平是由上拉电阻或上拉电流源产生的。当
MCU 以通用I/O 口接入时必须注意不宜直接将端口设为输出并置“1”来
输出高电平,否则当其他器件试图拉低总线时会产生很大的灌电流,不
利于数据传输可靠进行。虽然正常情况下只有MCU 会在SCL 线上发送时
钟,但如果MCU 发出的时钟脉冲过窄时,BL55070(A)会判别传输速度过
快而将SCL 总线拉低,通知MCU 数据传输过快,这就是所谓的“I2C 时
钟同步特性”。这时如果SCL 高电平是由MCU I/O 端口置“1”产生,就
会产生严重逻辑冲突,从而在MCU I/O 口上产生数mA 的灌电流同时也在
BL55070(A)的SCL 端流入数mA 的陷电流,对器件可靠工作大为不利。所
以推荐的MCU 通用I/O 端口模拟 I2C 端口的方法是:
• 输出“1”:I/O 口设为输入,由上拉电阻产生高电平
• 输出“0”:I/O 端口设为输出,置“0”,直接输出低电平

评分

参与人数 1给力 +2 酱油 +4 收起 理由
小路 + 2 + 4 很给力!

查看全部评分

发表于 2012-6-16 19:55:51 | 显示全部楼层
好像有人看没人回复的样子,虽然我看不懂
您需要登录后才可以回帖 登录 | 加入天马

本版积分规则

Archiver|手机版|小黑屋|天马行空工作室 ( 京ICP备12003429号  

GMT+8, 2019-10-21 11:17 , Processed in 1.233235 second(s), 25 queries .

Powered by Discuz! v8

© 2010-2014 基于PIC18F系列单片机的IIC通信协议(IO口模拟) - 嵌入式开发 天马行空工作室

快速回复 返回顶部 返回列表