IO口中断模拟I2C通信方式

更新时间:2024-01-30 15:44:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

一种IO口中断模拟I2C

通信的方法

单片机与单片机之间的通信方式

Jonney.Peng 2016/8/17

更可靠,效率更高的模拟I2C通信方式,主从机都可模拟

目录

一、 I2C通信原理 ........................................................................ 3 二、 利用IO口模拟I2C的优势 .................................................. 3 三、 利用IO口模拟I2C的原理 .................................................. 3 2、 中断接收数据函数 ............................................................ 4 3、 读指令函数 ........................................................................ 5 4、 发送一个字节函数 .................................................................. 6 5、 发送指令函数 .................................................................... 7 五、 源代码共享地址 ................................................................... 7

一、 I2C通信原理

I2C

总线系统是由SCL(串行时钟)和SDA(串行数据)两

根总线构成的。该总线有严格的时序要求,总线工作时,由串行时钟线SCL传送时钟脉冲,由串行数据线SDA传送数据。

二、 利用IO口模拟I2C的优势

简单的通过单片机IO模拟I2C通信,我们会发现数据接收不正常或者接收错误的情况,同时接收速率比较低,实时性比较差。最重要的是只能模拟主机通信,今天我所介绍的适用于所有单片机与单片机的通信,既可以接收数据也可以发送数据。只需要两个IO口,其中包含一个IO口中断,可以解决串口,I2C和SPI都不够用的问题。

三、 利用IO口模拟I2C的原理

传统的I2C通信方式,SCL负责传送信号脉冲,SDA负责传

送数据,SCL为低时,允许传送数据。通过中断方式实现I2C也是遵循了这个原理。与传统I2C的区别在于,当SCL电平变化时,只传送一位数据,所以接收完一个字节数据时,SCL需由高到低

变化八次。 四、 源代码分析

1、 初始化I2C函数

功能:将SDA与SCL电平置高,SDA可以为任何IO口,

SCL必须为带有中断的IO口。

void I2C_INIT() {

SDA=1; delays(2); SCL=1; delays(2); }

2、 中断接收数据函数

功能:实现数据的接收 变量名含义:

注:此接收函数根据通信协议可以适当调整,我的通信 协议格式是: 包头:00 地址:00-0XFF 包长度:命令+参数+结束位 命令:0X00-0XFF 参数:0X00-0XFF 结束位:0xFF INTTemp:接收数据变量,每一位都存入INTTemp

clk_over_timer:接收超时时基,用于复位相应标志位,后面会介

绍。

INT_i2c:中断标志位

F_INT_read:读数据标志位 F_read_ok:接收完数据标志位 INTnum:中断次数标志位 INTre[]:接收数据缓存区

INTbyteflag:接收字节个数标志位 F_long:接收的指令长度

void I2cRead() interrupt 0

{

INTTemp=INTTemp<<1; INTTemp=INTTemp|SDA; clk_over_timer=0; INT_i2c=1; F_INT_read=0; F_read_ok=0; INTnum++;

if(INTnum==8) //若INTnum为8,说明接收完一个字节的数据,

将数据存入INTre[]

{

INTnum=0;

INTre[INTbyteflag]=INTTemp;

减1,直到F_long=0,说明一条指令接收完毕

}

if(INTbyteflag==3) // INTbyteflag为3时说明长度位已接收完毕 {

值给F_long

}

}

F_long=INTre[2];

if(INTre[0]!=0x00) //包头不对,标志位复位,重新接收

INTbyteflag=0; F_long=32;

{ }

F_long--;

if(INTbyteflag>=3) //当接收数据位后面的数据时,长度标志位相应

INTbyteflag++;

If(INTre[0]==0x00&&INTre[1]==0x01) //包头和地址位接收正确,将长度为赋

{

}

if(INTre[1]!=0x01) //地址位不对,标志位复位,重新接收 INTbyteflag=0; F_long=32; {

}

3、 读指令函数

功能:判断指令接收完毕,当F_long=0说明指令已接收完毕,可以

根据指令处理相应事件。若20ms内没接收完数据,说明数据接收不正常,复位相应标志位。

void Read_ok()

{

if(F_long==0)

{

INTbyteflag=0; F_long=32; INT_i2c=1; F_INT_read=1; F_read_ok=1; clk_d=0; INTnum=0; clk_watch=0;

}

if(clk_over_timer>=2) { INT_i2c=0; INTnum=0; INTbyteflag=0; F_long=32; clk_d=0; clk_watch=0; clk_over_timer=0;

}

}

4、

发送一个字节函数

功能:通过I2C发送一个字数据

void send_byte(uchar b ) {

uchar i;

for(i=0;i<8;i++) { b=b<<1; SDA=CY; _nop_();_nop_();_nop_();_nop_();_nop_(); SCL=0; _nop_();_nop_();_nop_();_nop_();_nop_(); SCL=1; delays(1);

} //延时5us //SCL拉低,此时从

机响应中断进入接收 //延时5us //发送完毕后拉高

SCL和SDA

SCL=1; SDA=1; }

5、 发送指令函数

功能:发送一条指令

bit sendbytes(uchar *s,uchar a) {

uchar i;

EX0=0; //接收时关闭外部中断0,即停止I2C接收 for(i=0;i

IE0=0; //中断位请求标志位置0

EX0=1; //接收完毕,开外部中断,即可以接收I2C数据 INT_i2c=0; return TRUE;

}

五、 源代码共享地址

1、 相应的代码都是基于STC15系列单片机

2、 代码所实现的功能是:主单片机发送指令,12864

显示相应内容 3、 源代码所需硬件:

12864液晶一个,STC15w204s一片

有兴趣的童鞋可以自己写个主单片机发送命令的程序测试一下,亲测效果很好,我们公司现在通信方式都用这个,可以节省串口。 共享资料含通信协议: http://pan.http://www.wodefanwen.com//s/1boRjjo7

本文来源:https://www.bwwdw.com/article/mmmw.html

Top