I2C转UART
I2C转UART,51单片机普通IO口模拟I2C从机,解决UART不够的问题
/***************************************************************************
* 程序名:iic_uart.C
* 作者:
* 功能描述:实现IIC和UART数据交换
* 日期:2010.9.16 10.8最后修改
***************************************************************************/
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define LOC_address 0x48
sfr AUXR = 0x8e; //定时器倍率选择寄存器 10.17
sbit scl = P1^; //P1^3
sbit sda = P1^; //旧P1^4
sbit STROBE = P1^; //P1^6
sbit disp_led = P1^; //P3^7
void I2C_txbyte(uchar );
void uart_init(void );
void I2C_init(void );
void TIMER0_init(void );
void I2C_delay(void );
void I2C_respon(void );
uchar I2C_rxbyte(void );
void I2C_ack();
void start_scan();
void I2C_rxadd();
uchar I2C_rx7();
void uart_txbyte(uchar );
uchar xdata dat_I2C[] ,dat_UART[]; //10.16修改缓存大小
uchar num = ,
RX_flag = ,
NN, m = ,n = ,
TX_over = ;
uchar address = ,
rx_data,
START_flag = ,
STOP_flag = ,
PreState,
NowState,
DEV_address,
R_W,
uart_outtime=,
I2C_rx_outtime=,
TIME_MODE=;
/***************************************************************************
* 函数名:main()
* 功能描述:主程序
*
***************************************************************************/
void main()
{
uart_init(); //串口中断初始化
TIMER0_init(); //定时器0初始化
STROBE = ; //请求接受信号线初始化
disp_led = ; //指示灯初始化 1=熄灭 0=点亮
)
{
) //在接收数据吗?
{
) //等待数据超过0.5 秒了吗
{
TR0 = ; //关定时器0
uart_outtime = ; //UART等待计时清零
STROBE = ; //请求I2C上位机读数据
RX_flag = ; //清计时标志
TIME_MODE = ; //进入等待I2C读取计时模式 ,超过4S清空数据
TR0 = ; //开计时器0 ,10.17
}
}
start_scan(); //检测起始信号
)
{
START_flag = ; //开始信号清零
I2C_rxadd(); //收取地址及命令
if(DEV_address == LOC_address) //判断是否为本机地址
{
); //给予应答
m = ; //初始化m
) //主机向本机写数据
{
STROBE = (~STROBE); //通知主机收到起始信号 10.13
dat_I2C[m] = I2C_rxbyte(); //接收第一个字节
); //等待低电平结束
STROBE = (~STROBE); //10.7添加
);
m++;
);
PreState = sda; //记录SDA状态
)
{
) //在SCL为高端平期间检测结束信号
{
NowState = sda; //记录当前SDA状态
) //上升沿说明收到结束信号
{
STOP_flag = ; //收到结束信号
}
}
else
{
dat_I2C[m] = I2C_rx7(); //继续接收剩下的7位数据
);
);
m++;
);
}
}
STOP_flag = ;
;NN < m ;NN++)
{
uart_txbyte(dat_I2C[NN]); //将收到的数据通过UART发送给上位机
}
m=;
}
) //主机向本机读数据
{
TR0 = ; //关掉计时器 10 .17
STROBE = (~STROBE); //通知主机收到起始信号 10.13
);
I2C_txbyte(dat_UART[m]);
m++;
if(m == n) //如果数被读取完则通知上位机停止读
{
STROBE = ;
}
);
);
)
{
I2C_txbyte(dat_UART[m]); //将从UART接收到的数据通过I2C发送给主设备
m++;
if(m == n) //判断是否发送完了
{
STROBE = ;
}
); //等待低电平结束
);
}
);
STROBE = ;
m = ;
n = ;
disp_led = ; //读走后将灯熄灭
num = ; //清计时参数 10.17
TIME_MODE = ; //改回UART接收数据超时计时模式
}
}
}
}
}
/***************************************************************************
* 函数名:start_scan()
* 功能描述:起始信号检测子函数
*
***************************************************************************/
void start_scan()
{
NN = ;
PreState = sda; //记录当前SDA状态,用作比较
&& NN--)
{
NowState = sda;
&& NowState == ) //如果为上升沿则为开始信号
{
START_flag = ;
}
}
}
/***************************************************************************
* 函数名:uart_init
* 功能描述:串口中断初始化子函数
*
***************************************************************************/
void uart_init()
{
AUXR = 0x40; //T1为1T工作模式
TMOD = 0x21; //T1工作模式2
TH1 = 0xf7; //装填初值 .波特率为38400
TL1 = 0xf7; //f7
TR1 = ; //启动定时1
SM0 = ; //确定10位传输
SM1 = ;
REN = ; //打开允许接收
ES = ; //开总中断和串口中断
EA = ;
}
/***************************************************************************
* 函数名:TIMER0_init()
* 功能描述:定时器0初始化子函数
*
***************************************************************************/
void TIMER0_init()
{
TH0 = ( - ) / ; //装初值
TL0 = ( - ) % ;
ET0 = ; //开定时器中断允许
}
/***************************************************************************
* 函数名:uart_service()
* 功能描述:UART中断服务程序
*
***************************************************************************/
{
dat_UART[n] = SBUF; //存收到的数据
n++;
TR0 = ; //开定时器0 ,开始等待计时
RX_flag = ; //接收到数据标志,开始检测是否等待超时
uart_outtime = ; //等待超时计数清零
RI = ; //中断接收溢出标志位清零
}
/***************************************************************************
* 函数名:uart_txbyte()
* 功能描述:UART发送一个字节
*
***************************************************************************/
void uart_txbyte(uchar data1)
{
ES = ; //关串口中断
SBUF = data1; //发送数据
while( ! TI); //等待发送完毕
TI = ; //清溢出标志
ES = ;
}
/***************************************************************************
* 函数名:timer0{}
* 功能描述:定时器0中断服务程序,用来计算UART是否等待超时
*
***************************************************************************/
{
TH0 = ( - ) / ; //给定时器0装初值 50ms中断一次
TL0 = ( - ) % ;
num++;
) //用于UART接收数据超时计时
{
disp_led = ~disp_led; //显示灯闪
) //等待超过0.5秒到了
{
uart_outtime = uart_outtime + ; //等待超时计数加一
num = ;
}
}
) //用于I2C读走数据超时计时 10.17
{
disp_led = ; //灯常亮,等待读走
) //超过2秒未读走
{
num = ; //清计时参数
STROBE = ; //不通知I2C读取
n = ; //数据缓存下标清零 ,准备接收新数据
TIME_MODE = ; //改回UART接收数据超时计时模式
disp_led = ; //超时未读走则熄灭
TR0 = ; //关定时器0
}
}
}
/***************************************************************************
* 函数名:I2C_txbyte()
* 功能描述:I2C发送一个字节
*
***************************************************************************/
void I2C_txbyte(uchar dat_byte)
{
uchar i,temp;
temp = dat_byte;
);
); //等待主机释放数据总线
;i < ;i++) //从最高位开始,依次发送8位
{
temp = temp << ; //将要发送的数最高位移到CY中
sda = CY; //数据线发送CY中存的位数据
);
);
}
sda = ; //发完释放数据总线
}
/***************************************************************************
* 函数名:I2C_rxadd()
* 功能描述:接收设备地址
*
***************************************************************************/
void I2C_rxadd()
{
uchar i,j,k=;
);
;i < ;i++)
{
while( ! scl); //等待SCL由0变为1
)
j = ;
else
j = ;
k=(k << ) | j; //将收到的位放入K中
); //SCL高电平时等待
}
R_W=k&0x01; //主机是读还是写
DEV_address= (k >> ) & 0x7f; //求出前7位的设备地址
}
/***************************************************************************
* 函数名:I2C_rxbyte()
* 功能描述:I2C接收一个字节子函数
*
***************************************************************************/
uchar I2C_rxbyte()
{
uchar i,j,k=;
); //等待SCL拉低
;i < ;i++)
{
while( ! scl); //等待SCL由0变为1
)
j = ;
else
j = ;
k=(k << ) | j;
while(scl); //SCL高电平时等待
}
return(k); //将接收到的数据返回
}
/***************************************************************************
* 函数名:I2C_rx7()
* 功能描述:检测结束信号时收数据子函数
*
***************************************************************************/
uchar I2C_rx7()
{
uchar i,j,k=;
k=(k << ) | PreState; //将上一个位数据存入K中
;i < ;i++)
{
); //等待SCL变高
)
j = ;
else
j = ;
k=(k << ) | j; //将收到的位数据存入K
); //等待SCL拉低
}
return(k); //将收到的整个字节数据返回
}
测试代码如下:
/***************************************************************************
* 程序名:test.c
* 作者:
* 功能描述:测试I2C_uart 转接器
* 日期:2010.10.8
***************************************************************************/
#include<reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit sda = P2^; //定义数据线
sbit scl = P2^; //定义时钟线
sbit STROBE = P2^; //定义信号线
, //读数据缓存数组下标
tx = ,
rx_flag=;
uchar dat[]; //定义缓存数据数组
void delay(unsigned int i) //延时程序 ,延时约i ms
{
uint j,k;
;j--)
;k > ;k--);
}
void flash() //I2C所需时序延时 5us
{ ; ; }
/***************************************************************************
* 程序名:start()
* 功能: I2C起始信号
*
***************************************************************************/
void start() //启动I2C总线
{
sda = ;
flash();
scl = ;
flash();
sda = ;
flash();
scl = ;
flash();
}
/***************************************************************************
* 程序名: stop()
* 功能: I2C结束信号
*
***************************************************************************/
void stop() //停止I2C总线
{
sda = ;
flash();
scl = ;
flash();
sda = ;
flash();
}
/***************************************************************************
* 程序名: writex (uchar j )
* 功能: I2C写一个字节子函数
*
***************************************************************************/
void writex(unsigned char j)
{
unsigned char i,temp;
temp = j;
;i < ;i++)
{
temp = temp << ;
scl = ;
flash();
sda = CY; //将进位寄存器中的数赋给数据线
flash();
scl = ;
flash();
}
scl = ;
flash();
sda = ; //释放数据线
flash();
}
/***************************************************************************
* 程序名: readx()
* 功能: I2C读一个字节子函数
*
***************************************************************************/
unsigned char readx()
{
unsigned ;
scl = ;
flash();
sda = ; //释放数据线
;i < ;i++)
{
flash();
scl = ;
flash();
)
j = ;
else
j = ;
k=(k << ) | j;
scl = ;
}
flash();
return(k);
}
/***************************************************************************
* 程序名: clock()
* 功能: I2C等待应答子函数
*
***************************************************************************/
void clock()
{
unsigned ;
scl=;
flash();
) && (i < )) //SDA=0时说明有应答,无应答则等待直到超时
{
i++;
}
scl = ;
flash();
}
/***************************************************************************
* 程序名: IIC_read()
* 功能: I2C读数据
*
***************************************************************************/
void IIC_read() //通过I2C读数据
{
) //当STROBE=0则一直发送起始信号及首地址 ,直到转接器收到 ,将STROBE变为1
{
P1=; //灯亮,作测试用
start();
writex(0x91); //发器件地址和读指令
clock();
}
) //读取数据直到读完 ,转接器会将STROBE拉低以通知发送完毕
{
dat[m] = readx(); //将读到的数据存入缓存数组中
m++; //缓存数组下标向下移一位
clock();
}
stop(); //发送结束信号
}
/***************************************************************************
* 程序名: IIC_write(uchar info)
* 功能:通过I2C将一个字节数据发给转接器
*
***************************************************************************/
void IIC_write(uchar info)
{
) //在STROBE=1时写数据 ,即无读请求时
{
)
{
start();
writex(0x90); //10.13号修改,将首地址放到WHILE外
clock();
}
writex(info); //写数据
clock();
stop();
}
else //在STROBE=0时写数据 ,此时有读请求
{
)
{
start();
writex(0x90);
clock();
}
writex(info); //写数据
clock();
stop();
}
}
/***************************************************************************
* 程序名: main()
* 功能: 程序主函数
*
***************************************************************************/
void main()
{
scl = ;
delay(); //初始化I2C
sda = ;
delay();
)
{
) //读请求
{
// IIC_write('g');
// IIC_write('e');
// IIC_write('t'); //测试用
// IIC_write(':');
IIC_read(); //读数据
delay(); //稍作延时,约1毫秒 ,紧随读数据之后
rx_flag = ; //读取到数据标志置1
P1=dat[]; //10.8,作测试用
}
) //读到数据了吗?
{
rx_flag = ;
;tx < m ;tx++) //将收到的数据返回
{
IIC_write(dat[tx]);
}
m = ; //将数据缓存下标清零
}
}
}
I2C转UART的更多相关文章
- SPI、I2C、UART(转)
UART与USART(转) UART需要固定的波特率,就是说两位数据的间隔要相等. UART总线是异步串口,一般由波特率产生器(产生的波特率等于传输波特率的16倍).UART接收器.UART发送器组成 ...
- SPI、I2C、UART、I2S、GPIO、SDIO、CAN 简介
转自http://sanwen.net/a/fmxnjoo.html SPI.I2C.UART.I2S.GPIO.SDIO.CAN,看这篇就够了 总线 总线,总要陷进里面.这世界上的信号都一样,但是总 ...
- SPI、I2C、UART三种串行总线协议的区别和SPI接口介绍(转)
SPI.I2C.UART三种串行总线协议的区别 第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART( ...
- SPI、I2C、UART、I2S、GPIO、SDIO、CAN
总线,总线,总要陷进里面.这世界上的信号都一样,但是总线却成千上万,让人头疼. 总的来说,总线有三种:内部总线.系统总线和外部总线.内部总线是微机内部各外围芯片与处理器之间的总线,用于芯片一级的互连: ...
- 串行总线 —— I2C、UART、SPI
I2C,也叫 IIC,是一种常见的串行总线,它只需要两根线即可在连接于总线上的器件之间传送信息. 0. 电气知识 开漏输出:Open drain output,不输出电压,低电平时接地,高电平时不接地 ...
- I2S/PCM/IOM-2、I2C/SPI/UART/GPIO/slimbus
概述 I2S,PCM,IOM-2都是数字音频接口,传数据的. I2C,SPI,UART,GPIO是控制接口,传控制信令的. I2S I2S(Inter-IC Sound Bus)是飞利浦公司为数字音频 ...
- SPI、I2C、UART三种串行总线协议的区别
第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART(Universal Asynchronous R ...
- UART,USART,SPI,I2C等总线的介绍与区别20160526
首先来说一下UART和USART的区别: 1.字面意义: UART:universal asynchronous receiver and transmitter通用异步收发器: USART:univ ...
- SPI,UART,I2C都有什么区别,及其各自的特点
区别: SPI:高速同步串行口.3-4线接口,收发独立.可同步进行 UART:通用异步串行口.按照标准波特率完成双向通讯,速度慢 I2C:一种串行传输方式,三线制,网上可找到其通信协议和用法的 3根线 ...
随机推荐
- javascript,jquery(闭包概念)(转)
偶尔听人说javascript闭包,让我联想起以前学编译原理和数字逻辑里讲的闭包,以前上课讲的闭包很难懂,而且含有递归的意思在里面,现在不想再查看里面的闭包概念. 但javascript我是经常要用, ...
- android 04 AbsoluteLayout
绝对布局:layout_x,layout_y:坐标精准定位 xml文件:不推荐使用 <AbsoluteLayout xmlns:android="http://schemas.andr ...
- 使用strace追踪多个进程
http://www.ttlsa.com/tools/use-strace-to-track-multiple-processes/ strace是Linux环境下的一款程序调试工具,用来监察一个应 ...
- 全面分析 Spring 的编程式事务管理及声明式事务管理--转
开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本 ...
- 你需要知道的 Android 拍照适配方案
近段时间,家里陪自己度过大学四年的电脑坏了,挑选好的新电脑配件终于在本周全部到货,自己动手完成组装.从AMD到i7的CPU,6G内存到14G内存,打开 AndroidStudio 的速度终于杠杆的上去 ...
- xslt语法之---运算符号
<xsl:param name="count">12</xsl:param > <xsl:template match="/" ...
- iOS UIKit:viewController之定义(2)
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- Junit简介和常用API
测试几个的概念 白盒测试——把测试对象看作一个打开的盒子,程序内部的逻辑结构和其他信息对测试人员是公开的. 回归测试——软件或环境的修复或更正后的“再测试”,自动测试工具对这类测试尤其有用. 单元测试 ...
- 知识点摸清 - - function()——JavaScript 函数名后什么时候加括号,什么时候不
加括号——调用函数 只要是要调用函数执行的,都必须加括号. 此时,function()实际上等于函数的返回值.(没有返回值也已经执行了函数体内的行为).就是说,只要加括号的,就代表将会执行函数体代码. ...
- 一次项目中用到的php函数总结
最近做的一个项目,我把做的过程中用到的php函数总结一下.以后遇到类似的不用百度,直接看自己总结的就好了.都是一些简单基础的函数,随手记下.方便以后学习. 1.array_sum() 返回数组中的所有 ...